Spec: F42 — PR Merge & Branch Hygiene
Status: partial, contract-owned (2026-07-15)
1. Problem & CEO Job
Job: Trust the signal — but the signal degrades when branches rot. This repo has 24+ open branches: 9 Dependabot PRs, 3 fleet branches with unreviewed variants, tmp branches from completed work. Stale Dependabot updates accumulate conflicts. Unmerged feature branches diverge from main. Merge debt compounds — the longer you wait, the more it costs.
2. User Stories & Acceptance Criteria
-
As a developer, I want ≤ 10 open branches at any time, so that the branch list shows only active work.
- Every open branch has an associated PR (draft or ready).
- Every open branch rebased on main within 7 days.
-
As a dependency maintainer, I want Dependabot PRs merged or closed within 7 days.
- Minor-level: reviewed and merged within 7 days.
- Major-level: reviewed within 7 days, closed with reason if not mergeable.
-
As a reviewer, I want abandoned PRs auto-closed.
- PR inactive for 14 days → bot comment “Still needed?”.
- PR inactive for 21 days → auto-closed.
-
As a developer, I want squash-merge with auto-delete-branch.
- All merges use squash-merge.
- Branch auto-deleted after merge.
-
MERGE_ORDER.mdtracks composeable branch sequence.
3. Scope Boundaries
- In: Branch hygiene rules, stale detection, squash-merge policy,
MERGE_ORDER.md, current branch cleanup. - Out: Code review process, release branching strategy, hotfix workflow, Dependabot patch auto-merge (dropped per owner decision 2026-07-02 — Dependabot PRs remain manual-review only).
4. Data Model
No model changes. GitHub repo settings + .github/workflows/ only.
5. API Contract
No API changes.
6. UI / UX
No application UI changes.
7. Test Plan
| # | Case | Type |
|---|---|---|
| 1 | Stale PR comment at 14 days | CI workflow |
| 2 | Stale PR auto-close at 21 days | CI workflow |
8. Current Behavior
24+ open branches as of 2026-06-12:
- 1 active branch:
fix/deploy - 9 Dependabot branches: accumulated patch/minor/major updates
- 6 fleet branches:
feat/fleet-A/B/C+ their-r03variants - 2 tmp branches:
tmp/pr26,tmp/pr27(dead) - The stale PR workflow is now present, but no repository-owned evidence proves live dispatch or enforcement of branch association, rebase age, merge style, branch deletion, or merge ordering.
Immediate cleanup:
- Close
tmp/pr26,tmp/pr27 - Review fleet branches — merge or close
- Review all Dependabot PRs — merge patch, review minor/major
9. Error States
- If stale automation comments on an actively reviewed PR, maintainers need a suppression label rather than manual churn every round.
- If
MERGE_ORDER.mdconflicts with actual code dependencies, the dependency graph wins and the doc must be corrected immediately.
10. Diagrams & Docs Touched
.github/workflows/repo-stale.ymlMERGE_ORDER.mdif implemented- Contribution/process docs that define branch hygiene
11. Implementation Audit
Edge Cases Catalog (formerly §10, 2026-06-14; 3 items): recently-pushed-but-stale branches still stale if no diff movement, Dependabot auto-merge needs allowlist for critical chains (auth/billing/mobile), fleet worktree branches need different hygiene rules from durable branches. Full catalog in git history.
| # | Claim | Status | Evidence |
|---|---|---|---|
| 1 | .github/workflows/repo-stale.yml (14-day stale + 7-day close, Mon–Fri 08:00 UTC) | 🚧 partial | .github/workflows/repo-stale.yml and scripts/tests/test_repo_stale_workflow.py; source matches, live GitHub execution is unverified |
| 2 | MERGE_ORDER.md | N/A | Not needed — main-branch-only workflow makes explicit ordering unnecessary |
11.1 .github/workflows/repo-stale.yml
name: Stale PR management
on:
schedule:
- cron: "0 8 * * 1-5" # 08:00 UTC Mon–Fri
workflow_dispatch: # manual trigger for cleanup
permissions:
contents: read
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 14
days-before-close: 7 # → 21 days total before closing
stale-pr-message: >
This PR has been inactive for 14 days and is marked as stale.
**Is this branch still needed?**
- If yes → rebase on main and push a commit to dismiss this label.
- If no → close the PR; the branch will be cleaned up automatically.
⏳ Auto-close in 7 days if no activity.
close-pr-message: >
This PR was automatically closed after 21 days of inactivity.
Reopen when ready to continue — the branch is preserved.
exempt-pr-labels: "wip,security,dependencies,automation"
exempt-draft-pr: true
operations-per-run: 100
enable-statistics: true
11.2 MERGE_ORDER.md (if implemented)
If the sequence of dependent PRs grows complex enough to require explicit ordering,
a MERGE_ORDER.md at the repo root tracks the merge queue. Format:
# Merge Order — 2026-06
| Priority | Branch | PR | Depends on | Status |
|----------|--------|----|------------|--------|
| 1 | feat/X | #123 | — | ✅ merged |
| 2 | feat/Y | #124 | feat/X | 🚧 in review |
The dependency graph always wins over the doc — update MERGE_ORDER.md immediately when
dependencies change.
12. Open Questions
- Fleet branches purpose: Ask team. Archive if abandoned.
- Branch naming: Enforce via PR description template, not CI.
13. Bug / Change Log
2026-07-02 — Decision: dependabot patch auto-merge dropped — not needed
Type: Owner Decision / Documentation Change
Summary:
- The product owner has reviewed the prior 2026-07-02 correction entry (which flagged
auto-merge-dependabot.ymlas absent and presented the choice of implement-or-drop) and decided: drop the promise.auto-merge-dependabot.ymlwill not be created; Dependabot PRs remain manual-review only. - Removed from §2 AC: “Patch-level: auto-merge if CI green.” Dependabot minor/major review timelines remain.
- Removed from §3 Scope In: “Dependabot auto-merge”. Moved to Out with a note.
- Removed from §11: row 2 (auto-merge-dependabot.yml ⚠️ gap) deleted; the “Open gap” note deleted; §11.2 (ABSENT gap YAML) deleted. Remaining rows renumbered (former row 3
MERGE_ORDER.mdis now row 2). - The prior 2026-07-02 “CI workflow drift correction” entry remains as historical record of how the gap was discovered. This entry supersedes its action-required outcome: the decision has been made.
Impact:
- Documentation only. No code, CI workflow, or behavior changed.
2026-07-15 — Migrate F42 into the Contract Graph
Type: Contract and evidence-boundary correction
Summary:
- Added source-level proofs for the actual
repo-stale.ymlconfiguration, including its self-hosted runner andactions/stale@v10version. - Corrected the spec’s embedded workflow example from v9 to the shipped v10 action.
- Preserved explicit gaps for live GitHub execution and all unchecked branch/merge policy promises.
2026-07-02 — CI workflow drift correction: stale.yml rename + auto-merge-dependabot.yml absent
Type: Documentation truth fix (supersedes the claims in the entry below of the same date)
Summary:
- Correction 1 — filename: The stale workflow was documented throughout this spec as
.github/workflows/stale.yml. The actual file is.github/workflows/repo-stale.yml. The 14/7-day behaviour (stale→close, Mon–Fri 08:00 UTC) is confirmed correct — only the filename was wrong. All references updated: §11 row 1, §11.1 heading. - Correction 2 — auto-merge absent:
.github/workflows/auto-merge-dependabot.ymldoes NOT exist onmain. The prior §13 entry (also dated 2026-07-02) incorrectly marked it ✅ confirmed. Verified:ls .github/workflows/— no such file;.github/dependabot.ymlis schedule-only with no merge keys;ci-fe.ymlcontains only a dep-age check job, not auto-merge. Changes made: §11 row 2 changed from ✅ match → ⚠️ gap; §11.2 heading and note updated; §2 AC “Patch-level: auto-merge if CI green” unchecked ([x]→[ ]).
Action required — decision for repo owner: The patch-level auto-merge capability was specified (§2 AC, §3 Scope) and designed (§11.2 YAML) but never implemented. The owner must choose one of:
- (a) Implement: Create
.github/workflows/auto-merge-dependabot.ymlfrom the §11.2 design — this is a security/repo-policy decision (auto-approve + auto-merge of third-party dependency PRs). Re-check the AC when shipped. - (b) Drop the promise: Remove auto-merge from §2 AC and §3 Scope; update §11 row 2 to N/A. Dependabot PRs remain manual-review only. Do NOT create the workflow without explicit owner sign-off.
2026-07-02 — Spec drift fix: check 3 confirmed-shipped ACs in §2
Type: Documentation truth fix
Summary:
- AC “Patch-level: auto-merge if CI green” checked (
[x]): confirmed by §11 row 2 ✅ (.github/workflows/auto-merge-dependabot.ymlwith--squash --delete-branchonversion-update:semver-patch). - AC “PR inactive for 14 days → bot comment ‘Still needed?’” checked (
[x]): confirmed by §11 row 1 ✅ (.github/workflows/stale.ymldays-before-stale: 14). - AC “PR inactive for 21 days → auto-closed” checked (
[x]): confirmed by §11 row 1 ✅ (days-before-stale: 14+days-before-close: 7= 21 days total). - Remaining
[ ]ACs (PR-per-branch enforcement, rebase-within-7-days, minor/major 7-day merge, squash-for-all-merges, branch-auto-delete-for-all, MERGE_ORDER.md) stay unchecked: no §11 rows confirm enforcement of these policy/process ACs beyond the Dependabot path.
2026-06-14 — Spec restructured to TEMPLATE.md canonical order (§1–§13)
Type: Documentation Change
Summary:
- §9 Implementation Audit (non-standard position) moved to §11; canonical 4-column table added (3 rows).
- §10 Edge Cases absorbed into §11 Implementation Audit note.
- §11 Error States → §9, §12 Diagrams & Docs Touched → §10, §13 Open Questions → §12.
Reason:
- Align with TEMPLATE.md canonical section order per SP fleet restructuring pass.
Impact:
- Spec authors and future implementation agents.
None yet (first version — no bugs or changes to the process itself).