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:
@@ -256,6 +256,11 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
|
||||
if err := m.createRoleCLAUDEmd(refineryRigPath, "refinery", opts.Name, ""); err != nil {
|
||||
return nil, fmt.Errorf("creating refinery CLAUDE.md: %w", err)
|
||||
}
|
||||
// Create refinery hooks for patrol triggering (at refinery/ level, not rig/)
|
||||
refineryPath := filepath.Dir(refineryRigPath)
|
||||
if err := m.createPatrolHooks(refineryPath); err != nil {
|
||||
fmt.Printf(" Warning: Could not create refinery hooks: %v\n", err)
|
||||
}
|
||||
|
||||
// Clone repository for default crew workspace
|
||||
crewPath := filepath.Join(rigPath, "crew", opts.CrewName)
|
||||
@@ -275,6 +280,10 @@ func (m *Manager) AddRig(opts AddRigOptions) (*Rig, error) {
|
||||
if err := os.MkdirAll(witnessPath, 0755); err != nil {
|
||||
return nil, fmt.Errorf("creating witness dir: %w", err)
|
||||
}
|
||||
// Create witness hooks for patrol triggering
|
||||
if err := m.createPatrolHooks(witnessPath); err != nil {
|
||||
fmt.Printf(" Warning: Could not create witness hooks: %v\n", err)
|
||||
}
|
||||
|
||||
// Create polecats directory (empty)
|
||||
polecatsPath := filepath.Join(rigPath, "polecats")
|
||||
@@ -573,6 +582,58 @@ func (m *Manager) createRoleCLAUDEmd(workspacePath string, role string, rigName
|
||||
return os.WriteFile(claudePath, []byte(content), 0644)
|
||||
}
|
||||
|
||||
// createPatrolHooks creates .claude/settings.json with hooks for patrol roles.
|
||||
// These hooks trigger gt prime on session start and inject mail, enabling
|
||||
// autonomous patrol execution for Witness and Refinery roles.
|
||||
func (m *Manager) createPatrolHooks(workspacePath string) error {
|
||||
claudeDir := filepath.Join(workspacePath, ".claude")
|
||||
if err := os.MkdirAll(claudeDir, 0755); err != nil {
|
||||
return fmt.Errorf("creating .claude dir: %w", err)
|
||||
}
|
||||
|
||||
// Standard patrol hooks - same as deacon
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`
|
||||
settingsPath := filepath.Join(claudeDir, "settings.json")
|
||||
return os.WriteFile(settingsPath, []byte(hooksJSON), 0600)
|
||||
}
|
||||
|
||||
// seedPatrolMolecules creates patrol molecule prototypes in the rig's beads database.
|
||||
// These molecules define the work loops for Deacon, Witness, and Refinery roles.
|
||||
func (m *Manager) seedPatrolMolecules(rigPath string) error {
|
||||
|
||||
Reference in New Issue
Block a user