chore: restore fleet automerge — close the Phase 3d rollout window - #299
Conversation
…dow closes Removes the eight `automerge: false` entries and the rollout-window comment added by #290, returning every target to the armed opt-out default. `automerge` is opt-out policy-as-data: `distribution/sync-manifest.sh:428` treats an absent key as `true`. The manifest carried no `automerge` key at all before #290, so the restore is a removal rather than a flip to `automerge: true` — writing the key explicitly would leave eight lines restating the documented default and permanently diverge the manifest from its pre-window shape. Restore preconditions, verified before this change: - `.github/workflows/sync.yml` pins the sync engine at `8202e03f`, where auto-merge arming is gated on `pull-request-number != ''` rather than `pull-request-operation == 'created'`, so arming takes on both the create and update paths. - `.github/workflows/standards-sync-stuck-automerge-alert.yml` pins the same `8202e03f`, so the never-armed scan is in place before it becomes load-bearing. That scan filters to targets the manifest marks `automerge: true`, so it is inert while the window holds and live once this lands. - No target has an open `chore/standards-sync` pull request, so no wave PR is left unarmed by the restore. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 1m 33s —— View job Code review
Scope: Verified claims in the PR body, against the actual repo state rather than taking them at face value:
Findings: none. This is a minimal, correctly-scoped, fully mechanical revert of a temporary rollout gate — no logic, tooling, or documentation changes beyond the manifest data itself, so there's nothing for the code-review lane (correctness, error handling, tests, maintainability) to flag. The deletion-only nature of the diff also means there's no new code path needing test coverage. Note: this repo's dedicated security lane ( |
|
Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count. |
…fixed (#315) ## Summary Restores `automerge: false` on all eight sync targets in `distribution/sync-manifest.yml` — the exact inverse of #299, which removed those keys on 2026-07-30. **This is temporary.** It reverts when #274 ships the watchdog fix. ### Why The stuck-automerge watchdog that would catch an armed sync PR wedging has **never once succeeded**. `standards-sync-stuck-automerge-alert` has failed every run since 2026-07-22 — 256 of 256 as of 2026-08-03 — on the App token mint (`GET /repos/melodic-software/standards/installation` → 404), because `standards` is the sync *source*, not a target, and the sync App's selected access covers only the eight targets. That is #273; the fix is #274. #274's own triage stated the ordering: *"the Phase 3d window is the only thing currently masking a dead watchdog. When `automerge: false` is reverted, sync PRs start arming again against an alarm that has never once succeeded. The watchdog fix should gate that revert."* #299 closed the window before that fix landed, so for the last four days all eight targets have armed auto-merge on sync PRs with no working alarm behind them. This puts the gate back where the triage placed it. ### Mechanism The manifest's own opt-out idiom, not a new one: an explicit `automerge: false` per target, because absent means true — *"automerge is opt-out policy-as-data, so a target that never mentions the key keeps the fleet-default armed behavior"* (`distribution/sync-manifest.sh:428`, also `distribution/README.md:41`). #299 disarmed by *removing* the keys; this re-arms the opt-out by *restoring* them, in the same position in each target block. The comment above `targets:` states the current reason (dead watchdog, gated on #274) rather than restoring #299's Phase 3d rollout-window prose, which is now stale — Phase 3d closed. Faithful reversal applies to the mechanism, not to prose that is no longer true. **The target set is untouched.** No target added, none removed, no `managed` or `locally-owned` assignment changed, and no GitHub App installation configuration touched — the attest step requires the installation's selected set to equal the derived target set, so any addition would fail the sync for every target. ## Test plan - `bash distribution/sync-manifest.sh validate` → `Manifest valid: 34 components, 8 targets`, exit 0. - `bash distribution/sync-manifest.sh matrix` → all 8 targets emit `"automerge":false` as a JSON **boolean** (the behavioral proof, not just text). - Target-set equality proved mechanically, not by eye: `diff <(yq '.targets | map_values(del(.automerge))' -o=json)` between `origin/main` and this branch → empty. Same for `.components`. - `git diff --name-only` vs merge base → exactly one file, `distribution/sync-manifest.yml`. - `bash harness/shell/run-tests.sh distribution/sync-manifest.test.sh` → 1 passed, 0 failed. - `npm run test:runner-policy` → 242 pass, 0 fail. `npm run lint:runner-policy` → `Runner policy passed.` - Independent fresh-context verifier: **PASS** on all four checks it was given (disarms all 8 per the manifest's own semantics; target set and App access provably untouched; faithful inverse of #299 with the comment-text divergence disclosed and justified; no other `automerge` consumer broken or falsified — it separately confirmed the `runner-policy` README and the watchdog workflow header describe the disarmed state as expected behavior, so neither becomes false). ## Related No linked issue: this PR closes no GitHub issue, and deliberately leaves both of the following open. - #273 — watchdog has never run; App token mint 404s on every scheduled run. - #274 — the fix. **This PR reverts when #274 ships.** - #299 — the change being reversed. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Summary Phase 1.5 of the standards-sync audit: the `.github` canary was observed end-to-end on 2026-08-23, inside the Phase 1.4 time box. PR 62 opened at 02:28:08Z, the sync App armed auto-merge on it two seconds later (`enabledBy` the App itself, SQUASH), and it self-merged at 02:28:39Z with `mergedBy` the same App and no human action, all four required contexts green. That discharges the 1.4 gate, so the fleet re-arms. ## Fix `automerge: false` removed from 8 targets — the 7 originals (ci-runner, ci-workflows, claude-code-plugins, dotfiles, github-iac, medley, provisioning) plus codex-plugins. Absent key = armed default (schema-optional; the engine sets `automergeValue = "true"` unless the key is present, `sync-manifest.mjs:666-684`). Removal rather than an `automerge: true` flip, matching PR #299 and PR #418. (To be precise about the engine: an explicit literal `true` would be both schema-legal and engine-legal; the literal-spelling rule at `sync-manifest.mjs:678-682` only rejects non-canonical spellings such as `True` or `yes`. Removal is the house pattern because it keeps the armed default terse, not because a flip would be rejected.) Three Phase 4 targets keep the key: **agent-plugins, claude-code-proxy, cursor-plugins**. Their default branches are not covered by the org `ci-gate` ruleset (id 17989001) — the rule supplying `pr-title`, `pr-issue-linkage`, `do-not-merge` and `ci-status` as required contexts. They resolve `base` + `signing` only, so they carry no required status checks at all and an armed sync PR would merge with nothing gating it. That is proven live rather than inferred: **claude-code-proxy PR 182 merged 2026-08-23 with `ci-status`, Ruff, Pester and pytest all FAILURE**, precisely because none of them are required. agent-plugins PR 2 and cursor-plugins PR 12 each show a single GitGuardian entry as their entire check rollup. The opt-out is therefore not roster vintage — codex-plugins entered in the same Phase 4 window and **is** armed here, because it alone among the four carries `ci-gate` (verified on its PR 22: all four contexts SUCCESS). Each surviving key now carries a comment naming its own blocker and removal trigger, and the fleet-automerge header comment is re-cut to the restored state. This corrects the count in #481 and in PLAN.md Phase 1.5 (7 removals, residue 0). Both were authored on 2026-08-17 against an 8-target roster, two days before the Phase 4 expansion took it to 12; `git log -S` puts both lines in the same commit, `967ef48`. Phase 4R reconciled the Brief against the new roster but never revisited 1.5's count. Also in this PR: PLAN.md Phases 1.4 and 1.5 tagged DONE with evidence, the stale 1.5 sanity check corrected (`→ 0` was arithmetic from the 8-target era), the discharged Brief constraint marked, and a new **Phase 1.6** filed to extend `ci-gate` to the three disarmed repositories — a Pulumi change in github-iac per repo convention, never the GitHub UI or ad-hoc `gh`. ## Verification `node distribution/sync-manifest.mjs validate` → `Manifest valid: 33 components, 12 targets`, exit 0 (counts unchanged — pure policy change). `yq '[.targets[] | select(has("automerge"))] | length'` → **3**, and those three are exactly agent-plugins, claude-code-proxy, cursor-plugins. Engine-computed matrix (`sync-manifest.mjs matrix`) — 9 armed, 3 disarmed: ``` melodic-software/.github automerge=true melodic-software/agent-plugins automerge=false melodic-software/ci-runner automerge=true melodic-software/ci-workflows automerge=true melodic-software/claude-code-plugins automerge=true melodic-software/claude-code-proxy automerge=false melodic-software/codex-plugins automerge=true melodic-software/cursor-plugins automerge=false melodic-software/dotfiles automerge=true melodic-software/github-iac automerge=true melodic-software/medley automerge=true melodic-software/provisioning automerge=true ``` `npm run lint:md` → 118 files, 0 issues. Pre-commit lefthook green (editorconfig, typos, gitleaks, markdownlint). Merge-path safety for the 8 armed targets was checked the same way Phase 1.4 checked `.github`: `gh api repos/<repo>/rules/branches/main` for required contexts plus `statusCheckRollup` on each repo's most recent real bot sync PR. All 8 carry the four required contexts with `allow_auto_merge` and `allow_squash_merge` true. github-iac PR 348 is currently open and BLOCKED on a flaked `pr-title` — the armed-BLOCKED condition the now-proven watchdog reports, not a blocker to arming. The two conditional comment re-cuts from Phases 1.1 and 1.2 were checked and had already landed on `main` (ci-workflows reusable, now at lines 215-218 after file growth; the standards caller at lines 20-22). Neither becomes false when the fleet re-arms, so neither is carried here. ## Related Closes #488. Related: #481 (operator checklist — its 11 → 4 count is superseded by 11 → 3), #418 (canary), #299 (prior fleet restore), #406 (audit umbrella). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01EtfvgtanSD6nyC9JqYMz6A Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Summary
Closes the claude-review-lanes Phase 3d rollout window by removing the 8
automerge: falsekeys and the window comment fromdistribution/sync-manifest.yml— the exact inverse of the window-opening commit (69788e3, standards#290). Removal, notautomerge: true: the manifest documents absent-means-true as opt-out policy-as-data (sync-manifest.sh:428,distribution/README.md:41), and #290's own body pre-registered the post-restore check asgrep -c "automerge: false" == 0.Preconditions all verified before branching:
8202e03f(arming gatepull-request-number != '') on main.8202e03f(standards#295) — the never-armed scan becomes load-bearing the moment this merges; its deadline (before restore) is satisfied.chore/standards-syncPRs across all 8 targets (positive-control-checked).Merge effect, deliberate: merging is a push to main and fires a real sync run (benign — cardinality unchanged, engine at the fixed pin), all 8 targets enter the watchdog's scope, and sync PRs self-merge again once green. Combined with this repo's
babysit_loop_merge: c3-autonomous, this removes the two-checkpoint shape #290 installed — the intended end state of closing the window.Test plan
bash distribution/sync-manifest.sh validate→Manifest valid: 34 components, 8 targets, exit 0 (stage the file first — validate reads the indexed object).bash distribution/sync-manifest.sh matrix→ all 8 targetsautomerge=trueas JSON boolean (the behavioral proof).grep -c automerge distribution/sync-manifest.yml→ 0.69788e3^for automerge handling; the mechanical form matches the documented opt-out convention"), and it independently reached the removal-not-flip conclusion.Related
No linked issue: this PR closes no GitHub issue. Related: standards#290 (opened the window), standards#295 (watchdog re-pin), ci-workflows
docs/topics/claude-review-lanes/PLAN.md3d pre-steps + Sanity Check (automerge-restore expectation).