Skip to content

chore: restore fleet automerge — close the Phase 3d rollout window - #299

Merged
kyle-sexton merged 1 commit into
mainfrom
chore/restore-fleet-automerge
Jul 30, 2026
Merged

chore: restore fleet automerge — close the Phase 3d rollout window#299
kyle-sexton merged 1 commit into
mainfrom
chore/restore-fleet-automerge

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Summary

Closes the claude-review-lanes Phase 3d rollout window by removing the 8 automerge: false keys and the window comment from distribution/sync-manifest.yml — the exact inverse of the window-opening commit (69788e3, standards#290). Removal, not automerge: 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 as grep -c "automerge: false" == 0.

Preconditions all verified before branching:

  • Engine pin at 8202e03f (arming gate pull-request-number != '') on main.
  • Watchdog caller at the same 8202e03f (standards#295) — the never-armed scan becomes load-bearing the moment this merges; its deadline (before restore) is satisfied.
  • Zero open chore/standards-sync PRs 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 validateManifest valid: 34 components, 8 targets, exit 0 (stage the file first — validate reads the indexed object).
  • bash distribution/sync-manifest.sh matrix → all 8 targets automerge=true as JSON boolean (the behavioral proof).
  • grep -c automerge distribution/sync-manifest.yml → 0.
  • Independent fresh-context verifier: PASS ("byte-identical to 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.md 3d pre-steps + Sanity Check (automerge-restore expectation).

…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

claude Bot commented Jul 30, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 1m 33s —— View job


Code review

  • Gather context (PR body, changed files)
  • Understand the request (review the automerge-restore diff)
  • Review diff against CLAUDE.md / REVIEW.md criteria
  • Post findings

Scope: distribution/sync-manifest.yml (+0/-10), the only changed file.

Verified claims in the PR body, against the actual repo state rather than taking them at face value:

  • git diff origin/main...HEAD -- distribution/sync-manifest.yml is byte-identical to the inverse of git show 69788e3 (standards#290) — same 8 automerge: false lines and the same 2-line window comment, nothing more, nothing less.
  • "Absent means true" is exactly what sync-manifest.sh:428-431 does (automerge_value=true default, only overridden when the key is present), and matches distribution/README.md:41-43's documented opt-out convention. Removal (not flipping to automerge: true) is the correct mechanical form.
  • grep -c automerge distribution/sync-manifest.yml0 on the PR's tree, matching the test plan.
  • Both preconditions the body cites are actually true on main right now: .github/workflows/sync.yml and .github/workflows/standards-sync-stuck-automerge-alert.yml are both pinned at 8202e03f (confirmed by reading the workflow files), and the watchdog pin landed in 89a6d12, which is already an ancestor of this branch — so the "never-armed scan becomes load-bearing" ordering claim holds.
  • File ends cleanly (no stray trailing blank line or whitespace artifact left behind by the comment removal).

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-security-review) owns any security-relevant read of the automerge/permission implications per REVIEW.md; nothing here changes that scope since the diff only removes data, it doesn't touch permissions or workflow logic directly.

@github-actions

Copy link
Copy Markdown

Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count.

@kyle-sexton
kyle-sexton merged commit add5936 into main Jul 30, 2026
43 checks passed
@kyle-sexton
kyle-sexton deleted the chore/restore-fleet-automerge branch July 30, 2026 19:04
kyle-sexton added a commit that referenced this pull request Aug 4, 2026
…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>
kyle-sexton added a commit that referenced this pull request Aug 26, 2026
## 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant