fix(hooks): remove Stop hook that caused 30s timeouts (gt-quoj)
The Stop hook with `gt costs record` was causing 30-second timeouts on every session stop due to beads socket connection issues. Since cost tracking is disabled anyway (Claude Code doesn't expose session costs), this hook provided no value. Changes: - Remove Stop hook from settings-autonomous.json and settings-interactive.json - Remove Stop hook validation from claude_settings_check.go - Update tests to not expect Stop hook The cost tracking infrastructure remains in costs.go for future use when Claude Code exposes session costs via API or environment variable. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -65,17 +65,6 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "export PATH=\"$HOME/go/bin:$HOME/bin:$PATH\" && gt costs record"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,17 +65,6 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "export PATH=\"$HOME/go/bin:$HOME/bin:$PATH\" && gt costs record"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,8 +335,8 @@ func (c *ClaudeSettingsCheck) checkSettings(path, _ string) []string {
|
||||
// All templates should have:
|
||||
// 1. enabledPlugins
|
||||
// 2. PATH export in hooks
|
||||
// 3. Stop hook with gt costs record (for autonomous)
|
||||
// 4. gt nudge deacon session-started in SessionStart
|
||||
// 3. gt nudge deacon session-started in SessionStart
|
||||
// Note: Stop hook was removed (gt-quoj) - cost tracking is disabled
|
||||
|
||||
// Check enabledPlugins
|
||||
if _, ok := actual["enabledPlugins"]; !ok {
|
||||
@@ -359,10 +359,9 @@ func (c *ClaudeSettingsCheck) checkSettings(path, _ string) []string {
|
||||
missing = append(missing, "deacon nudge")
|
||||
}
|
||||
|
||||
// Check Stop hook exists with gt costs record (for all roles)
|
||||
if !c.hookHasPattern(hooks, "Stop", "gt costs record") {
|
||||
missing = append(missing, "Stop hook")
|
||||
}
|
||||
// Note: Stop hook with gt costs record was removed in gt-quoj.
|
||||
// Cost tracking is disabled - Claude Code doesn't expose session costs.
|
||||
// The Stop hook was causing 30s timeouts on session stop with no benefit.
|
||||
|
||||
return missing
|
||||
}
|
||||
|
||||
@@ -56,17 +56,6 @@ func createValidSettings(t *testing.T, path string) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"Stop": []any{
|
||||
map[string]any{
|
||||
"matcher": "**",
|
||||
"hooks": []any{
|
||||
map[string]any{
|
||||
"type": "command",
|
||||
"command": "gt costs record --session $CLAUDE_SESSION_ID",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -106,17 +95,6 @@ func createStaleSettings(t *testing.T, path string, missingElements ...string) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"Stop": []any{
|
||||
map[string]any{
|
||||
"matcher": "**",
|
||||
"hooks": []any{
|
||||
map[string]any{
|
||||
"type": "command",
|
||||
"command": "gt costs record --session $CLAUDE_SESSION_ID",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -156,9 +134,6 @@ func createStaleSettings(t *testing.T, path string, missingElements ...string) {
|
||||
}
|
||||
}
|
||||
hookObj["hooks"] = filtered
|
||||
case "Stop":
|
||||
hooks := settings["hooks"].(map[string]any)
|
||||
delete(hooks, "Stop")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,33 +349,6 @@ func TestClaudeSettingsCheck_MissingDeaconNudge(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaudeSettingsCheck_MissingStopHook(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
// Create stale settings missing Stop hook (at correct location)
|
||||
mayorSettings := filepath.Join(tmpDir, "mayor", ".claude", "settings.json")
|
||||
createStaleSettings(t, mayorSettings, "Stop")
|
||||
|
||||
check := NewClaudeSettingsCheck()
|
||||
ctx := &CheckContext{TownRoot: tmpDir}
|
||||
|
||||
result := check.Run(ctx)
|
||||
|
||||
if result.Status != StatusError {
|
||||
t.Errorf("expected StatusError for missing Stop hook, got %v", result.Status)
|
||||
}
|
||||
found := false
|
||||
for _, d := range result.Details {
|
||||
if strings.Contains(d, "Stop hook") {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("expected details to mention Stop hook, got %v", result.Details)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaudeSettingsCheck_WrongLocationWitness(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
rigName := "testrig"
|
||||
@@ -468,7 +416,7 @@ func TestClaudeSettingsCheck_MultipleStaleFiles(t *testing.T) {
|
||||
createStaleSettings(t, mayorSettings, "PATH")
|
||||
|
||||
deaconSettings := filepath.Join(tmpDir, "deacon", ".claude", "settings.json")
|
||||
createStaleSettings(t, deaconSettings, "Stop")
|
||||
createStaleSettings(t, deaconSettings, "deacon-nudge")
|
||||
|
||||
// Settings inside git repo (witness/rig/.claude/) are wrong location
|
||||
witnessWrong := filepath.Join(tmpDir, rigName, "witness", "rig", ".claude", "settings.json")
|
||||
@@ -1037,8 +985,7 @@ func TestClaudeSettingsCheck_TownRootSettingsWarnsInsteadOfKilling(t *testing.T)
|
||||
"env": {"PATH": "/usr/bin"},
|
||||
"enabledPlugins": ["claude-code-expert"],
|
||||
"hooks": {
|
||||
"SessionStart": [{"matcher": "", "hooks": [{"type": "command", "command": "gt prime"}]}],
|
||||
"Stop": [{"matcher": "", "hooks": [{"type": "command", "command": "gt handoff"}]}]
|
||||
"SessionStart": [{"matcher": "", "hooks": [{"type": "command", "command": "gt prime"}]}]
|
||||
}
|
||||
}`
|
||||
if err := os.WriteFile(staleTownRootSettings, []byte(settingsContent), 0644); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user