Review: Worktree flow — detect stale branches mid-session

review-241-2026-03-27-v3 Review

review ready

Verdict: READY

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — traces to plan-pal-e-agency Phase 16, sibling issues documented
  • [x] Repo — forgejo_admin/claude-custom
  • [x] User Story — well-formed (dev agent / stale base detection / reduce rebase churn)
  • [x] Context — thorough: documents what exists, the gap, sibling status, and resolved decision (notification-only)
  • [x] File Targets — create and do-not-touch lists both present
  • [x] Acceptance Criteria — 4 criteria, all testable
  • [x] Test Expectations — 3 manual tests covering positive, negative, and non-interference
  • [x] Constraints — hook patterns, remote detection, worktree compatibility, lightweight fetch
  • [x] Checklist — PR, tests, no unrelated changes, SOP update (separate deliverable)
  • [x] Related — links to SOPs, conventions, sibling issues, cross-repo item

Traceability

  • [x] story:dev-execute — present on board item #241
  • [x] arch:hooks — present on board item #241
  • [x] Forgejo issue — claude-custom#136, open
All three legs of the traceability triangle verified.

File Targets

  • [x] hooks/check-branch-freshness.sh — verified: does NOT exist yet (correct, new file to create)
  • [x] settings.json — verified: exists, hook wiring pattern confirmed. PreToolUse matchers for mcp__forgejo__submit_pr already exist (can be extended or a new matcher added)
  • [x] Do-not-touch list verified: post-merge-rebase.sh, post-mcp-merge-rebase.sh, check-agent-spawn.sh all exist and function as described

Repo Placement

OK. Issue filed on forgejo_admin/claude-custom, all file targets are in claude-custom. Single-repo scope.

Dependencies

  • #193 (pre-spawn freshness) — marked done, delivery VERIFIED. Commit 356c83a merged to main. Hook pre-spawn-freshness.sh exists on main and is wired in settings.json under PreToolUse/Task. The ticket's "Note on #193" paragraph is stale (says delivery unverified) but harmless — the ticket explicitly says it does NOT absorb #193 scope.
  • #194 (post-merge worktree cleanup) — marked done, delivery verified. Commit c0c534f merged to main. Logic integrated into post-merge-rebase.sh.
  • #195 (repo list fix) — marked done, commit 1137caa merged.
  • #184 (worktree enforcement gaps) — board item #485, marked done.
  • Board item #418 (cross-repo worktree isolation, pal-e-platform#188) — in todo column. Complementary, not blocking. Correctly noted in Related section.
  • No blockers found. All siblings are delivered. No in_progress items conflict.

Acceptance Criteria

4 ACs, all verifiable by an agent:
  • AC1: Warning when origin/main advances past merge-base — testable via manual push + hook trigger
  • AC2: Scoped trigger (not every tool call) — verifiable by checking settings.json wiring and testing non-matching tool calls
  • AC3: Notification-only, no auto-rebase — verifiable by confirming no git rebase in hook code
  • AC4: No interference with existing hooks — verifiable via the third test expectation
All criteria are concrete and machine-verifiable. Trigger examples given (PreToolUse on gh pr create / mcp__forgejo__submit_pr) provide clear implementation guidance.

Blast Radius

  • No existing hooks use git merge-base or compare branch divergence — no double-check risk
  • Existing git fetch calls: only in post-merge-rebase.sh (line 52), scoped to post-merge events. New hook fetches at a different trigger point (PreToolUse on PR creation). Minimal overlap.
  • pre-spawn-freshness.sh fetches at spawn time (PreToolUse/Task). The new hook fetches at PR submission time. Different lifecycle stages, no conflict.
  • Constraints section correctly mandates lightweight fetch (git fetch origin main --quiet only), multi-remote support, and worktree compatibility.

Decomposition

2 file targets, 1 repo, 4 acceptance criteria. Estimated agent time: 3-4 minutes (one new shell script + one settings.json edit). Well within the 5-minute rule. No decomposition needed.

Recommendation

  • [BODY] Minor: The "Note on #193" paragraph says delivery is unverified, but it has been verified (commit 356c83a, hook wired in settings.json on main). Consider updating to "Verified: #193 delivered in commit 356c83a" to avoid confusing the implementing agent. Non-blocking — the paragraph already says this ticket does NOT absorb #193 scope.
No other action needed. Ticket is agent-ready.