Repository navigation
Commit 1a6bc8e
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
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1558 | 1558 | | |
1559 | 1559 | | |
1560 | 1560 | | |
1561 | | - | |
1562 | | - | |
1563 | | - | |
1564 | | - | |
| 1561 | + | |
| 1562 | + | |
| 1563 | + | |
| 1564 | + | |
| 1565 | + | |
1565 | 1566 | | |
1566 | | - | |
1567 | | - | |
1568 | | - | |
1569 | | - | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
| 1571 | + | |
| 1572 | + | |
| 1573 | + | |
| 1574 | + | |
| 1575 | + | |
| 1576 | + | |
| 1577 | + | |
| 1578 | + | |
| 1579 | + | |
| 1580 | + | |
1570 | 1581 | | |
1571 | 1582 | | |
1572 | 1583 | | |
| |||
0 commit comments