docs(formula): re-anchor the dead tracker citations to the commit that decided them (stage 12 of #20595) - #21635
Conversation
…t decided them Six comment and docblock sites in packages/formula cited a tracker number that now answers 404 (four census sites in src/cel-engine.ts, two test comments in src/validate.test.ts). Each now cites commit e9b5265, the change that added current_user to SCOPE_ROOTS and moved the field-level rejection into its own rule. Comment text only; no line count changes. Claude-Session: https://claude.ai/code/session_017ErfyP2Rx7XWHJA27QjyUi Co-authored-by: Claude <noreply@anthropic.com>
Two of the four rewritten cel-engine.ts lines reach the published dist (the SCOPE_ROOTS docblock in the declarations, one kept comment in the JavaScript), measured with a three-leg dist reading. Claude-Session: https://claude.ai/code/session_017ErfyP2Rx7XWHJA27QjyUi Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 8 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin cf96ff502106cbbeefea4ee201e519182028cdd4 && git checkout cf96ff502106cbbeefea4ee201e519182028cdd4
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin a4f0cb0a45b2b3841947520c896037e122d1c2a1 b89eb86cbe1542c7adea98424516f17ca3a10a70 && git checkout -B drift-repro a4f0cb0a45b2b3841947520c896037e122d1c2a1 && git merge --no-ff b89eb86cbe1542c7adea98424516f17ca3a10a70
node scripts/docs-audit/affected-docs.mjs --json a4f0cb0a45b2b3841947520c896037e122d1c2a1 |
ACCEPT — PR #21635 at head
|
Part of #20595
Clause-②: no
What changed
Stage 12 of the
domain:enginelane of the dead-citation sweep:packages/formula/**, comment and docblock prose only, per the claim (5973031304). Stages 1 to 11 landed asa7d9768ec,d150c3039,4bf4e7e70,13a24ece2,db0cf2231,85986144c,48fa7a381,c205b6c35,c98a72d69,fd5a1cd59andf97660cdd. #20595 stays open: the lane's other remaining package,metadata-fs(2 census sites after this stage), is not touched here, and neither are the test-string sites the card carries for a widened stage.Every comment or docblock site in the package that cited a tracker number answering 404 is rewritten in ruling C+D's form C (record
5749154545on #19123): the ADR when one records the decision, otherwise the commit in this repository's history that made it. That is 6 sites on 6 lines in 2 files, all citing one number (#6290), all re-anchored to one commit,e9b526597:src/cel-engine.ts:120, :147, :160, :173): the wholeallocated-but-absentpopulation of the gate's own census in this package at the base;src/validate.test.ts:933 and :958), which the census defers by its test-file exclusion. Same number;README.md,package.json,tsconfig.json,tsconfig.test.json,test-typecheck-debt.jsonandvitest.config.tscarry 10 citations between them, and all 10 resolve on the enumerated board (below);5865693155(the ruling record on [Decision] How does a filter say 「is empty」 on a multi-value field? A declared$emptyoperator, or reopen the empty-list refusal (ruling B on #20311, its third arm) #20399, atmatches-filter.ts:808andmatches-filter-empty-operator.test.ts:8), answers 200.Anchors: 1 number, by commit; 0 by ADR, 0 by repository qualifier; 1 sha.
e9b526597is the anchor thepackages/lintsweep (aa23e2c8f) already chose for the same number; it is reused here and re-proven below for this package's sentences.Only comments changed. Both files keep their line counts (6 lines out, 6 in, plus the changeset), so no line citation into either file moves. No code token moves (the guard below). All 12 changed lines open with a comment marker. No citation number is added: the
+lines carry no tracker number at all, and their only new nine-hex span ise9b526597, 6 times.A
patchchangeset: 2 of the 4 rewritten non-test lines are in the publisheddist(theSCOPE_ROOTSdocblock in the.d.ts, and one//line inside that list that esbuild keeps in the JavaScript), anddistis not byte-identical with the base text (see Changeset).H0: the package and its size
The gate's own
node scripts/check-issue-citations.mjs --census --jsonat base045b94625(the before run below),allocated-but-absentper remainingdomain:enginepackage:formulametadata-fsdrivers/driver-mongodb,drivers/driver-turso,metadata-core,core,metadata-protocol,objectql,metadata,drivers/driver-sql,drivers/driver-memory,drivers/driver-sqlite-wasm,plugins/plugin-pinyin-search,platform-objectsThe lane total goes 6 to 2.
formulareads 4, as at stage 11's head census (b69c176e9): the 4 sites, the one number and the one file the dispatch named. So the stage went ahead.Census:
formula, before and afterInstrument (A1). The gate's own
node scripts/check-issue-citations.mjs --census --json, read-only and unchanged. The count is itsallocated-but-absentfindings underpackages/formula/.allocated-but-absent045b94625, run 20:12:19Z to 20:16:21Z7a520db9d, run 20:22:39Z to 20:25:58Zb89eb86cb, run 20:48:23Z to 20:51:45ZThe whole-repo drop is 4, and the before and after finding sets differ by exactly the 4 rows of this package, removed; none was added.
resolves(35,759),resolves-as-pull-request(2,383) andcross-repo-unjudged(1,254) did not move. The head's only later commit is the changeset; the head run's finding set is identical to the after run's, line numbers included.Supplementary instrument, the whole package. The census reads neither test files nor strings nor files outside
src. A second reading runs the gate's own exportedextractCitations(whole-file and comment-prose projections) over every tracked file in the package (69) and classifies each citation with the gate'sclassifyCitationagainst one board enumerated by the gate'senumerateBoard(195 pages, frontier #21629, 19,450 records, read from 20:17:47Z to 20:21:16Z), the same board for both readings.045b946257a520db9dThe citation count drops by 6, the 6 rewritten sites; no respelling stays a citation. The live counts did not move (src comment: 229 resolve as issues, 6 as pull requests, 1 cross-repo; test comment: 148, 11 and 1; test string: 100, 1 and 2; files outside
src: 10 resolve as issues). A third, raw reading (every#followed by 2 to 6 digits, whatever surrounds it,CHANGELOG.mdaside) counts 527 before and 521 after: also a drop of 6.Single reads over the issues endpoint (20:21:27Z): #6290 answers 404; the controls #6584, #6713, #6146, #6798, #6585, #6711, #16412 and #3447 answer 200. Comment
5865693155answers 200, and the control5973031304(the claim) answers 200. Noissuecommentordiscussion_rlink stands in the package (git grep exit 1).Per-number table
srccounts census sites,testthe test-comment sites.#6290e9b526597packages/lintsweepaa23e2c8f), re-proven herecurrent_user, ADR-0068 D1's canonical user root, joinsSCOPE_ROOTS, and the field-level*Whenrejection stops falling out of that list's omission and becomes@objectstack/lint's own rule with its own prescription. It wrote the'current_user'entry with its comment, the block comment after the list, and bothvalidate.test.tsdocblocks (the squash of PR #6584)The proof, per the earlier stages' standard:
git rev-parse --disambiguate=e9b526597matches exactly one commit,e9b5265970029092a8b7124f8c2df98aa6ac0b15.git merge-base --is-ancestorputs it under the base045b94625and underorigin/main045b94625(exit 0 both; exit 0 is self-proving, and the repository is not shallow).git blameat the base puts 5 of the 6 changed lines on it. The sixth,cel-engine.ts:120, was written byd5e9f6e7c, a later change that cites finding: packages/formula 一包两话 —— SCOPE_ROOTS 不含 current_user 而 introspectScope 宣告它;字段级 visibleWhen 的 lint 拒绝还附错误修法「Write record.current_user」 #6290 as the change in whichcurrent_userarrived. That arrival ise9b526597's diff: the'current_user',entry added toSCOPE_ROOTS.docs/adr, exit 1). ADR-0068 D1 records thatcurrent_useris the canonical spelling, a decision these sentences already cite by its own ADR id. It does not record the list change that the number stood for.Wordings to check
All 6 rewrites swap a tag in place, in stage 1's forms:
(#N)became(commit SHA)atcel-engine.ts:147and:160.[#N]became[commit SHA]atvalidate.test.ts:933and:958.current_userarrived in finding: packages/formula 一包两话 —— SCOPE_ROOTS 不含 current_user 而 introspectScope 宣告它;字段级 visibleWhen 的 lint 拒绝还附错误修法「Write record.current_user」 #6290」 became 「current_userarrived in commit e9b5265」 (cel-engine.ts:120). This is thepackages/lintsweep's wording for the twin sentence invalidate-expressions.ts.cel-engine.ts:173).A cross-package quotation stays verbatim.
packages/lint/src/validate-expressions.ts:769quotes this package'sSCOPE_ROOTSentry as "the last one this list was missing". That phrase is all oncel-engine.ts:146, which this stage does not touch, and the rewritten(commit e9b526597)is on the next line. No other file cites a line ofcel-engine.ts(git grep forcel-engine.ts:followed by a line number, no hit).No reflow. No line was reflowed, so
:120,:173andvalidate.test.ts:958are now longer than their block's wrap.eslint.config.mjsdeclares no line-length rule, and a reflow would move neighbouring lines.Sites left
ittitles atvalidate.test.ts:950and:964(finding: packages/formula 一包两话 —— SCOPE_ROOTS 不含 current_user 而 introspectScope 宣告它;字段级 visibleWhen 的 lint 拒绝还附错误修法「Write record.current_user」 #6290). Strings are outside this stage's surface, and the number's anchor is in this stage's table. Non-test strings cite no dead number.src: the release-ownedCHANGELOG.mdnames finding: packages/formula 一包两话 —— SCOPE_ROOTS 不含 current_user 而 introspectScope 宣告它;字段级 visibleWhen 的 lint 拒绝还附错误修法「Write record.current_user」 #6290 on 4 lines (2875, 2946, 4350, 4421); left.packages/lint/src/validate-expressions.test.tscites finding: packages/formula 一包两话 —— SCOPE_ROOTS 不含 current_user 而 introspectScope 宣告它;字段级 visibleWhen 的 lint 拒绝还附错误修法「Write record.current_user」 #6290 on 9 lines. That is another lane's test file, and thepackages/lintsweep's own PR notes it.Mechanical guard: no code token moves
The guard compares base
045b94625against the tree over both touched files, with TypeScript 6.0.3, to the earlier stages' two-reading specification. Stage 11's guard script was a scratch file, so it was rewritten here to that specification and proven with the controls below.forEachChildwalk. Comments are trivia there, and JSDoc is never visited. A leaf that is not itself a token is re-scanned with trivia skipped.getChildrenwalk, with JSDoc nodes skipped. String, template and numeric literals are compared in full on both readings.Results, at
7a520db9d(the later commit touches neither file):cel-engine.ts) and 「Pinned as behaviour」 to 「Pinned as BEHAVIOUR」 (validate.test.ts). 0 files changed (exit 0 each).export const SCOPE_ROOTStoXSCOPE_ROOTS,cel-engine.ts): DIFFER on both readings (exit 1).toContain('current_user')to'current_useR',validate.test.ts): DIFFER on both readings (exit 1).${root}.xtemplate to${root}.y,validate.test.ts): DIFFER on both readings (exit 1).maxAstNodes: 256to257,cel-engine.ts): DIFFER on both readings (exit 1).Each mutation went through
scripts/ablation-replace.mjs(wrap mode; the anchor hit 1 before and 0 after, and the blob changed). It ran under a shell trap that restores by absolute path fromHEAD. Each restore was proven equal to itsHEADblob (6fa1738be716,832c4f069ec7), and afterwardsgit diff HEADwas empty and the tree clean.Changeset:
patch(distmeasured)files[]isdist,README.mdandCHANGELOG.md, and the package is not private. One script ran under the shared verify lock (VERDICT command-exit 0, held 75s, shared-box seconds), at7a520db9d. It built the dependency closure first (pnpm --filter '@objectstack/formula^...' build, exit 0), then ran the package's ownbuild(tsup andcheck-dts-emitted) three times, exit 0 each:Leg 1, the head text: 6
distfiles hashed (index.js,index.mjs, their sourcemaps,index.d.ts,index.d.mts). 2 of the 4 rewritten non-test lines appear verbatim indist:SCOPE_ROOTSdocblock line (cel-engine.ts:120) inindex.d.tsandindex.d.mts;// (commit e9b526597).line inside the list (cel-engine.ts:147) inindex.jsandindex.mjs.The other 2 (
:160,:173) sit in a block comment the build drops.Leg 2, the base text put back in
cel-engine.ts(proven equal to its base blob667f87448eeb, written to the tree only): 4 of the 6 files differ from leg 1 (index.d.ts,index.d.mts,index.js,index.mjs); the two sourcemaps do not.scripts/ablation-dist-preflight.mjsfinds the base marker 「arrived in finding: packages/formula 一包两话 —— SCOPE_ROOTS 不含 current_user 而 introspectScope 宣告它;字段级 visibleWhen 的 lint 拒绝还附错误修法「Write record.current_user」 #6290) is silently unreported at」 in the 2 declaration files (exit 0).Leg 3, after the proven restore (equal to its
HEADblob6fa1738be716,git diff HEADempty, porcelain empty): all 6 files are byte-identical to leg 1. The preflight's--absentreading exits 0 with a clean tree. So the build is deterministic, and the difference is the rewrite.So the rewrite ships.
.changeset/20595-formula-provenance-anchors.mddeclares apatchfor@objectstack/formula, comment text only, with the claim'sClause-②: noline. The anchor is a commit, so the changeset names no ADR, repository qualifier or bracketed substitution. It says which published files carry the reworded text, as measured above. The changeset commit touches no file underpackages/formula.Gates (head
b89eb86cb)node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandsatb89eb86cb(3 paths against merge base045b94625) derived 63 commands. All 63 ran (20:36:36Z to 20:47:06Z, after the workspace build), each exit code captured before any pipe: 63 exit 0.--ranreports 「63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN」 (a derived zero) and exits 0..changeset/path adds: the ADR-0087 registration and empty-changeset pairs,check:objectui-changeset,check:pm-changeset-deadline-censusand two release self-tests;check:type-check-coverageandcheck:type-check-debt;check:engine-double-contract,check:objectql-double-limit,check:query-options-erasureandcheck:where-matcher.node scripts/check-issue-citations.mjsexits 0 (「no issue citations added against 045b946」).pnpm check:issue-citationsexits 0 (its self-test, 173 cases, 9 batteries).pnpm check:doc-authoringexits 0 (the sibling-package prose-id baseline holds, no growth).pnpm check:nul-bytesexits 0 (9,998 files, no raw control bytes), and a control-byte grep over the 3 changed files finds none (exit 1).check-adr-0087-registration(「1 non-breaking changeset(s) seen」),check-empty-changeset(「1 declaring changeset(s) added」),check-changeset-no-major(「nomajorbump」), andcheck:changeset-gate-self-tests. The Clause-② level axis ofcheck-changeset-no-majorreads the pull request body, so it does not apply to a local run; that reading is CI's.b89eb86cb:turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=2): VERDICT command-exit 0, held 213s, shared-box seconds; 71 of 71 tasks, 17 cached.pnpm --filter @objectstack/formula test: 43 test files pass, 1,257 tests pass.pnpm --filter @objectstack/formula typecheck(tsc --noEmitandcheck:test-typecheckovertsconfig.test.json) exits 0.tsc --listFilesOnlyputs both touched files in a program:cel-engine.tsin both configs, andvalidate.test.tsintsconfig.test.json, whose program holds all 43 tracked test files (tsconfig.jsonexcludes them).b89eb86cb:--format json) over the 2 touched files plusdist/index.jsas the control.--print-configresolves a config for each.eslint.config.mjsnever enables type-aware linting (its lines 327 and 328 say so;--print-configshows noparserOptions.projectfor either file), so a comment edit cannot move the verdict on an untouched file.pnpm lintis CI's run.Acceptance notes
origin/mainat045b94625, and the worktree was cut there. Every reading above is on this branch's own tree. Just before this PR was opened,mainmoved one commit,a4f0cb0a4: aservice-automationchange, with its changeset and one lockfile line.packages/formula,check-issue-citations.mjsnordispatch-gates.mjs.git merge-treeof the head with it is clean (exit 0), and the anchore9b526597is under it too (--is-ancestor, exit 0).045b94625, and CI and the merge queue run on the merged ref.git rev-parse --is-shallow-repositoryanswers false), so no deepening was needed before the blame, ancestry and history readings.formula's 2 test-string sites (above);CHANGELOG.md(release-owned);packages/lint's test file (another lane).Generated by Claude Code