Skip to content

fix: use American spelling in prose, identifiers and generated output - #21

Closed
datapointchris wants to merge 6 commits into
mainfrom
american-spelling
Closed

datapointchris wants to merge 6 commits into
mainfrom
american-spelling

Conversation

@datapointchris

@datapointchris datapointchris commented Sep 3, 2026 •

Copy link
Copy Markdown
Owner

This repo prefers American spelling in prose and identifiers alike, and it carried
the British forms in comments, docstrings, test names, one Python parameter and
one warning string. This converts those, puts the en-GB_to_en-US dictionary on
the codespell hook, and adds the check that finds what the hook structurally
cannot. Five sites keep the British spelling because another program owns the
name; each is declared with its reason.

What to look at

  1. lib/generators/tmux.sh — three *-colour option names and two
    align=centre are untouched, and the comment above the first block says why.
    The same file's comments no longer name a sibling repo, and 50 lines of that
    left the 25 generated tmux.conf files with them.
  2. scripts/check-spelling.sh — new. Its SETTLED table is the only record
    of which British spellings are deliberate. Read whether each pattern is narrow
    enough to reject a real one, and whether the reasons are checkable.
  3. .codespellrc — ignore-regex = align=centre|\["[^"]*"\] rather than a
    word list, plus builtin so a bare codespell matches the hook.
  4. themes/everforest-dark-hard/theme.yml — grey1 and grey2 stay in the
    comments that name upstream's slots. Every other comment in that column names
    an everforest slot too.
  5. themes/retrobox/theme.yml and its generated palette.lua — the extended
    key grey becomes gray, the only key rename in the diff.
  6. lib/lib.sh:395 — the only user-visible string that changed.

Every other file in the diff is a comment, a docstring or a bats test name.

How it was verified

What the second instrument was actually worth, measured before the change
rather than after it.
Taken at the head, a codespell run returns 0 because the
conversion is what produces the 0. Against the parent of the spelling commit:

git diff abc9d69..f3277cc -U0 -- . ':!.pre-commit-config.yaml' ':!.codespellrc' \
  | rg '^-[^-]' | sed 's/^-//' > removed.txt                      -> 111 lines
codespell --config /dev/null --builtin 'clear,rare,en-GB_to_en-US' removed.txt \
  | cut -d: -f2 | sort -u | wc -l                                 -> 110

So codespell alone would have found 110 of the 111 lines this change edits. The
one it misses is # bell style: inverted rather than merely recoloured. The
second instrument's contribution to the diff is one word. Its contribution to the
census is different and is where it failed: it was supposed to tell a deliberate
keep from a miss, and it missed grey1 and grey2 entirely.

The three blind spots that produce that, each measured. codespell keeps a
hyphenated or digit-suffixed token whole, so display-panes-colour and grey1
both exit 0. There is no word boundary between a letter and a digit, so an rg
pattern anchored on \b misses the same two — one shared failure, not two
independent ones. And codespell refuses a dot-prefixed file without -H, even
when the file is named explicitly: identical bytes gave 0 findings as
.pre-commit-config.yaml and 9 as plain.yaml. A file inside a dot-prefixed
directory is read normally; .github/PROBE.yml was flagged either way.

scripts/check-spelling.sh is the instrument that survives this PR. One
codespell call with -H --regex "[a-zA-Z']+" splits on -, _ and digits and
opens the dot-files, which reaches all three classes at once. At the head:

183 settled, nothing to review        (exit 0)

Its assertion was proved able to fire. A planted # a colour and a centre and a grey thing produces three findings, including the two words no earlier
instrument here could catch.

Regeneration is byte-identical across two consecutive runs, and the committed
artifacts match what the generators emit.

The effect was diffed rather than reasoned about. theme apply gruvbox ran
twice into a sandbox with HOME and all four XDG paths repointed and every
reload command stubbed, once from each of the two trees. Both installed the same
31 files, and the whole content difference was one comment line. The resulting
gruvbox.conf then sourced into an isolated tmux -L server at exit 0, with
show-options -g reading back display-panes-colour #665c54.

bats tests/ — 243 passing, exit 0.

What changes

One user-visible string. The warning shown when a plugin theme's colorscheme is
absent and the theme ships no fallback now ends "the editor keeps its previous
colors".

codespell run bare at the repo root now applies the same dictionaries as the
hook. It previously exited 0 on files the hook rejects.

The commit gate now reads dot-named files. .codespellrc, .gitignore,
.editorconfig and .pre-commit-config.yaml were skipped at exit 0 before, so
the config installing the check sat outside it. Proved by planting # a colour of a thing in .gitignore: the old invocation is silent, the new one reports it.

The generated tmux.conf files lost two comment lines each that named a sibling
repo. Nothing reads them.

Nothing else observable changes. The rest of the generated output differs only in
comments, and retrobox's renamed palette key is read by nothing.

Decisions, and what they rejected

  • The three tmux *-colour options keep their spelling — they are tmux's
    canonical names. tmux accepts display-panes-color and stores it back under
    display-panes-colour, which is what show-options prints and what the
    manpage documents. The alias makes a rename survivable rather than correct, and
    the generated config would stop matching what tmux reports.
  • align=centre keeps its spelling, and the reason is the opposite of loud.
    A style refuses the other spelling: set-option -g status-style 'align=center' exits 1 with invalid style. A format validates nothing, and
    every align= site in this repo is inside pane-border-format:
    #[align=center] and #[align=bogusvalue] both set at exit 0 and simply draw
    left. So the wrong spelling here fails silently at draw time, which is why the
    literal is exempted rather than the word.
  • everforest's grey1 and grey2 stay — every comment in that palette names
    the upstream slot its value came from, and gray1 would name a slot the plugin
    does not have. That is the same failure as renaming a third-party option key:
    it reads as working and points at nothing.
  • The exception is scoped to the literal, not the word — ignore-words-list = centre switches the correction off repo-wide, so the gate this change installs
    would pass the British spelling in any prose written here afterwards. Measured
    both ways against the same file: with the regex form, the tmux literal passes
    and prose is still a finding.
  • grey becomes gray in retrobox — no generator consumes EXTENDED_GREY,
    no highlight file references palette.grey, and every other theme spells that
    slot gray.
  • Smallest change that would work — running codespell alone and stopping.
    It converts 110 of the 111 edited lines, so it is most of the change rather
    than none of it. What rules it out is the five sites that had to be recognized
    and kept: it cannot see four of them, and a clean run reads identically whether
    they were considered or overlooked.

Risk and rollback

Nothing deploys. A revert restores the British spellings, the wider codespell
exception and the sibling-repo comments, and costs nothing else — no state is
written and no schema moves.

A revert cannot undo a theme applied to a machine in the meantime. That machine
keeps a tmux.conf whose comments differ, which nothing reads.

What this does not do

It does not change any color value, palette, or generated configuration that an
application parses. It does not sweep the sibling-repo references
outside the tmux generator: bin/theme sources a path under another repo as
working code, and the test fixtures use machine names, and both need decisions
this change does not make.

The review

#21 (comment) — 4
correctness, 8 break a rule, 3 should be rules, 4 design.

  1. fixed — 95aaab7. ignore-regex = align=centre scopes it to the literal.
  2. fixed — 95aaab7. The three grey1/grey2 were a real miss and stay as
    everforest's slot names, now recorded in the theme.yml itself. Both figures in
    this body were wrong and are replaced; the survivor scan is retired in favor
    of scripts/check-spelling.sh, which finds them.
  3. fixed — the rejection is now measured against the parent at 110 of 111, and
    the claim about what the second instrument added is corrected.
  4. fixed — 79e156d. The stamp is declared in the generator repo rather than here,
    so the bump happened there and the regenerated config lands in that commit.
    Stamp 21 separates this block from the two that both carried 20 while
    holding different codespell args.
  5. fixed — 639dde5. The generator comments carry the mechanism without the name,
    and 50 lines left the generated artifacts.
  6. fixed — the opening sentence.
  7. fixed — the standards pointer is replaced by what the rule said.
  8. fixed — the verification section names the two trees rather than the route.
  9. fixed — 95aaab7. .codespellrc names the dictionaries the hook passes.
  10. fixed — 639dde5. The constraint is stated above the option block. That comment
    carries no backticks, because the heredoc is unquoted and a backtick in it is
    command substitution — the first version of it silently generated an empty gap
    where each option name should have been.
  11. fixed — the style-versus-format distinction is corrected, and it strengthens
    the decision rather than weakening it.
  12. fixed — item 2 asks about a fact instead of asking for a decision.
  13. proposed as a rule — a scoped lint exception is a third tier between a
    repo-wide word list and a per-line suppression, and most linters ship one.
  14. proposed as a rule — a second extraction has to differ in what it looks for,
    not only in what does the looking. All three instruments here shared one word
    list and missed grey together.
  15. proposed as a rule — a receipt ruling out a smaller alternative is taken on
    the tree before the change, never on the tree the change produced.
  16. partly fixed — the generator half is done and the generated artifacts are
    clean. The rest is named under What this does not do rather than left as
    an absence.
  17. fixed — the receipts that could only confirm themselves are re-measured
    against the parent tree, and the ones that cannot be are labeled as counts
    rather than as evidence.
  18. fixed — the convention is now recorded at the sites: the tmux option block,
    everforest's palette, scripts/check-spelling.sh's SETTLED table, and the
    CLAUDE.md section read while transcribing a palette.
  19. fixed — scripts/check-spelling.sh, in the shape of the existing maintenance
    check rather than a theme subcommand.

Two tmux surfaces keep the British spelling, because both are tmux's own
vocabulary rather than this repo's:

  display-panes-colour, display-panes-active-colour, clock-mode-colour —
  tmux's canonical option names. tmux accepts a `color` alias and stores
  it back as `colour`, which is what the manpage documents and what
  `show-options` prints.

  align=centre — tmux rejects `align=center` with "invalid style", the
  same error a bogus value gets. Every theme's pane-border-format needs
  it to parse.

`centre` is declared in .codespellrc beside `noice`, which sits there for
the same reason: a third party's spelling of its own thing.

retrobox's extended key `grey` becomes `gray`, matching every other
theme. Nothing reads it — no generator consumes EXTENDED_GREY and no
highlight file references palette.grey.
codespell runs `--builtin clear,rare,en-GB_to_en-US`, so a British
spelling is a finding at the moment it is typed. Its exclude gains
`.csv` and `.tsv`, where a British place or company name is the record
rather than a misspelling.
The block's comment states the constraint without spelling out a British
example, so the generated config carries none of the words its own hook
exists to catch.

@datapointchris datapointchris left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR review

Read: pull-requests.md, ci.md, documentation.md, shell.md end to end; testing.md and git-workflow.md by rule listing with the rules the diff reaches opened.
Not routed: go.md, rust.md, frontend.md, cli-design.md, release.md, data.md, api-design.md, infrastructure.md — the diff touches nothing they cover. python.md is not selected for this repo and the one .py hunk is a local parameter rename; nothing in its naming rules reaches it.
Read at 361e332. The branch moved twice during the review; every measurement below is at that head.
Findings: 1 correctness · 6 break a rule · 1 should be a rule · 1 design

Two of the body's claims I ran and they hold. Regeneration is byte-identical: git archive HEAD into two scratch trees, lib/generate-all.sh in one, diff -rq between them returns 0 differing files, at 7.4s wall and 625% CPU. And tmux does accept the American option aliases — set-option -g display-panes-color red exits 0 and show-options -g reads back display-panes-colour red, so the decision to leave those three names alone is right.

Correctness

  1. .codespellrc:4 — the centre entry disables the centre ==> center correction across the whole repo, so the gate this PR installs passes a British centre in any prose written here from now on. Measured against the branch's own config: printf 'The centre column.\n' > probe.md then codespell --builtin 'clear,rare,en-GB_to_en-US' probe.md exits 0. The narrower declared form was measured too. With ignore-words-list = noice and ignore-regex = align=centre, git ls-files | tr '\n' '\0' | xargs -0 -r codespell --builtin 'clear,rare,en-GB_to_en-US' still exits 0 over the whole tracked tree, and the same probe goes back to probe.md:1: centre ==> center, exit 65. So the tree stays green and the word stops being free. ci.md § "A lint rule is never switched off globally to satisfy one call site" is the rule, and the noice precedent the body leans on does not reach this case — that rule's carve-out is for a proper noun with no source fix available, and centre is an ordinary English word the new dictionary exists to catch. Fix: replace the word entry with ignore-regex = align=centre, keeping ignore-words-list = noice.

Breaks a written rule

  1. lib/generators/tmux.sh:43,176,183 — documentation.md § "A repo is a product for a stranger; the fleet is one deployment of it" — theme is public (gh api repos/datapointchris/theme --jq .private returns false), and three generator comments name a private sibling repo. Line 43 sends the reader to docs/architecture/tmux-sessions.md in dotfiles, which no stranger can open. Lines 176 and 183 are copied verbatim into every generated artifact: git grep -n -i dotfiles -- 'themes/*/tmux.conf' returns 50 lines across 25 files. The rule names generated config as where this vocabulary concentrates. This PR rewrote comments in that generator and regenerated all 25 tmux.conf, which is the one moment the other repo-wide comment sweep was free to run. Fix: state the mechanism without naming the repo — "a status-line installer run before this file is sourced" carries it — then lib/generate-all.sh --generators tmux.

  2. .codespellrc — ci.md § "Tool-specific config goes in the tool's own file, not a hook arg" — the dictionary selection exists only in the hook's args:, so running the tool by hand in this repo does not reproduce the gate. Measured with the branch's .codespellrc in place, on The colour of the behaviour we organise.: codespell probe.md exits 0, and codespell --builtin 'clear,rare,en-GB_to_en-US' probe.md returns three findings. Adding builtin = clear,rare,en-GB_to_en-US to .codespellrc returns the same three with no hook arg at all. The rule names .codespellrc by name and cites this repo's noice entry as the worked shape. Fix: declare builtin in .codespellrc. The hook arg is forge's block and is not this repo's to change; the point is that the repo's own file should answer the same question.

  3. lib/generators/tmux.sh:108,109,136 — documentation.md § "Document a constraint at the edit site" — display-panes-active-colour, display-panes-colour and clock-mode-colour are deliberate and carry no note at the lines that hold them. The gate cannot supply one either: codespell --builtin 'clear,rare,en-GB_to_en-US' over a file containing display-panes-colour exits 0, because its word regex keeps a hyphenated token whole. So the only record that these three are tmux's own names is the merge commit, and a reader editing that generator meets neither. .codespellrc documents centre at its edit site and these get nothing. Fix: one line above the block saying tmux owns the names and the spell gate cannot see them.

  4. PR body, How it was verified — pull-requests.md § "A receipt names the tool's blind spot" — the survivor scan reports "78 hits, every one a tmux option name", and that is not the population. Over the same file list, git ls-files -z | xargs -0 rg -uu -oi '(colour|centre|grey|behaviour|artefact|licence|organis|recognis|judgement)' returns 78 colour, 55 centre and 3 grey. The centre hits split 50 in themes/*/tmux.conf, 2 in lib/generators/tmux.sh and 3 in .codespellrc. The three grey are themes/everforest-dark-hard/theme.yml:14, :15 and :61, annotating base16 slots as grey1 and grey2. That word is in the dictionary — a file holding bare grey gives grey ==> gray, exit 65 — while grey1 grey2 exits 0, which is exactly the compound-token blind spot the body documents two paragraphs above. It is also the word this PR renamed in retrobox, and none of the three instruments carries the stem. Fix: convert them, or name them in Decisions beside the tmux options as everforest's own slot names.

  5. PR body:71 — git-workflow.md § "A message describes the repo, never the route the change took", which pull-requests.md § "The body is the merge commit, so it is written as permanent history" extends to a body — "once from this branch, once from a git archive of the parent commit". this branch is in that rule's banned list verbatim, and the sentence stops parsing the moment the history is linear. Fix: "once at this head, once from a git archive of the parent commit".

  6. PR body, Decisions — pull-requests.md § "A claim reasoned to rather than run does not go in a body" — "tmux rejects align=center with invalid style, the same error align=bogusvalue gets. Every theme's pane-border-format depends on it." The first sentence is true of a style option and the second names a format, where it is false. On tmux 3.7c, set-option -g status-style 'align=center' exits 1 with invalid style: align=center; set-option -g pane-border-format '#[align=center]X' exits 0, and so does align=bogusvalue, because a format's #[...] is resolved at draw time rather than validated at set time. Both of this repo's align= sites are formats — status-format[0] and pane-border-format — and git grep -n 'style .*align=' themes/*/tmux.conf lib/generators/tmux.sh returns nothing. The decision is right and gets stronger from the correction: on the surface this repo actually uses, a wrong value is not refused, it just draws left. Fix: say the style parser accepts only centre, and that inside a format a wrong value fails silently.

Should be a rule

  1. PR body, How it was verified — proposed: a-second-extraction-differs-in-vocabulary-not-only-in-tool — pull-requests.md § "A receipt names the tool's blind spot" asks for "a second extraction by different means", and this body did that three times: codespell, an rg survivor scan, and an -ise/-yse/doubled-l scan. All three share one word list, so all three miss grey together, and finding 4 above is the result. Different tool with the same vocabulary is one extraction run three times, and it reads as triangulation because the tools differ. The rule would say a second extraction differs in what it looks for, not only in what does the looking — and that a sweep's vocabulary must not be derived from what the first instrument already reported, which is how this one was built. testing.md § "Two extractors in one comparison share one identifier grammar" is the near rule and asks for the opposite property in a different situation, so it does not reach this. It belongs in pull-requests.md beside the blind-spot rule, with this branch as the worked example.

Design and architecture

  1. scripts/ — the instruments that found the survivors exist only as three command blocks in a merge commit, and the next person doing this reconstructs them from prose. That reconstruction is what missed three grey this time, so the cost is already paid once. The repo has the pattern for it: scripts/check-plugin-drift.sh is a maintenance check, deliberately not a theme subcommand, run once or twice a year and after adding a plugin theme. A spelling sweep has the same shape and the same cadence. It is also smaller than what the body ran — git ls-files | tr '\n' '\0' | xargs -0 -r codespell -H --builtin 'clear,rare,en-GB_to_en-US' --regex "[a-zA-Z']+" replaces all three scans, because the regex splits hyphens and digits and the -H reaches the dot-files; it reports all 136 British tokens, with hex fragments (EDE, CAF, DAA) and Noice as the known false positives to filter. Without it, the sentence "78 hits, every one a tmux option name" is a fact about one afternoon, and the check that would keep it true is not in the repo.

This review does not gate merge.

@datapointchris datapointchris left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR review

Read at 361e332, the current head.

Read: pull-requests.md, ci.md, documentation.md end to end; git-workflow.md headings plus its message and merge-commit rules; testing.md, python.md and shell.md at rule-list level, opening the gate-proving and generated-artifact rules.
Not routed: api-design.md, cli-design.md, configuration.md, data.md, go.md, rust.md, frontend.md, infrastructure.md, repo-structure.md, tool-tiers.md — the diff adds no surface, no schema and no code in those stacks.
Findings: 2 correctness · 4 break a rule · 1 should be a rule · 1 design

The design pass first, since it decides whether the rest matters. The change should exist: American spelling is the stated house preference, and the repo carried the British forms in comments, docstrings, bats names, one parameter and one warning string. The two tmux exemptions are real and I ran both. tmux set-option -g status-style 'align=center' returns invalid style: align=center at exit 1, the same output align=bogusvalue produces. tmux set-option -g display-panes-color red is accepted and show-options -g reads it back as display-panes-colour red. The smallest-change rejection also holds: codespell alone returns 0 over the head tree while 133 British tokens remain. Regeneration is byte-identical — git archive 361e332 into a scratch tree, bash lib/generate-all.sh, diff -r against a pre-run copy is empty. bats tests/ in that tree is 243 tests at exit 0.

Correctness

  1. .codespellrc:6 — ignore-words-list = noice,centre switches the new gate off for centre across the whole repo, so a British centre typed into any prose here is never a finding. That is the outcome the branch exists to prevent, and a narrower declared exception in the same file avoids it. Measured on the head tree. With ignore-regex = align=centre and ignore-words-list = noice, codespell -H --builtin 'clear,rare,en-GB_to_en-US' over every file returns 0 — the config's own comment survives, because every centre in it sits inside align=centre. A probe file holding The centre of the screen. then returns centre ==> center at exit 65. Under the committed config that same probe returns 0. ci.md § "A lint rule is never switched off globally to satisfy one call site" is the rule the body cites; its noice carve-out reasons from a proper noun with no source fix available, and centre is neither. Fix: ignore-regex = align=centre, with ignore-words-list = noice.

  2. themes/everforest-dark-hard/theme.yml:14,15,61 — three British spellings survive and the survivor scan reports none. The body states the scan returns "78 hits, every one a tmux option name". Two extractions over git ls-files at 361e332 disagree. An explicit stem list returns 78 colour, 55 centre and 3 grey. codespell's own dictionary_en-GB_to_en-US.txt, 526 entries, matched as substrings with rg -f over the same file list, returns the same three grey lines once the tmux surfaces and .codespellrc are set aside. They are palette comments: # grey1 - comments, line numbers, # grey2 - dark foreground, # grey1 - NOT white!. codespell cannot see them because grey1 is one token, which is the blind spot the body itself names. grey->gray is in the dictionary, so a bare grey is caught. Commit 6ef3c90 converted the same word in themes/retrobox/theme.yml, at # Comments (grey) and # ANSI 8 - grey. Two further things about that count. align=centre occurs 52 times across 25 tmux.conf files and lib/generators/tmux.sh, is kept deliberately, and is absent from the 78. And a scan "matching British stems anywhere inside a token" cannot return 78, since centre is such a stem. I am certain the three lines are there and that the count is not the count; I do not know whether they were missed or kept. If they were kept, Decisions owes a third bullet — a reader who finds two documented exemptions and a third undocumented one reads the third as an oversight.

Breaks a written rule

  1. Body, opening sentence — documentation.md § "A repo is a product for a stranger; the fleet is one deployment of it" — "The fleet prefers American spelling in prose and identifiers alike" names a private arrangement. datapointchris/theme is public, and merge_commit_message=PR_BODY puts this sentence into public git log verbatim. pull-requests.md § "A receipt is remeasured at the head, and a contract stated once" records exactly this gap: that rule's sweep reads git ls-files, so it cannot see a body, which makes the body the one artifact certain to land on main and structurally invisible to the check. Fix: state it as this repo's own convention.

  2. Body, Decisions, third bullet — pull-requests.md § "A body cites only what the repo carries" — ci.md § "A lint rule is never switched off globally to satisfy one call site" points at a corpus no reader of this repo can open. Fix: carry what the rule said instead. A repo-wide exception declares its reason in the tool's own config file.

  3. Body, How it was verified — git-workflow.md § "A message describes the repo, never the route the change took" — "once from this branch, once from a git archive of the parent commit". this branch is in that rule's banned list verbatim, and the rule's own tell applies: after the merge there is no this branch. Fix: name the two commits.

  4. Body, What to look at, item 2 — pull-requests.md § "The body addresses everyone who ever reads it, never one person" — "Check this is the right register for the exception, and that a per-line # codespell:ignore would not have been better" hands the reader a decision. Directing attention is allowed and asking for a decision is not. Item 3's "Check nothing resolves it by name" is the sanctioned shape, because it names a fact. Fix: drop the second clause. Decisions already records the choice.

Should be a rule

  1. .codespellrc — proposed: narrowest-declared-lint-exception — ci.md § "A lint rule is never switched off globally to satisfy one call site" names two tiers. A repo-wide declared exception carrying its reason, and a per-line suppression needing approval. It names no tier for a scoped pattern, and its worked example, ignore-words-list = noice, is the widest of the three. So the body reasons straight from "not per-line" to "declared word list" and never weighs ignore-regex, which is neither. Most linters ship the middle tier — codespell's ignore-regex, ruff's per-file-ignores, a shellcheck directive scoped to one function. The existing rule is written too narrowly to catch a case where the narrow form exists and is free.

Design and architecture

  1. themes/*/theme.yml — the only instrument that can see a British spelling inside a compound token is a command typed once into a PR body. codespell tokenizes, so grey1, and every upstream palette slot spelled the British way, is invisible to the gate this branch installs. Finding 2 above is that gap firing on the current tree. The consequence is for whoever transcribes the next plugin palette: they write # grey0, # grey1 from upstream's own names, the hook passes, CI passes, and nothing reports it. CLAUDE.md § "Mapping a Palette into theme.yml" is the section read at the moment that decision is made and it says nothing about spelling, so the convention 6ef3c90 establishes for retrobox is recorded nowhere. tests/generators.bats already holds the repo-wide invariants that used to live in CLAUDE.md as shell one-liners, which is the shape this scan fits.

This review does not gate merge.

@datapointchris datapointchris left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR review

Read end to end: pull-requests.md, ci.md, shell.md, python.md, configuration.md, README.md
Read in part: documentation.md (the comment, canonical-source, pointer, citation and repo-is-a-product-for-a-stranger rules), testing.md and code-quality.md (heading list, then the sections the diff reaches)
Not routed: go.md, rust.md, frontend.md, data.md, api-design.md, cli-design.md, tool-tiers.md, release.md, infrastructure.md, repo-structure.md, dependencies.md, help.md, common-errors.md, claude-output-style.md — the diff touches nothing they cover
Findings: 3 correctness · 5 break a rule · 1 should be a rule · 1 design

The regeneration claim holds and I re-ran it. lib/generate-all.sh over every theme and every generator, into a copy of the tree at f3277cc, then diff -rq against the committed artifacts: no differences, 9.8s wall. Both tmux decisions hold too, measured on tmux 3.7c — set-option -g display-panes-color '#665c54' exits 0 and show-options -g reads back display-panes-colour #665c54, and set-option -g status-style 'align=center' exits 1 with invalid style: align=center, the same error align=bogusvalue gets. The grey rename is unreferenced: no generator reads EXTENDED_GREY or EXTENDED_GRAY, no highlight file references palette.grey or palette.gray, retrobox carries no colliding key, and the five other themes with such a slot all spell it gray.

Correctness

  1. .pre-commit-config.yaml:1 — the committed generated config is not what the generator emits, and the stamp says the repo is current in both states. abc9d69 and f3277cc both carry # forge-toolchain: 20, and their codespell blocks differ. The block moved again after this commit, so the die now emits a third text: the paragraph at :109 and the one above the exclude: are both superseded, and the later revision exists specifically because the example words in the first one trip the hook the block installs. The next apply rewrites this file with no commit accounting for the diff. Nothing can report that: the stamp declaration's own bump_when reads "any change to what a generator emits — a new block, a dropped block, or different content out of an existing one", and the stamp has not moved since 2026-09-01, so a stamp-only currency check answers "current" before this change, after it, and after the correction. ci.md § "forge is the source of truth" and § "Generated configs carry a # <tool>-toolchain: N stamp". Fix: bump the declared stamp, re-run the apply, and commit the result on this branch so the file matches the die and the stamp separates the two states.

  2. The body's Smallest change that would work is measured on the tree the change produced, and the measurement taken on the tree that decides the question says the opposite. The body: "running codespell alone and stopping. Rejected by measurement: it returns 0 while 78 British tokens remain." A 0 at the head is guaranteed — the conversion is what produces it. Run it against the parent instead. Take the 111 lines the spelling commit removed and hand them to the same dictionary:

    git diff $(git merge-base origin/main f3277cc)..f3277cc -U0 \
      -- . ':!.pre-commit-config.yaml' ':!.codespellrc' \
      | rg '^-[^-]' | sed 's/^-//' > removed.txt              → 111 lines
    codespell --builtin 'clear,rare,en-GB_to_en-US' removed.txt \
      | cut -d: -f2 | sort -u | wc -l                          → 110
    

    Two extractions agree on the input: rg -c -i 'colour|behaviour|artefact|licence|organis|recognis|judgement|labelled|favour|honour|grey|analyse' over the same file returns 111. So codespell alone finds 110 of the 111 lines this change edits. The single line it misses is # bell style: inverted rather than merely recoloured. What it genuinely cannot see is the 78 tmux compound names and everforest's grey1/grey2 — and the change converts neither of those, so the second instrument's unique contribution to the diff is one word. Under merge_commit_message=PR_BODY this sentence is permanent history asserting the opposite of what the code shows. Fix: state the measurement over main, and say what the survivor scan actually added.

  3. The survivor scan's pattern omits the two words the change is about, and three real survivors fall outside the count. The body reports "82 hits: 78 tmux option names, 4 inside forge's generated hook comment." The same scan over the same tree with centre and grey in the pattern returns 141 occurrences: 79 colour, 55 centre, 3 grey, and one each of licence, Centre, behaviour and artefact. The three grey are themes/everforest-dark-hard/theme.yml:14, :15 and :61 — grey1 and grey2 inside comments, compound tokens codespell cannot match, which is exactly the blind spot this instrument exists to cover. They are everforest's own palette slot names (everforest-nvim/lua/everforest/types.lua:66-68 declares grey0, grey1, grey2), so keeping them is very likely right; nothing in the change says so, and the receipt reads as an exhaustive account of what survived. The hook-comment figure is short too: at f3277cc that file carries nine British spellings, and codespell flags eight of them the moment the filename does not start with a dot. Fix: rerun the scan with centre and grey in the pattern, correct the number, and record what happens to grey1/grey2.

Breaks a written rule

  1. .codespellrc:6 — ci.md § "A lint rule is never switched off globally to satisfy one call site" — ignore-words-list = noice,centre turns the word off across the whole repo to satisfy align=centre in 25 generated files. ignore-regex is the scoped form, and it works:

    ignore-regex = align=centre
      codespell --builtin 'clear,rare,en-GB_to_en-US' themes/gruvbox/tmux.conf   → exit 0
      printf 'the centre of the screen\n' > p.txt ; codespell … p.txt            → exit 65
    ignore-words-list = noice,centre   (as committed)
      codespell … p.txt                                                          → exit 0
    

    The committed form is the one that lets a prose centre through the gate this change exists to install; the narrower one does not, and silences the generated files just as completely. The Decisions entry cites that same section in support, and the section's remedy is a declared exception scoped to the case — toolchain.shellcheck_disable is the shape it names. The sanctioned codespell precedent beside it is noice, which the same paragraph distinguishes explicitly: teaching a checker a proper noun is not disabling a check, and there is no source fix when the word is correct. centre has a source fix everywhere except tmux's style value, and ignore-regex is what says so. Fix: ignore-words-list = noice plus ignore-regex = align=centre, keeping the comment where it is.

  2. .pre-commit-config.yaml:114 — ci.md § "Tool-specific config goes in the tool's own file, not a hook arg" — args: ['--builtin', 'clear,rare,en-GB_to_en-US'] puts half of codespell's configuration in the hook while the other half sits in .codespellrc, and the two halves disagree for anyone not going through pre-commit. Measured at the repo root: codespell themes/gruvbox/tmux.conf lib/generators/tmux.sh CLAUDE.md exits 0, so a developer checking their own work locally gets a pass on the files the hook is gating. .codespellrc takes the setting — with builtin = clear,rare,en-GB_to_en-US in that file, codespell on the colour is grey returns two findings and themes/gruvbox/tmux.conf stays clean. That rule's own worked example is codespell and it names .codespellrc as the destination. The edit belongs in the die, since generation rewrites this file wholesale.

  3. body:106 — pull-requests.md § "A body cites only what the repo carries" — the Decisions entry carries ci.md § "A lint rule is never switched off globally to satisfy one call site" into the merge commit. gh api repos/datapointchris/theme --jq .visibility returns public, and no reader of this repo can open that file. documentation.md § "A repo is a product for a stranger; the fleet is one deployment of it" ships the sweep; its citation half hits this line and nothing else in the body or the tree. Fix: write what the rule said — a check is not switched off repo-wide to satisfy one call site — and drop the pointer.

  4. body:1 — the same two rules, term half — "The fleet prefers American spelling in prose and identifiers alike". Fix: "This repo prefers American spelling in prose and identifiers alike". Run over the tracked tree at f3277cc, both halves of that sweep are otherwise clean: the only hits are # forge-managed header lines and macmini in test fixtures, which are values a program reads rather than prose.

  5. body:71 — git-workflow.md § "A message describes the repo, never the route the change took", reached through pull-requests.md § "Sweep the ban list rather than reading for it" — "once from this branch, once from a git archive of the parent commit". this branch is in that ban list verbatim. Fix: name the two commits.

Should be a rule

  1. body — proposed: rejected-alternative-measured-before-the-change — a receipt ruling out a smaller alternative is taken on the tree before the change, never on the tree the change produced. The post-change tree can only return the answer the change was built to produce, so the number is guaranteed, says nothing, and reads exactly like evidence. No rule reaches it. pull-requests.md § "A rejected alternative carries the same receipt a finding does" requires a receipt and is silent on which tree it is taken from, and § "A receipt is remeasured at the head, and a contract stated once" points the other way for behaviour receipts — correctly, for what it governs, which is what makes this the easy mistake. It belongs in pull-requests.md beside the rejected-alternative rule. Finding 2 above is the worked example.

Design and architecture

  1. lib/generators/tmux.sh:108, :109, :136, :188 and themes/everforest-dark-hard/theme.yml:14 — the change deliberately keeps a British spelling in five places and the repo records the reason at none of the sites. .codespellrc:3-5 explains centre, in a file nobody opens while editing a generator. The three *-colour option names and everforest's grey1/grey2 have nothing anywhere in the tree; their reasons live in a commit message and in this PR. Both failure directions are silent. Renaming the option names is absorbed — set-option -g display-panes-color exits 0 and tmux stores it back under colour, so the edit reads as working while the generated configs stop matching what show-options prints. And align=center is rejected by tmux's style parser (invalid style: align=center) while set-option -g pane-border-format '#[align=center]X' exits 0, so the one spelling with a hard failure is the one nothing catches at edit time. The repo's CLAUDE.md Key Insights is where every trap of this shape already lives, including the quoted GENERATOR_OUTPUT subscripts, whose whole content is that a formatter rewrote something and the only symptom was silence. Fix: one bullet there naming the three option names, align=centre and everforest's grey1/grey2, with the tmux error as the reason.

This review does not gate merge.

@datapointchris

datapointchris commented Sep 3, 2026 •

Copy link
Copy Markdown
Owner Author

PR review — merged

Three reviewers ran, blind to each other and to the session that launched them. This
unions 5096649195,
5096650780 and
5096650820.
The author's session launched the round. No reviewer held any of its context.

All three read at 361e332. The branch moved twice during the round and every
measurement below is at that head.

Findings 5 and 16 as first posted called the sibling repo private. It is public,
private=false. Both findings stand on the rule, which bans naming a sibling tool
whatever its visibility.

Findings: 4 correctness · 8 break a rule · 3 should be rules · 4 design
Convergence: three findings were reported by all three reviewers, three by two.

The three agree on what the change gets right, each having run it independently.
Regeneration over every theme is byte-identical to what is committed, measured three
times at 7.4s, 9.8s and once more with diff -r empty. bats tests/ is 243 tests at
exit 0. Both tmux exemptions reproduce on tmux 3.7c. The grey→gray rename in
retrobox is referenced by nothing and matches the five other themes carrying that slot.

Correctness

  1. .codespellrc:6 — all three reviewers — ignore-words-list = noice,centre
    disables the centre ==> center correction across the whole repo, so the gate this
    PR installs passes a British centre in any prose written here from now on. That is
    the outcome the branch exists to prevent. The scoped form is free and was measured by
    two reviewers independently:

    ignore-regex = align=centre  +  ignore-words-list = noice
      codespell -H --builtin 'clear,rare,en-GB_to_en-US'  over every tracked file  -> exit 0
      printf 'the centre of the screen\n' > p.txt ; codespell ... p.txt            -> exit 65
    ignore-words-list = noice,centre   (as committed)
      codespell ... p.txt                                                          -> exit 0
    

    The tree stays green and the word stops being free. ci.md § "A lint rule is never
    switched off globally to satisfy one call site" is the rule the body already cites in
    support. Its noice precedent does not reach this case: that carve-out is for a proper
    noun with no source fix available, and centre has a source fix everywhere except
    tmux's style value. Fix: ignore-words-list = noice plus ignore-regex = align=centre,
    keeping the comment where it is.

  2. themes/everforest-dark-hard/theme.yml:14,15,61 and the body's How it was verified
    — all three reviewers — three British spellings survive and the receipt reports
    none. The body states the survivor scan returns "78 hits, every one a tmux option
    name". The three lines are # grey1 - comments, line numbers, # grey2 - dark foreground and # grey1 - NOT white!. codespell cannot see them because grey1 is
    one token, which is the compound-token blind spot the body itself documents two
    paragraphs above. A bare grey is caught — grey ==> gray is in the dictionary, and
    commit 6ef3c90 converted exactly that word in themes/retrobox/theme.yml. The count
    is wrong in a second way: align=centre occurs 52 times, is kept deliberately, and is
    absent from the 78, so a scan described as matching British stems anywhere in a token
    cannot return 78. One reviewer also measured the hook-comment figure — the body says 4
    and that file carries 9 at f3277cc. The three independent recounts agree on the three
    grey lines and differ by one on colour, at 78, 78 and 79. Whether the three lines
    were missed or kept is not established. Fix: rerun the scan with centre and grey in
    the pattern, correct both figures, and either convert the three lines or record them in
    Decisions beside the tmux options as everforest's own slot names.

  3. Body, Smallest change that would work — the rejection is measured on the tree the
    change produced, and the tree that decides the question says the opposite. The body
    rejects "running codespell alone and stopping" because "it returns 0 while 78 British
    tokens remain". A 0 at the head is guaranteed, because the conversion is what produces
    it. Run against the parent instead:

    git diff $(git merge-base origin/main f3277cc)..f3277cc -U0 \
      -- . ':!.pre-commit-config.yaml' ':!.codespellrc' \
      | rg '^-[^-]' | sed 's/^-//' > removed.txt              -> 111 lines
    codespell --builtin 'clear,rare,en-GB_to_en-US' removed.txt \
      | cut -d: -f2 | sort -u | wc -l                         -> 110
    

    So codespell alone finds 110 of the 111 lines this change edits. The one it misses is
    # bell style: inverted rather than merely recoloured. What it genuinely cannot see is
    the 78 tmux compound names and everforest's grey1/grey2, and the change converts
    neither. The second instrument's unique contribution to this diff is one word. Under
    merge_commit_message=PR_BODY that sentence becomes permanent history asserting the
    opposite of what the code shows. Fix: state the measurement over main, and say what
    the survivor scan actually added.

  4. .pre-commit-config.yaml:1 — the committed generated config is not what the die emits,
    and the stamp says the repo is current in both states. abc9d69 and f3277cc both
    carry # forge-toolchain: 20 and their codespell blocks differ. The block moved again
    after that commit, so the die now emits a third text. The next apply rewrites this file
    with no commit accounting for the diff, and nothing can report it: the stamp
    declaration's own bump_when covers "different content out of an existing one", and
    the stamp has not moved since 2026-09-01. A stamp-only currency check answers "current"
    before this change, after it, and after the correction. ci.md § "forge is the source
    of truth" and § "Generated configs carry a # <tool>-toolchain: N stamp". Fix: bump
    the declared stamp, re-run the apply, and commit the result here so the file matches the
    die and the stamp separates the two states.

Breaks a written rule

  1. lib/generators/tmux.sh:43,176,183 — documentation.md § "A repo is a product for a
    stranger; the fleet is one deployment of it" — three generator comments name a sibling
    repo. Both repos are public — private=false on each — so nothing private is disclosed
    here. The rule bans naming a sibling tool regardless of its visibility, and its own
    sweep lists that name explicitly. Line 43 sends the reader to a design document that
    sibling holds, which a stranger reading this repo has no reason to know exists. Lines
    176 and 183 are copied verbatim into every generated artifact.
    Confirmed at 361e332: searching the tracked themes/*/tmux.conf for that repo name
    returns 50 lines across 25 files. The rule names generated config as where this
    vocabulary concentrates. This PR rewrote comments in that generator and regenerated all
    25 artifacts, which is the one moment the sweep was free to run. Fix: state the
    mechanism without naming the repo — "a status-line installer run before this file is
    sourced" carries it — then lib/generate-all.sh --generators tmux.

  2. Body, opening sentence — two reviewers — the same rule, term half. "The fleet
    prefers American spelling in prose and identifiers alike" names a private arrangement,
    and merge_commit_message=PR_BODY puts it into public git log verbatim. Fix: "This
    repo prefers American spelling in prose and identifiers alike".

  3. Body, Decisions — two reviewers — pull-requests.md § "A body cites only what
    the repo carries" — the entry carries a ci.md section path into the merge commit, and
    no reader of this repo can open that corpus. Fix: write what the rule said — a check is
    not switched off repo-wide to satisfy one call site — and drop the pointer.

  4. Body:71 — all three reviewers — git-workflow.md § "A message describes the repo,
    never the route the change took" — "once from this branch, once from a git archive of
    the parent commit". this branch is in that rule's banned list verbatim, and the
    sentence stops parsing the moment the history is linear. Fix: name the two commits.

  5. .pre-commit-config.yaml:114 and .codespellrc — two reviewers — ci.md §
    "Tool-specific config goes in the tool's own file, not a hook arg" — the dictionary
    selection lives only in args: ['--builtin', 'clear,rare,en-GB_to_en-US'], so half of
    codespell's configuration sits in the hook and half in .codespellrc. The two halves
    disagree for anyone not going through pre-commit. Measured at the repo root: codespell themes/gruvbox/tmux.conf lib/generators/tmux.sh CLAUDE.md exits 0, so a developer
    checking their own work locally gets a pass on the files the hook gates. With builtin = clear,rare,en-GB_to_en-US in .codespellrc, codespell on the colour is grey
    returns two findings and the generated file stays clean. That rule's own worked example
    is codespell and it names .codespellrc as the destination. The edit belongs in the
    die, since generation rewrites this file wholesale.

  6. lib/generators/tmux.sh:108,109,136 — documentation.md § "Document a constraint at
    the edit site" — display-panes-active-colour, display-panes-colour and
    clock-mode-colour are deliberate and carry no note at the lines that hold them. The
    gate cannot supply one either, because codespell's word regex keeps a hyphenated token
    whole and a file containing display-panes-colour exits 0. So the only record that
    these are tmux's own names is the merge commit. .codespellrc documents centre at
    its edit site and these get nothing. Fix: one line above the block saying tmux owns
    the names and the spell gate cannot see them.

  7. Body, Decisions — pull-requests.md § "A claim reasoned to rather than run does
    not go in a body" — "tmux rejects align=center with invalid style, the same error
    align=bogusvalue gets. Every theme's pane-border-format depends on it." The first
    sentence is true of a style option. The second names a format, where it is
    false. On tmux 3.7c, set-option -g status-style 'align=center' exits 1 with invalid style: align=center, while set-option -g pane-border-format '#[align=center]X' exits
    0, and so does align=bogusvalue — a format's #[...] is resolved at draw time rather
    than validated at set time. Both of this repo's align= sites are formats, and a
    search for a style option carrying align= returns nothing in the generator or the
    generated configs. The decision is right and the correction strengthens it: on the
    surface this repo actually uses, a wrong value is not refused, it just draws left. Fix:
    say the style parser accepts only centre, and that inside a format a wrong value
    fails silently.

  8. Body, What to look at, item 2 — pull-requests.md § "The body addresses everyone
    who ever reads it, never one person" — "Check this is the right register for the
    exception, and that a per-line # codespell:ignore would not have been better" hands
    the reader a decision. Directing attention is allowed and asking for a decision is not.
    Item 3's "Check nothing resolves it by name" is the sanctioned shape, because it names
    a fact. Fix: drop the second clause. Decisions already records the choice.

Should be a rule

  1. .codespellrc — proposed: narrowest-declared-lint-exception — ci.md § "A lint rule
    is never switched off globally to satisfy one call site" names two tiers: a repo-wide
    declared exception carrying its reason, and a per-line suppression needing approval. It
    names no tier for a scoped pattern, and its worked example, ignore-words-list = noice,
    is the widest of the three. So a reader reasons straight from "not per-line" to
    "declared word list" and never weighs the middle form. Most linters ship one —
    codespell's ignore-regex, ruff's per-file-ignores, a shellcheck directive scoped to
    one function. The existing rule is written too narrowly to catch a case where the narrow
    form exists and is free. Finding 1 is the worked example.

  2. Body, How it was verified — proposed: a-second-extraction-differs-in-vocabulary-not-only-in-tool — pull-requests.md § "A
    receipt names the tool's blind spot" asks for a second extraction by different means,
    and this body did it three times: codespell, an rg survivor scan, and an
    -ise/-yse/doubled-l scan. All three share one word list, so all three miss grey
    together. A different tool with the same vocabulary is one extraction run three times,
    and it reads as triangulation because the tools differ. The rule would say a second
    extraction differs in what it looks for, not only in what does the looking, and that
    a sweep's vocabulary must not be derived from what the first instrument already
    reported. testing.md § "Two extractors in one comparison share one identifier
    grammar" is the near rule and asks for the opposite property in a different situation,
    so it does not reach this. It belongs in pull-requests.md beside the blind-spot rule.
    Finding 2 is the worked example.

  3. Body — proposed: rejected-alternative-measured-before-the-change — a receipt ruling
    out a smaller alternative is taken on the tree before the change, never on the tree
    the change produced. The post-change tree can only return the answer the change was
    built to produce, so the number is guaranteed, says nothing, and reads exactly like
    evidence. pull-requests.md § "A rejected alternative carries the same receipt a
    finding does" requires a receipt and is silent on which tree it is taken from, and § "A
    receipt is remeasured at the head, and a contract stated once" points the other way for
    behaviour receipts — correctly, for what it governs, which is what makes this the easy
    mistake. It belongs beside the rejected-alternative rule. Finding 3 is the worked
    example.

Design and architecture

  1. Fleet vocabulary reaches this repo's permanent artifacts by three routes, and the
    sweep that exists covers one of them.
    No reviewer reported the
    boundary; each found a different instance. The three are the generator comments copied
    into 25 tracked tmux.conf files (finding 5), the body's opening sentence (finding 6),
    and the body's standards citation (finding 7). The sweep in pull-requests.md § "A
    receipt is remeasured at the head, and a contract stated once" reads git ls-files, so
    it cannot see a body at all — which makes the body the one artifact certain to land on
    main and structurally invisible to the check. For the tracked half the sweep can
    reach, its vocabulary decided the answer: one reviewer ran it over the same tree and
    reported it clean, because the word list held fleet terms and no sibling repo name.
    Fifty lines across 25 files were sitting in it. The consequence is that the next
    generator comment naming a sibling repo reaches every generated artifact and no
    instrument reports it.

  2. Every receipt in this body is measured against something the change itself
    determined, so each one confirms itself.
    Findings 3, 2 and 14 are three instances,
    and two of the three proposed rules above are generalizations of the same shape from
    different angles — which is the tell that it is one shape rather than three faults. The
    smallest-change rejection is run at the head where its number is guaranteed. The
    survivor scan's pattern is built from the words the change converted, so it omits
    centre and grey and cannot find what stayed behind. The three instruments share one
    word list, so their agreement measures the list rather than the tree. Each reads as
    evidence and none of them can return a surprising answer. It happened once more inside
    this review round, in a reviewer's own disclosure sweep, which is how strong the pull
    is. The consequence for the next PR of this kind: a receipt built this way cannot fail,
    so it certifies nothing, and the reader has no way to tell that from the page.

  3. themes/*/theme.yml and lib/generators/tmux.sh — two reviewers — the repo
    records the spelling convention at none of the five places a British spelling is
    deliberately kept.
    They are the three tmux *-colour option names, align=centre,
    and everforest's grey1/grey2. .codespellrc explains centre, in a file nobody
    opens while editing a generator. The other decisions live in a commit message and in
    this PR. Both failure directions are silent. Renaming an option name is absorbed —
    set-option -g display-panes-color exits 0 and tmux stores it back under colour, so
    the edit reads as working while the generated configs stop matching what show-options
    prints. And align=center is rejected by the style parser while the format form exits
    0, so the one spelling with a hard failure is the one nothing catches at edit time. The
    concrete consequence is for whoever transcribes the next plugin palette: they write
    # grey0, # grey1 from upstream's own names, the hook passes, CI passes, and nothing
    reports it. CLAUDE.md § "Mapping a Palette into theme.yml" is the section read at the
    moment that decision is made and it says nothing about spelling, and Key Insights is
    where every trap of this shape already lives, including the quoted GENERATOR_OUTPUT
    subscripts, whose whole content is that a formatter rewrote something and the only
    symptom was silence.

  4. scripts/ — the instruments that found the survivors exist only as command blocks in
    a merge commit, and the next person doing this reconstructs them from prose.
    That
    reconstruction is what missed three grey this time, so the cost is already paid once.
    The repo has the pattern: scripts/check-plugin-drift.sh is a maintenance check,
    deliberately not a theme subcommand, run once or twice a year and after adding a
    plugin theme. A spelling sweep has the same shape and the same cadence. It is also
    smaller than what the body ran — one codespell call over git ls-files with -H and
    --regex "[a-zA-Z']+" replaces all three scans, because the regex splits hyphens and
    digits and -H reaches the dot-files. It reports all 136 British tokens, with hex
    fragments and Noice as the known false positives to filter. tests/generators.bats
    already holds the repo-wide invariants that used to live in CLAUDE.md as shell
    one-liners, which is the other shape this fits. Without either, "78 hits, every one a
    tmux option name" is a fact about one afternoon and the check that would keep it true
    is not in the repo.

This review does not gate merge.

`ignore-words-list = centre` turned the correction off repo-wide, so the
gate this branch installs passed the British spelling in any prose written
here. `ignore-regex = align=centre` exempts the tmux literal and leaves
the word a finding, measured both ways against the same file under
codespell's default token regex and the widened one.

`.codespellrc` also names the dictionaries the hook passes on the command
line. Without them a bare `codespell` at the repo root reports nothing on
the files the hook gates, so a developer checking their own work gets a
pass the commit refuses.

`scripts/check-spelling.sh` covers what neither the hook nor a
`\b`-anchored search reaches. codespell keeps a hyphenated or
digit-suffixed token whole and refuses a dot-prefixed file without `-H`,
and there is no word boundary between a letter and a digit, so
`display-panes-colour` and `grey1` are invisible to both instruments at
once. The script widens the token regex to letters only, passes `-H`, and
declares the five sites where the British spelling is correct.

everforest's `grey1` and `grey2` are among them. Every comment in that
palette names the upstream slot its value came from, so `gray1` would
point at a slot the plugin does not have.
Three generator comments named a sibling repo and a tool it ships, and two
sat inside the heredoc, so every generated tmux.conf carried them — 50
lines across 25 themes. A repo is read by someone who has never heard of
the machines it happens to be deployed on, and a comment copied into
generated config is where that vocabulary travels furthest. The mechanism
is what a reader needs and it survives without the name: a status
installer relocates tmux's stock window row, and a remote shell sets
pane_title over OSC 2.

The three `*-colour` option names now say at the edit site that the
spelling is tmux's own. Nothing else can say it. codespell keeps a
hyphenated token whole, so a file holding that name exits 0, and tmux
accepts the `-color` alias while storing it back, so a rename reads as
working while the generated config stops matching what `show-options`
prints.

That comment carries no backticks. The heredoc is unquoted, so a backtick
in it is command substitution: the quoted name runs as a command and the
generated file gets an empty gap where the name should be, with nothing
failing.

`scripts/check-spelling.sh` settles the `-colour` suffix those comments
name, and iterates its patterns in sorted order so the per-pattern counts
are the same on every run.
codespell runs with `-H`, so a file whose basename starts with a dot is
read rather than skipped at exit 0. `.pre-commit-config.yaml`,
`.codespellrc`, `.gitignore` and `.editorconfig` sat outside the check
this file installs. A dot-named directory was always read, so `.github/**`
never needed it.

The stamp moves to 21, which is what lets a currency check tell this block
apart from the one before it. Two commits carrying stamp 20 held different
codespell blocks, and nothing could report the difference.
@datapointchris

Copy link
Copy Markdown
Owner Author

Closing without merging.

The sweep this belongs to is cancelled. Converting existing British spellings across the portfolio was never the goal — stopping Claude Code from writing them is. Those are different problems, and this PR is what the first one costs.

This repo is the case that should have ended the sweep rather than been worked around. tmux's own option names are display-panes-colour, display-panes-active-colour and clock-mode-colour, and its style parser accepts align=centre and refuses align=center. everforest's palette slots are grey1 and grey2. The spelling is not this repo's to choose in any of those places.

Meeting that with a SETTLED allowlist, a check-spelling.sh, an .codespellrc ignore-regex, and a paragraph in each affected file explaining why the spelling stays is 420 net added lines to leave the spellings where they were. The conclusion available was that the repo is out of scope.

The existing comments about tmux's option names were already accurate and needed nothing.

Branch american-spelling is left in place rather than deleted, in case any single fix in here is wanted on its own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant