Mindbridge Β· track status

MR-DRAIN

Suppressions and debt accumulate faster than they are drained β€” the track ratchets the hook-suppression count to shrink-only, then audits and drains it.

Re-measured 2026-08-16 from live gh issue list. Verify before starting: the 603-suppression inventory is the ratchet issue's 2026-08-02 count β€” re-run the inventory on origin/main before acting.

Next β†’the suppression ratchet (#2976) β€” ratchet FIRST: baseline today's count shrink-only so the denominator stops moving before any audit or drain.
Paused for WIRE-TRUTH. 8 open β€” the suppression ratchet (#2976, p2) first, the tracker's merged-reference blind spot (#3305, p2) second, the 8 superseded person methods (#2987, p3) last.
603Hook suppressions
584Prose-or-nothing (96%)
19Cite an issue
8Superseded methods
Open workWhy this orderStanding rulingsHistory
Ratchet β€” before any drain
p2 #2976 MR-DRAIN Part C: ratchet the 603 hook suppressions (ratchet FIRST), then audit and drain false justifications can rot unnoticed Dev only
603 hook suppressions across ten families, only 19 citing an issue β€” 584 (96%) are prose-or-nothing, so a false justification rots unnoticed. Ratchet FIRST: baseline today's count shrink-only, then audit + categorize, then drain. The gate must check justification quality β€” a new deferral must cite an open tracker β€” not just the count.
Tracker blind spot β€” before trusting counts
p2 #3305 Suppression tracker audit is blind to MERGED references β€” a noqa citing a PR is 'tracked' forever and never re-checked merged PRs evade the re-check Latent
The audit only treats CLOSED as stale; a merged PR resolves to MERGED, so a # noqa citing one passes forever. Measured on main: six cited trackers, two of them merged PRs, reported by --audit-trackers as “none closed” β€” invisible debt, and citing a merged PR is strictly better for passing the gate than citing an open issue. Fix shapes: treat MERGED as stale (the minimum), or reject PR references at write time. Fixing it will likely turn the nightly red on the two existing citations β€” resolve or re-point those two in the same change.
Superseded code β€” drain last
p3 #2987 ADR-084 leftovers: 8 person methods superseded by PersonIdentityRepository but still live on PersonData/PersonResolution eight tests guard dead code Dev only
Eight person methods still live on the older repos (PersonDataRepository, PersonResolutionRepository) while production calls only the PersonIdentityRepository twin, so eight real-DB tests guard code paths production has routed around. Split out of the V1-XFAIL drain batch (#2986, merged), which deleted three sibling methods on the same basis but left these eight because deleting eight methods from two live classes is a bigger change than a list drain and deserves its own review.
Why is it in this order?

Ratchet before drain, then close the tracker's blind spot before trusting its counts, then drain what production has routed around. Applied top to bottom; each rung only breaks ties left by the one above it.

  1. Ratchet before drain. Land the shrink-only baseline so the count stops moving (+91 in three weeks), then audit and drain β€” a drain without a ratchet chases a moving denominator.
  2. Close the tracker's blind spot before trusting its counts. A suppression citing a merged PR is classified “tracked”, drops out of the unjustified count, and has a re-check that structurally cannot fire.
  3. Drain what production has routed around. Superseded methods whose tests guard code paths production no longer calls sort last.

What this deliberately ignores: the backlog size (603 is a moving denominator β€” the ratchet moves first), issue age or filing order, how many suppressions one change removes, the apparent smallness of a deletion (the eight methods are, per their own issue, “a bigger change than a list drain”), and priority labels alone (the two p2s are ordered by the ratchet rule, not by label).

What the audit found β€” generated

Evidence below is generated from the read-only audit of 2026-08-29 and reconciled against the open issues at build time. Every claim cites the issue it came from. Nothing here is a decision β€” rulings stay in the prose above, which is written by hand.

#1323 Conversation-First Epic 4 β€” Sunsetprodhigh confidence

PR-A partially landed: `ca6d3de93` ("retire 12 legacy v1 graph-building phases + dead types (Epic 4 PR-A, #1323)", PR #1550) is on origin/main, and `backend/app/slices/` has no `inference/` directory (`git ls-tree -d origin/main backend/app/slices/` lists 20 dirs, inference absent). PR-B, PR-C, PR-D are NOT done: production schema census shows `public.nodes_v2` (111,542 exact rows) and `public.edges_v2` (233,603) still carrying the `_v2` suffix β€” the rename never happened. `git grep -n substrate_version origin/main -- backend/app` still returns `app/db/substrate_version.py` live and imported by `app/db/substrate_routing.py:28` and `app/slices/message/repo/search.py:34`. The flags survive: `backend/app/models/tenant.py:162 conversation_graph_writer_enabled: bool = True`, plus read/write endpoints at `backend/app/api/endpoints/platform/feature_flags.py:27,35,40,87`, and `legacy_extraction_disabled` documented live at `backend/app/core/config.py:638`. `org_inference_phase.py` still exists at `backend/app/slices/graph_building/phases/org_inference_phase.py`.

#1341 [Tracker] Per-slice Materializer.add_intent() paths for direct repo writes from phasescodehigh confidence

Of the six named callsites, two were deleted with their phases and four are still unconverted, with the noqa the issue says to remove still in place. Still violating: `backend/app/connectors/whatsapp/webhook_connection.py:244` and `:624` β€” both `await self._instance_repo.update(instance.id, upd) # noqa: materializer-writes` (the file moved from `webhook.py`, the pattern did not change); `backend/app/orchestration/phases/sensitivity_classification_phase.py:56` still carries the verbatim justification `# noqa: materializer-writes β€” direct SensitivityEvidenceRepository write (propagate_conversation_tiers); pre-dates ctx.repos write surface (see #1341)`, and line 458 still calls `self._sensitivity_repo.propagate_conversation_tiers()`. Gone, not fixed: `entities_phase.py` and `topic_segmentation_phase.py` no longer exist under `backend/app/orchestration/phases/` (retired by ca6d3de93); `git grep -n "get_or_create(" origin/main -- backend/app/orchestration/phases/person_resolution_phase.py` returns ZERO hits, so that third site is also gone by deletion rather than by an intent path. Scale check: `git grep -h "noqa: materializer-writes" origin/main -- backend/` counts 611 suppressions, versus the ~26 the issue body describes.

#1342 [Tracker] Add ctx.repos.messages.hybrid_search + thread ctx through ask retrievalcodehigh confidence

origin/main:backend/app/services/ask/reasoning/retrieval.py:40 still carries `from app.slices.message.repo import ( # noqa: materializer-writes β€” read-only (hybrid_search) from a service that has no ctx in scope; ... see #1342)`, and the direct call survives at retrieval.py:287 (`message_repository.hybrid_search(...)`, as_user=True). `git show origin/main:backend/app/orchestration/ctx_repos/messages.py | grep 'def '` lists 24 methods (get_messages_without_embeddings … get_latest_timestamp_for_person) and NONE is hybrid_search β€” so the requested ctx.repos surface does not exist. Sub-premise check: `git grep -n "no ctx.repos path exists for agent tools" origin/main -- backend/app` β†’ 0 hits, so the '21 ask-layer read' noqa wording in the body no longer exists in the tree; the materializer-writes noqa population is now 148 files (`git grep -c 'noqa: materializer-writes' origin/main -- backend/app | wc -l`).

#1410 Migrate app/services/ask/ β†’ app/slices/ask/ (vertical-slice alignment)codehigh confidence

`git ls-tree -r --name-only origin/main backend/app/services/ask/ | wc -l` β†’ 93 files (grown from the body's ~43); `git ls-tree -r --name-only origin/main backend/app/slices/ask/ | wc -l` β†’ 0. The slice does not exist. HOWEVER the body's headline cost is STALE: .pre-commit-config.yaml:352-358 now reads 'Collect ALL of `app/` recursively so the tests run against the same tree --cov=app measures β€” enumerated globs silently dropped colocated tests outside `app/slices/` (app/core, app/services, ...)', and colocated tests now live inside the tree (derived_test.py, graph_traversal_test.py, tools/_candidate_disclosure_test.py, reasoning/surface_relevant_to_now_test.py, plus app/services/ask/tests/integration/). So the coverage-hook rationale is closed; only the slice-gate/public-API rationale remains.

#2976 MR-DRAIN Part C: ratchet the 603 hook suppressions (ratchet FIRST), then audit and draincodehigh confidence

Step 1 (the ratchet, which the issue's own checklist puts FIRST) has SHIPPED and is reachable, not merely present: `backend/scripts/hooks/suppression_ratchet.py` + `backend/scripts/hooks/suppression_baseline.json` (32,241 bytes, per-file→rule→kind counts) exist on origin/main, and the hook is WIRED in `.pre-commit-config.yaml:235-242` (`id: suppression-ratchet`, `files: ^backend/(app|scripts|tests)/.*\.py$`, `pass_filenames: false`). The design constraints the issue demanded were honoured: the baseline distinguishes `tracked` (cites #NNNN) / `permanent` / `unjustified`, gates unjustified growth specifically, and records `malformed` tokens matching no rule — closing the PERMANENT-vs-DEFERRED conflation and the malformed `# noqa: function-level import` family the body called out. The openness half the issue said a count-only ratchet cannot see also shipped: `.github/workflows/suppression-tracker-nightly.yml` (`cron: 0 6 * * 1`, calls `suppression_ratchet.py --audit-trackers`), whose header states exactly this issue's premise. A companion `backend/scripts/hooks/noop_suppression_check.py` is wired at .pre-commit-config.yaml:267-271. Step 2 (audit) was executed and reported in the issue's own comment. What remains open is steps 3-4 (document per-category rulings, drain), which are a different, smaller task than the issue title. Prod cross-check: the weekly tracker job ran 2026-08-24 and ended `failure` (2 of last 3) — consistent with its documented design of exiting non-zero when stale trackers are found, but I did not read the run log.

#2987 [L2-g4-w6] ADR-084 leftovers: 8 person methods superseded by PersonIdentityRepository but…codehigh confidence

6 of the 8 rows are still exactly as described on origin/main; 2 are stale. Still present as dead twins: `find_person_by_email` (person_resolution_repository.py:113), `find_person_by_phone` (:89), `find_persons_by_display_name` (:67), `link_person_to_user` (person_data_repository.py:117), `update_person_user_id` (:499), `merge_person_properties` (:535). Every non-test production call site resolves on the PersonIdentityRepository receiver, not these: identity_service.py:334,590,605,389; jid_auto_matcher.py:190,215,323; webhook_connection.py:472,501; profile_fetch_queue.py:573; platform_service.py:394 β€” all `person_identity_repo.`/`_person_identity_repo.`. Search that establishes the absence of callers on the old receivers: `git grep -n "\.<method>(" origin/main -- backend | grep -v test`, population = every .py under backend/ on origin/main, run for all 8 names; the only non-test hits are the identity-repo receivers listed plus one intra-class self-call at person_identity_reads_repository.py:316. Stale rows: `find_person_node_ids_by_user_ids` no longer exists anywhere on origin/main (`git grep -n "def find_person_node_ids_by_user_ids" origin/main -- backend` β†’ no output) β€” both the PersonDataRepository copy (deleted by PR #3169, per the issue comment) and the identity twin are gone; and `find_unlinked_persons` now exists only on person_identity_admin_repository.py:280, so its PersonDataRepository copy is already removed.

#3305 Suppression tracker audit is blind to MERGED references β€” a noqa citing a PR is 'tracked'…codehigh confidence

backend/scripts/hooks/suppression_ratchet.py:466 on origin/main still reads `if probe.stdout.strip() == "CLOSED":` and nothing else; `git grep -n 'MERGED' origin/main -- backend/scripts/hooks/suppression_ratchet.py` returns no hits (all MERGED handling in the repo lives under scripts/auto_fix/, a different tool). Line 476 still prints `tracker audit: OK ({len(cited)} distinct tracker(s) cited, none closed)`, so fix shape 3 is unimplemented too. The three commits touching this file since the ratchet was built β€” f05473b63, 65fd52ac7, 9843e6dcf (PR #3606, most recent) β€” none touch audit_trackers. Compounding, from the prod cron census: suppression-tracker-nightly.yml (`0 6 * * 1`) FAILED 2 of its last 3 weekly runs, so the audit itself is not green.

Open questions β€” what the audit could not settle
  • #1323 Whether every tenant is actually v2-only, which PR-B presupposes. Close with: `select count(*), conversation_graph_writer_enabled, legacy_extraction_disabled from public.tenants group by 2,3;` against prod (35 tenant rows).
  • #1341 How many of the 611 suppressions are the direct-write pattern versus the import-only pattern β€” that decides whether a ratchet is viable. Close with: `git grep -h "noqa: materializer-writes" origin/main -- backend/ | grep -cE "^\\s*(await |)self\\._?[a-z_]*repo\\."` versus the same grep on lines starting `from `/`import `.
  • #1342 Whether the 3 sibling ask noqa sites (content_resolver.py:642, tools/find_attachment.py:352, tools/search_messages.py:135) are meant to close with the same fix β€” the body's counted population no longer exists verbatim. Close with: git grep -n 'noqa: materializer-writes' origin/main -- backend/app/services/ask
  • #1410 The current import/string-reference blast radius (body says ~460 imports, 331 string literals) was not re-counted. Close with: git grep -c 'app\.services\.ask' origin/main -- backend | wc -l and git grep -n '"app\.services\.ask' origin/main -- backend | wc -l
  • #2976 Whether the weekly suppression-tracker failures are the intended stale-tracker verdict or an infra/auth failure (i.e. whether the openness invariant is actually reporting). Closes with: `gh run list --workflow=suppression-tracker-nightly.yml --limit 3 --json databaseId,conclusion` then `gh run view <id> --log | sed -n '/Audit cited trackers/,/^$/p'`. Also unclosed: current directive count vs the 603/654 in the body β€” closes with `cd backend && poetry run python scripts/hooks/suppression_ratchet.py --update-baseline --dry-run` (or regenerating and diffing suppression_baseline.json).
  • #2987 Whether a non-grep consumer holds the old copies alive (registry entries, __init__ exports, DI providers, dynamic dispatch) β€” the 'no caller is not dead' seam the issue's own gotchas name. Closes with: `codegraph_explore "PersonResolutionRepository PersonDataRepository callers and exports"` plus `git grep -n "PersonResolutionRepository\|PersonDataRepository" origin/main -- backend/app/slices/graph_building/repositories/__init__.py backend/app/**/deps.py`.
  • #3305 Whether the two cited merged PRs (#1695, #1834) are still cited on current main and whether the six-reference census holds β€” it was measured 2026-08-14 and three ratchet commits have landed since. Closes with: `cd backend && python scripts/hooks/suppression_ratchet.py --audit-trackers`. Also open: why the weekly nightly fails β€” `gh run list -w suppression-tracker-nightly.yml -L 5 --json conclusion,databaseId` then `gh run view <id> --log-failed`.
Not yet assessed β€” filed after the audit
  • #1351 ADR-071 Wave 3: add orchestrator-entrypoint E2E for graph materialization

Standing rulings

track-order.json records no decided rulings for this track. The rulings in force are the two the page already cites: ratchet FIRST β€” baseline today's count shrink-only, then audit and drain (owner ruling 2026-08-02, stated in the suppression ratchet, #2976); and paused for WIRE-TRUTH, resume at the ratchet (the index row).
History & forensics

The ratchet's measured instance. A # noqa justification (“deferred to post-Landing-11 read-API migration”) was false for 2.5 months β€” Landing 11 closed 2026-05-16 β€” and nothing noticed. The per-file .ai/materializer-write-allowlist.txt that once counted suppressions was drained 145 β†’ 0 and deleted 2026-07-12 (the allowlist retirement, PR #2411). Over that window per-line noqa went 211 β†’ 425, then 425 β†’ 516.

Blind-spot provenance. The merged-reference hole was found by the round-3 adversarial lens on the no-op suppression drain (PR #3302, merged β€” retired 22 no-op suppressions). The two merged PRs cited as trackers are the WhatsApp reply/mention context PR #1695 and the live Exchange staged-drain PR #1834.

Superseded-methods provenance. The 8-method issue split out of the V1-XFAIL drain batch (#2986, merged β€” drained test_person_repositories_e2e.py 66 β†’ 51), which deleted three sibling methods on the same zero-caller basis.