Skip to content

Commit 0a0debb

Browse files
docs(formula): re-anchor the dead tracker citations to the commit that decided them (stage 12 of #20595) (#21635)
Part of #20595 Clause-②: no ## What changed Stage 12 of the `domain:engine` lane of the dead-citation sweep: `packages/formula/**`, comment and docblock prose only, per the claim (`5973031304`). Stages 1 to 11 landed as `a7d9768ec`, `d150c3039`, `4bf4e7e70`, `13a24ece2`, `db0cf2231`, `85986144c`, `48fa7a381`, `c205b6c35`, `c98a72d69`, `fd5a1cd59` and `f97660cdd`. #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 `5749154545` on #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`**: - **4 census sites** (4 lines, `src/cel-engine.ts` :120, :147, :160, :173): the whole `allocated-but-absent` population of the gate's own census in this package at the base; - **2 test-comment sites** (2 lines, `src/validate.test.ts` :933 and :958), which the census defers by its test-file exclusion. Same number; - **outside the census glob, inside the claimed surface: none.** `README.md`, `package.json`, `tsconfig.json`, `tsconfig.test.json`, `test-typecheck-debt.json` and `vitest.config.ts` carry 10 citations between them, and all 10 resolve on the enumerated board (below); - **dead comment ids: none.** The package's only ten-digit id, `5865693155` (the ruling record on #20399, at `matches-filter.ts:808` and `matches-filter-empty-operator.test.ts:8`), answers 200. **Anchors: 1 number, by commit; 0 by ADR, 0 by repository qualifier; 1 sha.** `e9b526597` is the anchor the `packages/lint` sweep (`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 is `e9b526597`, 6 times. **A `patch` changeset**: 2 of the 4 rewritten non-test lines are in the published `dist` (the `SCOPE_ROOTS` docblock in the `.d.ts`, and one `//` line inside that list that esbuild keeps in the JavaScript), and `dist` is 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 --json` at base `045b94625` (the before run below), `allocated-but-absent` per remaining `domain:engine` package: | package | before | after this stage | |---|---|---| | `formula` | **4** | **0** | | `metadata-fs` | 2 | 2 | | `drivers/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-objects` | 0 each | 0 each | The lane total goes 6 to 2. `formula` reads 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 after **Instrument (A1).** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged. The count is its `allocated-but-absent` findings under `packages/formula/`. | reading | tree | board | whole-repo `allocated-but-absent` | sites | lines | files | numbers | |---|---|---|---|---|---|---|---| | before | base `045b94625`, run 20:12:19Z to 20:16:21Z | enumerated, 195 pages, frontier #21629, 19,450 records | 119 | **4** | 4 | 1 | 1 | | after | `7a520db9d`, run 20:22:39Z to 20:25:58Z | enumerated, 195 pages, frontier #21630, 19,451 records | 115 | **0** | 0 | 0 | 0 | | head | `b89eb86cb`, run 20:48:23Z to 20:51:45Z | enumerated, 195 pages, frontier #21633, 19,454 records | 115 | **0** | 0 | 0 | 0 | The 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) and `cross-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 exported `extractCitations` (whole-file and comment-prose projections) over every tracked file in the package (69) and classifies each citation with the gate's `classifyCitation` against one board enumerated by the gate's `enumerateBoard` (195 pages, frontier #21629, 19,450 records, read from 20:17:47Z to 20:21:16Z), the same board for both readings. | reading | citations | dead | src comment | test comment | test string | other files | changelog | |---|---|---|---|---|---|---|---| | before, `045b94625` | 763 | **12** | 4 | 2 | 2 | 0 | 4 | | after, `7a520db9d` | 757 | **6** | 0 | 0 | 2 | 0 | 4 | The 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.md` aside) 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 `5865693155` answers 200, and the control `5973031304` (the claim) answers 200. No `issuecomment` or `discussion_r` link stands in the package (git grep exit 1). ## Per-number table `src` counts census sites, `test` the test-comment sites. | number | src | test | anchor | kind | source | what it decided | |---|---|---|---|---|---|---| | `#6290` | 4 | 2 | `e9b526597` | commit | reused (`packages/lint` sweep `aa23e2c8f`), re-proven here | `current_user`, ADR-0068 D1's canonical user root, joins `SCOPE_ROOTS`, and the field-level `*When` rejection 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 both `validate.test.ts` docblocks (the squash of PR #6584) | The proof, per the earlier stages' standard: - `git rev-parse --disambiguate=e9b526597` matches exactly one commit, `e9b5265970029092a8b7124f8c2df98aa6ac0b15`. - `git merge-base --is-ancestor` puts it under the base `045b94625` and under `origin/main` `045b94625` (exit 0 both; exit 0 is self-proving, and the repository is not shallow). - It names #6290 in its message (the subject's suffix) and in its diff (18 diff lines). - `git blame` at the base puts 5 of the 6 changed lines on it. The sixth, `cel-engine.ts:120`, was written by `d5e9f6e7c`, a later change that cites #6290 as the change in which `current_user` arrived. That arrival is `e9b526597`'s diff: the `'current_user',` entry added to `SCOPE_ROOTS`. - No ADR or ruling record names #6290 (git grep over `docs/adr`, exit 1). ADR-0068 D1 records that `current_user` is 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)` at `cel-engine.ts:147` and `:160`. - `[#N]` became `[commit SHA]` at `validate.test.ts:933` and `:958`. - 「`current_user` arrived in #6290」 became 「`current_user` arrived in commit e9b5265」 (`cel-engine.ts:120`). This is the `packages/lint` sweep's wording for the twin sentence in `validate-expressions.ts`. - 「Before #6290 that」 became 「Before commit e9b5265 that」 (`cel-engine.ts:173`). **A cross-package quotation stays verbatim.** `packages/lint/src/validate-expressions.ts:769` quotes this package's `SCOPE_ROOTS` entry as "the last one this list was missing". That phrase is all on `cel-engine.ts:146`, which this stage does not touch, and the rewritten `(commit e9b5265)` is on the next line. No other file cites a line of `cel-engine.ts` (git grep for `cel-engine.ts:` followed by a line number, no hit). **No reflow.** No line was reflowed, so `:120`, `:173` and `validate.test.ts:958` are now longer than their block's wrap. `eslint.config.mjs` declares no line-length rule, and a reflow would move neighbouring lines. ## Sites left - **In comments (src, test, outside the glob): none.** - **String literals: 2 test-string sites, 1 number**: the `it` titles at `validate.test.ts:950` and `:964` (#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. - **Outside `src`:** the release-owned `CHANGELOG.md` names #6290 on 4 lines (2875, 2946, 4350, 4421); left. - **Outside this package:** `packages/lint/src/validate-expressions.test.ts` cites #6290 on 9 lines. That is another lane's test file, and the `packages/lint` sweep's own PR notes it. ## Mechanical guard: no code token moves The guard compares base `045b94625` against 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. - **Reading 1**: the parser's leaf nodes, from a `forEachChild` walk. Comments are trivia there, and JSDoc is never visited. A leaf that is not itself a token is re-scanned with trivia skipped. - **Reading 2**: the full token stream in parser context, from a `getChildren` walk, 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): - Real run: 13,628 base tokens, **0 files with a token change** (exit 0). - Comment controls: 「Membership of THIS list can.」 to 「… CAN.」 (`cel-engine.ts`) and 「Pinned as behaviour」 to 「Pinned as BEHAVIOUR」 (`validate.test.ts`). 0 files changed (exit 0 each). - Positive control, an identifier (`export const SCOPE_ROOTS` to `XSCOPE_ROOTS`, `cel-engine.ts`): DIFFER on both readings (exit 1). - Positive control, a string literal (`toContain('current_user')` to `'current_useR'`, `validate.test.ts`): DIFFER on both readings (exit 1). - Positive control, a template literal (the `${root}.x` template to `${root}.y`, `validate.test.ts`): DIFFER on both readings (exit 1). - Positive control, a numeric literal (`maxAstNodes: 256` to `257`, `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 from `HEAD`. Each restore was proven equal to its `HEAD` blob (`6fa1738be716`, `832c4f069ec7`), and afterwards `git diff HEAD` was empty and the tree clean. ## Changeset: `patch` (`dist` measured) `files[]` is `dist`, `README.md` and `CHANGELOG.md`, and the package is not private. One script ran under the shared verify lock (VERDICT command-exit 0, held 75s, shared-box seconds), at `7a520db9d`. It built the dependency closure first (`pnpm --filter '@objectstack/formula^...' build`, exit 0), then ran the package's own `build` (tsup and `check-dts-emitted`) three times, exit 0 each: - **Leg 1**, the head text: 6 `dist` files hashed (`index.js`, `index.mjs`, their sourcemaps, `index.d.ts`, `index.d.mts`). 2 of the 4 rewritten non-test lines appear verbatim in `dist`: - the `SCOPE_ROOTS` docblock line (`cel-engine.ts:120`) in `index.d.ts` and `index.d.mts`; - the `// (commit e9b5265).` line inside the list (`cel-engine.ts:147`) in `index.js` and `index.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 blob `667f87448eeb`, 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.mjs` finds the base marker 「arrived in #6290) is silently unreported at」 in the 2 declaration files (exit 0). - **Leg 3**, after the proven restore (equal to its `HEAD` blob `6fa1738be716`, `git diff HEAD` empty, porcelain empty): all 6 files are byte-identical to leg 1. The preflight's `--absent` reading 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.md` declares a `patch` for `@objectstack/formula`, comment text only, with the claim's `Clause-②: no` line. 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 under `packages/formula`. ## Gates (head `b89eb86cb`) - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands` at `b89eb86cb` (3 paths against merge base `045b94625`) 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. `--ran` reports 「63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN」 (a derived zero) and exits 0. - The PM's lead derivation (49 commands, one path) is a subset. The extra 14 are: - the eight families the `.changeset/` path adds: the ADR-0087 registration and empty-changeset pairs, `check:objectui-changeset`, `check:pm-changeset-deadline-census` and two release self-tests; - `check:type-check-coverage` and `check:type-check-debt`; - four gates whose sources name the touched files: `check:engine-double-contract`, `check:objectql-double-limit`, `check:query-options-erasure` and `check:where-matcher`. - **Named readings:** - `node scripts/check-issue-citations.mjs` exits 0 (「no issue citations added against 045b946」). - `pnpm check:issue-citations` exits 0 (its self-test, 173 cases, 9 batteries). - `pnpm check:doc-authoring` exits 0 (the sibling-package prose-id baseline holds, no growth). - `pnpm check:nul-bytes` exits 0 (9,998 files, no raw control bytes), and a control-byte grep over the 3 changed files finds none (exit 1). - The changeset gates exit 0: `check-adr-0087-registration` (「1 non-breaking changeset(s) seen」), `check-empty-changeset` (「1 declaring changeset(s) added」), `check-changeset-no-major` (「no `major` bump」), and `check:changeset-gate-self-tests`. The Clause-② level axis of `check-changeset-no-major` reads the pull request body, so it does not apply to a local run; that reading is CI's. - **Build, tests and typecheck, under the verify lock**, at `b89eb86cb`: - The workspace build (`turbo run build --filter='./packages/*' --filter='./packages/*/*' --concurrency=2`): VERDICT command-exit 0, held 213s, shared-box seconds; 71 of 71 tasks, 17 cached. - The tests and typecheck: VERDICT command-exit 0, held 19s. `pnpm --filter @objectstack/formula test`: 43 test files pass, 1,257 tests pass. `pnpm --filter @objectstack/formula typecheck` (`tsc --noEmit` and `check:test-typecheck` over `tsconfig.test.json`) exits 0. - `tsc --listFilesOnly` puts both touched files in a program: `cel-engine.ts` in both configs, and `validate.test.ts` in `tsconfig.test.json`, whose program holds all 43 tracked test files (`tsconfig.json` excludes them). - No importing package owes a run, because the declaration files change only in comment text. - **Lint, as a proven narrowing, at `b89eb86cb`:** - eslint ran with inline config disabled (`--format json`) over the 2 touched files plus `dist/index.js` as the control. - 3 results: 0 errors, and 1 warning, which is the control's ignore notice. Neither touched file is reported ignored, and `--print-config` resolves a config for each. - `eslint.config.mjs` never enables type-aware linting (its lines 327 and 328 say so; `--print-config` shows no `parserOptions.project` for either file), so a comment edit cannot move the verdict on an untouched file. - The repo-wide `pnpm lint` is CI's run. ## Acceptance notes - **Base, and no merge.** The dispatch read `origin/main` at `045b94625`, and the worktree was cut there. Every reading above is on this branch's own tree. Just before this PR was opened, `main` moved one commit, `a4f0cb0a4`: a `service-automation` change, with its changeset and one lockfile line. - It touches neither `packages/formula`, `check-issue-citations.mjs` nor `dispatch-gates.mjs`. - A local `git merge-tree` of the head with it is clean (exit 0), and the anchor `e9b526597` is under it too (`--is-ancestor`, exit 0). - The branch is not merged with it: the gate derivation reads the three-dot change set against the merge base `045b94625`, and CI and the merge queue run on the merged ref. - **History.** The repository is not shallow (`git rev-parse --is-shallow-repository` answers false), so no deepening was needed before the blame, ancestry and history readings. - **The same dead number outside this package**, each left to its own carrier: `formula`'s 2 test-string sites (above); `CHANGELOG.md` (release-owned); `packages/lint`'s test file (another lane). - **Wording only:** no line without the number was changed. --- _Generated by [Claude Code](https://claude.ai/code/session_017ErfyP2Rx7XWHJA27QjyUi)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5b5e83f commit 0a0debb

3 files changed

Lines changed: 21 additions & 6 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/formula': patch
3+
---
4+
5+
Provenance comments in `@objectstack/formula` cite the commit that decided them, not a tracker number that no longer resolves
6+
7+
Clause-②: no
8+
9+
Comments and docblocks in the package cited an issue-tracker number that now answers 404 on GitHub.
10+
Each one now cites the commit in this repository's history that made the decision it describes. One of
11+
these docblocks sits on an exported member (`SCOPE_ROOTS`), so the reworded text appears in the
12+
published `index.d.ts` / `index.d.mts`; one comment esbuild keeps inside that list appears in the
13+
JavaScript output (`index.js` / `index.mjs`); the sourcemaps do not change.
14+
15+
Comment only: no export, type, error code, status, message text or runtime behaviour changes.

‎packages/formula/src/cel-engine.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export function buildEnv(
117117
* `*When` gate is exactly such a surface — it binds `record` / `previous` /
118118
* `parent` and nothing else — and it used to carry a hand-written DENYLIST of
119119
* three roots instead. A denylist structurally cannot track this list: every
120-
* root added here (`current_user` arrived in #6290) is silently unreported at
120+
* root added here (`current_user` arrived in commit e9b526597) is silently unreported at
121121
* that surface until somebody remembers to copy it over, and #6713 measured 21
122122
* roots sitting in that gap.
123123
*
@@ -144,7 +144,7 @@ export const SCOPE_ROOTS = [
144144
// env doesn't misread `current.x` as a bare field reference.
145145
'current',
146146
// ADR-0068 D1's CANONICAL user root, and the last one this list was missing
147-
// (#6290). `buildScope` mounts the same `EvalUser` object under
147+
// (commit e9b526597). `buildScope` mounts the same `EvalUser` object under
148148
// `current_user` / `user` / `ctx.user` / `os.user` whenever the evaluation
149149
// carries a user, and this package already told the rest of the platform so:
150150
// `introspectScope` lists `current_user` among the roots it hands an author,
@@ -157,7 +157,7 @@ export const SCOPE_ROOTS = [
157157

158158
/*
159159
* Why widening this list is the safe direction, and where the narrow verdict
160-
* lives instead (#6290).
160+
* lives instead (commit e9b526597).
161161
*
162162
* This list is a "never faults" BASELINE, not a per-surface contract —
163163
* `SCOPE_ROOTS`'s own doc-comment opens by saying exactly that, and every entry
@@ -170,7 +170,7 @@ export const SCOPE_ROOTS = [
170170
*
171171
* That matters here because field- and section-level `visibleWhen` genuinely do
172172
* NOT bind `current_user` (#6146, measured at both ends: `evalFieldPredicate`
173-
* binds `record` + `previous` + `parent` and nothing else). Before #6290 that
173+
* binds `record` + `previous` + `parent` and nothing else). Before commit e9b526597 that
174174
* surface's rejection came out of this list's omission as a SIDE EFFECT, and it
175175
* showed: the diagnostic was the generic bare-field one, so it prescribed
176176
* "Write `record.current_user`" — a shape that binds on no layer at all. A

‎packages/formula/src/validate.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ describe('validateExpression (ADR-0032)', () => {
930930
});
931931

932932
/**
933-
* [#6290] The package must give ONE answer about what a root is.
933+
* [commit e9b526597] The package must give ONE answer about what a root is.
934934
*
935935
* `introspectScope` is the roots list this package HANDS an author (and the
936936
* agent authoring tool); `firstUndeclaredReference` is the strict env that
@@ -955,7 +955,7 @@ describe('validateExpression (ADR-0032)', () => {
955955
});
956956

957957
/**
958-
* [#6290] The same drift, seen from `checkRoleCatalog`'s side: its four
958+
* [commit e9b526597] The same drift, seen from `checkRoleCatalog`'s side: its four
959959
* position-membership regexes accept `current_user` / `user` / `ctx.user`
960960
* as the user subject, so a role-catalog verdict on a `current_user`
961961
* predicate was only ever reachable at sites that do not run the

0 commit comments

Comments
 (0)