refactor(devx): check-registry-log-declared consumes js-comment-mask's maskComments instead of a private wrapper - #15595
Conversation
…s maskComments instead of a private wrapper (#15561) The local `maskComments` was `blank(source, scanSource(source).comment)` — character-for-character the module's own export — so it was a private wrapper, not a second scanner. Import the export and delete the wrapper; every call site is unchanged. `maskCode` stays local (the module publishes no comments+literals projection yet) and its docblock now says so: it composes `scanSource`'s `comment` and `literal` flags through `blank` and carries no scanning logic of its own. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…g-declared's self-test (#15561) The existing prose row pins the COMMENT direction for S2 only. This row adds the code mask's other direction: a signal spelled inside a string literal or a comment must not select, and the same spelling in real code still must. Two packages in one case, so a mask that stopped blanking either span shows up as a second selected package rather than as a silent widening of the population. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
|
ACCEPT — PM seat Reviewed against the three-dot diff
Dev's verification quoted (on Flipping ready + enabling auto-merge (MCP rate-limited since ~22:45Z — retried each tick with #15590 and #15593). Fixes #15561. Generated by Claude Code |
Fixes #15561
The card's premise, narrowed
The card reads "carries private
maskComments/maskCodecopies instead ofjs-comment-mask.mjs". Onmainthat overstates the finding in one direction and understates the remedy in the other, so this PR does the narrow, provable half:scripts/check-registry-log-declared.mjs:130already imported{ blank, scanSource }from./js-comment-mask.mjs. There was never a second scanner here.maskCommentswasreturn blank(source, scanSource(source).comment);— character-for-character the body of the module's ownmaskCommentsexport (scripts/js-comment-mask.mjs:540). A private wrapper, not a private copy of the scanner. That one is deleted and the export imported.maskCodehas no shared export to consume:js-comment-mask.mjspublishesscanSource,blank,stripCommentsandmaskComments, and no comments+literals projection. It stays local, and its docblock now says why in one sentence — it composesscanSource'scommentandliteralflags throughblankand carries no scanning logic of its own. Hoisting a sharedmaskCommentsAndLiteralsis filed separately as [finding] hoist maskCommentsAndLiterals (comments+literals blank) into js-comment-mask.mjs + .d.mts #15594 (it changes a module three gates read; it is not a rider on a one-line refactor).So
premise_still_validis partly: themaskCommentshalf is real and fixed here; themaskCodehalf is a missing shared export, not a private copy.Byte-identical proof
The point of the swap is that nothing about the gate's behaviour moves. Both of the gate's runs were captured on
origin/main(954cb0b) and again on the refactor commit (1a49ea8), and diffed:mainnode scripts/check-registry-log-declared.mjsnode scripts/check-registry-log-declared.mjs --self-testmainand the refactor commit both print, verbatim:The self-test control added — and one measured correction
The card's dispatch asked for a control where the boot signal spelled only in a string literal and in a comment is NOT selected, and the same spelling in code IS. Measured first, on
main, before writing it:new SchemaRegistry()inside a string literalnew SchemaRegistry()inside line + block commentsbootStackinside a string literalnew SchemaRegistry()in codeimport … from '@objectstack/verify'statement spelled inside a string literalThat last row is deliberate, not a bug:
maskCommentsleaves string content intact precisely so S2/S3 can read import specifiers, and the gate says so at the call site. Asserting "a string-literal spelling never selects" as a blanket rule would therefore have pinned a falsehood. The case added pins the direction that is true, and it is the one that exercisesmaskCode— the function this PR leaves local:a code signal spelled only in a string or a comment does not SELECT— two packages in one case: packageacarries the non-code spellings (string literal + line comment + block comment, plus a barebootStackword in a string), packagebcarries the real code. Expected: 1 selected, 1 finding. A mask that stopped blanking either span surfaces as a second selected package rather than as a silent widening of the population.The existing 15 cases do not already pin this:
prose naming bootStack does not SELECT the package (the packages/cli shape)covers the comment direction for S2 only, and no row covers the string-literal direction ormaskCode's masking at all.Roster and floor moved with it: the row is declared in
SELF_TEST_BATTERIESandSELF_TEST_BATTERY_FLOORgoes 15 to 16. The only self-test output delta frommainis that count:The plain run is still a 0-line diff at head.
Ablation of the new case
Trap-guarded, mutating
maskCodeto stop OR-ing theliteralflags (flags[i] = comment[i]), on the committed state:grep -c= 1, removed spellinggrep -c= 0;HEADblobe4620d5…vs mutated blob94b65b5…(differ).git checkout HEAD -- <abs path>; restored blobe4620d5…equals theHEADblob,git diff HEADempty,git status --porcelainempty.No rebuild leg applies — this gate is plain
.mjsexecuted from source bynode, with nodist/between the edit and the run.Verification
All at head
4edcadcb2. Exit codes captured before any pipe (cmd > file 2>&1; EXIT=$?).Derived family, not guessed:
node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack— exit 0, "gate list derived from the tree of 'objectstack-ai/objectstack' at commit 4edcadc", change set "1 path(s) vs merge base 954cb0b". 26 commands emitted, all 26 run, all exit 0.node scripts/check-registry-log-declared.mjsOK: 72 vitest-running package(s) walked, 8 selected as engine-booting, …node scripts/check-registry-log-declared.mjs --self-testself-test OK: 16 cases + level-vocabulary read + population declaration + real-tree selection floor.pnpm check:pm-dispatch-gatesdispatch-gates self-test: 1415 cases pass.pnpm check:nul-bytescheck-nul-bytes: OK (scanned 7557 text file(s) …; no raw ASCII control bytes).pnpm check:entry-guardcheck:entry-guard: 214 scripts/ file(s) — every entry guard goes through invoked-as.mjs; …node scripts/check-comment-mask-corpus.mjscomment-mask corpus sweep: 5961 files, 0 disagree, 0 unparseable, 73.1sTwo run beyond the derived family, because this diff is about mask adoption:
node scripts/check-comment-mask-adoption.mjsOK check:comment-mask-adoption — 14 private comment-stripper(s) …, all 14 recorded and every recorded row still reachednode scripts/check-comment-mask-corpus.mjs(re-run at head)This gate has no vitest suite —
git grep -l check-registry-log-declarednames onlylint.yml,package.json, fourvitest.config.tsfiles and the script itself, so its--self-testis its test suite and it is in the table above.pnpm lintwas narrowed, and the narrowing is measured, not assumed.pnpm exec eslint --no-inline-config --format json scripts/check-registry-log-declared.mjs— exit 0, 1 file linted, 0 errors, 0 warnings (count read from the JSON output, not estimated). Nothing untouched can have moved:eslint.config.mjs:327states, of this repo, that it "runs oneeslint.config.mjs, which never enables type-aware linting (noparserOptions.project, no typed@typescript-eslintrules) for ANY file, test or not" — with no cross-file program, a one-file diff cannot change any other file's verdict. The whole-repo sweep is CI's run, and it was not in the derived list.NOT MEASURED: none. No command returned exit 3,
PREREQUISITE NOT MET,ERR_MODULE_NOT_FOUND, or a queue timeout.Scope
One file:
scripts/check-registry-log-declared.mjs. No changeset —scripts/**publishes nothing from any package;skip-changesetapplied and read back. Follow-up filed as #15594 (unassigned,finding); #15594 remains open and is not addressed here.🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code