Add a gate that keeps FOS prose in US spellings - #169
Merged
Conversation
The sweep in #168 made the tree clean; nothing stopped it drifting back. This is the gate. It matters more here than in most repos because these strings are read off a screen by a technician standing at a machine mid-enrollment. A whole-tree scan, not a diff. The obvious shape is "check only the lines this pull request adds", and it needs a base ref: a shallow clone has no merge-base, so the check would find nothing to look at and pass -- for a reason that has nothing to do with spelling, silently and forever. A gate that can only report success is worse than no gate, because it also reports "verified". Scanning everything needs no ref, cannot skip, and is only possible because the tree is already clean. Two patterns, because one right-hand boundary cannot serve both shapes. The word/camelCase one refuses a following lower-case letter, so `enrol` does not fire inside `enrolled` or `enrollment`. The ALL CAPS one refuses a following letter of any case, or `ENROL` matches inside `ENROLL_SECUREBOOT` and the gate fails on a correctly spelled name. Both are case-sensitive: a trailing /i also folds the [a-z] and [A-Z] in the boundary assertions, which collapses the camelCase hump into "letter, letter" -- no boundary at all. Also sweeps the five words the first pass missed (afterwards, towards, artefacts) now that the sweep carries the match's own case rather than an enumerated list of forms. Proven by mutation, not by being green: a lower-case word, a Title-case word, an ALL-CAPS word, an ALL-CAPS word inside SNAKE_CASE, a camelCase identifier, a UK word in an untracked new file, and a broken file enumeration each make it fail; `enrollment`, `enrolled` and `ENROLL_SECUREBOOT` each leave it green. tests/run-all.sh: 18 passed, 0 failed. Co-Authored-By: Claude <noreply@anthropic.com>
The empty-enumeration guard covered "git exited non-zero". It did not cover the case that actually happens: git exits 0 and returns no rows, because a path moved or an ignore rule grew to swallow it. That printed "0 file(s) scanned, no UK spellings in scope" and exited 0 -- green, and meaningless. Exactly the silent pass the whole file exists to avoid. Checked per SCOPE entry rather than as a total, because a total still passes when one directory of the four drops out. Mutation-proven both ways: renaming one scope entry fails, and making the enumeration return nothing at all fails. tests/run-all.sh: 18 passed, 0 failed. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#168 made the tree clean. Nothing stopped it drifting back — this is the
gate. It matters more here than in most repos: these strings are read off
a screen by a technician standing at a machine mid-enrollment.
Why a whole-tree scan and not a diff
The obvious shape is "check only the lines this PR adds". It needs a base
ref, and a shallow clone has no merge-base — so the check would find
nothing to look at and pass, for a reason that has nothing to do with
spelling, silently and forever. A gate that can only report success is
worse than no gate, because it also reports "verified".
Scanning everything needs no ref, cannot skip, and is only possible
because the sweep already made the tree clean.
Two patterns
One right-hand boundary cannot serve both shapes:
enroldoes not fire inside
enrolledorenrollment.five-letter UK form matches inside
ENROLL_SECUREBOOTand the gatefails on a correctly spelled name.
ENROLMENT_MODEstill matches,because
_is not a letter.Both are case-sensitive. A trailing
/ialso folds the[a-z]and[A-Z]in the boundary assertions, collapsing the camelCase hump into"preceded by a letter, followed by a letter" — i.e. no boundary at all.
That mistake made an earlier draft fire on
labellinginsideRelabelling, which reads like a find and is really the guard raildissolving.
Also sweeps the words the first pass missed (
afterwards,towards,artefacts) now that the sweep carries the match's own case instead ofworking from an enumerated list of forms.
Proven by mutation, not by being green
SNAKE_CASEenrollment,enrolledENROLL_SECUREBOOTIt also caught its own README entry on the first run, which is the best
evidence it does what it says.
tests/run-all.sh: 18 passed, 0 failed.