Date. 2026-08-15 · Item. [B-93] (two named FKs, twice-predicting). Mode. READ-ONLY, nothing built. Engine 1adcd17 deployed; production data.
The ranking, as the Operator framed it: earned by evidence — two eye-tests paid its toll, it predicted its own second instance before the fix — and sharpened by B-98's faces shipping: a conversationally-created candidate with an open finding can now be UNBLOCKED but still can't be DISCARDED. The permanent-object pair is half-closed; B-93 closes the other half.
The ordered question: are two FKs the whole set, or is "handle the FKs that point at a candidate" open-ended?
The census: 27 foreign keys reference engagements(id) (information_schema, production). discard_candidate_engagement handles exactly 4 (memory_events, memberships, engagement_api_keys, uploaded_files) plus the row itself — a per-table list grown one incident at a time. 23 are unhandled.
Of the 23, THREE are observed blockers — the census found the third before anyone paid its toll:
conversation_turns — the first (E0128's shape, CR-2026-209's cleanup).host_account.current_engagement_id — the second (visiting sets focus; two eye-tests paid it).companion_notifications — NEW, found by this census: E0129 holds one right now. The surviving control-test candidate is undiscardable today for a reason nobody has hit yet — the endpoint would 500 on companion_notifications_engagement_id_fkey before ever reaching the turns it would also 500 on. The suppression property's third prediction, caught by enumeration instead of by toll.The remaining 20 hold zero candidate rows today — and "zero today" is not "unreachable." Candidates run conversation, rooms, and job machinery (notifications just proved a "surely active-only" table reachable); any future feature that writes engagement-scoped rows during candidacy silently adds a member. The set is open-ended by construction. Two was never the number; the number changes with the schema.
The per-table DELETE list is the wrong shape — it is how the endpoint got here (4 entries, each added after a block). The right shape is the arc's own pattern, fourth application (after CR-204's AST test, CR-205's source-scrape, CR-213's kinds fence): the contract enforced against the source — here, the schema.
delete (rows about a thing being unmade — turns, notifications, uploads, events, memberships, api keys), null (stale pointers — current_engagement_id), or active_only (a declared assertion that this table cannot reference a candidate — render pipeline, manifestation views, contributors-at-commit, personal_engagement_id).active_only declarations are cheap and honest; a wrong one converts to a one-line policy change the day its table proves reachable.active_only; the drafting cost is reading, not designing.Fix-shape delta from B-93's entry: the entry's "sweep information_schema so the fix enumerates rather than chases" is confirmed and PROMOTED from a drafting step to the mechanism itself — the sweep is not preparation for the fix; the sweep-as-standing-test IS the fix's load-bearing half, exactly as the kinds fence is CR-213's.
The B-93 CR draft on the policy-plus-fence shape (engine only; the endpoint, the policy table, the schema-reading fence test, the three observed policies, twenty declarations; E0129 as the eye-test specimen, which also finally cleans up the control-test residue).
DUNIN7 — Done In Seven LLC — Miami, Florida — B-93 FK census — v0.1 — 2026-08-15 Two was never the number. Twenty-seven references, one policy each, and a fence that asks the schema — the census caught the third toll before anyone paid it.