fix: improve state detection accuracy and notification UX

- Hook reads JSON from stdin (not env vars) matching Claude Code protocol
- end_turn = Idle (not NeedsInput); real questions come from hooks
- Permission prompt (stale tool_use) never becomes Idle
- Notifications auto-expire after 10s (--expire-time)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pierre Martin
2026-03-24 11:29:26 +01:00
parent 0e4ced5b1f
commit 001c453462
5 changed files with 41 additions and 23 deletions

View File

@@ -8,6 +8,8 @@ import (
var testNow = time.Date(2026, 3, 23, 12, 0, 30, 0, time.UTC)
func TestDetectState_EndTurnText(t *testing.T) {
// end_turn = Claude finished, prompt waiting. This is Idle, not NeedsInput.
// Real NeedsInput comes from hooks (Stop, Notification) or AskUserQuestion.
msgs := []JSONLMessage{{
Type: "assistant",
Timestamp: "2026-03-23T12:00:00Z",
@@ -19,8 +21,8 @@ func TestDetectState_EndTurnText(t *testing.T) {
}}
state := DetectState(msgs, testNow)
if state != NeedsInput {
t.Errorf("expected NeedsInput, got %v", state)
if state != Idle {
t.Errorf("expected Idle for end_turn, got %v", state)
}
}
@@ -84,6 +86,24 @@ func TestDetectState_ToolUseStale(t *testing.T) {
}
}
func TestDetectState_ToolUseStaleNeverIdle(t *testing.T) {
// A tool_use older than IdleThreshold should still be NeedsInput, not Idle
msgs := []JSONLMessage{{
Type: "assistant",
Timestamp: "2026-03-23T11:58:00Z", // 2min30s before testNow (> IdleThreshold)
Message: &MessagePayload{
Role: "assistant",
Content: []ContentBlock{{Type: "tool_use", Name: "Bash"}},
StopReason: "tool_use",
},
}}
state := DetectState(msgs, testNow)
if state != NeedsInput {
t.Errorf("expected NeedsInput for very old tool_use (permission), got %v", state)
}
}
func TestDetectState_Progress(t *testing.T) {
msgs := []JSONLMessage{{
Type: "progress",