Skip to content

finding: check-role-word skips a configured ROOT that does not exist, silently — the verdict half that #9910 deliberately left alone #9932

Description

@os-steve

Observation only — no gate is red. Found while implementing #9910, whose dispatch scoped that card visibility-only by ruling; this is the verdict half it deliberately did not take, recorded rather than fixed. Filed unassigned.

Sibling of #9911, which is the same question on check:published-readme-exports.

The line

scripts/check-role-word.mjs:

constROOTS=['content/docs','skills'];
...
for(constrootofROOTS)if(existsSync(root))walk(root,files);

A configured root that does not exist is skipped and nothing is said. The gate then reaches its verdict over whatever the surviving roots contributed, and can green.

Why it is not currently an alarm

Today each root has ledger entries (34 under content/docs, 9 under skills, measured on d7c4240), so losing a root drops its baselined files out of current and the ratchet-DOWN branch reports them. That is the same incidental protection #9910 measured for the total-scan case, and it has the same two escape hatches:

  • it evaporates when the ledger empties, which is the state this ratchet exists to reach; and
  • it never existed for a root whose ledger share is already zero — remove such a root today, with the ledger fully populated, and the run is green and silent.

The second one is not hypothetical in shape: skills/ held 0 baselined files as recently as the directory's introduction, and any future root added to ROOTS starts there by definition.

What #9910 did and did not do

The work on #9910 made the condition legible — every configured root is now named on every green run with its own count, so skills 0 is on the screen:

check-role-word: OK, no new occurrences of the reserved word.
Scanned: 215 .md/.mdx file(s) read across 2 root(s) — content/docs 179, skills 36.

That was the whole of its scope. It does not refuse: a run over a vanished root still exits 0. Making it refuse is a verdict change and a separate decision, which is why it is carded here rather than folded in.

The decision, if this is picked up

Whether a configured root that resolves to nothing should be a hard error rather than a skip. Arguments both ways are real: existsSync was presumably written to keep the gate runnable in partial checkouts, and refusing would newly fail such trees; against that, a root named in ROOTS is a declaration that the directory is in scope, and a declaration that silently self-cancels is the shape this repo keeps carding. A middle route exists — refuse only when every root is missing — which closes the total-scan case without touching partial checkouts.

Not urgent, and cheapest to settle before the ledger empties, for the same reason #9910 was.

Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions