fix(cleanup): prove squash merges by PR record, ff the local default first, clear worktrees in groups - #600
Merged
Merged
Conversation
…first, clear worktrees in groups CHANGELOG: post-merge cleanup now proves squash merges via the PR record instead of STOPping on them, fast-forwards a stale local default before checkout, and standup can clear stale worktrees as one named group Claude-Session: https://claude.ai/code/session_01QjJeSbcwPHwMmd6CEZeagB
The ca-pi release guard requires the version bump to ride a new changelog heading; the prior commit bumped the version without one. Claude-Session: https://claude.ai/code/session_01QjJeSbcwPHwMmd6CEZeagB
The release-trace guard requires ca's manifest version to be reconciled with CHANGELOG.md's top section; add the missing heading for this PR's version bump. Claude-Session: https://claude.ai/code/session_01QjJeSbcwPHwMmd6CEZeagB
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
…ainment contract test_the_skill_carries_the_issue_308_acceptance_gates pinned the OLD Phase-1 ancestry-only wording and the OLD unconditional "-d, never -D" wording, both of which this branch deliberately replaced (#586). Repoint at the new contract instead of deleting: containment is now proven by ancestry OR the PR-record squash proof (MERGED + headRefOid == HEAD), and `-D` is forbidden everywhere except the scoped Phase-5 exception. Also fixes an assertion that was already wrap-fragile ("MUST NOT delete a remote branch" spans a line break in the rewritten Hard rules block) by matching on \s+ instead of a literal space, following the pattern the file already used elsewhere. Verified the repointed assertions actually pin the new contract: swapped in the pre-#586 SKILL.md from origin/main for one vendored copy and confirmed the test fails at the first new assertion (`contained in the fetched default`); separately reverted just the Phase-1 gate line and the Phase-5 -d/-D hard rule and confirmed the `-D` scoping assertion also fails on its own. Restored the fix before committing. CHANGELOG: repoints the #308 acceptance-gate test at the #586 content-containment contract instead of the retired ancestry-only wording, so the suite pins the current gate rather than a regression to it Claude-Session: https://claude.ai/code/session_01QjJeSbcwPHwMmd6CEZeagB
…cleanup # Conflicts: # CHANGELOG.md # README.md # package.json # plugins/ca-codex/.codex-plugin/plugin.json # plugins/ca-pi/CHANGELOG.md # plugins/ca-pi/package.json # plugins/ca/.claude-plugin/plugin.json
SUaDtL
added a commit
that referenced
this pull request
Aug 5, 2026
Union-merged the version surfaces over #601 and #600: changelog sections kept on both sides version-ordered ([2.11.5] atop [2.11.3]/[2.11.2]; ca-pi [0.2.4] atop [0.2.2]/[0.2.1]), manifests and README badge/ships line kept at this branch's higher versions, root package.json regenerated via build-host-packages. Claude-Session: https://claude.ai/code/session_01QjJeSbcwPHwMmd6CEZeagB
SUaDtL
added a commit
that referenced
this pull request
Aug 5, 2026
Resolves conflicts on the shared version surfaces against #601 (release-lane fixes, ca 2.11.2) and #600 (post-merge-cleanup containment contract, ca 2.11.3 / ca-codex 0.4.2 / ca-pi 0.2.2), both merged after this branch was cut. Resolution: this branch's version bumps (ca 2.11.4, ca-codex 0.4.3, ca-pi 0.2.3) sit strictly above main's on every changelog, README badge, and manifest; every other surface (release skill/_releaselib, post-merge-cleanup, standup, cleanup) takes main's side untouched, since this lane only edits ORCHESTRATOR.md §6. Claude-Session: https://claude.ai/code/session_01QjJeSbcwPHwMmd6CEZeagB
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.
Summary
This repo squash-merges by default, so
post-merge-cleanupPhase 1's SHA-ancestrycheck (
git merge-base --is-ancestor) failed on every normally-merged branch, whileits own prose asserted squash merges were safe to delete — a self-contradiction.
Phase 4 also assumed the local default ref was current, so a stale local
maincould make Phase 3's blocked-checkout STOP misattribute the block to a correctly-kept
artifact instead of the real cause.
core/surface/skills/post-merge-cleanup/SKILL.md— Phase 1 rewritten from bareancestry to content-containment: ancestry, or a squash-merge proof via the merged
PR record (
headRefOid == HEAD), or (withoutgh) a byte-identical tree diff.Phase 3 now distinguishes a genuinely conflicting kept artifact from a stale local
default ref. Phase 4 fast-forwards the local default ref (
git fetch origin <default>:<default>) before checking it out — git's own refusal of anon-fast-forward update on a ref not checked out preserves the
--ff-onlyguarantee — with a documented, correctly-attributed STOP if that fetch itself
refuses (another worktree holding the default). Phase 5 documents why
git branch -dalready accepts a squash-merged branch via its upstream, and sanctionsgit branch -Donly when this run's Phase 1 proof was the PR-record squash proof and-drefused, with the proof restated and the branch named.core/surface/commands/cleanup.mdandcore/surface/skills/INDEX.md—hard gate and catalog line reworded to match: containment, not bare ancestry.
core/surface/commands/standup.md(closes standup/cleanup: stale worktrees can only be cleared one confirmation at a time #596) — stale worktrees can now beconfirmed for removal as one explicitly enumerated group naming every member,
falling back to per-item confirmation on decline; branch pruning documents the
same squash-merge
-Dexception, scoped identically topost-merge-cleanup.site/src/curated/commands/cleanup.md/standup.md— hand-written docsaligned with the new contracts (no drift gate covers these).
plugins/ca,plugins/ca-codex,plugins/ca-pi) viatools/build-surface.py;--checkandsync-core --checkboth pass.
ca2.11.1 → 2.11.3,ca-codex0.4.0 → 0.4.2,ca-pi0.2.0 →0.2.2 (regenerated repo-root
package.jsonviabuild-host-packages.py).README version badge, the "currently ships
ca-codex X.Y.Z" line, and bothroot/
ca-piCHANGELOGs updated to match — each pinned by its own CI gate(
check_badge_consistency.py,readme-professional.test.ts,test_release_trace.py,build-host-packages.py --release-guard-base).Deviation from #586's suggested contract
#586 suggested the squash-merge proof require
git diff --quiet origin/<default> HEAD(byte-identical tree) and the PR record. This PR demotes the diff tocorroboration: requiring it empty re-breaks the gate the instant any later PR merges
to the default branch — the common state on an active repo, not an edge case. The
PR-record identity (
MERGED+headRefOid == HEAD) is what proves every commit onthe branch rode that PR's squash into the default; the diff is reported as a fact
either way (empty or not) but is never a requirement.
Test plan
python tools/build-surface.py --check— OK (claude, codex, pi in sync)python tools/sync-core.py --check— OK (56 core files × 3 plugins, byte-identical)git diff --check— no CR/whitespace errorspython -m pytest .github/scripts/test_build_surface.py— 40 passedpython -m pytest .github/scripts/test_release_trace.py— 29 passed, 34 subtestspython .github/scripts/test_badge_consistency.py— 11 passedpython .github/scripts/check_badge_consistency.py— consistentpython .github/scripts/payload_version_gate.py --plugin plugins/ca --base origin/main— advanced 2.11.1 → 2.11.3python .github/scripts/payload_version_gate.py --plugin plugins/ca-codex --base origin/main— advanced 0.4.0 → 0.4.2python tools/build-host-packages.py --check --release-guard-base origin/main— advanced 0.2.0 → 0.2.2cd site && npm ci && npm run build && npm test— 512/512 passedcd site && npm run typecheck— cleancd site && npm run link-audit— 20057 internal links resolveenv -u NO_COLOR python -m pytest plugins/ca/hooks/tests— 1298 passed, 130 subtests; 10 failures confirmed pre-existing/environmental (worktree-checkout git-enforce resolution, not caused by this change — reproduced identically on the unmodified tree viagit stash)Closes #586
Closes #596
https://claude.ai/code/session_01QjJeSbcwPHwMmd6CEZeagB