Repository navigation
docs(spec): anchor five dead tracker citations to commits, and measure the true clean-up scale - #20226
Conversation
…its, not deleted tracker numbers Five lines in packages/spec/src/ui cited two tracker numbers GitHub no longer serves. Each now anchors to the commit in this repository's history that decided it and states in its own words what that commit decided: - app.zod.ts (two docblock sentences, shipped as source): the filters docblock states no precedence order because objectui's hand-written mirror copied one and accepted a combination the schema refuses; the guard is exported so a mirror chains the schema's own rule (commit 4cfc93b). - app-nav-target-exclusivity-export.test.ts: the header and one test title (the title no longer carries a number; the comment below it anchors). - object-refinement-check-exports.test.ts: the declaration-count hardening closes a residual hole, no live shadowing existed (commit b37f0b1). Prose, comments and one test title only; no assertion changes meaning. Claude-Session: https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ 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 — 136 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 7816169646105a021c7ac14d03a1773d1c097994 && git checkout 7816169646105a021c7ac14d03a1773d1c097994
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 805af4f290565955d6e6b56ee46fed45f721d955 98edadd03c06f76737180e09c613cd69024305fc && git checkout -B drift-repro 805af4f290565955d6e6b56ee46fed45f721d955 && git merge --no-ff 98edadd03c06f76737180e09c613cd69024305fc
node scripts/docs-audit/affected-docs.mjs --json 805af4f290565955d6e6b56ee46fed45f721d955 |
Contract reviewServed-tier: Read: card #19123 body and all 6 comments (ruling 5749154545, pointer 5807032824, dispatch 5855287758, dev report 5855787862), PR #20226 object/body/files/commits/check-runs, the full diff against merge-base 4df101c, the four files at the head, anchor commits 4cfc93b and b37f0b1 (stat, message, relevant hunks), retirement commit 28ce612, AGENTS.md (citation rule, changeset step 3, Touched packages/spec, Prime Directive 14), the headers of check-changeset-no-major / check-empty-changeset / check-changeset-fixed and check-issue-citations (surfaces, deferred table, cause table). Ran: a TypeScript-scanner token comparison of app.zod.ts base vs head with trivia dropped, an independent comment-region state machine over the same pair, git grep sweeps at base and head, REST probes of 17 issue numbers and 3 commit-to-PR associations, census arithmetic, 4 site-count reproductions, a bounded CI poll to convergence. NOT MEASURED: a local run of the two test files (the shared checkout has no node_modules; CI Test Core green stands in), the 1,958-probe census totals and era table, the check-issue-citations --census totals and the 40-line sample (spot-checked, not re-run), and the four derived gates the dev declared NOT MEASURED (CI ran them). ① Derived judgments(a) No accept set or runtime string moves. app.zod.ts base vs head through the TypeScript scanner with comment and whitespace trivia dropped: 3974 tokens each, identical token for token. Independent state machine: the 10 changed lines all lie inside (b) No assertion changes meaning. app-nav-target-exclusivity-export.test.ts changes a header docblock (lines 3 to 9), one (c) Anchors are faithful and on the right rung. (d) Ruling D on the two shipped lines. Head 457 to 460: "objectui's hand-written mirror did exactly that, which is why commit 4cfc93b took the ordering out of this docblock" and head 506: "EXPORTED (commit 4cfc93b), one function per refinement, the same posture" carry no tracker number and each states the decision in words (the ordering was removed because a mirror copied it and accepted what the schema refuses; the guard is exported so a mirror chains the schema's own rule), so a reader needs no link. Caveat, non-blocking: the same sentence continues on head line 507, re-wrapped by this diff, with "the (e) The one added tracker number, (f) Census. Method: REST ② Semver level
③ Boundary flagsBlocking: none CI at this head: 35 check-runs on 98edadd, converged 12:40Z: 32 success, 3 skipped (Build Docs, Console Pin Gate, Packed-tarball smoke (opt-in)), 0 failed, 0 pending. All seven required contexts from the main-branch ruleset are success: TypeScript Type Check, Test Core, Dogfood Regression Gate, Build Core, Temporal Conformance (live PG + MySQL), Lint & Repo Gates, Governed Surface Queue Guard. mergeable_state clean, PR still draft. Closing keywords: the body carries Implemented-by: VERDICT: PASS |
…acts/ to the commits and ADRs that decided them (stage 1) (objectstack-ai#20326) Part of objectstack-ai#20234 Clause-②: no ## What changed This is stage 1 of the staged sweep, covering `packages/spec/src/kernel/**` and `packages/spec/src/contracts/**` and nothing else. Later stages cover the other areas, so this PR carries `Part of`. Every comment or docblock site in these two areas that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123): **160 sites on 151 lines in 45 files, covering 47 numbers (152 lines rewritten)**. Each rewritten line now cites the object this repository controls that decided the matter: - an ADR or ruling record where one exists; - otherwise the commit in `origin/main` history that decided it. Each line also says in its own words what that object decided. Where nothing answers, the sentence keeps its reason in words and the number is gone: that happened for four numbers. Only comments changed. Every file keeps its line count (152 lines out, 152 in), so no line citation into these files moves. No code token moves (see the guard below). String literals carrying a dead number are tokens: 30 such sites are left as they were and listed below. **No citation number is added.** Every tracker number on an added line was already on the line it replaces. That includes the two PR numbers now standing beside their shas as convenience links: PR objectstack-ai#6900 beside `b5404f496`, and PR objectstack-ai#7211 beside `1507ba356`. ## Census: this stage's two areas, before and after **Instrument.** This is PR objectstack-ai#20226's instrument: REST `GET /repos/objectstack-ai/objectstack/issues/N` without following redirects, over every distinct in-repo number cited in the two areas. The population is: - bare `#N`, `objectstack#N`, `framework#N`, and the `pre-#N` / `post-#N` spellings, with N of 100 or more; - excluding the ordinal heads the citation gate declares (Prime Directive, `PD`, decision `batch`) and `summon`. **Controls.** The lit controls were `objectstack-ai#16862`, `objectstack-ai#16847` and `objectstack-ai#17698`. The dead controls were `objectstack-ai#16714`, `objectstack-ai#16715` and `objectstack-ai#16697`. They were probed at the start, after every 100 numbers and at the end: 6 checkpoints per run. They read 18 of 18 lit (200) and 18 of 18 dead (404) in both runs. | reading | tree | numbers probed | 200 | 404 | 301 or other | dead sites | kernel | contracts | lines | files | dead numbers | |---|---|---|---|---|---|---|---|---|---|---|---| | before | base `6a6a17b62`, probed 2026-09-27T20:14Z to 20:16Z | 445 | 398 | 47 | 0 | **190** | 106 | 84 | 180 | 45 | 47 | | after | head (probe at `eda5c6b27`, 2026-09-27T21:24Z to 21:26Z; source identical at the final head) | 415 | 398 | 17 | 0 | **30** | 18 | 12 | 29 | 14 | 17 | **Before, by class.** - 73 non-test docblock sites and 26 non-test line comments. - 22 test docblock sites and 39 test line comments. - 28 test string sites (describe and it titles, one assertion message). - 2 non-test strings. **After.** Only the 30 string sites remain. There are 0 comment sites. The head probe found no number newly dead since the base probe. PR objectstack-ai#20226's area table read kernel 105 and contracts 81 at an earlier base. This census reads 106 and 84 because it also counts the `pre-#N` / `post-#N` spelling: 3 dead sites. ## Per-number table The site counts give comments rewritten and strings left. The kind column says what each line now cites: - commit: the commit whose diff made the decision the line describes (read in each diff, not only in the subject); - ADR: the recorded decision; - dropped: the reason is kept in words and the number removed. | number | sites / files | rewritten / left (string) | anchor | kind | |---|---|---|---|---| | `objectstack-ai#5970` | 2/1 | 2/0 | `97e7e3caa`: `ActionSchema.visible` gains the boolean arm | commit | | `objectstack-ai#6083` | 1/1 | 1/0 | ADR-0122 phase 2, `53068c130`: find and findOne pinned to the parsed state | commit (ADR named) | | `objectstack-ai#6206` | 12/5 | 12/0 | `d7e0b4212`: maintainer ruling 2026-08-07, enforcement takes the full envelope with no per-site subset. One site cites `8e13ca876`, the route half that restored the five dropped fields. Two name the ruling in words where the same block already cites the sha | commit | | `objectstack-ai#6216` | 2/2 | 2/0 | `f586f1a89`: one ExecutionContext assembler, closed field-set pin | commit | | `objectstack-ai#6300` | 2/1 | 2/0 | `74155c735`: find and findOne accept the author state | commit | | `objectstack-ai#6361` | 1/1 | 1/0 | `90bbf2510`: notification-list `cursor` retired on both halves | commit | | `objectstack-ai#6362` | 3/2 | 3/0 | `b5404f496` (PR objectstack-ai#6900 beside it): `connector` keeps the ADR-0010 envelope | commit | | `objectstack-ai#6363` | 3/1 | 3/0 | `17d095413`: `unreadCount` counts the whole inbox, not the window | commit | | `objectstack-ai#6483` | 6/1 | 6/0 | ADR-0005 whitelist, executed by `ee58392e1`: nine unratified `allowOrgOverride: true` rolled back | commit (ADR named) | | `objectstack-ai#6511` (a PR) | 5/1 | 5/0 | `d7e0b4212`, its squash commit | commit | | `objectstack-ai#6523` | 7/3 | 6/1 | `aa4b90d9a`: sharing and approval enforcement take the full ExecutionContext | commit | | `objectstack-ai#6640` | 2/2 | 2/0 | `2ab1257c9`: `preserveAudit` is UPDATE-only, with a loud INSERT warn | commit | | `objectstack-ai#6723` (a PR) | 1/1 | 1/0 | `8ad609c69`, its squash commit: getObject's declared answer | commit | | `objectstack-ai#6725` | 6/2 | 4/2 | `1507ba356` (PR objectstack-ai#7211 beside it): facade object writes reach the map its reads use | commit | | `objectstack-ai#6745` | 2/1 | 2/0 | `7a5ef0008`: the getObject-equals-get conformance pin | commit | | `objectstack-ai#8715` | 3/3 | 3/0 | `2c86fe3ea`: the retirement pin form over `export-origins/` | commit | | `objectstack-ai#8794`, `objectstack-ai#8836` | 1/1 each | 1/0 each | `1850ebbb0`: measured the filter-reuse invariant and pinned it | commit | | `objectstack-ai#10194` | 7/2 | 6/1 | `2306a765c`: theme and analytics_cube bound at the /meta door | commit | | `objectstack-ai#10238` | 1/1 | 1/0 | none: whether cube authoring is live end to end is still its own measurement (`559041d39` leaves it open) | dropped | | `objectstack-ai#10338` | 2/1 | 1/1 | `d2619fd0c`: `ApiEndpoint.target` optional, the publish gate holds the requirement | commit | | `objectstack-ai#10485` | 5/2 | 5/0 | `35ad101bc`: `themes` carrier and ThemeSchema retired | commit | | `objectstack-ai#10627` | 3/2 | 3/0 | `be21955ba`, whose message records that controlled census | commit | | `objectstack-ai#10724` | 16/5 | 15/1 | `be21955ba`: nine dead `contributes` members tombstoned | commit | | `objectstack-ai#10726` | 6/3 | 4/2 | `bc56e1881`: `contributes.routes` retired, ruled Option B | commit | | `objectstack-ai#10812` | 2/2 | 2/0 | none: the cloud leg's clean close is kept as its date (2026-08-24, which `be21955ba` records) | dropped | | `objectstack-ai#11071` | 1/1 | 1/0 | `50fb191dc`: `os generate` file names derived from the registry, with the parity pin | commit | | `objectstack-ai#11330` | 2/1 | 1/1 | `a9ee98992`: trust-tier text states publish-gate-only enforcement | commit | | `objectstack-ai#11331` | 2/1 | 2/0 | none: an open "tracked on" pointer, and the enforce leg is unbuilt. The lines now say so | dropped | | `objectstack-ai#11332` | 9/2 | 8/1 | `dce5cd4f0`: three dead manifest containers retired | commit | | `objectstack-ai#11333` | 1/1 | 1/0 | `aaacf1d5c`: the commit that corrected the permissions half | commit | | `objectstack-ai#11350` | 1/1 | 1/0 | `ece4dad31`, which records the 2026-08-23 entry-nameability ruling | commit | | `objectstack-ai#11504` | 1/1 | 1/0 | `f90e82024`: `FLOW_INPUT_SCHEMA_INVALID` registered | commit | | `objectstack-ai#11741` | 5/2 | 4/1 | `b706af987`: `SendEmailInput.organizationId` | commit | | `objectstack-ai#11846` | 11/3 | 7/4 | `0c2334f6c`: preview mode retired | commit | | `objectstack-ai#12010` | 5/2 | 3/2 | none: that `ConnectionEngineLike` inventory is described in words | dropped | | `objectstack-ai#12165` | 1/1 | 1/0 | `b307bfd2a`: the glob-discovery disposition recorded beside `filePatterns` | commit | | `objectstack-ai#12248` | 19/4 | 15/4 | `8425c17cc`: the five ruled engine members adopted, getObject typed | commit | | `objectstack-ai#13135` | 9/7 | 8/1 | `9e0ba21a1`: paper customization protocol retired. ADR-0126 section 6 wall 4 stays cited where the line had it | commit (ADR named) | | `objectstack-ai#13608` | 2/1 | 2/0 | `fc9ba76a5`: eligibility held at redemption | commit | | `objectstack-ai#14143` | 2/2 | 2/0 | `f19475c0a`: the handler-face `ctx.recordLoadDenied` signal | commit | | `objectstack-ai#14192` | 4/1 | 0/4 | none rewritten: test titles only | (strings) | | `objectstack-ai#14722` | 2/1 | 2/0 | `23c72be3c`: pinned the measurement that refuted that card's premise | commit | | `objectstack-ai#16559` | 2/1 | 1/1 | `c7aca0dce`: ResumeFailureReport declared once | commit | | `objectstack-ai#16786` | 3/2 | 2/1 | `6059b29c0`: `updateById` declares its answer | commit | | `objectstack-ai#17147` | 5/2 | 3/2 | `aaacf1d5c`: the granted permission set is registered and refuses nothing | commit | | `objectstack-ai#18335` | 1/1 | 1/0 | ADR-0090 D10's 2026-09-16 note: an API key is a credential | ADR | Every cited sha resolves to exactly one commit, and every one is an ancestor of `origin/main` (38 shas, each `merge-base --is-ancestor` exit 0). ## The 30 string sites left as tokens - **Test titles and one assertion message (28 sites).** - contracts: `data-engine.test.ts` (4), `objectql-engine.test.ts` (2), `email-service.test.ts`, `resume-failure-report.pin.test.ts`, `scoped-context.test.ts` and `sharing-service.test.ts` (1 each). - kernel: `manifest-unknown-keys.test.ts` (4), `manifest.test.ts` (4), `preview-mode-retirement.test.ts` (4, one of them an assertion message), `plugin-runtime-tier-truthful-text.test.ts` (3), and 1 each in `metadata-customization-retirement.test.ts`, `metadata-type-api-registration.test.ts` and `metadata-type-schemas.test.ts`. - **Non-test strings (2 sites).** Two `why:` strings on rows of the exported `METADATA_ROUNDTRIP_CASES` table in `contracts/metadata-service-roundtrip-conformance.ts` (lines 194 and 202). They ship in the package as data. No runtime path prints them to an author: both test drivers title each case by its `id`. So they are not author-shown text in the form D sense, and they are not rewritten here. ## Mechanical guard: no code token moves The check is a comments-stripped token comparison, base `6a6a17b62` against the head. It uses the TypeScript parser's leaf tokens, so template literals are scanned in context, and it excludes JSDoc nodes. It ran over all 45 touched `.ts` files. - Real run: 60,827 base tokens, **0 files with a token change** (exit 0). - Comment-insertion control: 0 changes, as expected (exit 0). - Positive control (a declaration inserted): 1 file flagged (exit 1). - Positive control (one digit changed inside a test-title string): 1 file flagged (exit 1). ## Changeset This change ships bytes, so a `patch` changeset for `@objectstack/spec` is included; it says only that provenance comments were re-anchored. Measured on the built package: rewritten docblocks reach `dist/**/*.d.ts`. For example, `8425c17cc`, `17d095413`, `aa4b90d9a` and `fc9ba76a5` each appear in 1 declaration file, and the positive control, a pre-existing `notification-service` docblock sentence, appears in `dist/contracts/index.d.ts`. Rewritten comments also reach the bundled `.js`: `be21955ba` appears in 20 files. The `src/**/*.zod.ts` sources ship verbatim through `files[]`. ## Gates (head `ebbea0b6e`) - **Citation judging pass, run as CI runs it:** `pnpm check:issue-citations && node scripts/check-issue-citations.mjs` exits 0. It judged 23 citations: 21 resolve and 2 resolve as pull requests (the two convenience links). - **Doc authoring:** `pnpm check:doc-authoring` exits 0. - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 86 families, and all 86 exit 0. `--ran` reports 86 run, 0 NOT MEASURED, 0 unrun, and exits 0. Five of them (`check:doc-formula-expressions`, `check:dual-build-cjs-loads`, `check:i18n`, `check:lean-entry-closure`, `check:type-check-debt`) first exited 3, PREREQUISITE NOT MET. They exited 0 after a full `turbo run build` of `./packages/*` (71 tasks, exit 0, under the shared verify lock). - **Build, tests, typecheck:** - `pnpm --filter @objectstack/spec build` exits 0. - `vitest run src/kernel src/contracts` in `packages/spec`: 99 files and 1,608 tests pass. That covers all 24 touched test files and every test here that reads contract source text. - `pnpm --filter @objectstack/spec typecheck` exits 0, including `check:test-typecheck`. ## Acceptance notes - **Base.** The branch is 5 commits behind `origin/main` (`4e0f72e8d`). None of those commits touches `kernel/`, `contracts/` or any file here, so there was no merge. - **No author-shown string in scope.** Nothing in these two areas is form D's; the migration-entry fields belong to objectstack-ai#20233. - **Instrument note, not filed.** The citation gate reads `pre-#N` and `post-#N` as a cross-repository qualifier (`pre-`), so it never judges them. In these two areas that is 18 sites at base, 3 of them dead. This census counted them by hand. - **`framework#N` is NOT MEASURED as a repository.** `objectstack-ai/framework` answers 403 to this session's REST gate. The five numbers cited that way resolve 200 in this repository. None of them is in the dead set. - **Seat 2's pointer.** The 21 `objectstack-ai#13003` notes in `packages/spec/liveness/permission.json` are outside this stage, as the claim records. --- _Generated by [Claude Code](https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…ts that decided them (stage 2) (objectstack-ai#20342) Part of objectstack-ai#20234 Clause-②: no ## What changed This is stage 2 of the staged sweep. It covers `packages/spec/src/api/**` and nothing else, and it leaves out `packages/spec/src/api/rest-server.zod.ts`, which seat 2's objectstack-ai#20295 claim holds. Later stages cover the other areas, so this PR says `Part of`. Every comment or docblock site in scope that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123). That is **107 sites on 105 lines in 22 files, covering 30 numbers**. Each rewritten line now cites the commit in `origin/main` history that decided what the line describes, and it says in its own words what that commit decided. No ADR or ruling-record file in `docs/adr/` or `scripts/adr-anchors/` names any of the 32 dead numbers, so every anchor is a commit. Nothing was dropped: every number in scope had a deciding commit. One more comment site is left on purpose, because its number belongs to another repository (see Acceptance notes). Only comments changed. Every source file keeps its line count (112 lines out, 112 in), so no line citation into these files moves. Seven of those 112 lines carry no number; they are the second half of a sentence that had to be reflowed. No code token moves (see the guard below). The 34 string-literal sites that carry a dead number are tokens, so they are left as they were and listed below. **No citation number is added.** Every tracker number on an added line was already on the line it replaces. No PR number stands beside a sha. Two more kinds of file change, both mechanical: - **Regenerated reference pages.** Five of the rewritten docblock lines project into `content/docs/references/api/` (`dispatcher.mdx`, `error-code-ledger.mdx`, `plugin-rest-api.mdx`). `check:docs` proved those three pages stale, and `pnpm --filter @objectstack/spec check:generated --fix` regenerated only them. The diff is five lines, each the same substitution as its source line. - **A `patch` changeset** for `@objectstack/spec` (see Changeset below). ## Census: `api/`, before and after **Instrument.** This is stage 1's instrument. It sends REST `GET /repos/objectstack-ai/objectstack/issues/N` without following redirects, for every distinct in-repo number cited in `packages/spec/src/api`. The population is: - the citation gate's own `CITATION_RE`, kept when the qualifier is none, `objectstack`, `objectstack-ai/objectstack`, `framework`, `pre-` or `post-`; - N of 100 or more; - excluding the ordinal heads the gate declares, and `summon`. Each site is classified by the TypeScript parser as a line comment, a docblock or a string. **Controls.** The lit controls were `objectstack-ai#16862`, `objectstack-ai#16847` and `objectstack-ai#17698`. The dead controls were `objectstack-ai#16714`, `objectstack-ai#16715` and `objectstack-ai#16697`. They were probed at the start, after every 100 numbers and at the end, which is 5 checkpoints per run. They read 15 of 15 lit (200) and 15 of 15 dead (404) in both runs. | reading | tree | numbers probed | 200 | 404 | 301 or other | dead sites, all of `api/` | in scope | `rest-server.zod.ts` | in-scope lines | in-scope files | dead numbers in scope | |---|---|---|---|---|---|---|---|---|---|---|---| | before | base `21ab41041`, probed 2026-09-27T22:56Z to 22:58Z | 351 | 319 | 32 | 0 | **153** | 142 | 11 | 140 | 23 | 31 | | after | head `22a00c42d`, probed 2026-09-27T23:10Z to 23:12Z; `.ts` sources identical at the final head | 334 | 319 | 15 | 0 | **46** | 35 | 11 | 35 | 9 | 14 | **Before, in scope, by class.** 34 non-test docblock sites and 30 non-test line comments. 7 test docblock sites and 37 test line comments. 33 test string sites (describe and it titles). 1 non-test string. **After, in scope.** 34 string sites and 1 comment site remain. The comment site is `export-job-family-retirement.test.ts:25`, which names an objectui PR (see Acceptance notes). The head probe found no number newly dead since the base probe: 319 numbers answer 200 in both runs. PR objectstack-ai#20226's area table read `api` 153 at an earlier base, and this census reads the same 153 at `21ab41041`. Of those, 11 sites sit in `rest-server.zod.ts` (`objectstack-ai#14369` twice and `objectstack-ai#14691` nine times, all comments). They wait for objectstack-ai#20295 to land. `pre-#N` spellings do occur in `api/`: the at-tier review measured 15 sites on 15 lines in 13 files at the head, for example `discovery.zod.ts:913` `pre-objectstack-ai#4828`. All 15 numbers answer 200, so the gate's blind spot for that spelling (objectstack-ai#20330) hides no dead site in this stage. _(Corrected by the `domain:spec` seat 4 at 2026-09-28T00:48Z, from the at-tier review record 5861396181. The draft said that no such spelling occurs.)_ ## Per-number table The counts are in-scope sites and files. `rewritten / left` gives comment sites rewritten and string sites left. Every anchor was read in its diff or message, not only in its subject: it is the commit that made the change the line now describes, never a later refactor or a commit that merely mentions the number. | number | sites / files | rewritten / left | anchor: what it decided | |---|---|---|---| | `objectstack-ai#6037` | 5/2 | 3/2 | `18189983d`: declares `DataProtocol.validateData`, the validate-only operation, under objectstack-ai#4633 ruling D | | `objectstack-ai#6239` | 4/2 | 3/1 | `f549a0d4a`: retires `ViewProtocol` and its ten request/response schemas (ADR-0049, route 3) | | `objectstack-ai#6287` | 18/2 | 17/1 | `84c86fb45`: `preview` and `trial` fold to `sandbox` by declaration, and the fold table is typed total over `EnvironmentType` | | `objectstack-ai#6306` | 1/1 | 1/0 | `fec784863`: the direct-mount routes read the one API base | | `objectstack-ai#6361` | 5/3 | 4/1 | `90bbf2510`: the notification-list `cursor` is retired on both halves (maintainer ruling 2026-08-07, Option A) | | `objectstack-ai#6363` | 3/2 | 3/0 | `17d095413`: `unreadCount` counts the whole inbox, not the window | | `objectstack-ai#6704` | 4/1 | 3/1 | `c3f491626`: `runAutomations` declares the default the import route applies, with the agreement pin | | `objectstack-ai#8885` | 2/1 | 2/0 | `30b1c636a`: registers the nine REST wire codes that sweep found | | `objectstack-ai#9740` | 3/1 | 2/1 | `11b779e0f`: declares `getMetaItemLayered`. The two cross-references to its test block now name the block by member | | `objectstack-ai#9741` | 23/2 | 16/7 | `2a29caa53`: records the 2026-08-18 maintainer ruling. `previewDrafts` and `state` are declared, and `environmentId` stays transport-level | | `objectstack-ai#9934` | 4/4 | 4/0 | `79c46da90`: the producer-side `userMessage` channel | | `objectstack-ai#10264` (objectui) | 1/1 | 0/0 | not this repository's number: see Acceptance notes | | `objectstack-ai#10330` | 3/1 | 1/2 | `b9e9227e3`: declares `mappingName` on `ImportRequestSchema` | | `objectstack-ai#10338` | 4/2 | 3/1 | `d2619fd0c`: `ApiEndpoint.target` is optional, and the publish gate holds the flow requirement | | `objectstack-ai#10726` | 2/2 | 2/0 | `bc56e1881`: retires `contributes.routes`, ruled Option B (stage 1's anchor too) | | `objectstack-ai#11006` | 12/2 | 10/2 | `cccbe51bf`: declares `publishMetaItem` under the 2026-08-22 maintainer ruling, option B | | `objectstack-ai#11453` | 1/1 | 1/0 | `1a47a5368`: `ack()` refuses a row that is not `in_flight` | | `objectstack-ai#11504` | 4/2 | 2/2 | `f90e82024`: registers `FLOW_INPUT_SCHEMA_INVALID`, the contract half (stage 1's anchor too) | | `objectstack-ai#11846` | 1/1 | 1/0 | `0c2334f6c`: the preview-mode retirement, whose test states the same assertion-set reasoning (stage 1's anchor too) | | `objectstack-ai#11858` (a PR) | 1/1 | 1/0 | `1a47a5368`, its squash commit: `ack()` takes the shared `DELIVERY_NOT_ELIGIBLE` spelling | | `objectstack-ai#11859` | 2/1 | 2/0 | `d9cf78eaa`: `ack()` binds the claim credential in its compare-and-set | | `objectstack-ai#12194` | 1/1 | 1/0 | `311433f6b`: declares the item-name grammar and refuses it loudly at the publish door | | `objectstack-ai#13135` | 3/2 | 3/0 | `9e0ba21a1`: retires the paper metadata-customization protocol (stage 1's anchor too) | | `objectstack-ai#13197` | 1/1 | 1/0 | `56c093c4d`: the in-memory driver enforces field-level `unique` | | `objectstack-ai#14474` | 1/1 | 1/0 | `df657d9df`: the install-time namespace conflict refusal carries an ADR-0112 envelope | | `objectstack-ai#14691` | 16/1 | 4/12 | `b3a63d32c`: retires the ten inert `RestServerConfig` keys. All 16 sites are in `rest-server.test.ts`; the 9 in `rest-server.zod.ts` are out of scope | | `objectstack-ai#14723` | 1/1 | 1/0 | `65846bc46`: lands the 2026-09-03 maintainer ruling, so a unique-constraint refusal has one wire spelling, `UNIQUE_VIOLATION`, on every route | | `objectstack-ai#14748` | 2/2 | 2/0 | `92b5d7f00`: registers `NAMESPACE_CONFLICT` (its diff wrote the row this line glosses) | | `objectstack-ai#16649` | 12/2 | 11/1 | `613bfbd3d` for 9 sites: registers the fourteen remaining `door: 'none'` codes. `44c917a47` for 2 sites: widens the vocabulary gate's face to every published package and retires `boot-refusal` (each of its diffs wrote the line it now anchors) | | `objectstack-ai#17058` | 1/1 | 1/0 | `94c930248`: parses the dataset-query selection at the door, with its leniency sweep | | `objectstack-ai#19307` | 1/1 | 1/0 | `8f6d83147`: the `sys_permission_set` duplicate-name refusal carries `UNIQUE_VIOLATION` | Every cited sha resolves to exactly one commit (`git rev-parse --disambiguate`, count 1), and every one is an ancestor of the base (`merge-base --is-ancestor`, exit 0). That is 30 distinct shas. Two wordings to check, both true of their commit: - `error-code-ledger.zod.ts:919`: 「the contract review that passed commit 1a47a53 ruled option B」. The review record sat on PR objectstack-ai#11858, which answers 404 today. The line keeps that review's ruling as stated before and names the commit that landed it. - `discovery.zod.ts:291`: 「route B toward the single API base that commit fec7848 gave the direct-mount routes」. objectstack-ai#6633 is live and stays, and the dead goal it pointed at is now named by the commit that delivered it. ## The 34 string sites left as tokens - **Test titles (33 sites).** `protocol.test.ts` 12, `rest-server.test.ts` 12, `export.test.ts` 3, `error-code-ledger.test.ts` 2, `validate-data.test.ts` 2, and 1 each in `discovery.test.ts` and `endpoint.test.ts`. - **Non-test string (1 site).** `error-code-ledger.zod.ts:1692`, the `reason` of the `FLOW_INPUT_SCHEMA_INVALID` row in the exported `PROVENANCE_WAIVERS` table (it cites `objectstack-ai#11504`). It ships in the package as data. The one reader, `scripts/check-error-code-provenance.ts`, checks the table and never prints a `reason` to an author. So it is neither a comment nor author-shown text in the form D sense, and it is not rewritten here. No author-shown text was found in `api/`: nothing here is objectstack-ai#20233's form D. ## Mechanical guard: no code token moves The check is a comments-stripped token comparison, base `21ab41041` against head `22a00c42d` (the later commits add only the changeset and the regenerated pages). It uses the TypeScript parser's leaf tokens, so template literals are scanned in context, and it excludes JSDoc nodes. It ran over all 22 touched `.ts` files. - Real run: 88,201 base tokens, **0 files with a token change** (exit 0). - Comment-insertion control: 0 files changed, as expected (exit 0). - Positive control (a declaration appended): 1 file reads DIFFER (exit 1). - Positive control (one digit changed inside a `rest-server.test.ts` test-title string): 1 file reads DIFFER (exit 1). ## Changeset This change ships bytes, so a `patch` changeset for `@objectstack/spec` is included. It says only that the provenance comments were re-anchored. Measured on the built package: 8 of the touched sources are `src/**/*.zod.ts`, which `files[]` ships verbatim. The rewritten docblocks also reach `dist`: `2a29caa53`, `cccbe51bf`, `84c86fb45`, `613bfbd3d` and `90bbf2510` each appear in 1 declaration file, and `613bfbd3d` and `79c46da90` each appear in 6 bundled `.js` files. The positive control, a pre-existing `protocol.zod.ts` docblock sentence, appears in `dist/api/index.d.ts`. ## Gates (head `24d9fba68`) - **Citation judging pass, run as CI runs it:** `pnpm check:issue-citations && node scripts/check-issue-citations.mjs` exits 0. The self-test passes 73 cases in 7 batteries. The live run judged 13 citations across 8 files, and all 13 resolve. These are the live numbers left on changed lines, such as objectstack-ai#4633, objectstack-ai#4828, objectstack-ai#12004, objectstack-ai#11679 and objectstack-ai#16404. - **Doc authoring:** `pnpm check:doc-authoring` exits 0. - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at the final head derived 111 families, and all 111 exit 0. `--ran` reports 111 run, 0 NOT MEASURED, 0 unrun, and exits 0. - At the earlier head, before the reference pages were regenerated, the list held 87 families. `check:docs` exited 1 there; that is what proved the three pages stale. - Four gates (`check:doc-formula-expressions`, `check:dual-build-cjs-loads`, `check:lean-entry-closure`, `check:type-check-debt`) first exited 3, PREREQUISITE NOT MET. They exit 0 after a full `turbo run build` of `./packages/*` (71 tasks, exit 0, under the shared verify lock). - **Build, tests, typecheck and lint:** - `pnpm --filter @objectstack/spec build` exits 0. - `vitest run --maxWorkers=2 src/api` in `packages/spec`: 47 files and 1,518 tests pass. That covers all 13 touched test files. - The three spec script suites that read `api/` source text (`check-error-code-provenance`, `file-description`, `schema-index`) pass: 3 files, 144 tests. - `pnpm --filter @objectstack/spec typecheck` exits 0, including `check:test-typecheck` (53 files, 255 errors, 142 pinned signatures held). - `eslint --no-inline-config --format json` over the 22 touched `.ts` files: 22 files, 0 errors, 0 warnings. All 22 are in eslint's own population (`isPathIgnored` false for each). The config never enables type-aware linting, so a comment edit here cannot move the verdict on any untouched file. The repo-wide `pnpm lint` is CI's run. ## Acceptance notes - **The objectui PR number.** `export-job-family-retirement.test.ts:25` reads 「objectui retired its side first (objectui#10247, merged as objectui PR objectstack-ai#10264)」. The number belongs to objectui's board, but the citation grammar reads `objectui PR objectstack-ai#10264` as a bare number of this repository, so the census counts it as dead here (it is 404 on this board). `objectstack-ai/objectui` answers 403 to this session, on both REST and the web page, so whether that PR is live is NOT MEASURED. The line is left unchanged. This is the same grammar family as objectstack-ai#20330's `pre-` / `post-` blind spot, a qualifier the grammar does not recognise, and it is named there, not filed. - **Base.** The branch is 2 commits behind `origin/main` (`d3958bac6`, read at 2026-09-28). Neither commit touches `packages/spec/src/api` or `content/docs/references/api`, and a no-driver `merge-tree` of the head onto `d3958bac6` exits 0. So there was no merge. - **objectstack-ai#20295's branch.** It edits `rest-server.test.ts` too, in hunks at base lines 114 to 136, 152 to 185 and 663 to 679. This PR's four comment edits there are at lines 198, 206, 266 and 371. A no-driver `merge-tree` of this head with that branch's head `2e575f156` exits 0. - **Surface.** The regenerated reference pages under `content/docs/references/api/` are the one set of files outside `packages/spec/src/api/**` besides the changeset. They are generator output projected from the rewritten docblocks, and the required `TypeScript Type Check` job reds without them. --- _Generated by [Claude Code](https://claude.ai/code/session_01CiCTczDo7tGhafXjf61dUJ)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
…its that decided them (stage 3) (objectstack-ai#20533) Part of objectstack-ai#20234 Clause-②: no ## What changed This is stage 3 of the staged sweep. It covers `packages/spec/src/data/**` and nothing else. It leaves out the files an open PR or an in-flight claim holds: `data-engine.zod.ts`, `data-engine.test.ts`, `hook.form.ts`, `analytics*.ts`, `cube-member-inner-name-retirement.test.ts`, `driver/turso.zod.ts` and `filter-subtree-provenance.ts`, as the claim names them. It also leaves out four files that open PRs started editing after the claim: `driver/turso.test.ts` (PR objectstack-ai#20504, objectstack-ai#20437's, opened 2026-09-28T20:08Z), `object.form.ts` (PR objectstack-ai#20519, objectstack-ai#20432's, 21:55Z), `object.zod.ts` (PR objectstack-ai#20521, objectstack-ai#20494's, 22:10Z) and `filter-logic-conformance.ts` (PR objectstack-ai#20523, objectstack-ai#20444's, 22:39Z). See Acceptance notes. Later stages cover the other areas, so this PR says `Part of`. Every comment or docblock site in scope that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123). That is **163 sites on 161 lines in 44 files, covering 40 numbers**. Each rewritten line now cites the commit in `origin/main` history that decided what the line describes, and it says in its own words what that commit decided. No ADR or ruling-record file in `docs/adr/` or `scripts/adr-anchors/` records the decision behind any of the 43 dead numbers in scope. ADR-0104 names objectstack-ai#12380 only as a reference, and ADR-0055 states the rule that objectstack-ai#8772's ruling enforced, not the ruling itself. So every anchor is a commit: **38 distinct shas**. One number was dropped rather than anchored: objectstack-ai#17286, a tracking card that recorded an axis as undecided, under which no commit landed. The sentence keeps its reason in words. Three comment sites in scope are left on purpose (see Acceptance notes). Two are the `[objectstack-ai#6259]` marker in `api-derivation.ts:163`, which a test string reads, and the test comment that names that marker. The third is `field.zod.ts:370`, whose `objectstack-ai#6111` is objectui's number. Only comments changed. Every source file keeps its line count (174 lines out, 174 in, over 45 files), so no line citation into these files moves. Thirteen of those 174 lines held no dead citation. Eleven are the other half of a sentence that had to be reflowed or rewritten. One is a table header (`value-roundtrip-conformance.ts:20`, 「card」 to 「card or commit」, because its row now holds a commit). One is `api-derivation.ts:164`, which now carries the `[objectstack-ai#6259]` sentence's commit. No code token moves (see the guard below). The 41 string-literal sites that carry a dead number are tokens, so they are left as they were and listed below. **No citation number is added.** Every tracker number on an added line was already on the line it replaces. No PR number stands on an added line. Two more kinds of file change, both mechanical: - **One regenerated reference page.** Two of the rewritten docblock lines (`feed.zod.ts:15`, `:18`) project into `content/docs/references/data/feed.mdx`. `check:docs` proved that page stale, and `pnpm --filter @objectstack/spec check:generated --fix` regenerated only it. The diff is two lines, each the same substitution as its source line. No page a held file projects into (`analytics.mdx`, `data-engine.mdx`, `hook.mdx`, `driver-turso.mdx`) moved. - **A `patch` changeset** for `@objectstack/spec` (see Changeset below). ## Census: `data/`, before and after **Instrument.** This is the instrument of stages 1 and 2. It sends REST `GET /repos/objectstack-ai/objectstack/issues/N` without following redirects, for every distinct number cited in `packages/spec/src/data`. The population is: - the citation gate's own exported `CITATION_RE` and `NON_CITATION_HEADS`, kept when the qualifier is none, `objectstack`, `objectstack-ai/objectstack`, `framework`, `pre-` or `post-`; - widened here to the capitalised spellings of those qualifiers (`Pre-`, `POST-`, `Framework`: 7 sites, one of them dead), which stage 2's case-sensitive set did not read; - N of 100 or more, excluding `summon` heads. Each site is classified by the TypeScript parser as a line comment, a docblock, a block comment or a string. **Controls.** The lit controls were `objectstack-ai#16862`, `objectstack-ai#16847` and `objectstack-ai#17698`. The dead controls were `objectstack-ai#16714`, `objectstack-ai#16715` and `objectstack-ai#16697`. They were probed at the start, after every 100 numbers and at the end. They read 24 of 24 lit (200) and 24 of 24 dead (404) over 8 checkpoints in both runs. | reading | tree | numbers probed | 200 | 404 | 301 or other | dead sites, all of `data/` | in scope | excluded (held files) | in-scope lines | in-scope files | dead numbers in scope | |---|---|---|---|---|---|---|---|---|---|---|---| | before | base `9bf5e67af`, probed 2026-09-28T19:32Z to 19:36Z | 618 | 571 | 47 | 0 | **240** | 207 | 33 | 204 | 47 | 43 | | after | head `96fd49caa2`, probed 2026-09-28T23:19Z to 23:23Z | 600 | 571 | 29 | 0 | **77** | 44 | 33 | 43 | 16 | 21 | **Before, in scope, by class.** 92 non-test docblock sites and 13 non-test line comments. 16 test docblock sites and 45 test line comments. 39 test string sites. 2 non-test string sites. **After, in scope.** 41 string sites and 3 comment sites remain, all three deliberate. The head probe found no number newly dead since the base probe: the same 571 numbers answer 200. PR objectstack-ai#20226's area table read `data` 239 at an earlier base; this census reads 240 at `9bf5e67af`. The 33 excluded sites sit in `object.zod.ts` (15), `analytics.zod.ts` (3), `analytics-strictness-batchd.test.ts` (2), `analytics-date-range-two-bound-window.test.ts` (1), `driver/turso.zod.ts` (2), `driver/turso.test.ts` (3), `filter-subtree-provenance.ts` (3), `filter-logic-conformance.ts` (3) and `object.form.ts` (1). `data-engine.*` and `hook.form.ts` carry none. ## Per-number table The counts are in-scope sites and files at the base. `rewritten / left` gives comment sites rewritten and sites left. Every anchor was read in its diff or message, not only in its subject: it is the commit that made the change the line now describes, and its own diff or message names the number it replaces. | number | sites / files | rewritten / left | anchor: what it decided | |---|---|---|---| | `objectstack-ai#6111` (objectui) | 1/1 | 0/1 | objectui's number, left: see Acceptance notes | | `objectstack-ai#6259` | 5/2 | 1/4 | `6968885ef`: retires the producer-less `batch: 'bulk'` row of `DATA_ACTION_TO_API_OPERATION` and the prose calling `batch` a runtime action. The marker and 2 test strings stay (see Acceptance notes) | | `objectstack-ai#6345` | 18/5 | 17/1 | `e2798fab7`: one driver vocabulary; both boot hosts read the shared table; `mongo` to `mongodb`; turso a builtin; the fork-1 and fork-2 refusals | | `objectstack-ai#6571` | 10/2 | 8/2 | `2f3e79351`: `$between` endpoints accept the ISO/clock strings the platform produces, as a bare string (rider ①) | | `objectstack-ai#8495` | 9/2 | 6/3 | `4bfe1a539`: refuses `${…}` placeholders in memory `persistence.path` / `persistence.key` at publish | | `objectstack-ai#8656` | 1/1 | 0/1 | a test title only | | `objectstack-ai#8696` | 20/8 | 17/3 | `90a12fb18`, the card's mongodb arm: a bound secret rides beside an unmodified url as MongoClient `auth`. Its own pins carry the multi-host form `new URL()` cannot parse and the bound secret outranking `options.auth` | | `objectstack-ai#8772` | 3/2 | 3/0 | `75b7c240a`: Direction 2 of the 2026-08-16 maintainer ruling. The builder forces `required: true` on a `master_detail` under `controlled_by_parent`, and raw parse stays tolerant. ADR-0055 stays cited beside it | | `objectstack-ai#8778` | 1/1 | 1/0 | `7901b2dd2`: stamp-only `tenancy.organizationField`, declared by `sys_api_key` | | `objectstack-ai#8794` | 2/1 | 2/0 | `1850ebbb0`: corrects the reuse-safety claim on the filter-subtree mark from the survey's measurement, and routes a mechanism change to a spec-seat ruling (stage 1's anchor too) | | `objectstack-ai#8836` | 2/1 | 2/0 | `1850ebbb0`: the same commit, which pins the invariant (one line carries both numbers) | | `objectstack-ai#8873` | 6/3 | 6/0 | `096106522`: a bound `credentialsRef` reaches the postgres server on the DSN branch. Its diff records that `pg` sends a password only when the server asks | | `objectstack-ai#8874` | 1/1 | 1/0 | `d70428ae7`: a declared mysql `ssl` reaches `mysql2` as its own TLS options object, because `mysql2` rejects a bare boolean | | `objectstack-ai#8876` | 9/5 | 6/3 | `d634e665b`: exports `urlUserinfoUsername`, and its diff states the asymmetry that a username is not credential material | | `objectstack-ai#9040` | 20/6 | 14/6 | `24206416a`: refuses a credential in the mongo options passthrough at publish, and redacts the passthrough secret paths on read | | `objectstack-ai#9041` | 22/2 | 17/5 | `d491625c1`: refuses a bound `credentialsRef` with a user-less mongo `config.url`, with the triage's fences | | `objectstack-ai#10165` | 5/1 | 1/4 | `801296050`: `ttl.onlyWhen` with the canonical null predicate (maintainer ruling 2026-08-20, option A) | | `objectstack-ai#10274` | 1/1 | 1/0 | `d1ba685ec`: re-measures the objectui pin citations and gates the class | | `objectstack-ai#10329` | 6/2 | 6/0 | `15d58dbf1`: retires the import lookup transform's steering params (ADR-0049) | | `objectstack-ai#10347` | 2/1 | 2/0 | `530c1df65`: the Archiver honours a declared `ttl` (maintainer ruling 2026-08-20) | | `objectstack-ai#10527` | 2/1 | 1/1 | `5649efbf9`: refuses a diverging retention + ttl + archive triple at parse time | | `objectstack-ai#11065` | 7/3 | 5/2 | `20950404c`: a boolean aggregand counts as 1 or 0 in `avg` and `sum`, the first face aligned. No commit message names the card; this is where the number first entered the tree | | `objectstack-ai#11195` | 3/1 | 2/1 | `b37231883`: `UserActionsConfigSchema` adopts `group` / `hideFields` / `rowColor` | | `objectstack-ai#11215` | 1/1 | 1/0 | `42a117b88`: documents `NoSQLIndexSchema.unique`'s deliberate scope-vocabulary omission | | `objectstack-ai#11350` | 1/1 | 1/0 | `ece4dad31`: records the 2026-08-23 maintainer ruling on entry nameability (stage 1's anchor too) | | `objectstack-ai#11408` | 2/1 | 1/1 | `f11fc61c5`: declares `editMode` (maintainer ruling 2026-08-24) | | `objectstack-ai#11507` | 5/2 | 5/0 | `88b9d749a`: declares `sys_activity.type` an open, author-extensible vocabulary (maintainer ruling 2026-08-24, direction 4) | | `objectstack-ai#11658` | 1/1 | 1/0 | `1a6a19c31`: opens `RecordActivityProps.types` to author-contributed kinds | | `objectstack-ai#12380` | 4/2 | 4/0 | `4045b954d`: makes the SQLite `Field.json` codec injective; its message carries the measured boundary | | `objectstack-ai#12868` | 1/1 | 0/1 | a test title only. Its comment site sits in `object.form.ts`, now held by PR objectstack-ai#20519; its deciding commit is `c459da6bc` (see Acceptance notes) | | `objectstack-ai#13156` | 1/1 | 1/0 | `fd289be45`: strips tracker ids from function-declaration-built refusal prose (the card's A half) | | `objectstack-ai#13644` | 3/2 | 2/1 | `34ce8e7db`: declares `ctx.referentialFieldClear` on `HookContextSchema` | | `objectstack-ai#14426` | 2/2 | 1/1 | `40a44b91b`: the undefined-comparand refusal prescribes the null predicate by its ruled spellings, position-safe | | `objectstack-ai#14676` | 1/1 | 1/0 | `13c48c2a5`: retires `connector.errorMapping`; its test states the same assertion-set reasoning | | `objectstack-ai#16126` | 2/2 | 2/0 | `859ded3ec`: refuses a whitespace-only `reference` on lookup / master_detail | | `objectstack-ai#16685` | 4/2 | 4/0 | `ed7243d52`: accepts boolean / toggle for sum / avg / min / max (decision batch objectstack-ai#80) | | `objectstack-ai#16867` | 3/2 | 2/1 | `0ee32edef`: `notNull` / `not_null` prescribe `storage.notNull`, not `required` | | `objectstack-ai#17014` | 3/2 | 2/1 | `80aef8032`: the one-day date-range presets prescribe a one-day window, and the table states its end-token convention | | `objectstack-ai#17286` | 1/1 | 1/0 | dropped: a tracking card with no landing. The sentence now says the card is gone and to measure `driver-memory` for the open set | | `objectstack-ai#17348` | 1/1 | 1/0 | `51efbf116`: pins the `driver-memory` temporal text-operator divergence by name in that driver's conformance suite | | `objectstack-ai#17590` | 1/1 | 1/0 | `e04a0aff2`: `$contains` on a JSON column is a per-dialect membership test (director-seat ruling 2026-09-12) | | `objectstack-ai#18012` | 8/3 | 7/1 | `176b03582`: `$between` requires two non-blank endpoints (decision batch objectstack-ai#146 item 5, letter A) | | `objectstack-ai#19377` | 6/2 | 6/0 | `a60c913de`: refuses a `{ $field }` reference as a `$between` endpoint at the runtime filter door | Every cited sha matches exactly one commit (`git rev-parse --disambiguate`, count 1), and every one is an ancestor of the base (`merge-base --is-ancestor`, exit 0). That is 38 distinct shas. Wordings to check, each true of its commit: - `datasource.zod.ts:352` names only the card's mongo arm (`90a12fb18`) for "the defect class … closed", because the paragraph is about mongo. The card's mysql arm (`72050cc47`) is not cited anywhere in this stage. - `datasource.zod.ts:354`: 「the triage's, as commit d491625 landed them」. `d491625c1`'s message lists the fences as "per triage". - `filter.zod.ts:1021-1025`: the `objectstack-ai#17286` pointer becomes 「was measured on a tracking card … That card is gone: measure `driver-memory` for the open set, ⛔ not this text.」 The warning that this paragraph is not the authority is kept. ## The 41 string sites left as tokens - **Test titles and test-code strings (39 sites).** `driver/driver-credential-refusal.test.ts` 14, `object.test.ts` 6, `datasource-credential-redaction.test.ts` 3, `driver/driver-placeholder-refusal.test.ts` 3, `filter.test.ts` 3, `api-derivation.test.ts` 2 (the `split('[objectstack-ai#6259]')` literal and its message), `field.test.ts` 2, and 1 each in `date-range-presets.test.ts`, `driver/postgres.test.ts`, `field-rows-option-description.test.ts`, `filter-comparand-type.test.ts`, `hook.test.ts` and `object-strictness-batch20.test.ts`. - **Non-test strings (2 sites).** `aggregation-conformance.ts:398` and `:407`, the `note` of two exported `AGGREGATION_CASES` rows (`objectstack-ai#11065`, `objectstack-ai#11151`). They ship as data. Their only readers are driver conformance suites, which print a `note` as the assertion message when a case fails, to a driver developer and never to a metadata author. So they are neither comments nor form D author-shown text. This is the same disposition stage 1 gave the two `why` strings and stage 2 the `PROVENANCE_WAIVERS` reason. No author-shown text in `data/` carries a dead number, so nothing here is objectstack-ai#20233's form D. ## Mechanical guard: no code token moves The check compares leaf tokens with comments stripped, base `9bf5e67af` against head `96fd49caa2`. It uses the TypeScript parser's leaf tokens, so template literals are scanned in context, and it excludes JSDoc nodes. It ran over all 45 touched `.ts` files. - Real run: 140,379 base tokens, **0 files with a token change** (exit 0). - Comment-insertion control: 0 files changed, as expected (exit 0). - Positive control (a declaration inserted into `feed.zod.ts`): 1 file reads DIFFER (exit 1). - Positive control (one digit changed inside the `split('[objectstack-ai#6259]')` string in `api-derivation.test.ts`): 1 file reads DIFFER (exit 1). ## Changeset This change ships bytes, so a `patch` changeset for `@objectstack/spec` is included. It says only that the provenance comments were re-anchored. Measured on the built package: 14 of the touched sources are `src/**/*.zod.ts`, which `files[]` ships verbatim. The rewritten docblocks also reach `dist`. `88b9d749a`, `e2798fab7` and `24206416a` each appear in 1 declaration file. `24206416a` appears in 20 bundled `.js` files and `2f3e79351` in 28. The positive control, a pre-existing `feed.zod.ts` docblock sentence, appears in `dist/data/index.d.ts`. ## Gates (head `96fd49caa2`) - **Citation judging pass, run as CI runs it:** `pnpm check:issue-citations && node scripts/check-issue-citations.mjs` exits 0. The self-test passes 73 cases in 7 batteries. The live run judged 11 citations across 25 files, and all 11 resolve. - **Doc authoring:** `pnpm check:doc-authoring` exits 0. - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at the final head derived 108 families, and all 108 exit 0. `--ran` reports 108 run, 0 NOT MEASURED, 0 unrun, and exits 0. (`check:i18n` was derived at the earlier heads from `object.form.ts`, and left the set when that file went back to base.) - At an earlier head, four gates first exited 3 (PREREQUISITE NOT MET) because the workspace was unbuilt: `check:doc-formula-expressions`, `check:doc-security-posture`, `check:skill-examples` and `check:docs-transcript-drift`. At the final head a full `turbo run build` of `./packages/*` ran first (71 tasks, exit 0, under the shared verify lock), and every gate exited 0 on its first run. - `check:generated` was run under the lock against that build: all 15 artifacts are up to date. - **Build, tests, typecheck and lint:** - `pnpm --filter @objectstack/spec build` exits 0. - `vitest run --maxWorkers=2 src/data` in `packages/spec` at the final head: 107 files and 3,517 tests pass (1 todo), covering every touched test file. - The 12 spec suites outside `src/data` that read `data/` source text pass at the final head: 12 files, 503 tests. These are `scripts/{file-description,root-index,skill-map-guards,strictness-ledger}.test.ts`, `src/api/api-entry-graph.pin.test.ts`, `src/contracts/scoped-context.test.ts`, `src/shared/{alias-integrity,evaluated-slot-population,retired-key-migrate-sentence}.test.ts`, `src/system/constants/platform-object-names.test.ts`, `src/type-alias-convention.pin.test.ts` and `src/ui/dashboard.test.ts`. - `pnpm --filter @objectstack/spec typecheck` at the final head exits 0, including `check:test-typecheck` (53 files, 251 errors, 138 pinned signatures held). - Lint, as a proven narrowing at the final head: `eslint --no-inline-config --format json` over the 45 touched `.ts` files gives 45 files, 0 errors and 0 warnings. All 45 are in eslint's own population (`isPathIgnored` is false for each). `eslint.config.mjs` never enables type-aware linting (no `parserOptions.project`, which its own line 328 states), so a comment edit here cannot move the verdict on any untouched file. The repo-wide `pnpm lint` is CI's run. ## Acceptance notes - **The `[objectstack-ai#6259]` marker.** `api-derivation.test.ts:236` splits `DATA_ACTION_TO_API_OPERATION`'s TSDoc on the literal `[objectstack-ai#6259]`, and a test string may not change here. So the marker line `api-derivation.ts:163` is byte-identical to the base, and the test comment at `:232` that names the marker stays too. The sentence's deciding commit sits on the next line instead: 「(both by commit 6968885)」. A first attempt wrote the commit onto the marker line itself. The diff-scoped `check-issue-citations` then read the kept `objectstack-ai#6259` as an added citation and exited 1, so it was moved one line down (commit `b93f08f8d0`). - **objectui's `objectstack-ai#6111`.** `field.zod.ts:370` reads 「objectui#6110 + objectstack-ai#6111 (section)」. The qualifier covers only the first number, so the citation grammar reads `objectstack-ai#6111` as this repository's (404 here). It is objectui's number: its introducing commit `f887e5249` writes `(objectui#6111)` in the same diff, and `objectstack-ai/objectui` answers REST 200 for objectstack-ai#6111 to this session (and for objectstack-ai#6110 and objectstack-ai#10264). objectui has no `refs/pull/6111/head`, so it is an issue there, not a PR. The line is left unchanged. This is objectstack-ai#20330's grammar family, the same as stage 2's `objectui PR objectstack-ai#10264`, and it is noted there, not filed. - **Capitalised qualifiers.** `CITATION_RE` classes `Pre-#N`, `POST-#N` and `Framework#N` (7 sites in `data/`) as cross-repo and never judges them. This census read them as this repository's. One was dead and is rewritten here (`object.test.ts:223`, `POST-objectstack-ai#10347`). This is the same objectstack-ai#20330 family as stage 1's `pre-` / `post-` finding. - **Four files held after the claim.** Each joined the exclusions and went back to the base bytes (hypothesis 2 of the dispatch). Each PR's hunks were disjoint from this PR's lines, but the dispatch's rule is file-level. - `driver/turso.test.ts`: PR objectstack-ai#20504 (objectstack-ai#20437's) opened at 2026-09-28T20:08Z and edits it. Its two comment sites (`:4`, `:58`, both `objectstack-ai#6345`) went back to blob `7fe99ebf9` in commit `86463ed0a1`. A no-driver `merge-tree` of that head with PR objectstack-ai#20504's head `5dfa45e9f` exits 0. - `object.form.ts`: PR objectstack-ai#20519 (objectstack-ai#20432's) opened at 21:55Z and edits it. Its one comment site (`:256`, `objectstack-ai#12868`, whose deciding commit is `c459da6bc`) went back to blob `60713e06f` in commit `3479600dda`. - `object.zod.ts`: PR objectstack-ai#20521 (objectstack-ai#20494's) opened at 22:10Z and edits one line at `:2123`. Its 15 comment sites (`objectstack-ai#8772`, `objectstack-ai#10165`, `objectstack-ai#10347`, `objectstack-ai#10527`, `objectstack-ai#11195`, `objectstack-ai#11408`, `objectstack-ai#13608`) went back to blob `befde04ca` in commit `96fd49caa2`. Their deciding commits are `75b7c240a`, `801296050`, `530c1df65`, `5649efbf9`, `b37231883`, `f11fc61c5` and `fc9ba76a5`, all read for this stage. - `filter-logic-conformance.ts`: PR objectstack-ai#20523 (objectstack-ai#20444's) opened at 22:39Z. Its 3 comment sites (`objectstack-ai#13195`) went back to blob `c9b32acba` in the same commit. Their deciding commit is `9dac1ae01`, with `PR objectstack-ai#13529` as the link. - **What stays for later stages.** - The 33 dead sites in the held files listed above. The later stage can reuse the deciding commits named for them here. - The 41 string sites and the 3 deliberate comment sites above. - The `data/` numbers that also appear in `packages/spec/src/migrations/**`. Those are objectstack-ai#20233's form D, or the migrations stage. - **The rung.** Several anchored changes also have ADR-0087 entries in `packages/spec/src/migrations`. Examples are `cbp-master-detail-required-forced` for objectstack-ai#8772, `filter-between-blank-endpoint-refused` for objectstack-ai#18012, the `datasource-*` entries for objectstack-ai#9040, objectstack-ai#9041 and objectstack-ai#8873, and the `mapping-lookup-params-removed` conversion for objectstack-ai#10329. This PR takes the commit rung, as stages 1 and 2 did, so it is precedent-consistent. The D3 id is the more durable in-repo record, if the ruling's first rung is later read to include those entries. - **The citation gate's reach.** It defers `packages/**/*.test.ts`, so 20 of the 45 touched `.ts` files never enter its judging population. The added-minus-removed count over the whole diff covers them: 0 numbers added. - **Base.** The branch is 22 commits behind `origin/main` (`1378ec7c0c`, read at 2026-09-29T00:18Z). Four of those commits touch `data/`, all in excluded files: objectstack-ai#20475's `hook.form.ts`, objectstack-ai#20487's `data-engine.*`, and, since this stage excluded them, PR objectstack-ai#20521's `object.zod.ts` (`9e1689f8e2`) and objectstack-ai#20444's `filter-logic-conformance.ts` (`fb386074f5`). None touches a file in this diff, and a no-driver `merge-tree` of the head onto `1378ec7c0c` exits 0. So there was no merge. The open-PR file lists were re-read at 00:18Z: 11 open PRs, none touching a file in this diff. --- _Generated by [Claude Code](https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
Fixes #19123
Clause-②: no
What changed
Five lines in
packages/spec/src/uicited two tracker numbers GitHub no longer serves (#16714,#16715: REST 404, no 301, re-probed today against lit controls). They are rewritten on ruling C+D (comment 5749154545 on this card): each line now anchors to the commit in this repository's history that decided it, and says in its own words what that commit decided, so a reader never needs the link.4df101c38)app.zod.ts:457(shipped as source)(#16714)4cfc93b802filtersdocblock states no precedence order because objectui's hand-written mirror copied one and accepted a combination the schema refusesapp.zod.ts:504(shipped as source)EXPORTED (#16714)4cfc93b802app-nav-target-exclusivity-export.test.ts:4[#16714]header tag4cfc93b802, with PR #16862 beside it as a convenience link onlyfiltersdocblock, move no accept setapp-nav-target-exclusivity-export.test.ts:243(#16714 ruling)4cfc93b802object-refinement-check-exports.test.ts:469(#16715)b37f0b1767, the diff that added the lineNo ADR, ruling docblock or
scripts/adr-anchors/entry records either decision (objectNavTargetExclusivityindocs/adrandscripts/adr-anchors: 0 files), so both take the commit-sha rung of C. The twoapp.zod.tslines are the two shipped-tarball lines the ruling puts under D first: they now carry no tracker number, only the lesson and a sha. Thepatchchangeset for@objectstack/specsays a docblock citation changed and nothing else.Prose, comments and one test title only. No assertion changes meaning and no accept set moves.
Premise, re-measured on
4df101c38packages/spec/scripts/manifest-prescription.ts:78, has no live target. That file andcheck-react-blocks-declaration-parity.tswere retired by28ce61260.git grepover the whole tree finds the three numbers on 5 lines, all in the table above, and#16697on 0.#16715has a durable in-repo object. Commitb37f0b1767added the very line that cited it, and its message records the lesson: "a residual hole in the pin, not a live shadowing".Census: the true clean-up scale (read-only, nothing swept)
Population. Every tracker-shaped token in
packages/spec/src/**(1,594 tracked files) that names this repository: bare#Nandobjectstack-ai/objectstack#N, with N of 100 or more. Ordinals (batch #,summon #,Directive #,item #and similar) and 3- or 6-digit colour literals are excluded. Cross-repo tokens (objectui#,cloud#,ui#) are counted separately.Instrument 1: the REST status of every number (a full census, not a sample)
GET /repos/objectstack-ai/objectstack/issues/Nwithout following redirects, 2026-09-27T11:13Z to 11:16Z, plus 5 fully-qualified numbers at about 12:05Z.Controls. They were re-probed at the start, after every 250 probes and at the end, 9 checkpoints in all. The lit controls
#16862,#16847and#17698answered 200 at 9 of 9. The dead controls#16714,#16715and#16697answered 404 at 9 of 9. So the channel stayed up for the whole run, and the 404s are real readings.The dead rate depends on the number's era (bare numbers):
Contamination bound. Five numbers are cited only as sibling-repo PRs, written bare (for example
objectui PRfollowed by the number). One of them,8887, is among the 404s, and8758is cited both ways. So the in-repo dead count is 170 to 172 out of 1,953 to 1,958.Cross-repo tokens.
objectui(183 distinct) andcloud(36) are NOT MEASURED: this session's REST gate answers 403 for both repositories.hotcrmanswered 200 for 7 of 7 (lit controlhotcrm#1961: 200).Instrument 2: who owns the squash commit
GET /repos/objectstack-ai/objectstack/commits/SHA/pullsfor every dead number that appears as a squash suffix inorigin/mainhistory (8,715 commits, back to 2026-06-22). 11 of the 172 do, and all 11 answer[]: the PR object is gone. Controls:b37f0b1767answers[16847]and1124c45641answers[19107](lit);7936b29ce5, the card's known-dead#16697, answers[]. The other 161 dead numbers carry no squash suffix. They were cards, not PRs, and this instrument does not reach them.Independent cross-check:
check-issue-citations --censusI ran the repository's own citation gate in census mode at about 12:02Z. The board frontier is 20,223 and the board size is 18,050, so 2,173 minted numbers (10.7%) are holes. Tree-wide there are 2,779 unresolvable sites, 664 of them in
packages/spec/src.On the gate's surface (non-test comment prose), the two instruments agree on 661 of those 664 sites. The 3 sites only the gate found use the
objectstack-ai/objectstack#Nspelling, which my first extraction pass missed; I probed them afterwards and they are included above. My 297 extra comment sites break down as 271 in test files (the gate's declared deferred surface) and 26re-charter #13135sites that the gate reads as an ordinal.What remains after this PR
On this head,
packages/spec/src/**still has 1,295 dead-cited sites on 1,277 lines in 327 files, citing 170 numbers. On the base it was 1,300 sites, 1,282 lines, 330 files and 172 numbers.By area: migrations 438, data 239, api 153, ui 107, kernel 105, contracts 81, system 38, conversions 24, shared 20, other 90.
Load-bearing share. I read a seeded random sample of 40 dead-cited lines. 37 of the 40 cite a ruling, a deliberate tolerance or exclusion, a retirement, or a cautionary measurement, which is the dispatch's definition of load-bearing. The other 3 are incidental: a bare
Refs, a label, a process note. Applied to 1,277 lines, that is roughly 1,100 to 1,200 load-bearing lines, a sweep the ruling keeps out of a single PR. None of them is rewritten here.The runtime-text slice is the D half.
os migrate metaprints each migration entry'sreplacement,why:(reason) andverify:(acceptanceCriteria) to the author (packages/cli/src/commands/migrate/meta.ts:523-525). Acrosspackages/spec/src/migrations/**, those strings hold 2,060 tracker-id sites (478 distinct numbers; 178 sites are dead).pnpm check:doc-authoringis green over all of them, for two reasons: its Rule 3 does not recognise those property positions, and its cross-package leg excludespackages/spec/src. I report this to the seat as a finding and do not fix it here.Every dead number still cited, as number and sites/files, in numeric order. Any line is recoverable with
git grep -non the number underpackages/spec/src.#59706/3 ·#603711/5 ·#60488/3 ·#60721/1 ·#60752/2 ·#608310/7 ·#60852/1 ·#61113/3#614810/6 ·#620614/7 ·#62162/2 ·#62381/1 ·#623910/6 ·#62595/2 ·#627613/2 ·#62792/2#628718/2 ·#63002/1 ·#63061/1 ·#634532/11 ·#636120/11 ·#63629/5 ·#636312/6 ·#64836/1#65117/3 ·#652311/5 ·#65271/1 ·#657110/2 ·#65732/2 ·#66043/2 ·#66053/1 ·#66402/2#67046/3 ·#67231/1 ·#67255/2 ·#67452/1 ·#84602/1 ·#849559/27 ·#86561/1 ·#869634/13#87144/2 ·#871547/24 ·#87589/6 ·#877211/5 ·#87781/1 ·#87945/3 ·#88364/3 ·#887310/6#88741/1 ·#887611/7 ·#88852/1 ·#88872/2 ·#904020/6 ·#904128/5 ·#97403/1 ·#974123/2#99339/2 ·#99344/4 ·#99724/2 ·#101657/2 ·#1019412/4 ·#102381/1 ·#102641/1 ·#102747/3#1032910/4 ·#103303/1 ·#103386/3 ·#103475/2 ·#1048543/23 ·#105273/2 ·#1062712/7 ·#1072447/20#1072615/9 ·#108126/5 ·#1092611/6 ·#1100615/3 ·#110657/3 ·#110711/1 ·#111662/1 ·#111955/3#112151/1 ·#1128410/4 ·#113282/2 ·#113302/1 ·#113312/1 ·#1133219/7 ·#113333/3 ·#113509/5#114083/2 ·#114531/1 ·#115045/3 ·#115078/4 ·#115132/2 ·#116586/3 ·#116932/2 ·#117033/2#117419/4 ·#117536/2 ·#117574/2 ·#1184630/10 ·#118581/1 ·#118592/1 ·#120105/2 ·#121442/1#121651/1 ·#121762/1 ·#121944/4 ·#122452/1 ·#1224817/4 ·#123804/2 ·#124936/2 ·#128689/6#129503/2 ·#1296110/2 ·#130313/2 ·#131091/1 ·#1313570/25 ·#131564/4 ·#131953/1 ·#131971/1#132187/2 ·#136085/2 ·#136443/2 ·#136701/1 ·#136723/2 ·#136811/1 ·#141432/2 ·#141621/1#141925/2 ·#143121/1 ·#143654/3 ·#1436924/13 ·#144192/2 ·#144262/2 ·#144741/1 ·#145262/2#146624/2 ·#1467622/10 ·#146867/2 ·#1469150/16 ·#147224/2 ·#147231/1 ·#147482/2 ·#149022/2#149192/2 ·#149961/1 ·#161262/2 ·#165592/1 ·#166263/3 ·#1664912/2 ·#166595/4 ·#166854/2#167863/2 ·#168642/2 ·#168673/2 ·#170143/2 ·#170581/1 ·#170811/1 ·#171243/3 ·#171475/2#172861/1 ·#173481/1 ·#175901/1 ·#1798713/2 ·#180031/1 ·#1801210/5 ·#181777/2 ·#183351/1#193071/1 ·#193778/4Gates (head
98edadd03)node scripts/pm/dispatch-gates.mjs --ranreports 83 derived, 79 run with exit 0, 4 NOT MEASURED and 0 unrun. The four exited 3 (PREREQUISITE NOT MET):check:doc-formula-expressions,check:dual-build-cjs-loads,check:lean-entry-closureandcheck:type-check-debt. Each needs other packages'dist/, and both attempts to take the shared verify lock for that build ended in queue-timeout (99). This is a declared narrowing: the diff changes comment and test-title text in one package and nothing those four gates read, and CI'sLint & Repo Gatesruns them.check-changeset-fixed,check:meta-url-spelling,check:spec-changes,check:authz-resolver,check:error-code-casing,check:filter-alias-parity) all exit 0.pnpm --filter @objectstack/spec buildexits 0. The two edited test files pass: 2 files, 141 tests.pnpm --filter @objectstack/spec typecheckexits 0.node scripts/check-issue-citations.mjs --base 4df101c38(the diff-scoped verdict) exits 0. The change adds one citation,#16862, and it answers 200.Acceptance notes
packages/spec/srcbeyond the five, in this PR. At the measured 1,277 lines, about 92% of them load-bearing, that is the sweep the ruling keeps out of one PR, so this PR measures and lists them and rewrites none.28ce61260. The live D population is the migration-entry text above.re-charter #Nas a non-citation, which hides 26 real citations of#13135. My own first extraction pass missed theowner/repo#Nspelling (3 sites).Generated by Claude Code