Repository navigation
ci: flag user-facing strings and glossary changes that ship without their docs - #1194
Conversation
|
Review round 1 (Codex
Security: the workflow uses Maintainer setting: "Docs impact" is not in |
… real headings, report every stale definition
All four are fixed in
Self-tests: 13/13. The required-check gap you noted ( |
|
Review round 2 (Codex Every round 1 repro on both PRs is closed when both PRs are in place.
The CI base fetch works with |
…ose a fence only by CommonMark's rule
|
Done. #1194 head:
3 and 4 are listed in the body under "Known limits". The term-rule dedup is a note in the body, because #1193 is not on |
|
Round 2 fixes verified at
The review loop stops here. |
Ports #1194's Docs impact rule into the trimmed root AGENTS.md.
Adds a CI check that a PR adding user-facing strings also touches the docs that explain them, and that a changed glossary term keeps its in-app definition in step.
Closes #1186
(The first half of #1186, the glossary completeness test, is #1193.)
What it checks
.github/scripts/docs-impact.mjs --base <ref> [--head <ref>] [--body-file <file>], run from the repository root. Without--headit reads the working tree, so the CI command also works locally:node .github/scripts/docs-impact.mjs --base origin/main --body-file body.md.New strings with no docs change (
7564bb1e). The PR adds keys outsidehelptoweb/src/i18n/en.ts, and changes neitherspecs/product/GLOSSARY.mdnor anyhelp.*key. The failure names the new keys.Glossary drift (
63aa4af6, feat(web): prefill the farm code from ?farm= and remember it (#535) #588's shape). A GLOSSARY.md term's text changes, and that term has an in-app entry, but itshelp.glossary<Key>Definen.tsstays the same. When a term has several in-app entries (Daily entry lifecycle has three), every unchanged definition is reported. A term's text runs to the next term or heading, so a paragraph added under it counts. A brand-new term, or a term with no in-app entry, is not drift; test(web): require an in-app glossary entry or a reasoned exclusion for every GLOSSARY.md term #1193 covers those.Newly deferred glossary terms (
6f0a26b3, from test(web): require an in-app glossary entry or a reasoned exclusion for every GLOSSARY.md term #1193's review). The check loadsweb/src/routes/glossaryCoverage.ts(test(web): require an in-app glossary entry or a reasoned exclusion for every GLOSSARY.md term #1193) at base and head and refuses a term that isNOT_YETat head but not at the base. A count cannot tell a removal from a swap. No body line overrides this; aSPEC_ONLYrow with a real reason is the way. Until test(web): require an in-app glossary entry or a reasoned exclusion for every GLOSSARY.md term #1193 merges, the file is missing at the base and this check skips. That is the only skip: once the base has the module, a head without it fails, so a rename cannot retire the check.Either one passes when the PR body has a line
Docs-impact: none — <reason>(an en dash,-or--also work, followed by a space and a reason). The maintainer reads that line at merge, so only a visible line counts. A quoted line (> Docs-impact: …), a line inside a code fence or an HTML comment, and a line with no reason do not.A
--baseor--headthat does not resolve to a commit exits 2. A file that is missing at a revision is told apart from a git error, so a bad ref cannot skip a check. A bold term straight after a heading opens a section, the same rule as #1193'sglossaryCoverage.ts.en.tsandhelpGlossary.tshave no imports, so the script loads them as TypeScript from a temporary copy of each revision. It does not parse them with regular expressions.Why a separate workflow, not a step in
ci.ymlFixing the PR body has to re-run this check, so it needs the
editedpull-request type. That type is added to.github/workflows/docs-impact.yml, a one-job workflow, andci.ymlis unchanged:editedadded toci.yml, every body or title edit would start a full CI run.ci.ymljob withif: github.event.action != 'edited'is worse. An edited-event run then skips those jobs on the same head commit, and the skipped results replace the earlier ones. A red test job could read as skipped after a typo fix in the body.The workflow also has
concurrencywithcancel-in-progress, so a burst of body edits leaves one run. The PR body reaches the script throughenv, never interpolated into shell.AGENTS.md's "Keep documentation in sync" rule now names the workflow and the local command.Checks run locally
node --test .github/scripts/docs-impact.test.mjs: 14 passed at9326ef83.node .github/scripts/docs-impact.mjs --base origin/main: nothing to flag on this branch.Proof
Run locally at
63aa4af6against real history. The #588 states are throwaway commits made withgit commit-treefrom a temporary index, so no branch, index or worktree was touched.1. #588: GLOSSARY.md "Farm code" gains its prefill paragraph;
glossaryFarmCodeDefunchanged.Base =
origin/mainwith #588's paragraph ("On the SPA sign-in page the field is prefilled…") removed from GLOSSARY.md; head =origin/main. The diff is the paragraph #588 added, as it reads today (later PRs extended it).1 file changed, 13 insertions(+)
Green once the in-app definition changes with it:
2. New strings with neither docs change: #667 (
feat(web): expenses filters by a date range…).Squash commit
f13858f6, base = its parent.Green with the escape line in the body:
$ node .github/scripts/docs-impact.mjs --base 9d63c5b --head e7123a622b66eb96f5749d9ffcfd08f29b0fa474 # as at 63aa4af
docs-impact: nothing to flag.
exit=0
$ node .github/scripts/docs-impact.mjs --base 9d63c5b --head e7123a622b66eb96f5749d9ffcfd08f29b0fa474 # at 6f0a26b
"tray deposit" is newly deferred as NOT_YET in web/src/routes/glossaryCoverage.ts. Give it an in-app glossary entry, or a SPEC_ONLY row whose reason says why users never meet it.
exit=1