feat: Auto-create patrol hooks for witness/refinery/deacon (gt-qpoxz)

gt rig add now creates .claude/settings.json with patrol hooks for:
- witness/ directory (SessionStart, PreCompact, UserPromptSubmit hooks)
- refinery/ directory (same hooks)

gt deacon start also creates hooks if not present (idempotent).

These hooks run `gt prime && gt mail check --inject` on session start,
enabling autonomous patrol execution when daemon sends heartbeats.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-28 09:33:02 -08:00
parent ec870b92d8
commit f90b7d9817
2 changed files with 123 additions and 0 deletions

View File

@@ -169,6 +169,11 @@ func startDeaconSession(t *tmux.Tmux) error {
return fmt.Errorf("creating deacon directory: %w", err)
}
// Ensure deacon has patrol hooks (idempotent)
if err := ensurePatrolHooks(deaconDir); err != nil {
fmt.Printf("%s Warning: Could not create deacon hooks: %v\n", style.Dim.Render("⚠"), err)
}
// Create session in deacon directory
fmt.Println("Starting Deacon session...")
if err := t.NewSession(DeaconSessionName, deaconDir); err != nil {
@@ -388,3 +393,60 @@ func runDeaconTriggerPending(cmd *cobra.Command, args []string) error {
return nil
}
// ensurePatrolHooks creates .claude/settings.json with hooks for patrol roles.
// This is idempotent - if hooks already exist, it does nothing.
func ensurePatrolHooks(workspacePath string) error {
settingsPath := filepath.Join(workspacePath, ".claude", "settings.json")
// Check if already exists
if _, err := os.Stat(settingsPath); err == nil {
return nil // Already exists
}
claudeDir := filepath.Join(workspacePath, ".claude")
if err := os.MkdirAll(claudeDir, 0755); err != nil {
return fmt.Errorf("creating .claude dir: %w", err)
}
// Standard patrol hooks
hooksJSON := `{
"hooks": {
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "gt prime && gt mail check --inject"
}
]
}
],
"PreCompact": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "gt prime"
}
]
}
],
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "gt mail check --inject"
}
]
}
]
}
}
`
return os.WriteFile(settingsPath, []byte(hooksJSON), 0600)
}