Skip to content

Commit 1a6bc8e

Browse files
os-billclaude
andauthored
docs(spec): re-measure proof 4's two mislabelled census figures, each beside its population (#18863)
Fixes #18579 Clause-②: no Two census figures in the proof-4 prose of `packages/spec/scripts/build-schemas.ts` label a population they do not measure. Both are corrected, and both now carry their population — and the tree they were read on — in the same sentence, which is what the triage note on the card asked of whoever took it. ## The two figures **(1) The docblock's not-delivered rationale.** It said *"on the shipped graph 7 of the 8 defs in that state are unions"*. Measured: that state holds **9 keys on 4 defs**, and **3 of those 4 defs** are unions, carrying **7 of the 9 keys**. The 7 was the KEY count wearing the DEF label. **(2) The closing line of the same docblock**, which sent its reader to PR #18529's body *"for the census run"*. That body's census row labels *"defs resolving to exactly one declaration that names an undeclared key"* with **258** — but 258 is the count of defs resolving to exactly one declaration **whether or not it names anything**. The labelled population measures **147**. That row lives in a merged PR body and is not editable from here, so the docblock now records the census in the tree and tells its reader not to re-derive it from that body. The argument both figures support is unchanged — unions do dominate the not-delivered set (3 of 4 defs, 7 of 9 keys). Only the arithmetic moved. ## Re-measured on this head, not copied from the card The card's numbers were taken on branch `9e0324f807` and `packages/spec/src` has moved on `main` since, so nothing was copied. The whole census was re-derived with **this head's own verbatim `computeGuidanceRoutes`**: a byte-identical copy of `scripts/build-schemas.ts` (prefix proven equal by `git hash-object`: `0803422391…` on both) with a census block appended, run as the real generator so `zodByDefKey`, `generatedSchemas` and the declaration registry are the ones the gate itself sees. The copy was deleted before the first commit; it is in no diff. **Tree measured: `objectstack-ai/objectstack` at `88aa326deb`** — the merge base of this branch with `origin/main`. | population | count | |---|---| | emitted defs (`zodByDefKey`, = bundled `$defs`) | 1527 | | of those, emitted artifact carries `additionalProperties: false` | 1117 | | of those 1527, defs resolving to exactly one declaration (naming anything or not) | 258 | | of those 258, defs whose declaration NAMES a key the def does not declare | **147** | | keys those 147 defs are promised | 779 | | of those 779, keys the def delivers (`prescribed`) | 770 | | of those 779, keys not delivered (`declared-but-silent`) | **9** | | of those 9 keys, keys on `shared/RateLimitConfig` | 2 | | defs carrying a not-delivered key | **4** | | of those 4 defs, unions | **3** (`ui/ChartGroupBy`, `ui/ViewItem`, `ui/RecordHighlightsField`) | | of the 9 not-delivered keys, keys on those 3 union defs | **7** | | defs with an empty shape (excluded outright) | 6 | | declarations carrying an empty shape (what each of those 6 would answer to) | 9 | | defs whose match is ambiguous | 0 | | defs with no derivable shape | 304 | **What validates the instrument is the rest matching, not the conclusion agreeing.** Reproduced exactly against the card: 1117 · 258 · 147 · 779 · 770 · 9 · 2 · 6 · 9 · 0 ambiguous · 3-of-4 · 7-of-9. Drifted with `src`, as the card predicted: 1525 → **1527** emitted defs, 303 → **304** no-shape, 408 → **410** not-`additionalProperties`-false. Independent corroboration of the 1527/1538 pair from the generator's own summary line: `check:authorable-surface` prints `bundled schema: objectstack.json (1527 definitions)` / `Successfully generated 1538 schemas`. **Cross-check tying the partition to the gate's own function:** every one of the 779 promised (def, key) pairs the census derived was fed back through the head's verbatim `verdictFor` — **0** came back `none`. A replication that invented a pair the real lookup does not hold would show up there. ## Sequencing with PR #18861 PR #18861 (card #18578) repairs the `shared/RateLimitConfig` open-twin defect and therefore moves this exact partition (its author measures delivered 770 → 772, not delivered 9 → 7). It is **absent from the tree measured here**, proven twice: `git merge-base --is-ancestor 36adeca HEAD` exits 1 on a non-shallow checkout with a lit control leg (`88aa326deb` → exit 0), and the census itself still lists `shared/RateLimitConfig:keyBy` and `:store` as not-delivered, which is precisely the defect that PR removes. So both replacement sentences are written as readings of a **named commit** (`at 88aa326 that state held …`), not as claims about whatever `main` holds today. They stay true when #18861 lands; they become stale, visibly, with the commit that says so right there. The docblock also now tells its next reader that which defs sit in that state is a fact about the graph rather than a property of the proof — "closing an open door moves it" — and to re-measure rather than re-date. Nothing here waits on or depends on that branch. ## Not taken: the `delivers()` fixture The card's optional fourth item — a fixture for the `message`-includes leg, the one refusing a strict clone built without the declaration's error map — is **handed back, with a reason rather than a shrug**. Three routes exist and each is blocked by a rule this repo states out loud: 1. **A synthetic def on the shipped graph.** `packages/spec/src` is published (`files[]` carries `src/**/*.zod.ts`), so this ships a fake schema to consumers. 2. **A synthetic def in the test sandbox.** `build-schemas-check-mode.test.ts` builds each sandbox with `fs.symlinkSync` for `src` — its own comment says *"`src/` is the fixture's own, so the population a run observes is the repo's"*. A fixture def would have to be written into the real `src`, i.e. route 1. Copying `src` per sandbox instead is a structural change to a 4466-line harness. 3. **Exporting the leg for a unit test.** `delivers()` is a closure over module-level state, and that file's header rule is *no test-only seam*. So it is not a fixture-sized job; it is a restructuring, and the card is explicit that this PR should not become two things. Recommendation for whoever files it: route 2, as its own card, because it also unlocks fixtures for the other fail-closed legs. The census zero that defends the leg today is re-stated above with its tree, so the next reader can see what it rests on. ## Verification - `pnpm --filter @objectstack/spec build` — green (runs `gen:schema`, i.e. the edited generator, end to end) - `pnpm --filter @objectstack/spec typecheck` — green (all three legs: `tsc --noEmit`, `check:scripts-typecheck` which compiles the edited file, `check:test-typecheck`) - `pnpm --filter @objectstack/spec test` — 487 files / **14055 tests** passed - `pnpm --filter @objectstack/spec exec vitest run --project repo scripts/build-schemas-check-mode.test.ts` — 1 file / **85 tests** passed. This is the suite that spawns the edited generator, and it is **not** in the package's `pnpm test`: that script runs `--project local` only, and vitest's filter guard says so out loud when you aim the wrong project at the file. - `scripts/file-description.test.ts` + `scripts/def-key-collisions.test.ts` (`--project repo`) — 128 passed; these are the only other tests that read this script by name. - **53 gate families** derived by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` — 51 green. Two exit **3**, which is that gate's own NOT-MEASURED code and neither a pass nor a failure: `check:dual-build-cjs-loads` and `check:lean-entry-closure` both need a whole-repo `pnpm build` that this worktree does not carry. Neither can move on a comment in an unpublished script; CI builds fresh. - `pnpm lint` equivalent run whole, not narrowed: `npx eslint . --no-inline-config --format json` at `8f9a42d8a2` — **6846 files, 0 errors, 0 warnings**. - Control-byte self-scan over the edited file (`grep -naP` over the C0 range plus DEL) — no match; `pnpm check:nul-bytes` green. ## No changeset (`skip-changeset`) Nothing published moves. Measured rather than asserted: `@objectstack/spec`'s `files[]` is `dist · json-schema · liveness · prompts · llms.txt · README.md · src/**/*.zod.ts · CHANGELOG.md · api-surface · spec-changes.json` — **no `scripts/` entry** — and grepping every shipped path for `computeGuidanceRoutes` returns **0 hits**, against a lit positive control (`keySetMatches`, which is found in `dist/shared/index.js` and four more). The diff is comment-only inside that unpublished file, so the blast radius is the gate's next reader, not an author and not a consumer. --- _Generated by [Claude Code](https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent fb2bccf commit 1a6bc8e

1 file changed

Lines changed: 19 additions & 8 deletions

File tree

‎packages/spec/scripts/build-schemas.ts‎

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,15 +1558,26 @@ interface GuidanceRoutes {
15581558
* key in it, a union or pipe the probe cannot drive to a single door, or a refusal
15591559
* whose message does not carry the declared text — all read as "no evidence",
15601560
* never as "proved". ⛔ And the verdict for the second half says only THAT the
1561-
* prescription did not arrive, never WHY: on the shipped graph 7 of the 8 defs in
1562-
* that state are unions, where "the door is open" would be a guess this gate has
1563-
* not measured — the mistake this proof's first cut made about
1564-
* `additionalProperties` and must not repeat one layer down.
1561+
* prescription did not arrive, never WHY: at `88aa326deb` that state held 9 keys
1562+
* on 4 defs, 3 of those 4 defs unions carrying 7 of the 9 keys — for a union
1563+
* "the door is open" would be a guess this gate has not measured, the mistake
1564+
* this proof's first cut made about `additionalProperties` and must not repeat
1565+
* one layer down.
15651566
*
1566-
* Measured on the shipped graph at #18301 with THIS instrument — see the PR body
1567-
* for the census run: `integration/DataSyncConfig` has NO route (its shape is not
1568-
* a `strictObject` and nothing prescribes for `schedule`), so this proof does not
1569-
* reach the 2026-09-10 ruling that withheld that tombstone.
1567+
* Every count above is a reading of ONE tree — objectstack-ai/objectstack
1568+
* `88aa326deb`, where #18579 re-took all of them with THIS instrument — and each
1569+
* is written beside the population it counts: of the 1527 emitted defs, 258
1570+
* resolve to exactly one declaration, and 147 of those 258 name a key the def
1571+
* does not declare; those 147 defs promise 779 keys, of which 770 are delivered
1572+
* and the 9 above are not. Which defs sit in that last group is a fact about the
1573+
* graph at that commit and not a property of this proof — closing an open door
1574+
* moves it — so a later reader RE-MEASURES rather than re-dates these, and ⛔
1575+
* derives none of them from the #18301 PR body, whose census row gives the 147
1576+
* population the 258 count: a count wearing another population's label is the
1577+
* defect this docblock was corrected for.
1578+
* `integration/DataSyncConfig` has NO route (its shape is not a `strictObject`
1579+
* and nothing prescribes for `schedule`), so this proof does not reach the
1580+
* 2026-09-10 ruling that withheld that tombstone.
15701581
*/
15711582
function computeGuidanceRoutes(): GuidanceRoutes {
15721583
const shapeSignature = (shape: Record<string, unknown>): string =>

0 commit comments

Comments
 (0)