Skip to content

[Chore] warn-stale-review-markers.sh — surface invalidated reviews at push-time, not merge-time #115

@atlas-apex

Description

@atlas-apex

Driver

Review markers (<pr>-rex.approved, <pr>-ceo.approved, <pr>-design.approved) are bound to a specific HEAD SHA. When the author pushes new commits to an approved PR, the markers go stale — the merge gate catches this, but only at gh pr merge time, which can be hours or days after the push. The gap creates user-visible confusion ("Rex already approved, why is the merge blocked?") and false-starts at merge time.

Scope

Add .claude/hooks/warn-stale-review-markers.sh, wired to PostToolUse on Bash matching git push ….

The hook:

  1. After a successful git push, detect the PR number for the current branch (gh pr view --json number --jq '.number').

  2. If no PR exists, exit 0.

  3. Check $(git rev-parse --show-toplevel)/.claude/session/reviews/<pr>-*.approved for markers.

  4. For each existing marker, compare its SHA (file contents) against the current pushed HEAD.

  5. If they differ, print a one-line warning per stale marker:

    ⚠ Stale review marker: <pr>-rex.approved (was <old-sha>, now <new-sha>)
      Invoke /code-review again on the new HEAD before merging.
    
  6. Optional per-config: auto-delete stale markers instead of warning (belt-and-braces — the merge gate still catches missed re-reviews, so deletion is conservative):

    # .claude/project-config.json
    review_markers:
      on_stale: warn   # or: delete

Acceptance Criteria

  • Hook fires on git push; silent if no PR exists for the branch.
  • One clear warning line per stale marker, naming the marker and the SHA diff.
  • Hook is PostToolUse, so it does not block the push.
  • on_stale: delete mode removes stale markers; default mode only warns.
  • Fresh markers (SHA matches current HEAD) produce no output.
  • Fixtures in .claude/hooks/tests/ cover: no markers, fresh markers, stale markers (warn), stale markers (delete), no PR.
  • docs/rule-audit.md entry added.

Risks / Dependencies

  • git push into a branch that doesn't have a PR yet should produce no output. Covered by the early-exit.
  • gh pr view requires network. On offline push, the hook should fail silently (exit 0) — covered.
  • Choosing on_stale: delete as default is tempting but would silently undo review state. Default to warn and let fork owners opt in.

Glossary

Term Definition
Review marker A file under .claude/session/reviews/ containing the 40-char SHA of the commit that was approved. Written by the reviewer (Rex / CEO skill / design skill), checked by the merge gate.
Stale marker A review marker whose SHA no longer matches the current HEAD of the PR — usually because new commits were pushed after approval.
PostToolUse A Claude Code hook that runs after a tool call succeeds. Cannot block; used for warnings, auditing, and cleanup.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — plan-worthy, not urgentenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions