docs: add Stop hook design doc
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# Stop Hook Design
|
||||
|
||||
**Date:** 2026-02-21
|
||||
**Scope:** Project-level Claude Code hooks for Gravl
|
||||
|
||||
## Goal
|
||||
|
||||
Prevent Claude from stopping mid-session without completing its work. Two enforced conditions:
|
||||
|
||||
1. No uncommitted changes to tracked files
|
||||
2. No unresolved conversational TODOs or promises
|
||||
|
||||
## Approach
|
||||
|
||||
Two parallel hooks registered in `.claude/settings.json` under the `Stop` event. Both run every time Claude considers stopping.
|
||||
|
||||
## Hook 1 — Git Clean Check (command)
|
||||
|
||||
**File:** `.claude/hooks/git-clean-check.sh`
|
||||
|
||||
Uses `git diff --name-only HEAD` to detect modified tracked files that were not committed. Untracked files (e.g. `frontend/dist/`, planning docs) are intentionally ignored to avoid false positives.
|
||||
|
||||
- Exit 2 + JSON to stderr → blocks Claude from stopping, feeds reason back
|
||||
- Exit 0 + JSON to stdout → approves
|
||||
|
||||
## Hook 2 — Conversation TODO Check (prompt)
|
||||
|
||||
A prompt hook that reads the conversation transcript and looks for unresolved work: phrases like "I'll fix X later", "TODO:", "we should also…", or any task Claude mentioned but did not complete. Returns `approve` or `block` with a list of unresolved items.
|
||||
|
||||
## File Layout
|
||||
|
||||
```
|
||||
.claude/
|
||||
settings.json # Hook registration
|
||||
hooks/
|
||||
git-clean-check.sh # Git dirty state check
|
||||
```
|
||||
|
||||
## Decisions
|
||||
|
||||
- **Modified tracked files only (not untracked):** `frontend/dist/` and `.planning/` untracked files would cause constant false positives with a full `git status --porcelain` check.
|
||||
- **Prompt hook for TODOs (not grep):** The goal is conversational promises, not code comments. A prompt hook reads the transcript and can reason about intent.
|
||||
- **Project-level, not plugin:** These checks are specific to Gravl's GSD commit workflow; no plugin abstraction needed.
|
||||
Reference in New Issue
Block a user