Skip to content

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

Merged
noahgift merged 6 commits into
mainfrom
PMAT-3445-t0-milestone-gate
Sep 17, 2026
Merged

noahgift merged 6 commits into
mainfrom
PMAT-3445-t0-milestone-gate

Conversation

@noahgift

@noahgift noahgift commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

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>
    • Exit 0 only when the milestone has 0 open issues and PRs.
    • Exit 1 names each open item, with the exact carry or close command.
    • Exit 2 when it cannot judge: the title matches no milestone or several, the milestone is empty, the item list disagrees with open_issues, or gh is missing or unauthenticated.
    • Run with no arguments, it runs its self-test. guard_tree.sh picks it up.
  • 06x-release-schedule.md §4 and APR-RELEASE-001 §4 (T-0 and T-3). The milestone is read at the freeze, before the bump PR opens, and read again immediately before the tag. The second read is binding.
    • A carried item is moved to the next milestone with a slipped_from: comment. It is never left open, because the milestone is closed on open_issues.
  • Contract. contracts/release-schedule-06x-v1.yaml adds equation milestone_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 tag step read no milestone. Its only read was the close step, after publish.

Evidence

Check Result
bash scripts/check_milestone_cut.sh --self-test (also the bare run) exit 0, 25 checks
mutation: judge always passes / count cross-check deleted / --paginate dropped / epic admission removed / admission widened exit 1 each
live 0.67.0, 0.66.0 (first-green on real milestones) exit 0, exit 0
live 0.68.0 exit 1, named #3091 (P1) and #3450
live 0.69.0 exit 1, 48 open (matches the milestone API)
rehearsal: the autopilot's tag block with the gate as its first line, write verbs stubbed STOP … #3450, 0 write calls, no tag on the remote
pv validate (pinned pv 0.68.0) / pv lint 0 errors / PASS
cargo test -p aprender-core --test readme_contract 15 passed
check_guards_are_wired, check_no_timing_in_required, check_assertions_exclude, check_pass_grep_anchored, check_bashrs_gate exit 0
cargo fmt --all -- --check / cargo test -p aprender-contracts --lib / cargo deny check advisories exit 0 / 1538 passed / ok

The 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

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

noahgift and others added 4 commits September 17, 2026 15:21
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>
@noahgift noahgift added this to the 0.69.0 milestone Sep 17, 2026
@github-actions

github-actions Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

§13.11 rung 1 — quorum shadow verdict

S13-SHADOW pr=3455 head=fdbf19c7366c215099e1b2d9427d5cc9e63c25d2 verdict=REFUSE class=Q1 arm_rc=1

Shadow mode: this records a verdict and merges nothing. A refusal
to arm is not a block (§13 adds zero rows to §7) — the pull request is
exactly as green as it was.

@noahgift

Copy link
Copy Markdown
Contributor Author

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>
@noahgift

Copy link
Copy Markdown
Contributor Author

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>
@noahgift
noahgift enabled auto-merge September 17, 2026 14:15
@noahgift
noahgift added this pull request to the merge queue Sep 17, 2026
Merged via the queue into main with commit d79a687 Sep 17, 2026
18 of 19 checks passed
@noahgift
noahgift deleted the PMAT-3445-t0-milestone-gate branch September 17, 2026 15:00
@noahgift

Copy link
Copy Markdown
Contributor Author

Operator triage — closing-reference defect (#3400), fired on this PR.

This PR's body line no-close: #3091, #3450, #3454 and #3448 … was parsed by GitHub as close: #3091. closingIssuesReferences listed issue 3091 next to the intended 3445, and the merge at 2026-09-17T15:00:01Z closed issue 3091 three seconds later — its third wrongful close. It has been reopened with an explanation; nothing here fixed it.

For the author session, on every future PR (this one is merged, so its body is left as is):

  1. No closing keyword (close/closes/closed/fix/fixes/fixed/resolve/resolves/resolved), and no …close: #N pattern such as no-close: #N, may sit before a #-reference you do not intend to close. Write "issue 3091" (no #) when citing evidence or follow-ups.
  2. Before arming auto-merge, read back gh pr view <n> --json closingIssuesReferences and require it to equal the intended set exactly.
  3. After merge, verify each cited-but-not-fixed issue is still open.

Also check whether 3450 / 3454 / 3448 were caught by the same line.

noahgift added a commit that referenced this pull request Sep 17, 2026
… 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant