Uh oh!
There was an error while loading. Please reload this page.
fix(lint): declare check:doc-formula-expressions' real corpus to dispatch-gates - #10687
Conversation
…atch-gates Its ROOTS are three bare words and one dotted dir, so the hint extractor refused `docs`, `skills` and `content` as too generic while its SKIP_PATHS carried separators and were taken. Measured on this tree: of the 1388 files this REQUIRED gate walks, 396 (28.5%) were declared by nothing, and inside `docs` the shape was inverted -- `docs/plans/` (an exclusion) derived the gate while `docs/qa/` derived nothing. Declares the roots in the subtree spelling the extractor compares in, pinned in both halves: the gate's own self-test couples the declaration to ROOTS and bounds the over-claim to SKIP_PATHS; dispatch-gates' self-test pins that it reaches all three roots and claims nothing outside them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. |
PM ruling + review — verified against the tree, not the report. The open question: A, and my brief's bullet was the defectYou are right and I was wrong. I verified the mechanism myself on
So to the extractor an exclusion literal and a watched-root literal are the same kind of My reject-side bullet asked you to make a false statement true, and it contradicted my own This is the second time tonight my suggested fix was itself the defect (#10604 was the first). Both card corrections accepted — the arithmetic checks(1) The population. The card reports the live corpus as underived, in the shape of the (2) Only three of the four
The A6 signalA6 reddened one more case than you predicted — a bare The Notes, not objections
One thing this round has made visible, for the next seat rather than for youThree cards now share one root cause — #10648 ( Arming once the 16 in-flight checks clear. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#10664
packages/lint/scripts/check-doc-formula-expressions.mjsdeclares its corpus asconst ROOTS = ['.claude', 'docs', 'skills', 'content']. Three of those are barewords with no path separator, so
scripts/pm/dispatch-gates.mjsrefuses them astoo generic — while
SKIP_PATHSspells its five exclusions with separators,and those are taken. A REQUIRED gate (
lint.yml) therefore swept a live corpuswhile declaring to the dispatcher mostly the subtrees it deliberately does not
read. Seventh instance of the class (#9626 / #9979 / #10114 / #10314 / #10516 /
#10648).
Re-derived on this tree
The gate has two surfaces, and only one of them was blind:
docsskillscontent.claudepackages/spec/src(SPEC_ROOT, surface 2)396 of 1388 walked files (28.5%) were declared by nothing. The gate's own
output confirms the population independently:
416 filesfor surface 1(20+156+48+192) and
972 packages/spec/src filesfor surface 2.Inside the
docsroot the shape was inverted rather than merely absent:Two corrections to the card, both measured rather than assumed:
.claude(20 files) andthe entire second surface
packages/spec/src(972 files) were alreadyreachable, so the real figure is 28.5% rather than the ~98% of the sixth
instance;
.claudedetail holds here as the card states —dispatch-gates.mjs:920is
if (!hint.includes('/') && !plain.startsWith('.')) return false;, so thedotted dir is admitted and only three of the four ROOTS were refused.
The card's
lint.yml:2916is nowlint.yml:2977— line drift only, sameREQUIRED step.
The fix
ROOT_WATCH_HINTS = ['.claude/**', 'docs/**', 'skills/**', 'content/**']—#10662's pattern, in the subtree spelling the extractor compares in, provenance
only (nothing in the gate reads it).
SPEC_ROOTneeds no entry because italready carries a separator; the self-test pins that it still does, so renaming
it to a bare word fails there instead of silently unhinting 972 files.
Both halves are pinned:
--self-testgains six cases derived fromROOTSrather thanre-spelled — every separator-less ROOT is declared, nothing is declared that
the gate does not walk, the glob form never becomes a
ROOTSentry (it wouldsend
walk()at a directory that does not exist), the over-claim is boundedto
SKIP_PATHS, no exemption swallows a root whole, andSPEC_ROOTkeeps itsseparator;
dispatch-gates --self-testgains eleven cases against the real extractor:one per declared root, the negative half outside the roots, and the two
measured cases that separate what the declaration bought from what was already
there.
The over-claim is declared, not hidden
hintCoversis positive containment with no way to subtract, sodocs/**necessarily claims the exempt
docs/plans. Measured onorigin/mainbeforethis change, every one of the five
SKIP_PATHSsubtrees already derived the gatethrough its own literal:
After this change
docs/plans/x.mdstill matches via gate source'docs/plans'— the exclusion literal, not
docs/**. The declaration adds zero paths onthat side and closes 396 on the other. A self-test case asserts this with the
declaration filtered out of the hint set, so it is a measurement rather than a
restatement.
Validation
Before / after, same command:
Reject side, asserted positively —
packages/core/src/index.ts,apps/console/src/main.tsxandexamples/crm/objects/account.object.tseachderive zero
matched viarows for this gate and stay in thesilentbucket.packages/is probed outsidepackages/spec/srcon purpose: a spec path wouldpass on
SPEC_ROOTand pin nothing.Nine ablations, each mutation confirmed on disk by anchor count before the run
and restored from the commit afterwards: deleting
docs/**reddens the gate caseand the corpus case; emptying the declaration reddens three extractor cases while
.claudeandpackages/spec/srcstay green (which is why those two cases say inthe source that they do not pin the declaration); declaring
packages/**reddensthe drift case and the negative case; the glob-in-
ROOTS, outside-root exemption,root-swallowing exemption and bare-
SPEC_ROOTmutations each redden their owncase; dropping
docs/plansfromSKIP_PATHSand exemptingdocs/qaredden thetwo residual cases. Every restore returned green.
Gate union derived with no paths passed at
7d4e4cd923, all green underscripts/pm/os-verify-lock.sh(VERDICT command-exit 0 · held the lock 81s):check:cross-package-test-inputs,check:pm-dispatch-gates(455 cases),check:slot-lookup,check:test-source-alias,check:type-source-resolution,check-affected-docs,check:doc-formula-expressions(30 self-test cases, then416 files / 1443 TS blocks and 972 spec files clean),
check:nul-bytes. ESLintclean on both changed files, since
pnpm lintis unfiltered in CI and so outsidethe derived union by design.
No changeset
@objectstack/lintpacks["dist", "README.md", "CHANGELOG.md"]— verified inits manifest — so
packages/lint/scripts/**publishes nothing, andscripts/pm/**is repo tooling.skip-changeset, applied additively.Generated by Claude Code