script/fmt ran prettier with default settings over root-level *.md and
*.json, swallowing every failure with `|| true`, while script/fmt-check
checked gofmt only. The formatter and the gate therefore disagreed
silently: `make fmt` rewrote markdown that `make check` never looked at,
including REPO_POLICIES.md, which is a verbatim copy of an authoritative
upstream document that local tooling must not touch.
Configuration:
- .prettierrc pins the two policy deviations from prettier defaults,
four-space indents and proseWrap: always. Nothing else.
- .prettierignore excludes REPO_POLICIES.md so no local run can drift it
from upstream again, plus .golangci.yml (user-owned, and listed even
though the current file set does not reach it) and node_modules,
vendor, bin.
One canonical file set:
- New script/prettier takes --write or --check and applies the same
patterns in both modes, so script/fmt and script/fmt-check cannot
drift apart by construction. The patterns are repo-wide (**/*.md,
**/*.json) rather than root-only, so markdown in subdirectories such
as a future docs/ is covered.
- No `|| true` anywhere, and no --no-error-on-unmatched-pattern: both
patterns always match tracked files, so an empty match means the glob
broke and prettier should say so instead of passing vacuously. A
missing prettier is a hard error naming script/bootstrap, not a
silent skip.
Pinned prettier:
- package.json/yarn.lock pin prettier 3.9.6; the lockfile carries the
integrity hash, and --frozen-lockfile enforces it. script/prettier
prefers node_modules/.bin/prettier and warns on stderr when it has to
fall back to a PATH prettier of unknown version.
- script/bootstrap now installs node, yarn, and the locked JS deps. Its
NODE_VERSION and YARN_VERSION pins already existed.
Docker gate:
- The golangci-lint image has no node, so the lint stage runs the new
script/fmt-check-go (the Go half of fmt-check, extracted) instead of
the whole thing.
- The markdown half gets its own stage on a digest-pinned node image
shipping exactly the node and yarn versions bootstrap pins. The
builder stage takes a COPY --from dependency on it, so BuildKit cannot
skip it and a markdown violation fails `docker build .` rather than
being skipped somewhere nobody looks.
Markdown files other than REPO_POLICIES.md are reformatted here for the
first time under the policy settings.
Closes#39
Splits the Dockerfile into a dedicated lint stage using the `golangci/golangci-lint` image directly, rather than copying the binary into the builder stage.
## Changes
### Dockerfile
- **Lint stage** (`AS lint`): Uses the pre-built `golangci/golangci-lint` image (pinned by sha256) to run `make fmt-check` and `make lint`. This is a self-contained stage with its own `go mod download` and source copy.
- **Builder stage** (`AS builder`): Runs only `make test` and the final binary build. No longer needs golangci-lint installed.
- **Stage dependency**: `COPY --from=lint /src/go.sum /dev/null` forces BuildKit to always execute the lint stage (without this, unused stages are silently skipped).
- Both stages touch `mfer/mf.pb.go` to prevent make from trying to regenerate via protoc.
With BuildKit, the lint and builder stages run in parallel after their shared `go mod download` layers complete, so lint/formatting failures surface much faster without blocking on test execution.
### Makefile
- Added `lint` to the `check` target prereqs: `check: test lint fmt-check` (was `check: test fmt-check`), matching the [REPO_POLICIES](https://git.eeqj.de/sneak/prompts/raw/branch/main/prompts/REPO_POLICIES.md) requirement.
Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de>
Reviewed-on: #45
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>