README: state the container-lint claim as what is actually true
All checks were successful
check / check (push) Successful in 1m14s

The Linting section this PR adds claimed "There is no host lint path" and
then, two paragraphs later, documented script/fmt-check as a host-side
formatting check. Both cannot be true, and the absolute one is the false one.

What is true is narrower: no lint path reachable from script/check or
script/precommit runs on the host, so every lint verdict those two produce
comes from the container. script/fmt-check stays as a standalone entrypoint,
now stated as the one host formatting path with nothing reaching it. The
"exactly one place" and "in the container only" phrasings elsewhere are
qualified the same way.
This commit is contained in:
user
2026-09-04 11:27:49 +00:00
parent 956870889f
commit bd88eced84

View File

@@ -108,11 +108,14 @@ alpine. We provide:
### Linting
Linting runs in a container, one way, everywhere. `script/lint` builds
`Dockerfile.lint`, which copies the repo into a digest-pinned node image and
runs eslint and prettier as build steps, so a successful build is a clean lint.
There is no host lint path: docker is required to lint, and that also works
where the docker daemon is remote and bind mounts are impossible.
Linting runs in a container, one way, in every path that produces a lint verdict
for `make check` or the pre-commit hook. `script/lint` builds `Dockerfile.lint`,
which copies the repo into a digest-pinned node image and runs eslint and
prettier as build steps, so a successful build is a clean lint. No lint path
reachable from `script/check` or `script/precommit` runs on the host: every lint
verdict those two produce comes from the container. Docker is therefore required
to lint, and the container route also works where the docker daemon is remote
and bind mounts are impossible.
The formatting check is part of that, not a step beside it. `script/check` and
`script/precommit` therefore call `script/lint` and stop; neither calls
@@ -124,15 +127,17 @@ in each. `test/packaging/lint-once.test.ts` asserts that count by walking the
invocation graph, so a second pass cannot creep back in unnoticed.
`script/fmt-check` remains as a standalone entrypoint for asking the formatting
question on its own, without docker and without the rest of lint. Its verdict
cannot drift from the container's: prettier is pinned to an exact version,
installed from `yarn.lock` under `--frozen-lockfile` in both places, and reads
`.gitignore` as its default ignore file — which is why `.dockerignore`
deliberately keeps `.gitignore` in the build context.
question on its own, without docker and without the rest of lint. It is the one
formatting path that still runs on the host, and nothing reaches it: neither
`script/check` nor `script/precommit` calls it, so it never contributes to their
verdicts. Its own verdict cannot drift from the container's: prettier is pinned
to an exact version, installed from `yarn.lock` under `--frozen-lockfile` in
both places, and reads `.gitignore` as its default ignore file — which is why
`.dockerignore` deliberately keeps `.gitignore` in the build context.
Lint happens in exactly one place, which constrains the rest of the build.
`script/check` calls `script/lint`, so `make check` cannot run inside a
container without asking for docker inside docker. The image built from
Lint happens in exactly one place in that graph, which constrains the rest of
the build. `script/check` calls `script/lint`, so `make check` cannot run inside
a container without asking for docker inside docker. The image built from
`Dockerfile` therefore runs `make test` and `make build` and does not lint;
`script/cibuild` builds `Dockerfile.lint` first and that image second, so CI
gets both verdicts.
@@ -526,8 +531,8 @@ documents:
runs the tests) must pass before merging to `main`. `make fmt-check` is
available for a host-side formatting check on its own, but it is not a
separate requirement: `make lint` already covers it, and running both would
check formatting twice. Never invoke eslint or prettier directly; linting runs
in the container only.
check formatting twice. Never invoke eslint or prettier directly; every lint
verdict `make check` and the pre-commit hook produce comes from the container.
- **Formatting:** prettier with 4-space indents and `proseWrap: always` for
markdown. Use `make fmt` to format. Use `yarn` not `npm`.