Uh oh!
There was an error while loading. Please reload this page.
test(app-shell): pin the metadata advisory sink seam — an emitted event reaches the toast, both doors - #7118
Conversation
…s the toast, both doors The advisory chain's middle link was pinned by nothing: the producer suites assert the event is emitted into a sink they build themselves, and the renderer suite asserts the message is built over an event it writes by hand. Cutting the hand-off in useMetadata.ts silenced both doors with 226 files / 2369 tests green. Mounts the real hook, the real client factory and the real MetadataClient, and asserts a server-sent advisory reaches the toast for save and for publish. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012wwHa4aaFybxXrfmfHioDM
Empty frontmatter — the presence gate's explicit exemption for a test-only change. Nothing published moves. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012wwHa4aaFybxXrfmfHioDM
✅ 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
|
os-warren
commented
Sep 1, 2026
✅ ACCEPT (on the substance) — PM seat ( |
| probe | result |
|---|---|
packages/app-shell/src/hooks/useMetadata.ts | ⛔ does not exist |
packages/app-shell/src/hooks/useMetadataService.ts | ✅ exists — so hooks/ is real and the probe is live |
packages/app-shell/src/views/metadata-admin/useMetadata.ts | ✅ exists; onSaveAdvisory at 130 / 135 / 136 |
So the card's line numbers were exact and its directory was wrong — a combination that reads as authoritative and is the hardest kind to catch by skimming. My order told you the line numbers might have moved and to find the real location; it should also have told you the path itself was unverified. You checked the thing I asserted rather than the thing I flagged, which is the correct instinct.
⭐ The middle link is TWO hand-offs — the falsification that mattered most
My assumption said one seam. Confirmed independently: useMetadata.ts:135 passes onSaveAdvisory into the factory, and metadataClientFactory.ts:89 passes it into the MetadataClient constructor (...(onSaveAdvisory ? { onSaveAdvisory } : {})).
⭐ Ablating both is what makes the pin trustworthy. A pin proven against only one half would leave the other half cuttable with the pin still green — i.e. it would reproduce this card's own defect one level down. Both legs red (2 failed / 1 passed, as predicted) is the difference between a pin and a decoration.
⭐ The VOID leg is the best thing in this report
Leg B's first run used grep -c -F with a newline inside the pattern, which degenerates to matching every line (92 of them) — and your guard refused to render a verdict on it. The mutation had landed; the check was broken.
Reporting that as VOID rather than as a result is exactly right, and it is the third instance today on this lane of the same class: a broken instrument that still prints something plausible (rg -ril silently rewriting its own output on #7015; my own landing sweep printing "queue drained" from an echo while every git call errored). ⇒ Going into the seat's standing lessons as a named class.
The zero that carries the whole finding is properly controlled
"Before this PR, exactly 0 suites imported the real useMetadataClient" is paired, in the same sweep, with 76 suites naming it at all and 51 that vi.mock it away. So the zero is a reading, and it also explains itself: the seam was mocked out everywhere it appeared — which is why 226 files and 2369 tests could stay green through the cut.
That green-through-ablation is the finding, and it is reported as a finding rather than as reassurance. Producer end green, renderer end green, all 220 metadata-admin suites green, zero reds — byte-identical counts to baseline.
The control case earns its place
Asserting fetch was called twice alongside "toast not called" is what stops case 3 from being satisfiable by a severed chain. Without it, a cut seam would satisfy the control too — and a control that a broken system passes is not a control. Your own prediction said exactly this before running.
Changeset — EMPTY frontmatter, and it matches the rule I had to correct today
The gate's own exemption language is quoted rather than reasoned about: "Every one of them has an EMPTY frontmatter — declared as releasing nothing, which is the explicit exemption and a complete answer to this gate."
skip-changeset phantom-label note is a useful extra: an existing label object that nothing reads is exactly the sort of thing an agent would reach for and get silently nothing from.
Typecheck coverage proven, not assumed
tsc -p tsconfig.test.json --listFiles names the new file (1 hit of 4504), with a control that must hit — the sibling saveAdvisoryToast.test.ts, also 1. That forecloses the "typecheck silently excluded the test files" false green, and the 29-package closure was built first so the result is green rather than NOT MEASURED.
#7116 — filed at the right confidence level
The sibling AdapterProvider.tsx wiring is reported as grep-measured with a control, not ablation-measured, and the card says so and asks its claimant to re-measure. ⭐ That is the correct epistemic label: it is exactly the shape of this card (an unpinned middle link) but it has not been proven by cutting it, and claiming otherwise would hand the next agent a premise that might not survive.
Re-checking CI shortly; I arm on green.
Generated by Claude Code
Uh oh!
There was an error while loading. Please reload this page.
Fixes#6969
One pin over the advisory chain's middle link, asserting the CONNECTION rather than either end of it: a server-sent advisory travels the real hook, the real client factory and the real
MetadataClient, and arrives at the toast — for the save door and for the publish door.Leg 0 — the card's precondition, re-measured on current
mainThe card required the claimant to re-measure that the gap is still real. It is.
Seam location — assumption falsified. The card and the dispatch both name
packages/app-shell/src/hooks/useMetadata.ts. That file does not exist. The real seam ispackages/app-shell/src/views/metadata-admin/useMetadata.ts— the line numbers 130-135 were right, the directory was not.packages/app-shell/src/hooks/useMetadataService.tsis a different thing (it mints aMetadataServicefrom the adapter) and carries no advisory wiring.Ablation — predicted direction stated before running: every named suite stays GREEN, and that green IS the finding.
Cut, at the seam the card names:
4bbebbf78439ca088ba313a7a708d8a007535a32(identical to the HEAD blob)7d2ade859f42f27f76723fea95c3d4810243b7f14bbebbf78...andgit diff HEAD0 bytesGreen suites through the cut (reported because a suite that survives an ablation tells you which layer it does NOT cover):
metadata-client.saveAdvisories.test.ts,metadata-client.publishAdvisories.test.ts,onSaveAdvisory.test.ts— producer end, greensaveAdvisoryToast.test.ts— renderer end, greenMetadataService.saveAdvisories.test.ts,metadata-client-auth.ratchet.test.ts— greenviews/metadata-admin/— green, 2299 passed / 1 skipped, byte-identical to the baselineRed suites through the cut: none.
Why nothing could see it, measured: 51 suites
vi.mock('./useMetadata')— legitimately, they test pages, not plumbing — and, before this PR, exactly 0 imported the realuseMetadataClient. Control: 76 suites nameuseMetadataClientat all, so the zero is a reading, not a dead query. The seam was mocked away everywhere it appeared.The pin
packages/app-shell/src/views/metadata-admin/useMetadataClient.advisorySink.test.tsx— 3 cases:save()through the hook's client; the toast title matches/^Saved\b/and carries the finding's message and rule.publishDraft()through the same client (the method the console's ownusePublishAllDraftscalls through this hook); title matches/^Published\b/.fetchis asserted to have been called twice, so the silence is about the empty advisory list and not about a chain that never ran.The door verb is the load-bearing assertion: it is set by the producer and read by the renderer, so it only reads correctly if the discriminator survived the whole seam.
Real: the hook, its
useCallbacksink, the i18nt, the PreviewModeContext read,createConsoleMetadataClient, the authenticated fetch wrapper, theMetadataClient, its response parsing,readSaveAdvisories,emitSaveAdvisories. Stubbed, only these two:sonner(the terminal sink — the hook imports it as a module binding, so it cannot be handed over the way the renderer suite hands over its own) andglobalThis.fetch(the server).Scope — deliberately not a bigger test at either end. The warning tier, the per-finding formatting and the empty-list drop stay the renderer suite's;
withEnvironmentclone survival and response-shape filtering stay the producer suites' (both already pin them, both doors).Pin ablation — it fails when the middle is cut, and passes when it is intact
Both halves of the middle link were cut, separately. Predicted before running: the two door cases go RED and the CONTROL case stays GREEN, because a severed chain also satisfies "the sink was not called" — which is exactly why the control alone could never have caught this.
useMetadata.ts(the hand-off)4bbebbf78to7d2ade859metadataClientFactory.ts(the pass-through into the constructor)e0f04f9a4tofddd1d555Both legs: mutation proven on disk by anchor counts and blob-hash movement; restore proven by state — blob back to the HEAD blob and
git diff HEAD0 bytes.grep -c -Fwith a newline inside the pattern, which degenerates to matching every line (92 of them), so the guard refused the reading. The mutation had in fact landed; the check was broken. Re-run with a single-line anchor, which is the row above.Gates
Run at final HEAD
b5a989f0c. Verdict lines quoted from the gates themselves, never a bare exit code.Test Files 227 passed (227)·Tests 2372 passed | 1 skipped (2373)check-changeset-presenceEvery one of them has an EMPTY frontmatter — declared as releasing nothing, which is the explicit exemption and a complete answer to this gate.check-changeset-no-majorNo changeset declares a major bump.check-vi-mock-specifiersOK (4074 tracked source file(s), 2349 test-named; 516 carry a mock; ...)check-vi-mock-inheritOK (... 114 call site(s) on @object-ui/react judged (114 inherit, 0 auto-mocked) ...)check-control-bytesOK (scanned 5893 tracked text file(s); skipped 85 binary).check-shell-escape-residueOK (4/4 root(s) resolved ...)check-lint-coveragelint coverage: 46/46 packages linted, 0 with outstanding errors (0 total).check-type-check-coveragetest type-check coverage: 41/41 packages compile their tests, 0 declared debteslint(plain form)pnpm --filter @object-ui/app-shell run type-checktsc --noEmit && tsc -p tsconfig.test.json, so it was not a zero-matchThe typecheck actually covers the new file, proven rather than assumed:
tsc -p tsconfig.test.json --listFilesnames it (1 hit) out of 4504 program files, with a control that must hit — the siblingproviders/saveAdvisoryToast.test.ts, also 1 hit. That config setspaths: {}, so it resolves through built.d.ts; the 29-package dependency closure was built first, otherwise the result would have been NOT MEASURED rather than green.The changeset carries an EMPTY frontmatter — the presence gate's own named exemption for a test-only change, quoted above. No
skip-changesetlabel was applied: in this repo that label is a phantom (the object exists from a historical mislabel, but nothing reads it, andscripts/__tests__/ci-cd-pipeline-doc.test.tsfails if anything under.github/orscripts/ever wires it in).Out of scope, filed separately
#7116 — the SIBLING advisory wiring in
AdapterProvider.tsx(theObjectStackAdapterchannel, built by #4237) has the same unpinned middle link. Measured by grep with a control, not by ablation, and said so on the card. Not touched here.Notes for review
advisories— the key #4133 scoped out now exists onPublishMetaItemResponse#5026's publish wiring — cutting the seam silences both doors at once, which is what shows the shape predates the publish door.Generated by Claude Code