diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-14 00:33:46 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-14 00:33:46 +0000 |
| commit | 6ac15be438e3692cbc2ae2f36ab2d69468fc6372 (patch) | |
| tree | f0fded632c7ade09ed4232a4ac0dd90bce795a31 /internal/executor/claude_test.go | |
| parent | e2656fcaaed85028785822493a93c7be50dd44c2 (diff) | |
fix: cancel blocked tasks + auto-complete completion reports
Two fixes for BLOCKED task issues:
1. Allow BLOCKED → CANCELLED state transition so users can cancel tasks
stuck waiting for input. Adds Cancel button to BLOCKED task cards in
the UI alongside the question/answer controls.
2. Detect when agents write completion reports to $CLAUDOMATOR_QUESTION_FILE
instead of real questions. If the question JSON has no options and no "?"
in the text, treat it as a summary (stored on the execution) and fall
through to normal completion + sandbox teardown rather than blocking.
Also tightened the preamble to make the distinction explicit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/executor/claude_test.go')
| -rw-r--r-- | internal/executor/claude_test.go | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/internal/executor/claude_test.go b/internal/executor/claude_test.go index b5f7962..36affef 100644 --- a/internal/executor/claude_test.go +++ b/internal/executor/claude_test.go @@ -494,7 +494,7 @@ func TestBlockedError_IncludesSandboxDir(t *testing.T) { scriptPath := filepath.Join(t.TempDir(), "fake-claude.sh") if err := os.WriteFile(scriptPath, []byte(`#!/bin/sh if [ -n "$CLAUDOMATOR_QUESTION_FILE" ]; then - printf '{"question":"continue?"}' > "$CLAUDOMATOR_QUESTION_FILE" + printf '{"text":"Should I continue?"}' > "$CLAUDOMATOR_QUESTION_FILE" fi `), 0755); err != nil { t.Fatalf("write script: %v", err) @@ -578,3 +578,45 @@ func TestClaudeRunner_Run_ResumeUsesStoredSandboxDir(t *testing.T) { t.Errorf("resume working dir: want %q, got %q", sandboxDir, string(got)) } } + +func TestIsCompletionReport(t *testing.T) { + tests := []struct { + name string + json string + expected bool + }{ + { + name: "real question with options", + json: `{"text": "Should I proceed with implementation?", "options": ["Yes", "No"]}`, + expected: false, + }, + { + name: "real question no options", + json: `{"text": "Which approach do you prefer?"}`, + expected: false, + }, + { + name: "completion report no options no question mark", + json: `{"text": "All tests pass. Implementation complete. Summary written to CLAUDOMATOR_SUMMARY_FILE."}`, + expected: true, + }, + { + name: "completion report with empty options", + json: `{"text": "Feature implemented and committed.", "options": []}`, + expected: true, + }, + { + name: "invalid json treated as not a report", + json: `not json`, + expected: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := isCompletionReport(tt.json) + if got != tt.expected { + t.Errorf("isCompletionReport(%q) = %v, want %v", tt.json, got, tt.expected) + } + }) + } +} |
