fix(tooling): route check-stack-collection-maps through the shared comment mask - #13269
Draft
os-elon wants to merge 1 commit into
Draft
fix(tooling): route check-stack-collection-maps through the shared comment mask#13269os-elon wants to merge 1 commit into
os-elon wants to merge 1 commit into
Conversation
…mment mask Its private `maskLiterals` scanner was the one comment-scanning body under scripts/ that neither check:comment-mask-adoption (population packages/ + examples/) nor check:parse-guard (subject: the three TS parser entry points) could see. Measured against scanSource()'s comment|literal projection over the population this gate actually reads (8 files / 1,028,984 chars): 3 files disagree, 49 spans, 247 chars -- 18 a harmless regex-delimiter projection difference, 31 the private scanner mis-reading a nested template and handing the bracket counter 20 bracket characters out of literal interiors. Verdict-preserving on this tree (--list byte for byte identical); both directions pinned in --self-test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw
This was referenced Aug 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #13143 — deliberately not
Fixes. See "Why this isPart of" at the bottom; the sub-issue #13274carries the half this PR does not do.
Converts
scripts/check-stack-collection-maps.mjs' privatemaskLiteralsscanner onto the sharedscripts/js-comment-mask.mjs, with the before/after reading a conversion owes. The card's other route —widening
check-comment-mask-adoption.mjs' population toscripts/**— was priced first and is not takenhere; the price falsifies the assumption it rests on, and the numbers are below so #13274 can be written
against them rather than re-derive them.
All measurements on
e758630543unless a commit is named.What the card assumed, and what the tree says
The gap is structural — confirmed.
check-comment-mask-adoption.mjsderivesSCAN_ROOTSfromROOT_DIR_WATCH_HINTS = ['packages/**', 'examples/**']and pins the collapse (SCAN_ROOTS.join(',') === 'packages,examples')in its own
--self-test;check-parse-guard.mjswalksscripts/and its self-test forbids declaring any rootit does not walk, with a subject of three TypeScript parser entry points. Neither is a spelling artefact: the
adoption gate physically never reads this directory, and the parse guard physically never looks for a stripper.
The ledger's 14 rows really are all under
packages/**— confirmed. 14 of 14, zero underexamples/**,zero under
scripts/**. One row (packages/spec/scripts/lazify-schemas.ts) carries ascriptspath segmentinside
packages/, which is the shape that makes the sentence worth checking rather than assuming."Only
check-stack-collection-maps.mjs" does not hold — and it never did. Re-swept with probes independentof the gate's own vocabulary (declared name, character-scanner shape,
indexOfof a comment terminator), over193 sources under
scripts/**. Four hand-rolled comment scanners that do not import the shared mask:scripts/check-stack-collection-maps.mjsmaskLiteralsscripts/check-ratchet-remedy-authority.mjsauthorFacingMessagesregexAllowedAfterscripts/check-whole-set-label-write.mjsblankComments/blankJsCommentsopensRegexscripts/measure-partial-retirement-annotation.mjsextractProse//inside a regex literal as a line-comment opener19763458ff(git cat-file -e, and each declaration countedthere). So this is not drift since the card was filed — the card's hand-probe was narrow. Recorded that way
because "the tree changed under us" and "the instrument was narrow" call for different follow-ups.
Pricing the widening — the assumption it rests on is false in two ways
Running the adoption gate's own
shapesIn()overscripts/**(193 sources):maskLiteralsand nothing else":check-comment-mask-adoption.mjs(the gate itself),check-declaration-mirrors.mjs,check-live-db-isolation.mjs,check-optional-error-sink-contract.mjs,check-section-landing-index.mjs,check-type-check-coverage.mjs,check-type-source-resolution.mjs,check-undeclared-dep-imports.mjs,js-comment-mask.d.mts,js-comment-mask.mjs,pm/dispatch-gates.mjs.At least four of those are self-references or fabrications rather than private strippers: the gate's own SHAPES
regexes and self-test fixture strings, the shared module itself (which is that gate's declared POSITIVE CONTROL),
its
.d.mts, and a fixture string inside an adopter. A shrink-only ledger gaining eleven rows of which severalare artefacts is a ledger nobody can re-read.
shapesIn(check-stack-collection-maps.mjs)returns[]. Thescanner-declshape recognises(strip|mask|remove|without)Comment(s)?only, andmaskLiteralsis outside that vocabulary(
/…maskComments\s*\(/i.test('export function maskLiterals(source) {')isfalse).⇒ "widen the population and ledger
maskLiterals" is not executable as written: a ledger row for a file thescan does not find fails as stale, by the gate's own shrink-only invariant, on the very PR that adds it.
So the miss is two independent misses — population and vocabulary — and only the second one reaches this card's
own instance. Pricing the second axis too, for #13274: widening
scanner-decl's verbs and nouns (addingblank|scrub|elide|extractandLiterals?|Prose|NonProse|JsComments?) costs 0 new rows under today'spackages/**+examples/**population and newly reaches 5 files underscripts/**— including three of thefour scanners above.
authorFacingMessagesstays out of reach of any spelling rule.What this PR does instead
Option 2 from the card, for this one file, with the measurement Zone 1 requires.
maskLiteralskeeps its name, its contract and all four call sites, and its body becomes the shared scanner'scomment | literalprojection. Measured against the private scanner over the population this gate actuallyreads (its seven SITE files plus
stack.zod.ts— 8 files, 1,028,984 chars): 3 files disagree, 49 spans,247 characters, in two classes:
/delimiters; the shared scannerkeeps them as code. No bracket is a slash, so no caller here could see it.
${...}, flipping the parity of every backtick after it and handing the bracket counter 20 bracket charactersout of string and template interiors, in
packages/objectql/src/engine.tsandpackages/metadata/src/plugin.ts— both live SITE files. Same family as the
.describe('Screen Flows (ADR-0019)')incident this function'sdocblock records, through a different door.
maskLiteralssits in the careful family. This is that measurement, taken now, with controls.The instrument was shown able to fail first. Positive control: the naive two-regex pair diffed against the
shared scanner over the same eight files disagrees on 8 of 8 (3,884 spans on
engine.tsalone). Negativecontrol: the shared scanner diffed against itself returns 0 spans. Every file asserts non-empty bytes.
Verdict-preserving on this tree.
--listis byte-for-byte identical before and after(sha256
7a4c9bd44ff1355439a452231e53c2938a7d39a7807e0a52f4267deb4f940d30both ways), and the gate stays green.That is a fact about where this tree's nested templates sit, not a reason the private copy was safe — so both
directions are pinned in
--self-test, which grows from 13 to 15 assertions.Ablations — prediction named before each run
Both mutate the committed file, prove the mutation on disk by decomposed
grep -cof the injected and theremoved text plus
git hash-object, and restore under atrapon absolute paths, proving the restore by an emptygit diff HEADand a hash equal to the HEAD blob. No build step exists on this path:nodeexecutes the.mjssource directly, so there is no
dist/for a stale artefact to hide in.Ablation 1 — put the old private scanner back, keep the new pins.
Predicted:
--self-testexits 1 with exactly the two new pins failing, actuals["a"]and["a","${v}","b"];the 13 pre-existing assertions stay green; the main gate stays exit 0. Observed: exactly that, and
--listkeptthe same sha256 — an independent confirmation of verdict-preservation.
Ablation 2 — drop the⚠️ The main gate stayed
literalhalf of the projection (both[i] = comment[i]).Predicted:
--self-testreds; the literal flag is load-bearing rather than a wrapper. Observed: exit 1, twofailures — one new pin and the pre-existing
objectEntries() reads top-level keys only.exit 0 under this mutation, which is the "green over text it never read" direction in one line, and the reason
the pins are synthetic.
Gates
Family derived with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackon the committed diff(1 path, three-dot semantics), re-derived after the edit rather than from the dispatch brief. Exit codes captured
before any pipe; verdicts quoted from each gate's own line.
Green (exit 0):
check:stack-collection-maps(self-test 15 assertions + scan),check:agent-test-spelling,check:bash32-floor,check:cli-command-ids,check:cross-package-test-inputs,check:entry-guard,check:parse-guard,check:pnpm-filter-targets,check:watch-hint-literal,check-ci-filter-parity,check-shard-attestation, plus the convention pair for editing a gate script —scripts/pm/bare-root-worklist.mjs --self-testandcheck:pm-dispatch-gates. The adjacent mask family wasre-run too:
check-comment-mask-adoption(self-test + scan),js-comment-mask --self-test(35 cases), andcheck-comment-mask-corpus(5,454 files, 0 disagree) — all exit 0.pnpm lint— the whole repo,eslint . --no-inline-config, not a narrowed run — under the shared verifylock:
VERDICT command-exit 0 · held the lock 49s.NOT MEASURED, not red:
node scripts/check-test-completeness.mjswith no argument exits 3 and printsPREREQUISITE NOT MET; it grades a savedturbo run testlog CI tees.check-ci-filter-parityandcheck-shard-attestationfirst exited 1 withPREREQUISITE NOT MET — the dependency yaml is not installed;both are green above after
pnpm install.No changeset: this edits a CI-internal script and releases nothing — the
skip-changesetcase the lint workflownames in those words. The label is applied, and the read-back confirms it did not displace anything (the PR
carried no labels before the write).
Why this is
Part ofand notFixesThe dispatch word asked for
Fixes #13143; the measurement argues against it, so this deviates and says so.#13143's finding is that nothing watches
scripts/**for a private comment-stripper. This PR removes the oneinstance the card names, and leaves the watcher exactly as absent as it found it — plus three more live scanners
there that the same sweep turned up, none of which any gate can see. Merging with
Fixeswould close a card whosefinding is measurably still true. The remaining half is #13274, a sub-issue of #13143, carrying the eleven-row
population price and the zero-row vocabulary price as its starting measurement.
Generated by Claude Code