You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[finding] The one-value-site promise for CONTRACT_REVIEW_TIER (SKILL.md 「模型升级只改一行一个文件」) is held only by a manual grep — no self-test pins it, so the next model refresh can re-open the drift silently #14616
Filed unassigned by the os-dev flight on #14303 (session session_01LraLgQVGq8egUwfYZpbYt1), observation only — the fix is not in that PR by scope (the triage on #14303 queued exactly two limbs: bump the constant, make every other site name it).
One self-test case in scripts/pm/dispatch-gates.mjs: read every file under .claude/skills/pm-dispatch/** and scripts/pm/**, count occurrences of CONTRACT_REVIEW_TIER's own VALUE (the exact string, read from the constant — never a family/prefix pattern, and never a second literal), and assert the count is exactly 1 at the definition line. Exact-value only: a prefix scan would be the family floor the human floor has not granted, and would also be a second spelling of the model family inside the tool.
Two things the implementer has to respect, both measured before on this file:
Verbatim maintainer rulings in SKILL.md:586 and references/dispatch-runbook.md:17 mention the model family as prose (「Fable 5」, 「fable 5」); they are quotations, not values, and are not matched by the exact-value scan — the case must not be widened until it would touch them.
Refs: #14303 (the drift, and the PR that collapses 16 → 1).
Filed unassigned by the
os-devflight on #14303 (sessionsession_01LraLgQVGq8egUwfYZpbYt1), observation only — the fix is not in that PR by scope (the triage on #14303 queued exactly two limbs: bump the constant, make every other site name it).Blocked-by: #14303
What was measured
origin/main@a5b95ee6, the model id behindCONTRACT_REVIEW_TIERwas spelled as a VALUE in 16 places across.claude/skills/pm-dispatch/**andscripts/pm/**(3 prose sites inSKILL.md, 3 mandate-table rows, 2 header comments, 7 self-test assertions and fixtures, plus the definition), whileSKILL.md:773promises 「档位单源 … 模型升级只改一行一个文件」. finding(pm-dispatch):CONTRACT_REVIEW_TIER = 'claude-fable-5'no longer matches the served Fable tierclaude-fable-5-1, so the in-seat review fuse reads a literal mismatch on every current Fable seat #14303's PR takes that to 1 (the definition line).CONTRACT_REVIEW_TIER = 'claude-fable-5'no longer matches the served Fable tierclaude-fable-5-1, so the in-seat review fuse reads a literal mismatch on every current Fable seat #14303 is agit grepa human or a seat runs by hand;check:pm-dispatch-gates(the tool's own self-test, ~1240 cases) asserts the mandate rows and the rendering EQUAL the constant, but never that the constant's value is absent everywhere else. The 16-site drift that finding(pm-dispatch):CONTRACT_REVIEW_TIER = 'claude-fable-5'no longer matches the served Fable tierclaude-fable-5-1, so the in-seat review fuse reads a literal mismatch on every current Fable seat #14303 found is exactly what a manual promise looks like one refresh later.Suggested shape (not a decision)
One self-test case in
scripts/pm/dispatch-gates.mjs: read every file under.claude/skills/pm-dispatch/**andscripts/pm/**, count occurrences ofCONTRACT_REVIEW_TIER's own VALUE (the exact string, read from the constant — never a family/prefix pattern, and never a second literal), and assert the count is exactly 1 at the definition line. Exact-value only: a prefix scan would be the family floor the human floor has not granted, and would also be a second spelling of the model family inside the tool.Two things the implementer has to respect, both measured before on this file:
inherited-populationdeclaration and thecheck:watch-hint-literalgate guard that class). Directory names for the scan should be derived from an existing declared population or spelled in a way those guards accept, not added as fresh path literals.SKILL.md:586andreferences/dispatch-runbook.md:17mention the model family as prose (「Fable 5」, 「fable 5」); they are quotations, not values, and are not matched by the exact-value scan — the case must not be widened until it would touch them.Refs: #14303 (the drift, and the PR that collapses 16 → 1).