Conversation
Closes the exit criterion #3459 is actually about. v0.68.1 was tagged 2026-09-17 15:06:29Z by an autopilot copy living OUTSIDE the repository, six minutes after #3455 merged the milestone gate; `grep -c check_milestone_cut autopilot.sh` was 0. The spec required the read and no code path that cuts a tag made it. THE GATE IS INSIDE THE FUNCTION THAT TAGS. cut_tag() calls scripts/check_milestone_cut.sh ahead of `git tag`, and there is no path through it that reaches `git tag` with the gate unsatisfied. Both non-zero codes are fail-closed and they are DIFFERENT failures, named separately: rc 0 -> MILESTONE-GATE <v> clean at the cut; the tag is cut rc 1 -> the milestone holds open item(s): no tag, no publish rc 2+ -> the gate could not judge: no tag. Unknown is not a pass. THE GUARD IS BEHAVIOURAL, NOT A grep. "The file mentions the gate" is satisfied by a comment. scripts/check_tag_step_gated.sh EXTRACTS cut_tag() from the autopilot, runs it against a stubbed gate once per outcome, and asserts on whether a GIT-TAG appears in the transcript. Its --self-test then builds three mutants and requires each to be RED, and the real subject to be GREEN so a red subject cannot masquerade as a killed mutant: mutant 1 gate call deleted (the #3459 defect, restored) -> RED, 2 failing rows mutant 2 gate verdict discarded with `|| true` -> RED mutant 3 cut_tag() removed entirely -> ENV rc=2, never a pass That covers #3459's three required mutations: gate call removed => RED, gate exit 1 => no tag and no publish, gate exit 2 => no tag. contracts/tag-step-milestone-gate-v1.yaml (kind: pattern) lands in the same PR, per the ticket. `pv validate` and `pv lint` both PASS, and every one of its six falsification tests was RUN, not assumed -- which is how FALSIFY-TSMG-006 was caught asserting `test -x` on a file the repo deliberately keeps non-executable (guard_tree.sh invokes its whole universe as `bash scripts/...`, so the executable bit is not the property). The test was wrong, not the file; corrected to `test -f`. WIRING, with no .github/workflows edit and no operator check-in: guard_tree.sh's universe is exactly `git ls-files 'scripts/check_*.sh'`, a flat glob, so the guard runs in the guard-tree job -- and `ci / gate` reads needs.guard-tree.result, so it is gated by the required check transitively. #3459 notes that wiring a self-test literally inside the `ci` job would be a workflow edit; this route does not need one. SEC011 ("missing validation for 'd' before rm -rf") was real in the new guard and is fixed with ONE validated rmtree() used by every call site, not suppressed and not repeated per site. Gates, fresh worktree off origin/main 00e5d2d -- all 12 rc=0: check_tag_step_gated.sh and --self-test · check_hardcoded_paths.sh --full-if-capable check_bashrs_gate.sh and --self-test · check_apr_bin_pinned.sh check_no_pipe_into_grep_q.sh · check_shell_lint_ratchet.sh · check_guards_are_wired.sh check_contract_enforcement.sh · check_contract_test_binding.sh check_sourced_libs_option_neutral.sh NOT in this PR, deliberately: V/T/MS/EPIC and AP are still 0.68.2's. Parameterising them is its own row -- mixing it here would make the gate change unreviewable, which is the lesson this ticket has been teaching all day. The hazard is stated in the PR body: the hardcoded-path ratchet does NOT match /mnt (#3592, proved with a committed two-path probe scoring +1 not +2), so AP=/mnt/... passes every gate we own and must be changed by hand with nothing to remind anyone. Refs #3080, #3445, #3455, #3592 Pmat-Ticket: PMAT-3459 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Found while answering #3459's exit criterion 4. The self-test added in the previous commit was DISCOVERED BY NOTHING and therefore ran in no job at all: before: PASS scripts/check_tag_step_gated.sh [run] after: PASS scripts/check_tag_step_gated.sh [self-test] PASS scripts/check_tag_step_gated.sh [run] guard_tree.sh decides a guard "advertises --self-test" by looking for the literal substring `self-test` in that guard's OWN `--help` output (guard_tree.sh:47, advertises_self_test). check_tag_step_gated.sh had no --help handler, so it got one row instead of two and its three mutants were never executed by CI. The mutation proof existed and nothing ran it -- a facility with a self-test and no caller, in the commit that added the self-test. It is the same class this ticket keeps producing, and it was invisible to reading: the guard works, its self-test works, and the wiring between them did not exist. The fix is a --help handler printing the header comment, which is the idiom the rest of the tree uses (ci_run_explicit_test_commands.sh:147 and others). Verified by running guard_tree.sh --no-cargo, not by reading it: 66 checks, 0 failed, with both rows present. Refs #3080, #3459 Pmat-Ticket: PMAT-3459 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…t_tag() Throwaway branch for #3617's condition (b). Deletes ONE line -- the check_milestone_cut.sh invocation inside cut_tag() -- and nothing else, to show the named required context go RED on a real run rather than only in a local --self-test. Note the mutant still contains the string 'check_milestone_cut.sh' THREE times, in cut_tag()'s own die messages. A grep-based guard would pass this file. Only the behavioural guard, which runs cut_tag() against a stubbed gate, catches it: ok gate rc=0 -> the tag is cut FAIL gate rc=1 (milestone holds open items) -> A TAG WAS CUT ANYWAY FAIL gate rc=2 (Unknown) -> A TAG WAS CUT ANYWAY That is the v0.68.1 condition, reconstructed. This branch is never merged and is deleted once the run is cited.
|
§13.11 rung 1 — quorum shadow verdict Shadow mode: this records a verdict and merges nothing. A refusal |
Contributor
Author
|
Mutation proof complete and cited on #3617 (guard-tree → gate, both RED on this head; ci / gate green). Throwaway; closing and deleting the branch. |
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.
Throwaway, draft, never merged. Evidence for #3617 condition (b).
One line deleted: the
check_milestone_cut.shcall insidecut_tag(). Expectation:guard-treeRED (the behavioural guard refuses), thereforegateRED —gatereadsneeds.guard-tree.result != "success"and is a required context via ruleset 13878864.The mutant still contains the string
check_milestone_cut.shthree times, incut_tag()s own die messages — a grep-based guard would pass this file. Only runningcut_tag()against a stubbed gate catches it:That is the v0.68.1 condition reconstructed. Deleted once cited in #3617.
keep-open: throwaway evidence branch, closed by hand once #3617 cites the run. Refs #3459, #3617.
ont-delta: none — a throwaway mutation branch, never merged.