Add .prettierrc/.prettierignore, stop reformatting REPO_POLICIES.md, and make fmt-check cover markdown #69

Closed
opened 2026-08-09 03:40:38 +02:00 by clawbot · 1 comment
Collaborator

Context

The repo has no .prettierrc and no .prettierignore, and script/fmt:23
runs prettier -w *.md || true over every root markdown file with prettier's
default settings.

Policy requires prettier with two deviations from default: four-space
indents and proseWrap: always. Because neither is configured, make fmt
writes markdown that does not match policy — and it has already done damage:

  • main's REPO_POLICIES.md is byte-identical to the authoritative copy in
    the prompts repo.
  • On PR #59 it is not: 182 lines were rewritten, collapsing 4-space nested
    list indentation to 2-space and stripping code-fence indentation. Content
    is unchanged; only formatting drifted. The front-matter last_modified
    still matches, so the drift is silent.

REPO_POLICIES.md is a verbatim fetch of an authoritative upstream
document. Local tooling must not rewrite it, for the same reason
.golangci.yml must not be rewritten.

Compounding this: script/fmt-check checks only gofmt. It never checks
markdown at all. So make fmt writes markdown changes that make check will
never notice, in either direction — the formatter and the gate disagree, and
the gate is silent.

Definition of done

  • .prettierrc exists with the policy settings (four-space indent,
    proseWrap: always) and .prettierignore exists.
  • REPO_POLICIES.md is excluded from the prettier pass via
    .prettierignore, and the copy in the repo is restored to be
    byte-identical to
    https://git.eeqj.de/sneak/prompts/raw/branch/main/prompts/REPO_POLICIES.md.
  • script/fmt-check verifies markdown formatting (prettier --check) in
    addition to Go, so make check fails if make fmt would change anything.
  • script/fmt and script/fmt-check cover the same file set. Running
    make fmt then make fmt-check is clean; running make fmt-check on a
    deliberately misformatted file fails.
  • Prettier is no longer invoked with || true. A formatter that silently
    does nothing when it is missing is worse than one that fails loudly.
  • make check passes. TODO.md updated in the same commit.

Implementation requirements

  • Restore REPO_POLICIES.md by fetching the authoritative copy, not by
    hand-editing the diff back. Verify byte-identity explicitly before
    committing.
  • Do not add .golangci.yml handling here — it is not markdown and prettier
    does not touch it. But do add it to .prettierignore anyway if the
    prettier pass is widened beyond *.md.
  • prettier -w *.json on line 22 has the same || true problem and the
    same glob-only-root limitation; fix both invocations consistently.
  • The *.md glob only matches root-level files. Decide deliberately whether
    markdown in subdirectories (docs/, once it exists) should be formatted,
    and make fmt and fmt-check agree on the answer.
  • prettier must be installed by script/bootstrap for any of this to work
    on a fresh clone — that is tracked in #68 and this issue depends on it.
    If #68 has not landed, still make script/fmt-check fail loudly rather
    than skip.
  • Commit title must end with (closes #69).
## Context The repo has no `.prettierrc` and no `.prettierignore`, and `script/fmt:23` runs `prettier -w *.md || true` over every root markdown file with prettier's **default** settings. Policy requires prettier with two deviations from default: four-space indents and `proseWrap: always`. Because neither is configured, `make fmt` writes markdown that does not match policy — and it has already done damage: - `main`'s `REPO_POLICIES.md` is byte-identical to the authoritative copy in the `prompts` repo. - On PR #59 it is not: 182 lines were rewritten, collapsing 4-space nested list indentation to 2-space and stripping code-fence indentation. Content is unchanged; only formatting drifted. The front-matter `last_modified` still matches, so the drift is silent. `REPO_POLICIES.md` is a verbatim fetch of an authoritative upstream document. Local tooling must not rewrite it, for the same reason `.golangci.yml` must not be rewritten. Compounding this: `script/fmt-check` checks **only** `gofmt`. It never checks markdown at all. So `make fmt` writes markdown changes that `make check` will never notice, in either direction — the formatter and the gate disagree, and the gate is silent. ## Definition of done - `.prettierrc` exists with the policy settings (four-space indent, `proseWrap: always`) and `.prettierignore` exists. - `REPO_POLICIES.md` is excluded from the prettier pass via `.prettierignore`, and the copy in the repo is restored to be **byte-identical** to `https://git.eeqj.de/sneak/prompts/raw/branch/main/prompts/REPO_POLICIES.md`. - `script/fmt-check` verifies markdown formatting (`prettier --check`) in addition to Go, so `make check` fails if `make fmt` would change anything. - `script/fmt` and `script/fmt-check` cover the same file set. Running `make fmt` then `make fmt-check` is clean; running `make fmt-check` on a deliberately misformatted file fails. - Prettier is no longer invoked with `|| true`. A formatter that silently does nothing when it is missing is worse than one that fails loudly. - `make check` passes. `TODO.md` updated in the same commit. ## Implementation requirements - Restore `REPO_POLICIES.md` by fetching the authoritative copy, not by hand-editing the diff back. Verify byte-identity explicitly before committing. - Do not add `.golangci.yml` handling here — it is not markdown and prettier does not touch it. But do add it to `.prettierignore` anyway if the prettier pass is widened beyond `*.md`. - `prettier -w *.json` on line 22 has the same `|| true` problem and the same glob-only-root limitation; fix both invocations consistently. - The `*.md` glob only matches root-level files. Decide deliberately whether markdown in subdirectories (`docs/`, once it exists) should be formatted, and make `fmt` and `fmt-check` agree on the answer. - `prettier` must be installed by `script/bootstrap` for any of this to work on a fresh clone — that is tracked in #68 and this issue depends on it. If #68 has not landed, still make `script/fmt-check` fail loudly rather than skip. - Commit title must end with ` (closes #69)`.
clawbot added this to the 1.0.0 milestone 2026-08-09 03:40:38 +02:00
Author
Collaborator

Implementation plan

Branch prettier-fmt-check off origin/main.

Verified first: REPO_POLICIES.md on main is already byte-identical
to the authoritative copy
(sha256 117dde7f148ed3cd693b333312f6345a0a0ee84fadbbe5cca559ca6fed4a1775),
so the drift on PR #59 never reached main. The work here is to make it
impossible for make fmt to churn it again, and byte-identity will be
re-verified after make fmt runs on the branch.

1. Config files

  • .prettierrc: tabWidth: 4, proseWrap: "always" — the two policy
    deviations from prettier defaults, nothing else.
  • .prettierignore: REPO_POLICIES.md (verbatim upstream document,
    tooling must not rewrite it), plus .golangci.yml (user-owned),
    node_modules/, vendor/, bin/.

2. One canonical prettier file set, used by both fmt and fmt-check

New script/prettier entrypoint takes --write or --check and applies
the same patterns in both modes, so script/fmt and script/fmt-check
cannot drift apart by construction. Patterns: **/*.md (recursive, so
docs/ is covered when it exists — deliberate answer to the
root-glob-only question in the issue) and **/*.json (tolerant of no
match, since the repo currently has no tracked JSON; the markdown pattern
is not tolerant, so a broken glob fails loudly).

|| true is gone from both invocations. If prettier cannot be found,
script/prettier exits non-zero with an actionable message naming
script/bootstrap.

3. Pinned prettier

package.json + yarn.lock pinning an exact prettier version; the
lockfile carries the integrity hashes, so this is hash-pinned per policy
and identical in CI and on a dev box. script/prettier prefers
node_modules/.bin/prettier and only falls back to a PATH prettier with
a warning on stderr. script/bootstrap gains node/yarn/yarn install
(pinned NODE_VERSION / YARN_VERSION constants already exist there).
This is the prettier slice of #68 only; the rest of #68 (gofumpt,
hash-pinned Go tool installs) is deliberately left for #68.

4. The Docker gate — the actual hard part

The lint stage is golangci/golangci-lint, and I confirmed by running it
that the image has no node, npm, or yarn (command -v node exits
127). So script/fmt-check cannot be hard-required there without breaking
docker build ..

Resolution: the markdown check gets its own build stage on a node image
rather than being weakened.

  • script/fmt-check-go — the existing gofmt check, extracted. The lint
    stage runs this.
  • New mdfmt stage FROM node@sha256:... (node 22.17.0 bookworm-slim,
    which ships node 22.17.0 and yarn 1.22.22 — exactly the versions
    script/bootstrap already pins), runs yarn install --frozen-lockfile
    then script/prettier --check. That image has no make, so it calls
    the script/ entrypoint directly.
  • The builder stage takes a COPY --from=mdfmt dependency, the same trick
    already used to force the lint stage to run, so BuildKit cannot skip it.

Net effect: a markdown formatting violation fails docker build ., which
is the authoritative gate. Nothing silently skips anywhere.

script/fmt-check (and therefore make check locally) runs both halves:
script/fmt-check-go and script/prettier --check.

5. Verification

  • make fmt, then git diff --exit-code REPO_POLICIES.md clean and
    sha256 still matching the authoritative copy.
  • make fmt then make fmt-check clean.
  • Deliberately misformat a markdown file, confirm make check fails, and
    confirm docker build . fails on the mdfmt stage.
  • make check green, docker build . green.
  • README.md Entrypoints section and TODO.md updated in the same
    commit; .dockerignore / .gitignore gain node_modules.

Out of scope, not touched: .golangci.yml (user-owned), the rest of #68,
and the ensure_pb duplication between script/fmt and
script/fmt-check.

## Implementation plan Branch `prettier-fmt-check` off `origin/main`. **Verified first:** `REPO_POLICIES.md` on `main` is already byte-identical to the authoritative copy (`sha256 117dde7f148ed3cd693b333312f6345a0a0ee84fadbbe5cca559ca6fed4a1775`), so the drift on PR #59 never reached `main`. The work here is to make it impossible for `make fmt` to churn it again, and byte-identity will be re-verified after `make fmt` runs on the branch. ### 1. Config files - `.prettierrc`: `tabWidth: 4`, `proseWrap: "always"` — the two policy deviations from prettier defaults, nothing else. - `.prettierignore`: `REPO_POLICIES.md` (verbatim upstream document, tooling must not rewrite it), plus `.golangci.yml` (user-owned), `node_modules/`, `vendor/`, `bin/`. ### 2. One canonical prettier file set, used by both fmt and fmt-check New `script/prettier` entrypoint takes `--write` or `--check` and applies the same patterns in both modes, so `script/fmt` and `script/fmt-check` cannot drift apart by construction. Patterns: `**/*.md` (recursive, so `docs/` is covered when it exists — deliberate answer to the root-glob-only question in the issue) and `**/*.json` (tolerant of no match, since the repo currently has no tracked JSON; the markdown pattern is *not* tolerant, so a broken glob fails loudly). `|| true` is gone from both invocations. If prettier cannot be found, `script/prettier` exits non-zero with an actionable message naming `script/bootstrap`. ### 3. Pinned prettier `package.json` + `yarn.lock` pinning an exact prettier version; the lockfile carries the integrity hashes, so this is hash-pinned per policy and identical in CI and on a dev box. `script/prettier` prefers `node_modules/.bin/prettier` and only falls back to a `PATH` prettier with a warning on stderr. `script/bootstrap` gains node/yarn/`yarn install` (pinned `NODE_VERSION` / `YARN_VERSION` constants already exist there). This is the prettier slice of #68 only; the rest of #68 (gofumpt, hash-pinned Go tool installs) is deliberately left for #68. ### 4. The Docker gate — the actual hard part The lint stage is `golangci/golangci-lint`, and I confirmed by running it that the image has **no node, npm, or yarn** (`command -v node` exits 127). So `script/fmt-check` cannot be hard-required there without breaking `docker build .`. Resolution: the markdown check gets its own build stage on a node image rather than being weakened. - `script/fmt-check-go` — the existing gofmt check, extracted. The lint stage runs this. - New `mdfmt` stage `FROM node@sha256:...` (node 22.17.0 bookworm-slim, which ships node 22.17.0 and yarn 1.22.22 — exactly the versions `script/bootstrap` already pins), runs `yarn install --frozen-lockfile` then `script/prettier --check`. That image has no `make`, so it calls the `script/` entrypoint directly. - The builder stage takes a `COPY --from=mdfmt` dependency, the same trick already used to force the lint stage to run, so BuildKit cannot skip it. Net effect: a markdown formatting violation fails `docker build .`, which is the authoritative gate. Nothing silently skips anywhere. `script/fmt-check` (and therefore `make check` locally) runs both halves: `script/fmt-check-go` and `script/prettier --check`. ### 5. Verification - `make fmt`, then `git diff --exit-code REPO_POLICIES.md` clean and sha256 still matching the authoritative copy. - `make fmt` then `make fmt-check` clean. - Deliberately misformat a markdown file, confirm `make check` fails, and confirm `docker build .` fails on the `mdfmt` stage. - `make check` green, `docker build .` green. - `README.md` Entrypoints section and `TODO.md` updated in the same commit; `.dockerignore` / `.gitignore` gain `node_modules`. Out of scope, not touched: `.golangci.yml` (user-owned), the rest of #68, and the `ensure_pb` duplication between `script/fmt` and `script/fmt-check`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/mfer#69