feat(coord): the dispatch gate green-lit the two verdicts that mean DO NOT BUILD (BACKLOG #1334) - #582
Open
wshallwshall wants to merge 5 commits into
Open
feat(coord): the dispatch gate green-lit the two verdicts that mean DO NOT BUILD (BACKLOG #1334)#582wshallwshall wants to merge 5 commits into
wshallwshall wants to merge 5 commits into
Conversation
…O NOT BUILD (BACKLOG #1334) `judge()` tested exactly one verdict value -- `research`. `demand-gate` and `owner-ruling`, the two that mean the item is not yours to just start, fell through and were returned as ordinary build work. Confirmed by driving judge() rather than reading it: both returned `ok` with a `code` closing act, against a positive control (`build` -> ok), a second positive control (`research`/none -> advise) and a negative control (a nonsense verdict, which also returned ok and is the residual noted below). THE OBVIOUS JUSTIFICATION FOR THIS ITEM IS FALSE AND I ALMOST SHIPPED IT. This gate green-lit BACKLOG #1336 to a dispatcher on 2026-08-24, and #1336 was not startable -- an owner ruling ~105 lines below its banner put its only remaining route out of scope. That is true, it cost this lane a slot, and it is what the item was filed on. But measured at 883f773^, #1336's banner read `Verdict: build, Closing-act: code`. This change keys on the VERDICT FIELD, so it returns `ok` on that row exactly as the old code did. IT WOULD NOT HAVE CAUGHT #1336. The banner was wrong, and a reader of the banner cannot detect a wrong banner. What fixed #1336 was a person reading the body and correcting the row (PR 578). The two are complementary -- that corrected the DATA, this corrects the READER -- and the commit says so rather than letting a true story imply a false mechanism. WHAT IT BUYS, AT ITS REAL SIZE. 31 items at 883f773 declare a gated verdict. Every one is ALREADY `advise` on its closing act, so on today's corpus this changes NO LEVEL: it changes the REASON for 31 items, from one naming only who closes them to one naming what gates them and who lifts it. Measured, same ledger, base vs fixed: base {advise 131, refuse 344, ok 124} gated-note 0 fixed {advise 131, refuse 344, ok 124} gated-note 31 items that GAINED ok: [] items that LOST ok: [] The empty GAINED set is the safety property and it is structural, not luck: the branch only appends to `notes`, and non-empty `notes` forces `advise`. The level arm is real and currently unexercised -- it fires when a gated-verdict item carries a `code` closing act, which today's 31 do not (29 close by owner-ruling, 2 by blocked). The self-test drives that case directly rather than waiting for the ledger to grow one. THE BRANCH IS UNCONDITIONAL ON `Research:` AND GOES FIRST, and both are the fix: * Not mirroring the research branch's `research in ("", "none")` guard is deliberate. A demand gate is lifted by a RULING, not by finishing research. Mirroring it is the plausible wrong fix and re-greens the item the moment a completed pass is recorded. * The closing-act note ends "That is a complete outcome, not a failure." Left to lead, it tells the reader of a gated item that shipping the code finishes the job. Ordering gets an assertion, not a comment. MUTATION-PROVED WITH THREE MUTANTS, NOT TWO, and the third is the point. Each asserts its anchor is unique and the file hash CHANGED before scoring: A branch deleted 6 red the four gated cases, the ordering test, self-test B research guard mirrored 3 red EXACTLY the two discriminators, plus self-test C `verdict != "build"` 4 red test_completed_research_with_a_code_closing_act_passes Three mutants, three distinct red sets. C is why the third exists: the design this was built from claimed its plain-build case guards against the over-broad shape. It does not -- measured, `verdict != "build"` leaves build items untouched, so that case passes over it, and the guard is the EXISTING research test. Do not trim that test as redundant. A protocol that never mutates INTO the broad shape cannot see this, which is how the claim survived. Also adds `test_the_gated_verdicts_are_a_subset_of_the_closed_vocabulary`, which makes the constant's own "must stay a subset" comment executable against `_VERDICTS` in verdict_divergence_check.py. A typo in GATED_VERDICTS would silently gate nothing and every other test here would still pass, because they all drive judge() with the spelling this module defines. SCOPE FENCE HONOURED: parts one and two only. scripts/docs/backlog_status_check.py is NOT touched -- open rows #1324 and #1338 are against that file. Two files changed, both named in the dispatch. RESIDUAL, PRE-EXISTING, NOT CLOSED HERE: an unknown or misspelled verdict still green-lights -- `zzznonsense`, `demand gate` with a space, `demandgate` all return ok, before and after. Zero instances on today's ledger. Closing it means either importing a private from another module or writing a fourth copy of the vocabulary, and that is a design call rather than part of this row. Verification, with scope: tests/test_coord_dispatch_gate.py (20, was 13) and tests/test_tooling_partition.py -- 29 passed, on .venv/Scripts/python.exe (CPython 3.14.6 non-freethreaded, seven CI extras). `dispatch_gate.py --self-test` PASS at 9 cases, was 5. ruff 0.15.22 (== the constraints.lock pin) check and format --check clean; mypy strict clean on both files. NOT the full suite. No test was removed or weakened. The ledger row is not mine to author and is not in this commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
wshallwshall
enabled auto-merge (squash)
August 25, 2026 17:51
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
dispatch_gate.py'sjudge()tested exactly one verdict value.demand-gateandowner-ruling-- the two verdicts that mean an item is not a builder's to just start -- fell through the same path as ordinary build work and came backok. docs/BACKLOG.md untouched (verified, count 0) -- not this PR's row to author.Structurally cannot widen a bypass: the fix only appends to
notes, and a non-emptynotesforcesadvise. Measured base vs fixed over the live ledger: {advise 131, refuse 344, ok 124} identical on both sides -- zero items gainedok.What it does NOT catch, stated up front rather than implied: it would not have caught #1336 (the item that prompted filing this) -- at 883f773^ that item's banner read
Verdict: build, which is a legitimately wrong banner, and a verdict-field reader cannot detect a wrong verdict field. PR 578 fixed the data; this fixes the reader. Different defects.Changes no level on today's ledger: all 31 items carrying a gated verdict are already
adviseon their closing act, so this changes the stated REASON, not the count. The level only fires when a gated-verdict item also carries acodeclosing act, and none of today's 31 do.Mutation-proved, three mutants each with a unique asserted anchor and a changed-file-hash check before scoring: branch-deleted (6 red), research-guard-mirrored (3 red, the exact two discriminators), verdict != build (4 red including an existing test -- proving the plain-build case does NOT guard the over-broad shape it was claimed to guard).
Verification, explicitly scoped: 29 tests pass (test_coord_dispatch_gate.py 20 cases, up from 13; plus test_tooling_partition.py). dispatch_gate.py --self-test passes 9 cases, up from 5. ruff/ruff format/mypy clean. Full suite not run.