Repository navigation
docs(gates): record the #17242 re-census — the declined residual is a SPELLING population, not rot - #19733
Conversation
… SPELLING population, not rot `check-spec-docblock-symbol-anchors` declines every line citation naming no tracked file and enumerates them, but nothing said what those rows ARE. #17242 filed two questions as explicitly NOT MEASURED: the objectui cross-repo vs in-repo split, and how many would resolve under a spec-relative base. Both are measured here and kept as data, because this gate cannot re-derive them — the classification needs a sibling objectui checkout the gate is deliberately not given. - the residual grew 183 -> 467; swept with BOTH the old and the current resolver over the same tree, which return the identical 467, so the growth is population and not instrument drift - 463 of 467 name a file that really exists (408 in objectui, 55 here written package-relative); 4 bind in neither - zero live-tense defects: the four that bind nowhere are one retirement record and three dated re-reads at a named objectui pin - measured trap: repairing a package-relative citation's PATH alone makes it tracked and therefore JUDGED, turning this gate red — one repair was run against a single citation and restored `CENSUS_17065` is untouched and not restated; the scope call is unchanged. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude <noreply@anthropic.com>
|
reading at origin/main |
value |
|---|---|
root package.json |
@objectstack/spec-monorepo, private: true ⇒ publishes nothing |
package.json files under scripts/ |
0 ⇒ the file is inside no package directory |
manifests censused (packages/**, apps/**) |
77, of which 70 declare files[] |
escape hatches — a files[] entry beginning ../ or /, or naming scripts |
ZERO |
lit control — packages/spec's files[] on the same reader |
10 entries ⇒ the reader works, so the zero is a reading |
⇒ nothing in this PR can reach a published tarball. Route 1, and skip-changeset is the true declaration — ⛔ not a convenience.
Ruling D checked, ⛔ not assumed: the skip-changeset label is never applied to a PR that edits an existing changeset. Measured on this file list: zero .changeset/ files touched. ⇒ the ruling does not bar it here.
The re-run, because the label alone does not clear the red
Check Changeset ran before the label existed, and a labeled event spawns a run whose jobs skip — so nothing in the event graph re-judges the earlier red on its own. The seat re-ran the failed job in this same act, which is where the job's live label re-read makes attempt 2 green.
⛔ Not a flake re-run and ⛔ not spent against that budget: the gate's input changed after it ran.
Generated by Claude Code
…and pin the record F1 — the cross-repo reading named "objectui's main" with no sha, and a moving ref is not an anchor. Both sibling trees are data now, beside `measuredOn`: the `.objectui-sha` pin and objectui's main at the sha actually read, alongside the objectstack tree the sweep ran on. The two trees agree ROW BY ROW, not merely in the totals. F2 — the four-row "binds nowhere" cell was a sentence no reader could reconcile with the tree. The binding predicate is written out now (token, antecedent walk, resolution tiers, where it is basename-lenient, tie-break) and carried as data, and the cell is ENUMERATED with each row's coordinate, citation text, reason and hand-read tense. Re-measured under that stated predicate the split moves 408/55/4 to 409/53/5: it is stricter about directory-qualified tokens and walks comment blocks rather than whole files. The declared sensitivity with the directory fallback on is recorded beside it and moves exactly one row. F3 — `RECENSUS_17242` occurred once in the whole tree, its own definition, while `CENSUS_17065` thirty lines above is pinned five ways. A record nothing holds drifts from the code in silence, which is the defect class this corpus exists for. The self-test carries the re-census's arithmetic battery now, the sha forms, the sensitivity's invariants and a five-case exactness loop per enumerated row — 38 new cases, so the battery floor is raised from 64 to 102, the count the gate itself registered under a probe. The pins are internal to the record on purpose: the reading is frozen at the shas it names, so coupling a cell to the live tree would turn a historical record into a ratchet that reds on every unrelated spec docblock edit. Also adopts the review's sharpening on reproducibility: the binding split is re-runnable by any reader holding both checkouts, but the tense classifier exists nowhere in this repository, so nothing can re-derive the three tense totals — the record says that now, instead of "only an outside reading can". Gate behaviour delta is zero: 3437 anchors, 467 declined, 7 day-one residual, exit 0 before and after. Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx Co-authored-by: Claude <noreply@anthropic.com>
…y holds Round 2 shipped two sentences in this file that nothing held, and both were wrong about the tree they describe. 1. The via split read "188 of the 467 rows are bound that way and the other 279 carry their own path". The measured split is 276 own-path, 188 continuations that inherit a token, and 3 that inherit none and bind nowhere -- and 279 also contradicted `declinedByShape` twenty lines above (467 - 191 continuations = 276). The sentence is corrected and the three cells now live in `RECENSUS_17242.bindingVia`, held by two arithmetics: they exhaust `declinedCitations`, and the two antecedent cells are exactly the `continuation` shape count. `antecedentNoToken` is additionally held against the enumerated rows it names, which now carry a closed `via` vocabulary and must agree with their own `token`. 2. The token grammar's comment and its self-test case both said the longest-first alternation is what stops a `tsx` citation being truncated to `ts`. It is not: the pattern ends in a negative lookahead, so a `ts` arm fails on a `tsx` extension and the engine backtracks into the `tsx` arm. Measured both ways round -- a shortest-arm-first alternation returns the IDENTICAL token, and removing the lookahead while keeping longest-first truncates nothing; only removing BOTH truncates. The comment now names the lookahead, and that one case is replaced by three that pin it: its presence at the end of the pattern, the untruncated token it produces, and the order-independence itself -- with a case that refuses to compare a pattern with itself. Two smaller corrections of the same class: - Case 8's "one pinned five ways" counted five `check()` calls where seven reference `CENSUS_17065`. A count of pins is itself an unheld number, so it is gone rather than merely corrected. - The enumeration's comment claimed the self-test holds a row "by" its document and citation text. It required them to be CARRIED and keyed nothing by them. It now says what it does, and a new case makes the pair an identity by refusing two rows that share it. And one pin taken rather than argued about: every pin on this record was internal to it, which is exactly what cannot catch a sentence about a tree. The one cheap FROZEN reality pin available is now taken -- the objectui commit this repo was pinned to, read at `boundAgainstSha` -- and it is conditional on that object still being reachable, which it reports out loud when it is not. Battery floor 102 -> 120, read off a probe rather than derived. Gate behaviour delta is zero: the gate's stdout and `--list-unresolvable` are byte-identical at base and at head (sha256 match), and the self-test's success line is unchanged. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
…about a tree The note added one commit ago read "a sentence about a tree that nothing reading that tree holds -- which is what shipped here twice". Only one of the two was about a tree: the via split. The other was about the token pattern's own mechanism, and an internal pin did catch it -- it pinned the wrong mechanism. Saying "twice" overstates what the reality pin below is for, which is the same defect this round exists to remove. Comment text only. The gate's stdout stays byte-identical to base, and the self-test battery count is unchanged at 120. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
…ors where it survives the merge
Two fail bases in `scripts/check-spec-docblock-symbol-anchors.mjs`, both of the
class this file exists about: a self-test message describing a mechanism the
code does not have.
1. The NOT-TAKEN notice stated as fact that the sha "is not an object in this
clone". `readTextAtCommit` returned one `null` for FOUR causes -- git
missing, cwd not a repository, the commit absent, and the path absent at a
commit that is perfectly present -- and the code established none of them.
Measured: with the pin file renamed, the self-test printed that sentence and
exited 0 while `git cat-file -t` answered `commit` for the same sha, so a
rename or a typo in the pin path switched the guard off and its own notice
told the reader to expect the skip. The reader now establishes the cause
before it is named: `git rev-parse --git-dir`, then
`git cat-file -e <sha>^{commit}`, then the read. Only a MISSING COMMIT is NOT
TAKEN; a present commit whose pin path cannot be read is a hard red, and so
is a directory that is not a repository. The docblock lists all four.
2. The pin was read at `boundAgainstSha`, a commit ON this branch, so a squash
drops it from main's history and the pin holds nothing for the entire
post-merge life of the record -- exactly the one-cell-at-a-time drift the
case-8 comment says these pins close. `measuredOn` is the anchor the record
already carried: it is an ancestor of main, so under lint.yml's
`fetch-depth: 0` checkout it resolves before and after the squash, and
`.objectui-sha` reads the same `87af769e9a...` at both commits because the
only file differing between them is this gate. It is now the PRIMARY pin;
`boundAgainstSha` stays as a second, conditional one. The "one cheap FROZEN
reality pin available" sentence was wrong rather than optimistic -- frozen
does not pick an anchor, lifetime does -- and it is corrected in place.
State table, with a deliberately WRONG `objectuiPinSha` as the lit control in
every state:
clone state before after
full clone carrying the branch RED (exit 1) RED (exit 1)
depth-1 clone of head dark (exit 0) dark (exit 0), both anchors reported
main-shaped, no branch objects dark (exit 0) RED (exit 1)
The third row is the post-merge state. A genuinely shallow clone stays the only
NOT-TAKEN state, which is what the cause split buys.
Two cases written and removed rather than shipped, both because they could not
fail:
- A case comparing the two pin reads to each other is only reachable once both
have been asserted equal to the same string. Phantom; the loop already holds
the byte-identity claim.
- A case for the token grammar's third leg ("removing the lookahead while
keeping longest-first truncates nothing") is entailed by the two guard cases
above it, which catch every mutation that would light it first. The docblock
already says the battery pins the lookahead, not that leg, so it stays prose.
Battery floor 120 -> 124, read off a probe rather than derived.
Gate behaviour delta is zero: the gate's stdout and `--list-unresolvable` are
byte-identical at base and at head (sha256 match). The self-test's success line
is unchanged, and its stdout is byte-identical in a clone that carries the
branch; the added line appears only where an anchor is genuinely unreachable.
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
Two sentences in the previous commit went stale inside it. Both said the byte-identity of `.objectui-sha` at `measuredOn` and `boundAgainstSha` is held by an "equivalence case", and that case was written and then removed in the same round for being a phantom: it is only reachable once both reads have been asserted equal to the same string, so it can never fail. The claim itself is still held, by the loop rather than by a third case -- both anchors must read `objectuiPinSha`, so the pin file cannot differ between them without one of the two per-anchor cases reddening. The two sentences now say that, which is the same defect class this round is about, one level up. Comment-only. Gate stdout, `--list-unresolvable` and the self-test's output are byte-identical at base and at this head; the registered case count is unchanged. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
…git reports the clone shallow `commit-absent` was a skip for both anchors, so a one-digit typo in `measuredOn` switched the primary pin off in any clone. It is now a skip only for `boundAgainstSha`, or for `measuredOn` when `git rev-parse --is-shallow-repository` answers `true`; otherwise it fails the existing case. The NOT TAKEN notice now says only that the sha names no commit in this clone, and whether git reports the clone as shallow. Comments that said the pin loop holds the record's "the only file differing between the two commits is this gate" are narrowed to what the loop does: where both anchors resolve, it requires `.objectui-sha` to read `objectuiPinSha` at each, and it compares no other file. Three loose sentences corrected: "FOUR ways" (one of the four is a spawn failure, not a git exit), "Two of this record's shas are frozen", and "two anchors that fail in opposite ways". No case added or removed; the battery floor stays 124. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
…code does "Everything not `skipped` is a hard red" was false for a read that succeeded; it now reads "Every failed read not `skipped`". The red message's `no-repo` gloss now names the probe that failed rather than one of the two conditions that make it fail. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
A mistyped pin file reds only where an anchor resolves; in a clone that holds neither anchor both reads are skips. The red message's mistyped- literal gloss now names `measuredOn`, the only anchor whose absence can reach it. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx
…eason (objectstack-ai#19786) Fixes objectstack-ai#17242 Clause-②: no Round 6: one file, `scripts/check-spec-docblock-symbol-anchors.mjs`, comments only. ## What was stale The header section headed "`counts.symbol` is ZERO on this corpus", the case-4 note and one sentence of the case-5 note said the spec tree holds exactly one symbol-anchor-shaped span and that it does not resolve. They gave that as the reason the live-corpus self-test does not assert `symbol > 0`. ## Re-derived Instrument: this gate's `CORPUS` and `scripts/symbol-anchors.mjs` at `4b23e4fab5`, swept over a checkout of each tree. | tree | anchors | symbol (declaration) | declined | symbol-anchor-shaped spans | the `websocket.zod.ts` span | |:--|--:|--:|--:|--:|:--| | `08e38c6377` (census) | 2639 | 0 (0) | 183 | 1 | present, unresolved | | `fa29803417` (re-census) | 3437 | 6 (6) | 467 | 7 | present, unresolved | | `4b23e4fab5` (base) | 3448 | 6 (6) | 502 | 7 | present, unresolved, pinned | Controls: each older tree's own instrument gives the same counts. The gate at `fa29803417` prints 3437 / 6 (6) / 467. `08e38c6377` has no gate, so its own `symbol-anchors.mjs` was run with the same corpus spec and read 0 / 2639 / 183. The six resolving spans are 2 in `data/analytics.zod.ts`, 3 in `kernel/functional-completeness.ts` and 1 in `ui/action-params.zod.ts`. ⇒ The text was true at the census tree and false at `fa29803417` and at base. ## Change: deleted only - The header section, from its heading to its last paragraph. The `websocket.zod.ts` part was still true, and its `CENSUS_RESIDUAL` row still carries the doc, the citation and the repair. - The case-4 note. - The case-5 sentence that called that loop the positive control for "the ONE symbol-shaped span". No reason replaces them. Claim audit: 0 sentences added or changed in the file. The self-test still asserts `fileLevel` and does not assert `symbol > 0`. The ratchet recommendation recorded by objectstack-ai#19733 is unchanged and not restated here. ## Verification, at `d23edb4eef` - Gate, `--list-unresolvable` and `--self-test`: exit 0 at base and head, stdout byte-identical (`cmp` 0; sha256 `44a6a984…`, `af5d0039…`, `1dcc0b91…`), stderr empty. - Comment-only: the TypeScript printer's output with comments removed is identical at base and head (sha256 `8865ec39…`). Lit control: a one-character code mutation makes it differ. The self-test floor stays 124. - `check-scripts-symbol-anchors` (sweeps this file): exit 0. Anchors 3694 → 3691 and file-level 3642 → 3639; symbol 52 and declined 14 unchanged. The −3 are the three code spans in the deleted text. Its self-test exits 0. - `dispatch-gates`: 31 derived, 31 run, all exit 0; `--ran` reads 0 NOT-MEASURED, 0 UNRUN. Outside that total: the 2 workflow-valued families and the Test Core steps run in CI only. The 14 changeset-pending families do not apply (no changeset: a repo-root script in the private root package). - ESLint on the file: 0 errors, 0 warnings. Repo-wide lint is left to CI. - 0 control bytes and 0 model identifiers in the file and the commit message. Lit control: a planted control byte and a planted model identifier are both found. ## Acceptance notes - No `symbol > 0` live control is proposed. Case 1 already asserts `declaration >= 1` and `literal >= 1` through the same `CORPUS` on its fixture. A live floor would add a constraint on authors and no new detection. Noted, not filed; carrier: none. --- _Generated by [Claude Code](https://claude.ai/code/session_01UDXER3sdqfeVYpEWZs5mZx)_ Co-authored-by: Claude <noreply@anthropic.com>
Part of #17242
Clause-②: no
#17242 asked for three things: re-derive the population, tense-classify it, and answer the ratchet question with numbers. All three are done. The measurement inverts the card's working assumption, so the diff is one record rather than a cleanup — there is nothing to repair.
1. Re-derived population, with the historical pins reproduced as a lit control
08e38c63776465cc0a7cfa29803417Before today's number was taken, the instrument reproduced
CENSUS_17065verbatim at its own sha: 1,317 files swept, 189 comment-prose line citations, 6 naming a tracked target, 183 declined, by shape 69 bare-filename / 62 directory-qualified / 52 continuation. Every figure matches the constant in the gate, so the instrument could have given another answer and did not.The resolver changed, so the growth was re-measured with both
scripts/symbol-anchors.mjswas rewritten between the 217 reading and today (655 insertions, 40 deletions), which means 217 and 467 were not comparable on their face. This tree was therefore swept twice:Identical, declined-by-shape included. Instrument drift on this axis is zero and the three readings are comparable: 183 → 217 → 467 is real population growth.
2. What the residual actually IS — the question the card filed as NOT MEASURED
The card recorded two gaps explicitly: the objectui cross-repo vs in-repo split, and how many would resolve under a spec-relative base. Both are measured here by binding every declined citation against the sibling objectui checkout and against this repo:
462 of 467 name a file that really exists. The two sibling trees agree row by row — every one of the 467 lands on the same verdict against the⚠️ Round 2 moved these cells from 408 / 55 / 4: the binding predicate is now written out in full in the gate's docblock, and under it the split is 409 / 53 / 5, with a declared sensitivity — relaxing it for directory-qualified tokens gives 410 / 53 / 4, one row. Continuations (191 of the 467) carry no path of their own and are attributed to the antecedent they inherit — 188 inherit a token that way and 3 inherit none, which is held in ⚠️ An earlier revision of this paragraph added 「for 34 of them that antecedent is named in prose」; no field and no case carries that 34, and a re-derivation under one natural definition gives 36 / 152. ⛔ Unheld, so it is withdrawn rather than restated — it was neither confirmed nor refuted.
.objectui-shapin87af769e9a3ee28ace099fdd653d3ebd79fe82e2and against objectuimain0cf2d6644bdb96a9a6784ef801ee6a60a5306bd8, measured on the objectstack treecdd68cf15ed863468ce6eecdd5c0824b760ea22a. ⛔ A moving ref is not an anchor, so all three shas are carried as data inRECENSUS_17242, not as prose.RECENSUS_17242.bindingVia.⇒ this residual is a SPELLING population — abbreviated cross-repo and package-relative citations — not the stale-citation rot its headline number suggests.
3. Tense classification — the defect cell is EMPTY
A citation naming no tracked file is a defect only when the surrounding sentence is live-tense. The classifier asserts on the live / not-live axis and runs two controls first, refusing the population reading if either fails:
discovery-environment-subset.pin.test.tssaysEnvironmentTypeSchemais declared bycloud/environment.zod.ts— a directory #16325 removed, while the file's own import 26 lines below reads './discovery.zod' #17730 text quoted verbatim from that card: classifiedlive✅quickAddretirement record: classifieddated-measurement✅Over the whole residual: 300 live, 129 dated-measurement, 38 record. Crossed with binding, the defect cell — binds nowhere AND live-tense — contains 0 rows. The five that bind nowhere are enumerated as data in
RECENSUS_17242.bindingInNeitherRepoRows, each with its coordinate, citation text, reason and tense: one retirement record naming a file in thecloudrepo in prose; two continuations whose comment block names its file only AFTER the citation (a backward-only walk finds none); one whose block names no file at all — it declares from the read point rather than from objectui's mirror, which the row's ownwhysays; and one whose token tail-matches in no tree. All five are correct as written.⛔ Note
recordanddated-measurementare both correct historical prose; asserting the exact three-way label on a control would pin a sub-classification the rule never asked for, so the controls assert the live / not-live axis only.4. ⛔ The trap, measured — repairing the PATH alone turns this gate RED
The obvious cleanup is to rewrite a package-relative citation to its repo-root spelling so it resolves. That makes the path tracked, which moves the citation out of the declined set and into the judged one, where a line number is exactly what this gate refuses.
One such repair was performed against a single citation in
packages/spec/src/shared/union-author-message-pins.test.ts(api/protocol.zod.ts:2853rewritten to its repo-root spelling), throughscripts/ablation-replace.mjsso the mutation is proven on disk:The gate went from green to
❌ 1 finding(s), then was restored —blob == HEAD (d78fd346439f)andgit diff HEADempty.⇒ the path is only half the repair; the citation must also leave anchor form. A round that "works the 467 down" by fixing spellings alone lands one finding per repair.
5. The ratchet question — a recommendation, not a decision
Recommendation: do not flip it, on these numbers:
The only judgeable half is the 53 in-repo abbreviations, and §4 shows that repairing them is a two-part change. If the residual is ever worked down, the in-repo 53 are the tractable set and each needs the anchor-form half too.
⛔ Adding a required gate is the maintainer's floor; this PR records the measurement and does not change the scope call.
CENSUS_17065is untouched and not restated.Why the record lives in the gate header
The classification above cannot be re-derived by the gate: it needs a checkout of the sibling objectui repo, which the gate is deliberately not given — the same reason its cross-repo anchors are reported rather than judged.
--list-unresolvableenumerates the residual. ⛔ And the stronger, truer statement: the binding harness and the tense classifier exist nowhere in this tree, so the three tense totals can be re-derived by nothing — not even a reader holding both checkouts. The binding split is re-runnable, because the predicate is written out. So it is kept as data beside the census it extends.Verification
pnpm lint(repo-wide,eslint . --no-inline-config) — exit 0, dated atcdd68cf15eLint & Repo Gatesissuccessat the current head)scripts/pm/dispatch-gates.mjsfor this change set — 31 run, 0 NOT-MEASURED, 0 UNRUN, each with its exit code recorded and reconciled via--rancheck-spec-docblock-symbol-anchorsand its--self-test— exit 0; the residual arithmetic and the seven pinned day-one rows are unchangedcheck-scripts-symbol-anchors— exit 0; this file is swept by that corpus.988cf276bbthe corpus reads 3,653 → 3,659 (it read 3,658 at round 3's head; round 4's prose added one resolving anchor), with declined unchanged at 14 throughout, so the added prose contributes resolving anchors and no new residuenode_modules; re-run afterpnpm install, all exit 0. They are not reported as clean on the exit-3 reading.Acceptance notes
files[]has an entry escaping its own directory — soskip-changesetis the correct disposition and is owed from the seat.index.tsxin a docblock that is plainly about objectui binds to this repo's only file of that name). Every such case still names a file that exists, so it cannot create or hide a defect — it can only shift a row between the 409 and the 53. Noted, not filed.cloudrepo in prose, with a space rather than the grammar's cross-repo prefix. Verifying it needs acloudcheckout this container does not have, so its target is NOT MEASURED; its sentence is a retirement record either way, so it is not a defect on the tense axis. Noted, not filed.Generated by Claude Code