chore(scripts): record what the recorder-wait census's two matchers disagree about - #8706
Merged
os-justin merged 3 commits intoSep 9, 2026
Merged
Conversation
…dler's reload `expect(deletes).toEqual([])` was dated to the first PUT by `waitFor(puts)`. That covers the delete scan only because the scan happens to run before the save loop in `handleObjectsChange` — a property of the page, not one the file asserts. Anchor it on `reload()`, the handler's last statement, so the emptiness is read after every write the handler makes. Measured: with a stray `reset` issued after the saves, the `puts` wait leaves this assertion green while C0/H1/H2 in the same file — which already anchor on the reload — go red. objectui#8690 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
The detector answers where to look, never what is wrong, so it is a census tool and NOT wired into CI: a gate on this list would institutionalise the batch repair the card exists to prevent. Two recorder-matching modes, because the choice moves the numbers, and the header records what each one measured on the card's base commit rather than quoting the card's counts as reproduced. Changeset declares an empty frontmatter: test-only plus one repo script, nothing published moves. objectui#8690 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
…isagree about The census script's numbers move with an internal choice its header stated but never measured. objectui#8703 measured it, and the answer is wider than the mode choice: - The two `--recorder-match` modes are incomparable by construction — each flags a shape the other cannot see (forced on fixtures, both directions). - On da5e4f6 the buckets are nevertheless nested: ident's 15 is a subset of path's 18, ident-only is empty. "They do not contain each other" is an in-principle claim, false as a measurement of this tree. - The header's stated `path` blind spot (pushed bare, read as `host.inits[0]`) is wrong: both modes miss that shape. - Two mode-independent rules dominate the mode choice: the forward window ends at the next `await` in the FILE rather than at the end of the enclosing test, and any textual occurrence counts as a read. Seven of the eighteen strict flags on that tree point at a declaration, a destructuring, a reset or a function parameter — not at a read. Header rewritten to carry that, plus a caveat printed next to the counts. The detector's behaviour is unchanged: both modes print byte-identical site lists. Script and changeset only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
os-justin
marked this pull request as ready for review
September 8, 2026 23:48
os-justin
enabled auto-merge
September 8, 2026 23:48
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Sep 8, 2026
This was referenced Sep 9, 2026
os-justin
deleted the
claude/issue-8703-matcher-dependent-strict-bucket
branch
September 9, 2026 01:12
This was referenced Sep 9, 2026
os-justin
pushed a commit
that referenced
this pull request
Sep 9, 2026
One conflict, and it is an artefact of the merge base rather than a real divergence: `scripts/census-recorder-wait-shape.mjs` is absent at the merge base (da5e4f6), so both sides read as an ADD. Measured, not assumed: main's side of the conflict is blob 3732191, and that is byte-identical to this branch's own parent commit 3778170 — the version #8706 landed is exactly the version this branch built its AST matcher on top of. So resolving to this branch's side drops no byte main carries. git rev-parse MERGE_HEAD:scripts/census-recorder-wait-shape.mjs git rev-parse 3778170:scripts/census-recorder-wait-shape.mjs -> 3732191 (both) Byte identity is not claim identity, though: the header main carries makes five claims, and whether each still HOLDS after the AST matcher is a separate question this merge does not answer. The commit that follows answers it claim by claim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8703
scripts/census-recorder-wait-shape.mjsexists only onclaude/issue-8690-recorder-wait-audit, whose PR #8702 is not merged. That branch is based on the same commit as this one (da5e4f69e), so this branch was fast-forwarded onto it rather than duplicating the file. Until #8702 lands, this PR's diff shows its three files too. My own change is exactly two files:scripts/census-recorder-wait-shape.mjs(header, plus one printed caveat) and.changeset/issue-8703-matcher-dependent-strict-bucket.md. Nothing else on this branch is mine, and the plugin-designer test change belongs to #8702's card.Deliverable A — seven readings, zero repairs
All seven sites re-located by content on
da5e4f69e(the addresses held). Six of them are not reads at all, and the seventh was forced and measured sound.form-onchange-wiring.test.tsx:207const received: Record_[] = [];it; the wait's test closes at 203DatasetWidget.localSelectI18n.test.tsx:356const blobs: any[] = [];it; block closes at 347DatasetWidget.optionLabelI18n.test.tsx:313const { requested } = installMetaRouter(...)describe; blocks close at 304/305DatasetWidget.tableTotalsRow.test.tsx:319const blobs: Blob[] = [];it; block closes at 313ObjectView.tableColumnsForwarding.test.tsx:136const seen: any[] = [];ObjectView.tableColumnsForwarding.test.tsx:149gridSchemas.length = 0;PermissionMatrixEditor.scope.test.tsx:177expect(server.savedOpts[0]).toMatchObject(...)For each of the six, the wait's enclosing
itor helper closes before the flagged line and the flagged recorder is never mentioned inside the wait's own block — so there is no cross-recorder read in scope to repair. This is the objectui#8704 defect class, filed separately.The one genuine read, forced
PermissionMatrixEditor.scope.test.tsx:177waitsserver.savedand readsserver.savedOpts[0], the same construction as the twopackageDoorFacetssites objectui#8690 measured sound. Both pushes are consecutive synchronous statements in onesavedouble (lines 72-73, noawaitbetween), so no ordering can exist between them — but that is a reading, and the bar is a forcing.Leg 1 — split the co-located pair by 50ms (
setTimeout(() => { server.savedOpts.push(opts); }, 50)), mutation proven on disk in both directions (blobd86134f3…to5ef3556d…vs the HEAD blob, anchor counts 1→0 and 0→1, line-total gate 263 = 263), restored by state (git diff HEADempty):Exactly the flagged line, and only it; the three other tests and the
server.savedreads above it stayed green. So the assertion is live — this is not "both are undefined and nobody notices" — and since the ordering it depends on cannot occur in the real double, the site is sound. No repair, therefore no legs 2-4: there is no new wait to check under the forced ordering and no pre-fix pin to restore from the base blob. Saying so is more honest than manufacturing them.Baseline before the mutation: 4 of 4 passed. Per-test classification from vitest's JSON reporter in every leg.
⭐ Deliverable B — the disagreement, characterised
Recorded in the script header. Summary of what was forced on fixtures (a throwaway git repo, five files, run through the real script in both modes — never read off the regexes):
.push(site, matched textually at the read site by a name regex whose lookbehind forbids a preceding..pathonly: pushed and read as the same member path (fixture f1 — flagged bypath, invisible toident).identonly: pushed as a member, read under a bare alias (fixture f2 — flagged byident, invisible topath).da5e4f69e:ident15 strict,path18 strict,identminuspath= the empty set. The three extra are the app-shellserver.saved/server.savedOptssites. So "their strict buckets do not contain each other" is true in principle and false as a measurement of this tree — the union is justpath's bucket, and no third mode is needed to cover it.pathblind spot was wrong. A recorder pushed bare and read ashost.inits[0]is missed by both modes (fixture f3, zero flags in either) — the lookbehind blocks the dotted read regardless of mode. Shared blind spot, not apathone. Corrected in the header.awaitin the FILE rather than at the end of the enclosing test, and every textual occurrence counting as a read. Seven of the eighteen strict flags atda5e4f69epoint at a declaration, a destructuring, a reset or a function parameter. Fixture f4 reproduces the class in isolation; fixture f5 shows the mirror loss — a genuine cross-recorder hazard oneawaitfurther on draws zero flags in both modes.Reported outcome: the counts are not corpus facts. objectui#8690's 9, this file's 15/18, and the 14/17 this branch prints (one site fewer, because #8702's own repair removed it) are all readings of (matcher mode × window rule × occurrence class × tree). The script now prints that caveat next to its own numbers, and the header says what a quotable matcher would have to do instead — resolve recorder identity over an AST, scope the window to the enclosing test body, classify occurrences as read/write/declaration. Writing it was out of scope; it is filed as objectui#8704. The fence stands: this instrument stays out of CI.
Reproduction of the base numbers: a detached comparison worktree at
da5e4f69eprints 159/15 and 167/18, matching the header exactly; the only delta on this branch is #8702's repaired plugin-designer site.The card's second, unmeasured observation — measured
The
provider: 'value'control inListView.objectProviderBinding-7477was checked, since the card left that to its reader. A probe that starts a query 50ms after mount leaves bothfind-absence pins green (7 of 7 pass), while a temporary in-test diagnostic proves the deferred query really landed inside that same test — and the identical diagnostic fails with the probe removed, so it can fail. Green-while-meaningless against a deferred query, confirmed. Filed as objectui#8705, not folded in here: it is a mock-call absence, outside this detector's population.Fences honoured
contractEnvelope-6839family: no overlap. Itsplugin-dashboardfile isObjectPivotTable; mine were the threeDatasetWidget.*tests, and no test file was edited at all — every test-tree mutation in this PR's evidence was an ablation, restored by state.Verification
node scripts/census-recorder-wait-shape.mjsin both modes: byte-identical site lists before and after the header edit; behaviour unchanged.pnpm exec eslint scripts/census-recorder-wait-shape.mjs— clean.node scripts/check-changeset-presence.mjs— passes;node scripts/check-changeset-no-major.mjs— passes. The changeset has empty frontmatter (the real exemption;skip-changesetis a phantom label here).git diff HEADempty, verified by state).🤖 Generated with Claude Code
https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
Generated by Claude Code