You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
finding: the SIBLING advisory sink wiring in AdapterProvider.tsx is pinned by nothing — the same gap as #6969, on the adapter channel #7116
ObjectStackAdapter (the adapter every data surface uses)
AdapterProvider.tsx subscribes a.onSaveAdvisory(...) and calls emitSaveAdvisories
⛔ nothing
The second one is the wiring #4237 built. Both ends of ITS chain are pinned too — the adapter's emitter in packages/data-objectstack/src/onSaveAdvisory.test.ts, the renderer in saveAdvisoryToast.test.ts — and, exactly as in #6969, nothing asserts the two are connected.
Measurement (grep, with a control — not an ablation)
Stated plainly so the next reader knows what was and was not measured. This is a grep result, not the green-through-ablation that #6969 carried:
suites naming AdapterProvider: 40
of those, naming dvisor (matches advisory/advisories/Advisory): 1
CONTROL, of those, naming expect: 40/40 — so the query is live, and the 1 above is a reading rather than a dead zero
The single hit is packages/app-shell/src/services/MetadataService.saveAdvisories.test.ts, and its own docstring says it does not close this gap:
AdapterProvider is what wires the last two links in the real app; the sink is handed over here instead of mounting a toaster, exactly as saveAdvisoryToast.test.ts does, so nothing depends on module mocking.
⇒ the subscription in AdapterProvider.tsx (the a.onSaveAdvisory call and the emitSaveAdvisories inside it, plus its unsubscribe) is traversed by no test.
What a fix looks like
The same shape #6969 landed, one channel over: mount the real provider, have the real adapter emit, assert the sink receives it. ⛔ Not a bigger renderer test and ⛔ not a bigger adapter test — both ends are already covered.
⚠️ Worth re-measuring before claiming, same as #6969: this was measured by grep, so an ablation on AdapterProvider.tsx is the leg that actually settles it.
Build tier: opus (⚠️ Fable 5 quota exhausted; the standing maintainer exemption lowers the build tier only)
Not clause ② — a test asserting an existing connection. Nothing enters or leaves any published surface, so no CONTRACT_REVIEW_TIER is owed and the quota cannot strand it.
Dispatched on the strength of its sibling, which has now LANDED
#6969 — the same defect one seam over — landed as 7e2e6f42c minutes ago. Its shape transfers almost exactly, and its numbers are the reason this card is worth a slot rather than a shrug: cutting that seam left 226 files / 2369 tests green, zero reds, because 51 suites mocked the seam away and exactly 0 imported the real hook (control: 76 suites named it). A hole no green suite can see.
⇒ Whoever takes this has a landed reference implementation for the pin shape, the ablation discipline, and the "report the greens, they tell you which layer you do NOT cover" framing.
⚠️ The card's own confidence label is binding — it is grep-measured, NOT ablation-measured
This card was filed honestly at the weaker confidence level: 1 of 40 AdapterProvider suites names an advisory (control: all 40 name expect), and that one's own docstring says it hands the sink over rather than mounting the provider. That is suggestive, ⛔ not proof.
⇒ Leg 0 is an ablation, exactly as #6969's was. Cut the hand-off, run every named suite, and show they stay GREEN — that green is the finding. ⭐ If something goes red, the gap is already covered: STOP and report that. A card that turns out to be already-pinned is a valid and valuable outcome, not a failed dispatch — and given that #6969 just changed this area, it is a live possibility rather than a formality.
They are sibling channels, not the same channel: #6969 pinned the MetadataClient → toast seam via useMetadataClient; this is the ObjectStackAdapter channel built by #4237, reached through AdapterProvider.tsx. Measure the relationship rather than inheriting it — if the new pin does transitively cover this seam, that is the stop-and-report case above.
{
"issue": 7116,
"status": "done",
"branch": "claude/issue-7116-adapter-provider-advisory-pin",
"pr": "https://github.com/objectstack-ai/objectui/pull/7131",
"gap_still_real": true,
"premise_still_valid": true,
"seam_actual_location": "packages/app-shell/src/providers/AdapterProvider.tsx lines 91-93 (subscription + renderer call) and line 111 (unsubscribe). The PM path assumption was CORRECT this time, unlike the sibling card. Producer end confirmed genuinely pinned: installSaveAdvisoryInterceptor is installed in the ObjectStackAdapter CONSTRUCTOR at packages/data-objectstack/src/index.ts:2109, and onSaveAdvisory.test.ts drives a real SDK client through a fake fetch.",
"handoff_count": 3,
"covered_transitively_by_7118": false,
"precondition_ablation": {
"predicted": "GREEN at every cut - predicted BEFORE running, on the strength of a census showing 0 suites import the real AdapterProvider while 38 of 41 mock it away",
"observed": "GREEN at all three cuts, exactly as predicted. Baseline first: 45 files / 633 tests green. H1 (a.onSaveAdvisory subscription deleted outright): 45 files / 633 tests green, 0 red. H2 (subscription kept, emitSaveAdvisories call inside it cut): 45 files / 633 tests green, 0 red. H3 (unsubscribe cut): 45 files / 633 tests green, 0 red.",
"green_suites": "All 45: the 41 naming AdapterProvider, plus data-objectstack onSaveAdvisory.test.ts, metadata-client.saveAdvisories.test.ts, metadata-client.publishAdvisories.test.ts, and app-shell providers/saveAdvisoryToast.test.ts. Separately measured: the landed sibling pin useMetadataClient.advisorySink.test.tsx also stays green 3/3 under H1, which is the transitivity answer.",
"red_suites": "none - zero reds at any of the three cuts",
"blob_before": "aa396a951e9802dcaf04d46fb533aac3e24fae33 (verified equal to HEAD:packages/app-shell/src/providers/AdapterProvider.tsx before each mutation)",
"blob_after": "H1 6c8b6627ba8375860d2902bb116c6538547b803a | H2 5119a9784b04c33a71c0327814b02b2b555cb6a7 | H3 bf0309de61d5b668a556648684038c9c42f81360",
"restore_proven_how": "By state, never by exit code, on every leg: git checkout HEAD -- ABSOLUTE_PATH (never a bare checkout), then git diff HEAD empty YES, git diff --cached empty YES, blob hash back to aa396a95 YES, injected marker count back to 0. Mutation proven on disk by blob-hash change PLUS a marker count, never an editor exit code; each edit script refused to run unless its anchor hit exactly once. All legs carried a trap on EXIT INT TERM with an absolute REPO_ROOT path."
},
"files_changed": [
"packages/app-shell/src/providers/AdapterProvider.advisorySink.test.tsx (new, 249 lines)",
".changeset/adapter-advisory-sink-pin.md (new, empty frontmatter)"
],
"pin_ablation": {
"predicted": "RED at each of the three hand-offs, with H3 discriminating - failing only its unmount case",
"observed": "RED at all three, each for the right reason. H1: 2 failed 1 passed, expected [] to have a length of 1. H2: 2 failed 1 passed, same assertion. H3: 1 failed 2 passed, expected vi.fn() to not be called at all but actually been called 1 times. The discrimination held. Re-run on the FINAL version of the pin after a lint fix moved the capture into an effect; all three red legs reconfirmed.",
"ablated_at_each_handoff": true
},
"gates": [
{ "name": "vitest - 45 named suites (baseline, pre-change)", "exit": 0, "verdict": "green", "raw": "Test Files 45 passed (45) | Tests 633 passed (633)" },
{ "name": "vitest - 46 suites incl. new pin, at HEAD ad32812de", "exit": 0, "verdict": "green", "raw": "Test Files 46 passed (46) | Tests 636 passed (636)" },
{ "name": "app-shell type-check (tsc --noEmit && tsc -p tsconfig.test.json)", "exit": 0, "verdict": "green", "raw": "0 occurrences of 'error TS'; script name echoed once (zero-match control). FIRST attempt was NOT MEASURED, not red: it failed only with 'Cannot find module @object-ui/*' on an unbuilt closure. Built the closure with pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build (exit 0) and re-ran." },
{ "name": "check-changeset-presence (before adding changeset)", "exit": 1, "verdict": "red", "raw": "1 source file(s) of 1 released package(s) changed, and this change adds no changeset. Verdict quoted, not predicted. Its own text names the remedy: 'If this change really should release nothing, say so - that is a pass, not a workaround. Add .changeset with an EMPTY frontmatter.' NOTE: an earlier run of this same gate printed '0 file(s) changed ... no changeset is owed' and that reading was DISCARDED as an uncontrolled zero - the gate reads git diff and the new file was still untracked." },
{ "name": "check-changeset-presence (after adding changeset)", "exit": 0, "verdict": "green", "raw": "1 source file(s) ... declares 1 changeset(s). Every one of them has an EMPTY frontmatter - declared as releasing nothing, which is the explicit exemption and a complete answer to this gate." },
{ "name": "changeset:check (check-changeset-fixed + check-changeset-no-major)", "exit": 0, "verdict": "green", "raw": "All workspace packages are in the changeset fixed group. No changeset declares a major bump." },
{ "name": "check-changeset-overwrite", "exit": 0, "verdict": "green", "raw": "1 changeset(s) added, 0 modified, 0 deleted. No pre-existing changeset was modified or deleted." },
{ "name": "check-control-bytes", "exit": 0, "verdict": "green", "raw": "OK (scanned 5900 tracked text file(s); skipped 85 binary). Also self-scanned the new file with grep -naP for control chars: 0 hits." },
{ "name": "lint:coverage", "exit": 0, "verdict": "green", "raw": "lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total)." },
{ "name": "type-check:coverage", "exit": 0, "verdict": "green", "raw": "test type-check coverage: 41/41 packages compile their tests, 0 declared debt." },
{ "name": "eslint (plain form, new file)", "exit": 0, "verdict": "green", "raw": "clean. First run was exit 1 with a real react-hooks/globals error - reassigning a module-scope binding during render - fixed by moving the capture into useEffect." },
{ "name": "pnpm lint (repo-wide scan)", "exit": null, "verdict": "NOT_MEASURED", "raw": "DECLARED NARROWING, not a skipped gate. Narrowing proven excludes nothing: population read from eslint's own config rather than guessed (1038 files under packages/app-shell, counted from --format json, 0 errors); the new file confirmed present in that population; and no type-aware linting is configured (zero hits for projectService / parserOptions / project: in eslint.config.js, with a control proving the file is readable - rules 10, export default 1, files 10), so this diff cannot move the verdict of any untouched file. Repo-wide scan is CI's." }
],
"controls_used": [
"Census denominator: of the suites naming AdapterProvider, 41/41 name expect - the query is live, so the 1 dvisor hit is a reading not a dead zero.",
"Zero-import census: 0 suites import the real AdapterProvider. Control against a module that IS imported by tests - saveAdvisoryToast returns 2 hits - so the zero is a reading. This control was chosen deliberately after the warning that a control which itself returns zero is no control.",
"Typecheck coverage: confirmed the new pin is in tsconfig.test.json via --listFiles (1 hit), with the landed sibling pin as a must-hit control (1 hit).",
"eslint config readability control before trusting the no-type-aware-linting zero: rules 10, export default 1, files 10.",
"In-test control: a clean save asserts metaWriteCount() is 1 before asserting the sink stayed quiet, so the silence is about the absent advisory list and not a chain that never ran.",
"In-test control for the unmount case: the channel is asserted LIVE before unmount, and the post-unmount write is counted (2), so the silence is about the unsubscribe.",
"Every ablation edit script refused to write unless its anchor matched exactly once - a zero-hit edit could not masquerade as a successful mutation.",
"Exit codes captured by redirect-then-read throughout; never read through a pipe."
],
"assumptions_falsified": [
"PM assumption 'there is exactly one hand-off' is FALSE. There are THREE independently cuttable points, all in AdapterProvider.tsx: the a.onSaveAdvisory subscription, the emitSaveAdvisories call nested inside its callback, and the unsubscribe in the effect cleanup. Each was ablated separately; each left all 45 suites green. The pin covers all three, and H3 is the one a delivery-only pin would have missed - the card's own wording ('plus its unsubscribe') is what flagged it.",
"The card's '1 of 40' denominator has MOVED: it is now 1 of 41, because a suite landed since filing. The ratio and the conclusion are unchanged; recorded because the card asked for it to be re-derived.",
"PM assumption 'the seam is in AdapterProvider.tsx' is TRUE - it did not repeat the sibling card's wrong-directory path. Verified there is exactly one file named AdapterProvider in the repo.",
"PM assumption 'this needs no production-code change' is TRUE - no production code was touched.",
"NOT falsified but worth recording as the load-bearing discovery: AdapterProvider's optional adapter prop makes the effect return EARLY, before the subscription is installed. So the obvious way to write this pin - hand in a ready-made adapter - produces a test that is green against all three ablations and measures nothing. The pin therefore lets the provider build its own adapter."
],
"mcp_calls": 6,
"open_questions": [],
"out_of_scope_findings": []
}
CI convergence was not waited on, per the standing dispatch contract. The union run and every gate above were taken at the final HEAD ad32812de, after the last commit.
packages/app-shell/src/providers/saveAdvisoryToast.test.ts⚠️control — predates the PR
✅ present
The gap was confirmed by ablation, not inherited from the card's grep
This card was filed honestly at the weaker confidence level — "grep-measured, not ablation-measured" — and the dispatch made leg 0 an ablation for exactly that reason. Result: cutting the seam left 45 files / 633 tests green, zero reds, at each of three cut points.
⭐ And the transitivity question was measured, not reasoned: the sibling pin that landed an hour earlier (#6969 / PR #7118) stays green 3/3 under the same cut. Genuinely separate channels — MetadataClient → toast via the hook, versus the ObjectStackAdapter channel via the provider.
⭐⭐ The fixture trap this run avoided
AdapterProvider's optional adapter prop makes the effect return early, before the subscription is installed. So the obvious way to write this pin — hand in a prepared adapter, drive a save, assert the toast — yields a test that is green against all three ablations and measures nothing. It would have closed the card, read as rigorous, and left the hole untouched.
Passing no adapter and letting the provider run its real init() is what makes the pin load-bearing — and that is proven, not asserted: the pin goes red at all three cuts.
⚠️ This is subtler than the instrument failures this lane has been cataloguing all session. Nothing is broken; the fixture is simply too convenient, and it routes the test around the seam it is pinning. ⇒ If your pin cannot fail, it is not a pin.
⭐ Three hand-offs, not one — and the third is the one that matters
My dispatch assumed one. Measured: three independently cuttable points — the a.onSaveAdvisory subscription, the emitSaveAdvisories call nested in its callback, and the unsubscribe in the effect cleanup. Each left all 45 suites green.
The pin's ablation discriminates: H1/H2 fail the delivery cases; H3 fails only its unmount case. ⇒ A delivery-only pin would have missed the leaked subscription entirely. Same lesson #6969 produced with two hand-offs, now general: count them.
An uncontrolled zero discarded — from a gate
An earlier check-changeset-presence run printed a clean, quotable "0 file(s) changed … no changeset is owed". It was discarded, because the gate reads git diff and the new file was still untracked. After staging, the same gate said a changeset was owed. ⇒ A gate that reads the index measures what you staged, not what you wrote. Now a standing lesson on the seat post.
Also: eslint found a real bug (a module-scope binding reassigned during render) and it was fixed by moving the capture into useEffect rather than suppressed — and the three ablation legs were re-run against the final version, since a fix landing after an ablation invalidates it.
Activity
os-warren commentedon Sep 1, 2026
🔒 Claimed —
domain:uiexecution seat (objectui)session_012wwHa4aaFybxXrfmfHioDMclaude/issue-7116-adapter-provider-advisory-pinNot clause ② — a test asserting an existing connection. Nothing enters or leaves any published surface, so no
CONTRACT_REVIEW_TIERis owed and the quota cannot strand it.Dispatched on the strength of its sibling, which has now LANDED
#6969 — the same defect one seam over — landed as
7e2e6f42cminutes ago. Its shape transfers almost exactly, and its numbers are the reason this card is worth a slot rather than a shrug: cutting that seam left 226 files / 2369 tests green, zero reds, because 51 suites mocked the seam away and exactly 0 imported the real hook (control: 76 suites named it). A hole no green suite can see.⇒ Whoever takes this has a landed reference implementation for the pin shape, the ablation discipline, and the "report the greens, they tell you which layer you do NOT cover" framing.
This card was filed honestly at the weaker confidence level: 1 of 40
AdapterProvidersuites names an advisory (control: all 40 nameexpect), and that one's own docstring says it hands the sink over rather than mounting the provider. That is suggestive, ⛔ not proof.⇒ Leg 0 is an ablation, exactly as #6969's was. Cut the hand-off, run every named suite, and show they stay GREEN — that green is the finding. ⭐ If something goes red, the gap is already covered: STOP and report that. A card that turns out to be already-pinned is a valid and valuable outcome, not a failed dispatch — and given that #6969 just changed this area, it is a live possibility rather than a formality.
They are sibling channels, not the same channel: #6969 pinned the
MetadataClient→ toast seam viauseMetadataClient; this is theObjectStackAdapterchannel built by #4237, reached throughAdapterProvider.tsx. Measure the relationship rather than inheriting it — if the new pin does transitively cover this seam, that is the stop-and-report case above.Generated by Claude Code
os-warren commentedon Sep 1, 2026
os-dev-report
{ "issue": 7116, "status": "done", "branch": "claude/issue-7116-adapter-provider-advisory-pin", "pr": "https://github.com/objectstack-ai/objectui/pull/7131", "gap_still_real": true, "premise_still_valid": true, "seam_actual_location": "packages/app-shell/src/providers/AdapterProvider.tsx lines 91-93 (subscription + renderer call) and line 111 (unsubscribe). The PM path assumption was CORRECT this time, unlike the sibling card. Producer end confirmed genuinely pinned: installSaveAdvisoryInterceptor is installed in the ObjectStackAdapter CONSTRUCTOR at packages/data-objectstack/src/index.ts:2109, and onSaveAdvisory.test.ts drives a real SDK client through a fake fetch.", "handoff_count": 3, "covered_transitively_by_7118": false, "precondition_ablation": { "predicted": "GREEN at every cut - predicted BEFORE running, on the strength of a census showing 0 suites import the real AdapterProvider while 38 of 41 mock it away", "observed": "GREEN at all three cuts, exactly as predicted. Baseline first: 45 files / 633 tests green. H1 (a.onSaveAdvisory subscription deleted outright): 45 files / 633 tests green, 0 red. H2 (subscription kept, emitSaveAdvisories call inside it cut): 45 files / 633 tests green, 0 red. H3 (unsubscribe cut): 45 files / 633 tests green, 0 red.", "green_suites": "All 45: the 41 naming AdapterProvider, plus data-objectstack onSaveAdvisory.test.ts, metadata-client.saveAdvisories.test.ts, metadata-client.publishAdvisories.test.ts, and app-shell providers/saveAdvisoryToast.test.ts. Separately measured: the landed sibling pin useMetadataClient.advisorySink.test.tsx also stays green 3/3 under H1, which is the transitivity answer.", "red_suites": "none - zero reds at any of the three cuts", "blob_before": "aa396a951e9802dcaf04d46fb533aac3e24fae33 (verified equal to HEAD:packages/app-shell/src/providers/AdapterProvider.tsx before each mutation)", "blob_after": "H1 6c8b6627ba8375860d2902bb116c6538547b803a | H2 5119a9784b04c33a71c0327814b02b2b555cb6a7 | H3 bf0309de61d5b668a556648684038c9c42f81360", "restore_proven_how": "By state, never by exit code, on every leg: git checkout HEAD -- ABSOLUTE_PATH (never a bare checkout), then git diff HEAD empty YES, git diff --cached empty YES, blob hash back to aa396a95 YES, injected marker count back to 0. Mutation proven on disk by blob-hash change PLUS a marker count, never an editor exit code; each edit script refused to run unless its anchor hit exactly once. All legs carried a trap on EXIT INT TERM with an absolute REPO_ROOT path." }, "files_changed": [ "packages/app-shell/src/providers/AdapterProvider.advisorySink.test.tsx (new, 249 lines)", ".changeset/adapter-advisory-sink-pin.md (new, empty frontmatter)" ], "pin_ablation": { "predicted": "RED at each of the three hand-offs, with H3 discriminating - failing only its unmount case", "observed": "RED at all three, each for the right reason. H1: 2 failed 1 passed, expected [] to have a length of 1. H2: 2 failed 1 passed, same assertion. H3: 1 failed 2 passed, expected vi.fn() to not be called at all but actually been called 1 times. The discrimination held. Re-run on the FINAL version of the pin after a lint fix moved the capture into an effect; all three red legs reconfirmed.", "ablated_at_each_handoff": true }, "gates": [ { "name": "vitest - 45 named suites (baseline, pre-change)", "exit": 0, "verdict": "green", "raw": "Test Files 45 passed (45) | Tests 633 passed (633)" }, { "name": "vitest - 46 suites incl. new pin, at HEAD ad32812de", "exit": 0, "verdict": "green", "raw": "Test Files 46 passed (46) | Tests 636 passed (636)" }, { "name": "app-shell type-check (tsc --noEmit && tsc -p tsconfig.test.json)", "exit": 0, "verdict": "green", "raw": "0 occurrences of 'error TS'; script name echoed once (zero-match control). FIRST attempt was NOT MEASURED, not red: it failed only with 'Cannot find module @object-ui/*' on an unbuilt closure. Built the closure with pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build (exit 0) and re-ran." }, { "name": "check-changeset-presence (before adding changeset)", "exit": 1, "verdict": "red", "raw": "1 source file(s) of 1 released package(s) changed, and this change adds no changeset. Verdict quoted, not predicted. Its own text names the remedy: 'If this change really should release nothing, say so - that is a pass, not a workaround. Add .changeset with an EMPTY frontmatter.' NOTE: an earlier run of this same gate printed '0 file(s) changed ... no changeset is owed' and that reading was DISCARDED as an uncontrolled zero - the gate reads git diff and the new file was still untracked." }, { "name": "check-changeset-presence (after adding changeset)", "exit": 0, "verdict": "green", "raw": "1 source file(s) ... declares 1 changeset(s). Every one of them has an EMPTY frontmatter - declared as releasing nothing, which is the explicit exemption and a complete answer to this gate." }, { "name": "changeset:check (check-changeset-fixed + check-changeset-no-major)", "exit": 0, "verdict": "green", "raw": "All workspace packages are in the changeset fixed group. No changeset declares a major bump." }, { "name": "check-changeset-overwrite", "exit": 0, "verdict": "green", "raw": "1 changeset(s) added, 0 modified, 0 deleted. No pre-existing changeset was modified or deleted." }, { "name": "check-control-bytes", "exit": 0, "verdict": "green", "raw": "OK (scanned 5900 tracked text file(s); skipped 85 binary). Also self-scanned the new file with grep -naP for control chars: 0 hits." }, { "name": "lint:coverage", "exit": 0, "verdict": "green", "raw": "lint coverage: 46/46 packages linted, 0 with outstanding errors (0 total)." }, { "name": "type-check:coverage", "exit": 0, "verdict": "green", "raw": "test type-check coverage: 41/41 packages compile their tests, 0 declared debt." }, { "name": "eslint (plain form, new file)", "exit": 0, "verdict": "green", "raw": "clean. First run was exit 1 with a real react-hooks/globals error - reassigning a module-scope binding during render - fixed by moving the capture into useEffect." }, { "name": "pnpm lint (repo-wide scan)", "exit": null, "verdict": "NOT_MEASURED", "raw": "DECLARED NARROWING, not a skipped gate. Narrowing proven excludes nothing: population read from eslint's own config rather than guessed (1038 files under packages/app-shell, counted from --format json, 0 errors); the new file confirmed present in that population; and no type-aware linting is configured (zero hits for projectService / parserOptions / project: in eslint.config.js, with a control proving the file is readable - rules 10, export default 1, files 10), so this diff cannot move the verdict of any untouched file. Repo-wide scan is CI's." } ], "controls_used": [ "Census denominator: of the suites naming AdapterProvider, 41/41 name expect - the query is live, so the 1 dvisor hit is a reading not a dead zero.", "Zero-import census: 0 suites import the real AdapterProvider. Control against a module that IS imported by tests - saveAdvisoryToast returns 2 hits - so the zero is a reading. This control was chosen deliberately after the warning that a control which itself returns zero is no control.", "Typecheck coverage: confirmed the new pin is in tsconfig.test.json via --listFiles (1 hit), with the landed sibling pin as a must-hit control (1 hit).", "eslint config readability control before trusting the no-type-aware-linting zero: rules 10, export default 1, files 10.", "In-test control: a clean save asserts metaWriteCount() is 1 before asserting the sink stayed quiet, so the silence is about the absent advisory list and not a chain that never ran.", "In-test control for the unmount case: the channel is asserted LIVE before unmount, and the post-unmount write is counted (2), so the silence is about the unsubscribe.", "Every ablation edit script refused to write unless its anchor matched exactly once - a zero-hit edit could not masquerade as a successful mutation.", "Exit codes captured by redirect-then-read throughout; never read through a pipe." ], "assumptions_falsified": [ "PM assumption 'there is exactly one hand-off' is FALSE. There are THREE independently cuttable points, all in AdapterProvider.tsx: the a.onSaveAdvisory subscription, the emitSaveAdvisories call nested inside its callback, and the unsubscribe in the effect cleanup. Each was ablated separately; each left all 45 suites green. The pin covers all three, and H3 is the one a delivery-only pin would have missed - the card's own wording ('plus its unsubscribe') is what flagged it.", "The card's '1 of 40' denominator has MOVED: it is now 1 of 41, because a suite landed since filing. The ratio and the conclusion are unchanged; recorded because the card asked for it to be re-derived.", "PM assumption 'the seam is in AdapterProvider.tsx' is TRUE - it did not repeat the sibling card's wrong-directory path. Verified there is exactly one file named AdapterProvider in the repo.", "PM assumption 'this needs no production-code change' is TRUE - no production code was touched.", "NOT falsified but worth recording as the load-bearing discovery: AdapterProvider's optional adapter prop makes the effect return EARLY, before the subscription is installed. So the obvious way to write this pin - hand in a ready-made adapter - produces a test that is green against all three ablations and measures nothing. The pin therefore lets the provider build its own adapter." ], "mcp_calls": 6, "open_questions": [], "out_of_scope_findings": [] }Notes for the PM, outside the JSON:
ad32812de, after the last commit.packages/fields/**,packages/plugin-kanban/, orpackages/app-shell/src/views/metadata-admin/previews/__tests__/. The shared verify lock correctly serialized against sibling finding(app-shell):exclusion-reason-truthfulness's import set excludes app-shell, so a false "no renderer" on a shell singleton passes green #7117 twice during this run.Generated by Claude Code
os-warren commentedon Sep 1, 2026
🟢 LANDED — closing as completed
PR #7131 merged to
mainasbff35a07e: "test(app-shell): pin the adapter advisory sink seam — an emitted advisory reaches the toast".Landing verified with a control
packages/app-shell/src/providers/AdapterProvider.advisorySink.test.tsx— subjectmainpackages/app-shell/src/providers/saveAdvisoryToast.test.tsThe gap was confirmed by ablation, not inherited from the card's grep
This card was filed honestly at the weaker confidence level — "grep-measured, not ablation-measured" — and the dispatch made leg 0 an ablation for exactly that reason. Result: cutting the seam left 45 files / 633 tests green, zero reds, at each of three cut points.
⭐ And the transitivity question was measured, not reasoned: the sibling pin that landed an hour earlier (#6969 / PR #7118) stays green 3/3 under the same cut. Genuinely separate channels —
MetadataClient→ toast via the hook, versus theObjectStackAdapterchannel via the provider.⭐⭐ The fixture trap this run avoided
AdapterProvider's optionaladapterprop makes the effect return early, before the subscription is installed. So the obvious way to write this pin — hand in a prepared adapter, drive a save, assert the toast — yields a test that is green against all three ablations and measures nothing. It would have closed the card, read as rigorous, and left the hole untouched.Passing no adapter and letting the provider run its real
init()is what makes the pin load-bearing — and that is proven, not asserted: the pin goes red at all three cuts.⭐ Three hand-offs, not one — and the third is the one that matters
My dispatch assumed one. Measured: three independently cuttable points — the
a.onSaveAdvisorysubscription, theemitSaveAdvisoriescall nested in its callback, and the unsubscribe in the effect cleanup. Each left all 45 suites green.The pin's ablation discriminates: H1/H2 fail the delivery cases; H3 fails only its unmount case. ⇒ A delivery-only pin would have missed the leaked subscription entirely. Same lesson #6969 produced with two hand-offs, now general: count them.
An uncontrolled zero discarded — from a gate
An earlier
check-changeset-presencerun printed a clean, quotable "0 file(s) changed … no changeset is owed". It was discarded, because the gate readsgit diffand the new file was still untracked. After staging, the same gate said a changeset was owed. ⇒ A gate that reads the index measures what you staged, not what you wrote. Now a standing lesson on the seat post.Also: eslint found a real bug (a module-scope binding reassigned during render) and it was fixed by moving the capture into
useEffectrather than suppressed — and the three ablation legs were re-run against the final version, since a fix landing after an ablation invalidates it.Generated by Claude Code