Skip to content

fix(scripts): declare check-ratchet-remedy-authority's scan surface — BLOCKED on a recorded verdict, do not merge unreviewed - #12061

Closed
yinlianghui wants to merge 1 commit into
mainfrom
claude/issue-11935-ratchet-remedy-authority-watch-hint
Closed

fix(scripts): declare check-ratchet-remedy-authority's scan surface — BLOCKED on a recorded verdict, do not merge unreviewed#12061
yinlianghui wants to merge 1 commit into
mainfrom
claude/issue-11935-ratchet-remedy-authority-watch-hint

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Part of #11935implements one half, and must not be merged on that basis alone. See the blocker below. The other half (scripts/pm/bare-root-worklist.mjs) is deliberately untouched and is outside this card's declared file surface.

⛔ BLOCKER — this reverses a recorded, adjudicated verdict

The card asks for a watch-hint declaration on this gate. Implementing it works (evidence below), but the tree already carries a live verdict refusing exactly this, in scripts/pm/bare-root-worklist.mjs:

['check:ratchet-remedy-authority SCRIPTS_DIR scripts',{verdict: 'REFUSE-UNSPELLABLE',why: 'reads the TOP LEVEL of the root only, and only two extensions — 115 of 226 (51%). The '+'idiom has no non-recursive spelling: a subtree hint claims every nested directory too',}],

That verdict was upheld by a PM adjudication on 2026-08-23 closing #11155 — a prior filing of this same defect on this same gate — which declined the declaration option outright. #11935 appears to be an independent rediscovery filed two days later; nothing in it cites #11155.

I reproduced the refusal's measurement independently before finding it:corpusFiles() is a flat readdirSync, 141 files, against 256 tracked under scripts/ — 55%, the same side of the line. And the deeper claim holds as a proof, not a survey: to cover scripts/check-x.mjs a hint must collapse to scripts, and plain === 'scripts' necessarily also covers scripts/pm/** through the startsWith(plain + '/') branch. No honest spelling exists.scripts/* and scripts/** are byte-different and behaviourally identical.

Measured consequence of merging this as-is

Running the worklist on this branch, versus the unmodified tree:

row for this gate
unmodified (1e79aa4f8)REFUSE-UNSPELLABLE + matching reason — coherent
this branch (36c15e682)REACHABLE + the same refusal reason — self-contradictory

node scripts/pm/bare-root-worklist.mjs --self-test stays green (EXIT=0) across that flip. So merging this silently turns a coherent governance record into an incoherent one, and no gate catches it — exactly the outcome #11155's dev predicted and which is now measured rather than predicted.

What the branch does contain

A provenance-only ROOT_DIR_WATCH_HINTS = ['scripts/*'] plus seven self-test cases (20)–(26) run against the realhintCovers / collapseHint / extractWatchHints, every direction derived from the walked root and the live corpus rather than re-spelled. The flat glob, not the subtree form, because the gate's own header already spells its population scripts/*.{mjs,mts} and the sweep never recurses — 89 tracked files across nine subdirectories it never opens.

The card's assumed scripts/** spelling is wrong even if the decision goes toward declaring: it would claim those 89 files outright. scripts/* claims 26. Neither changes what the tool matches.

The --residue pair, on the card's exact invocation

Neither path is this gate's own file, so this is not the "appears when I touch its own file" false positive the card warns about.

matchedundetermined
before1454 (family here)
after15 (family here)53
- pnpm check:ratchet-remedy-authority [lint.yml] matched via
scripts/check-doc-authoring.mjs ⇢ gate source 'scripts/*';
scripts/check-skills-token-ratchet.mjs ⇢ gate source 'scripts/*'

The pin, shown going red

A pin that only ever answers "pass" is not a pin. All four wrong declarations observed red, each mutation proven on disk first:

mutationself-testfirst cause named
['scripts/**']EXIT=1, 1 caseflat sweep must use the flat glob
['scripts']EXIT=1, 5 casesextractor sees []
['packages/*']EXIT=1, 3 cases141 files uncovered
[]EXIT=1, 3 casesdeclares no root at all

Restore leg green. Two mutations initially failed to land (a perl -e quoting fault) and were reported VOID rather than as passes — without the on-disk proof they would have run the unmutated file and read as a clean EXIT=0.

Over-reach, stated plainly

A card touching only scripts/pm/check-half-states.mjs — which the sweep never reads — now derives this family too. That is the fabricated-lead cost the recorded verdict is about, and it is unavoidable in this vocabulary.

Gates

9/9 green at 36c15e682, derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, each exit code captured before any pipe. skip-changeset: root scripts/ tooling, nothing published.

Generated by Claude Code

…o gate-script cards derive it
The sweep assembled its population as join(REPO_ROOT, 'scripts'), so no path
literal ever reached the source and extractWatchHints returned an empty set.
The family — a REQUIRED gate whose population is gate scripts — therefore sat
in the dispatch derivation's Undetermined bucket, invisible to exactly the
cards most likely to violate it.
Declares the scan surface as the FLAT glob, matching the flat readdirSync the
sweep really performs, and pins it in both directions against the real
hintCovers/extractWatchHints rather than a paraphrase of them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjM2ia8Av1v5NqfqQEQmC6
@yinlianghuiyinlianghui added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 25, 2026 — with Claude
@yinlianghuiyinlianghui changed the title fix(scripts): declare check-ratchet-remedy-authority's scan surface so gate-script cards derive itfix(scripts): declare check-ratchet-remedy-authority's scan surface — BLOCKED on a recorded verdict, do not merge unreviewedAug 25, 2026
@os-zhuangClaude

Copy link
Copy Markdown
Contributor

Closing under the maintainer's ruling, 2026-08-25 (option A1, upholding the recorded verdict): 「我看到了,你分析过了,接受你的建议」.

The 2026-08-23 adjudication on #11155 refused this same declaration outright (REFUSE-UNSPELLABLE: the flat sweep has no honest hint spelling — scripts necessarily claims the 89 nested files the gate never opens), and this PR's own measurement confirmed that merging it would turn the coherent worklist row self-contradictory with no gate catching it. The dev's blocker analysis was exactly right — thank you for refusing to merge it quietly. Card #11935 is closed as a duplicate of #11155.


Generated by Claude Code

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

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@yinlianghui@os-zhuang@claude