Repository navigation
PMAT-3445: no tag while the milestone being cut holds an open item — check_milestone_cut.sh at the freeze and before the tag - #3455
Conversation
The 0.68.x autopilot tag step reads no milestone; the only read is the close step, after publish. Plan for a milestone gate, a versioned tag step that calls it, and the spec/contract wiring. Grilled by a width-3 quorum before code lands. Pmat-Ticket: PMAT-3445 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… 0 open items at the cut v0.68.0 was tagged while milestone 0.68.0 held #3091 (P1, reopened 85 min before the tag) and #3450. The autopilot's tag step read no milestone; the only read was the close step, after publish. This gate exits 0 only when the named milestone has zero open issues AND pull requests, exit 1 naming each open item with its carry/close remedy, exit 2 when it cannot judge (unresolvable or duplicate title, empty milestone, a listed-vs-open_issues disagreement, gh missing/unauthenticated, a failed read). Plan v2 applies the width-3 grill's 3/3 consensus: carry = re-milestone (no comment/event scraping), no release_tag.sh (guard_tree runs only check_*.sh; it would be dark or refused as unwired), every read paginated as JSON lines. Self-test (also the bare run): 18 checks, S1..S16, no network (gh stubbed). Mutations, each on a scratch copy: (a) judge always passes -> RED: S2 S3 S4 S12 S15 S16 (6 of 18) (b) count cross-check deleted -> RED: S6 S7 (2 of 18) (c) --paginate dropped (items) -> RED: S15 (1 of 18) bashrs lint --level error: exit 0. First-green proof, live 2026-09-17: check_milestone_cut.sh 0.67.0 -> 0 (0 open, 50 closed) check_milestone_cut.sh 0.66.0 -> 0 (0 open, 10 closed) check_milestone_cut.sh 0.68.0 -> 1 (#3091 issue [bug,P1], #3450 pr) check_milestone_cut.sh 0.69.0 -> 1 (48 open at the read; milestone API open=48) Pmat-Ticket: PMAT-3445 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… equation milestone_settled_at_cut 06x-release-schedule.md §4 step 1 reads the milestone at the freeze (before the bump PR opens) and step 4 re-reads it immediately before the tag (after the bump merges) — the binding read, the one that would have seen #3091 reopened 85 min before v0.68.0. Carry = re-milestone plus a `slipped_from:` comment, never an item left open (step 8 closes on open_issues). APR-RELEASE-001 §4 T-0 and T-3 rows carry the same two reads. contracts/release-schedule-06x-v1.yaml: equation milestone_settled_at_cut, RS0-INV-007, FALSIFY-REL-06X-009 (the self-test) and -010 (both specs name the gate), qa_gate check. Verified: pv validate (pinned pv 0.68.0 via verifier_pin.sh) 0 errors; pv lint PASS; FALSIFY-010 exit 0; cargo test -p aprender-core --test readme_contract 15 passed; guard_tree.sh --dry-run --no-cargo prints `run: scripts/check_milestone_cut.sh`; check_guards_are_wired, check_no_timing_in_required, check_assertions_exclude, check_pass_grep_anchored, check_sourced_libs_option_neutral, check_bashrs_gate all exit 0. Pmat-Ticket: PMAT-3445 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Verification table (claimed vs rerun), dispatch ledger with the 3/3 v1 grill and the superseded goal lane, the autopilot-tag rehearsal (STOP, 0 write calls), I-3 attempted=2 running_peak=2 slots=3, findings F-1..F-8. The untracked autopilot tag step is filed separately; it is named in the receipt. Pmat-Ticket: PMAT-3445 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
§13.11 rung 1 — quorum shadow verdict Shadow mode: this records a verdict and merges nothing. A refusal |
|
quorum-review (AD-04): three PASS — agreed (auto_merge: checked=true was_armed=false disarmed=false) {
"ticket": "PMAT-3445",
"head": "dfe0852941cd2ddeaca8a170c8b5e2c21efca0bf",
"width": 3,
"executor": "agy",
"agreed": true,
"auto_merge": {
"checked": true,
"was_armed": false,
"disarmed": false,
"note": "auto-merge not armed"
},
"lanes": [
{
"lane": 1,
"verdict": "PASS",
"findings": 0
},
{
"lane": 2,
"verdict": "PASS",
"findings": 0
},
{
"lane": 3,
"verdict": "PASS",
"findings": 0
}
]
} |
…ut by design Found at pre-merge review (delegate-measured, orchestrator re-measured): each train's release epic sits in its own milestone (06x §5) and is closed at §4 step 8, after publish — #3078 was open in milestone 0.67.0 at the v0.67.0 tag (tagged 07:35Z, epic closed 09:14Z). The binding pre-tag read would have been RED at every cut. The gate now admits exactly one item: an issue labelled `epic` whose title is literally `EPIC: release train <M>` followed by end or whitespace, printed as ADMITTED; two claimants exit 2. A topic epic, a PR, an unlabelled look-alike and another train's epic stay ordinary open items. Self-test 25 checks (S17-S23 added). Mutations on scratch copies: (d) admission removed -> RED S17 S22 S23 (e) admission widened to any `epic` label -> RED S18 S20 S21 (a)(b)(c) still RED (a: 11 checks, b: S6 S7, c: S15) Live: 0.69.0 -> 1, ADMITTED #3080 + 24 other open; 0.70.0 -> 1, ADMITTED #3081 + 28; 0.67.0/0.66.0 -> 0. pv validate 0 errors, pv lint PASS, readme_contract 15 passed, FALSIFY-010 exit 0, check_no_claim_literals 0. 06x §4 step 1 no longer claims step 8 "closes on open_issues" (step 8 does not say so); the refusal is attributed to the train driver. Pmat-Ticket: PMAT-3445 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
quorum-review (AD-04): three PASS — agreed (auto_merge: checked=true was_armed=false disarmed=false) {
"ticket": "PMAT-3445",
"head": "b5a09b0ba0ce50f07b73f79019046eb975c87bcd",
"width": 3,
"executor": "agy",
"agreed": true,
"auto_merge": {
"checked": true,
"was_armed": false,
"disarmed": false,
"note": "auto-merge not armed"
},
"lanes": [
{
"lane": 1,
"verdict": "PASS",
"findings": 0
},
{
"lane": 2,
"verdict": "PASS",
"findings": 0
},
{
"lane": 3,
"verdict": "PASS",
"findings": 4
}
]
} |
Merge-rail artifact from quorum-review.sh round 2 (gemini-3.1-pro-high, gemini-3.8-flash-high, gemini-3.7-flash-high; author family claude). Commit touches only the verdict so it speaks for its parent. Round 1 at dfe0852 is superseded: it missed the release-epic defect and two of its lanes read lane 1 first (receipt F-9, F-10). Pmat-Ticket: PMAT-3445 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Operator triage — closing-reference defect (#3400), fired on this PR. This PR's body line For the author session, on every future PR (this one is merged, so its body is left as is):
Also check whether 3450 / 3454 / 3448 were caught by the same line. |
… of over it The operator's revision was cut from a working copy that predates #3268 and #3455; landing it verbatim deleted §4.1-4.3, §5.1, §6.1-6.4, §10-§12 (596 lines, incl. the §11.1 ont-delta rule the PR-body guard cites). This keeps main as the base and adds the revision: header notes, selector row 1a, capacity-source rule, §1.5/§1.6, the §2 rows + measurement hygiene, rule 4 group size, rule 7 (publish_strict, history kept), rules 9-15, T-0/T-2/T-3 clauses appended to main's rows, T-4 replaced, the P0 Frag/Runners/Pins/Fan-out/Unwedge rows, the milestone bullet, six §7 lines, the §8 stops, and §9 with the 0.68.1 measurements. vs main: +229 / -14, every removed line is a row that was extended or superseded by a later ruling. Pmat-Ticket: PMAT-3468 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tion, B2 split, unattended cascade; 0.68.1 SHIPPED (paiml#3474) * docs(spec): APR-RELEASE-001 revision 2026-09-17 — rules 9-15, fan-out by construction, B2 split, derived publish order, unattended cascade; 0.68.1 SHIPPED recorded in §1.6 Operator's revision, landed verbatim plus the §1.6 0.68.1 line updated with what the train measured. Refs paiml#3079 Pmat-Ticket: PMAT-3468 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * docs(spec): merge the 2026-09-17 revision ONTO main's lineage instead of over it The operator's revision was cut from a working copy that predates paiml#3268 and paiml#3455; landing it verbatim deleted §4.1-4.3, §5.1, §6.1-6.4, §10-§12 (596 lines, incl. the §11.1 ont-delta rule the PR-body guard cites). This keeps main as the base and adds the revision: header notes, selector row 1a, capacity-source rule, §1.5/§1.6, the §2 rows + measurement hygiene, rule 4 group size, rule 7 (publish_strict, history kept), rules 9-15, T-0/T-2/T-3 clauses appended to main's rows, T-4 replaced, the P0 Frag/Runners/Pins/Fan-out/Unwedge rows, the milestone bullet, six §7 lines, the §8 stops, and §9 with the 0.68.1 measurements. vs main: +229 / -14, every removed line is a row that was extended or superseded by a later ruling. Pmat-Ticket: PMAT-3468 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
… gate inside cut_tag(), 3 mutants killed (paiml#3617) * PMAT-3459: the tag step cannot be reached without a clean milestone Closes the exit criterion paiml#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 paiml#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 paiml#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 paiml#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. paiml#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 (paiml#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 paiml#3080, paiml#3445, paiml#3455, paiml#3592 Pmat-Ticket: PMAT-3459 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3459: give the tag-gate self-test a caller — it was running nowhere Found while answering paiml#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 paiml#3080, paiml#3459 Pmat-Ticket: PMAT-3459 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3459: the contract's formals carry Σ symbols; census, graph and README regenerated Fixes the three REAL reds on this PR's first run (the rest were env: gx10 ENOSPC and an intel "dep info ... No such file" mid-build, paiml#2822 class). 1. sigma gate (shard 3/3, lint_passes_on_real_contracts): two errors. - `proof_obligations[1].formal` carried an em-dash, which Σ does not declare. - formal_prose rose 1464 -> 1467: three `formal:` entries with no Σ symbol, against a shrink-only baseline. `prose: true` exempts the glyph check but NOT the ratchet (sigma_symbols.rs:107 counts before :110 checks the flag), so the fix is real formals, not a marker: ∀ rc ∈ {1, 2}: cut_tag(v, t, mc) with gate(v) = rc ⇒ ¬ tagged(t) ∧ gate(v) = 0 ⇒ tagged(t) ∀ m ∈ {gate_call_deleted, verdict_discarded, cut_tag_removed}: guard(m) ≠ 0 ∧ guard(subject) = 0 scripts/release/autopilot.sh ∈ tracked(main) ∧ cut_tag ∈ autopilot.sh The shell commands that were there belong in falsification_tests, where they already are. This is a better contract, not just a passing one. My local `pv lint` had reported "not armed: sigma" and I read that as clean. CI's test arms it. The CLAUDE.md pre-push checklist names `cargo test -p aprender-contracts --lib`, which reproduces CI exactly; I did not run it before the first push. Run now: 1666 passed, 0 failed. 2. the_tracked_repo_graph_is_fresh (shard 1/3): contracts/contracts.nt lacked the new contract's 5 triples. `pv extract contracts` with the pinned binary. 3. README claims must match measurement (guard-cargo): contracts/census.json said 1799, HEAD carries 1800. `pv census contracts --format json > contracts/census.json` (the Makefile's form -- bare `pv census` prints and writes nothing) and `scripts/readme_sync.sh --write`, CONTRACT_COUNT now 1800. All three derivatives produced with `. scripts/pv_bin.sh` (pv 0.68.2 from this tree's target dir), never a bare pv. Each of the three failing CI tests reproduced locally and re-run green. Refs paiml#3080, paiml#3459, paiml#3569 Pmat-Ticket: PMAT-3459 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3459: regenerate census, graph and README from the merged tree paiml#3617 went CONFLICTING after paiml#3614 landed: paiml#3581 and this branch each regenerated contracts/census.json, contracts/contracts.nt and README.md for their own contract additions, and git saw two edits to the same generated bytes. Resolved the only correct way for a derived file: merge origin/main (taking either side on the conflict, since it is overwritten next), then REGENERATE all three from the merged tree with the pinned pv (scripts/pv_bin.sh, pv 0.68.2) -- never by hand. A hand-merged contracts.nt is a derived file no derivation produced. Only census.json hard-conflicted. contracts.nt and README.md would have auto-merged line-wise, which is the worse case: combined derived output that happens to apply cleanly. Regenerated anyway and compared: contracts.nt is byte-identical to what git produced (15605 lines both ways) -- verified, not assumed. census 1800 -> 1801 (main's one plus this branch's one); README CONTRACT_COUNT 1801. cargo test -p aprender-contracts --lib 1666 passed, 0 failed the_tracked_repo_graph_is_fresh ok check_readme_claims.sh rc=0 check_tag_step_gated.sh --self-test rc=0 check_pr_ont_delta.sh on the merged file set PASS Refs paiml#3080, paiml#3459, paiml#3569 Pmat-Ticket: PMAT-3459 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3459: AD-04 quorum receipt — 3/3 PASS, three independent lanes docs/audits/quorum-PMAT-3459.json from quorum-review.sh --base origin/main --pr 3617 --author-model claude-opus-5, executor agy, width 3, judged at head b0e4be8: lane 1 gemini-3.1-pro-high PASS 4 findings (all confirmations, 2 cited / 2 asserted) lane 2 gemini-3.8-flash-high PASS lane 3 gemini-3.7-flash-high PASS dissent: none Independence inspected, not assumed: every lane file (lane-{1,2,3}.{json,err}) has zero references to a sibling lane, to $WORK or to the .lanes/ dir -- the recorded failure where a 3/3 was one vote read through $WORK. Three models, none in the author's family. This receipt was owed before arming and was not there: the PR was armed through arm_pr_automerge.sh, which asserts guard-tree on the head and by its own header says nothing about review. Pulled from the merge queue, judged, re-armed on this receipt. The ticket text the lanes judged against came from paiml#3461's registration (PMAT-3459's fragment lives only on that unmerged branch); it was placed in the working tree for `pmat work status` and never staged, so the diff the lanes judged is base...HEAD unchanged -- the six files this PR carries. Pmat-Ticket: PMAT-3459 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
….0 must-carry) and the epic-by-number follow-up (paiml#3461) * PMAT-3459 + PMAT-3460: register the in-repo tag path (P0, 0.69.0 must-carry) and the epic-by-number exemption tickets Roadmap only; no work started. paiml#3459 is a must-carry child of the 0.69.0 epic paiml#3080. paiml#3460 is the follow-up to paiml#3455 (milestone 0.70.0). Fragments written with roadmap_fragments.py adopt; roadmap.yaml regenerated. Pmat-Ticket: PMAT-3459 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * PMAT-3461: a registration row for the registration PR, so the quorum judges what the diff does Round 0 of this PR's quorum was 3/3 FAIL with --ticket PMAT-3459: every lane correctly observed that the diff registers PMAT-3459 and does not move the tag path into the repo. The lanes answered the question they were asked; the question was wrong — this PR IS the registration, and paiml#3599 is the tag path. Same remedy the board applied to paiml#3637 for PMAT-3604: a kind:triage row whose acceptance is the registration itself (both entries transcribed faithfully, aggregate additive, body carries keep-open and nothing GitHub parses as closing paiml#3459). The quorum re-runs with --ticket PMAT-3461. Refs paiml#3459, paiml#3460, paiml#3080 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * PMAT-3461: quorum verdict 3/3 on 8488319 (AD-04) Round 0, asked against PMAT-3459 (the implementation), was 3/3 FAIL for the right reason: the diff registers, it does not implement. Round 1, asked against PMAT-3461 (the registration), is 3/3 PASS. gemini-3.1-pro-high, gemini-3.1-pro-low, gemini-3.6-flash-high; each model measured; no dissent. Refs paiml#3459, paiml#3461 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Closes #3445
What
A release train may no longer cut a tag while the milestone being cut still has an open issue or PR.
scripts/check_milestone_cut.sh <milestone>open_issues, or gh is missing or unauthenticated.guard_tree.shpicks it up.slipped_from:comment. It is never left open, because the milestone is closed onopen_issues.contracts/release-schedule-06x-v1.yamladds equationmilestone_settled_at_cut, RS0-INV-007 and FALSIFY-REL-06X-009/010.Why
v0.68.0 was tagged 06:35Z on 2026-09-17 while milestone 0.68.0 still had #3091 open (P1, reopened 85 min before the tag). The autopilot's
tagstep read no milestone. Its only read was theclosestep, after publish.Evidence
bash scripts/check_milestone_cut.sh --self-test(also the bare run)--paginatedropped / epic admission removed / admission widened0.67.0,0.66.0(first-green on real milestones)0.68.00.69.0tagblock with the gate as its first line, write verbs stubbedSTOP … #3450, 0 write calls, no tag on the remotepv validate(pinned pv 0.68.0) /pv lintcargo test -p aprender-core --test readme_contractcheck_guards_are_wired,check_no_timing_in_required,check_assertions_exclude,check_pass_grep_anchored,check_bashrs_gatecargo fmt --all -- --check/cargo test -p aprender-contracts --lib/cargo deny check advisoriesThe plan went through a width-3 grill. v1 got 3/3
do-not-implement-as-written, and v2 applies every consensus edit (docs/audits/impl-PMAT-3445-plan.md§6). Full receipt:docs/audits/impl-PMAT-3445-receipt.md.Known gaps
b5a09b0ba). Each train's release epic is open in its own milestone until close (EPIC: release train 0.67.0 — 06x-release-schedule.md §3 (0.67.0) #3078 was open at the v0.67.0 tag), so the gate now admits exactly that one item and prints it asADMITTED. Self-test is now 25 checks, with mutations (d) and (e). Round 1's 3/3 PASS atdfe085294missed this, and lanes 2 and 3 had read lane 1's verdict first. Round 2 atb5a09b0ba: 3/3 PASS, and no lane read a sibling verdict.guard_tree --no-cargofailscheck_baseline_ratchetsandcheck_complexity_ratchetwith atool_versionmismatch only: baselines recorded under pmat 3.40.1, host runs 3.40.2. Complexity delta +0 and this PR changes no.rsfile.no-close: #3091, #3450, #3454 and #3448 are cited as evidence or follow-up, not fixed here.
ont-delta: none — the #3445 finding landed as a guard (
scripts/check_milestone_cut.sh) and a contract equation (milestone_settled_at_cut, FALSIFY-REL-06X-009/010), not as prose; no ontology type, shape or known-red list changed🤖 Generated with Claude Code