GATE D RERUN, 29 July 2026 night. VERDICT: PASS. Every item of the protocol's Gate D list, each with the control that lets it fail. 1. THE FROZEN ENGINE. Diff 0 against e74fd2e at internal/modules/matching/engine. ANCHOR AND PATH ASSERTED FIRST, because this check has failed open twice: anchor e74fd2e exists, and the path holds 10 files at the anchor and 10 at HEAD. A diff against a missing commit or an empty path prints nothing and exits zero, which is indistinguishable from no drift. CONTROL: the same diff against the WRONG anchor 9e77f65 is 1476 lines. That number is what makes the zero mean something. AND THE ZERO IS RE EARNED FOR TONIGHT: 11 files changed since 3eeaa4d and 0 of them are under the engine path. NOTE ON MY OWN FIRST ATTEMPT EARLIER TONIGHT: I ran this against a GUESSED path holding zero files at both ends and got a clean zero. That is finding D8 reproduced by me, and it was caught only by asserting the path. 2. ZERO PYTHON, ZERO DASHES, each with a planted positive control. Python: 0 tracked, 0 untracked. CONTROL: a planted .py file is detected. Dashes: 0 across every tracked doc. CONTROL: a planted spaced dash is detected. THIS ITEM FAILED WHEN FIRST RUN TONIGHT AND WAS FIXED RATHER THAN EXCUSED. The full sweep found 110 occurrences: 59 in AI_RESEARCH.md, 37 in STACK_DECISIONS.md, 2 in a plan, 2 in a Phase 2 evidence file, 1 in AI_GROUNDING_PROGRAM.md. My earlier check tonight looked only at the files I had touched and reported 0 for each, which was true and far narrower than it read. I CHECKED WHETHER THEY WERE QUOTATIONS BEFORE TOUCHING THEM, because rewriting a quoted sentence to satisfy a house style falsifies the citation. They were our own prose, so they were fixed: em and en dashes between words became commas, and the prose was spot checked afterwards. 3. MIGRATION VERSIONS MATCH, each database queried DIRECTLY and never summarised. missionmatch (tenant, M4 5432) 85 missionmatch_staging (M4 5432) 85 missionmatch (control plane, WSL 5433) 85 PARITY WAS BROKEN BY ME EARLIER TONIGHT AND RESTORED DELIBERATELY. Migration 0085 was applied to staging first, putting it at 85 against 84 elsewhere, which is exactly the drift this item exists to catch. 0085 is guarded to act only inside missionmatch_staging, so applying it to the tenant and the control plane was a genuine no op, and both logged "skipped, this is missionmatch, not missionmatch_staging" before recording the version. The version line is level because the schema is, not because a row was inserted to make it look so. 4. BUILD FEATURE ROUTES DARK IN PRODUCTION. CONTROL FIRST, routes that DO exist: / answers 200, /api/auth/csrf answers 200. So a 404 below means absent rather than unreachable. GET /api/opportunities/tracked/{id}/scope 404 GET /api/opportunities/tracked/{id}/scope/items 404 GET /api/opportunities/tracked/{id}/amendments 404 GET /api/opportunities/{id}/documents 404 POST /api/opportunities/tracked/{id}/scope/items/{i}/split 404 POST /api/opportunities/tracked/{id}/scope/items/{i}/merge 404 AND THE STRONGER PROOF, which needs no authenticated leg to be conclusive: the production API binary hash is 8f24414531e80a9a, BYTE IDENTICAL to the pre build hash recorded before any Phase 2 work began. A binary that has not changed cannot have gained a route, so the unauthenticated 404s are explained by absence rather than by an auth layer masking a handler. 5. SECRET SWEEP, repository and out of repo. CLEAN. Working tree clean, and 15 of 15 enumerated out of repo scopes answered and clean. CONTROLS: 13, run both directions, tracked and untracked, inside and outside the repository, including a mode check controlled on a file of its own so no real credential file's permissions were loosened. No value was printed at any point. 6. NEW TENANT TABLES SPOT CHECKED. 7 of 7 correct on all four properties. opportunity_documents, opportunity_document_chunks, opportunity_scope_items, opportunity_versions, requirement_drafts, outcome_events, term_expansions. Each: organization_id present, RLS enabled, RLS FORCED, and organization_id leading an index. 7. BUILD_STATE AND REALITY AGREE. Exactly one "## SESSION HANDOFF" section and exactly one "CURRENT PHASE:" line. The task list carries 23 open items and every one traces to a recorded finding or decision. 8. INSTRUMENT CALIBRATION AT FULL SCALE, the D16 standing rule. Every instrument whose numbers are quoted in this bundle, with where it ran at the largest input this protocol can demand: stress tool 30 minute soak, 2,028,801 samples, recorded in stress/gate-b-results-2.txt. This is the instrument the rule was written from: it could never report the soak the protocol asks for until the percentile function was fixed. secret sweep 15 of 15 scopes, the full enumerated scope, not a subset. extraction pipeline 16 documents, both real solicitation packages, against functional/known-good-fixture.txt. integration suite 217 tests with EVERY optional environment variable supplied. Running it with the defaults executes 195 and silently omits 22, which is the same class of shortfall as a convenience scale soak. engine diff the whole engine path, 10 files, not a sample. 9. NO RESOURCE LIMIT OR RUNTIME CONSTRAINT CHANGED TONIGHT, so the D18 rule is not triggered rather than satisfied, and saying which of the two it is matters. Tonight's changes were an audit routing decision, a grants and policy migration, a gateway allow list registration, and four test credential fixes. No rlimit, no GOMEMLIMIT, no worker count, no timeout, no batch size. Had any changed, known-good-fixture.txt would have to be rerun and matched before the change counted. REPRODUCE. Every command is in the numbered items above; each is a single command and each carries its control.