149 lines
3.8 KiB
Go
149 lines
3.8 KiB
Go
package inbox
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestCancelMarksThreadCancelled(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dbPath := filepath.Join(t.TempDir(), "coord.db")
|
|
runInboxCommand(t, "--db", dbPath, "--json", "init")
|
|
|
|
sendOut := runInboxCommand(
|
|
t,
|
|
"--db", dbPath,
|
|
"--json",
|
|
"send",
|
|
"--from", "leader",
|
|
"--to", "worker-a",
|
|
"--subject", "Implement cancellation",
|
|
"--summary", "Initial request",
|
|
)
|
|
|
|
var sendResp map[string]any
|
|
mustDecodeJSON(t, sendOut, &sendResp)
|
|
threadID := nestedString(t, sendResp, "data", "thread", "thread_id")
|
|
|
|
cancelOut := runInboxCommand(
|
|
t,
|
|
"--db", dbPath,
|
|
"--json",
|
|
"cancel",
|
|
"--agent", "leader",
|
|
"--thread", threadID,
|
|
"--reason", "Task superseded by a larger refactor",
|
|
)
|
|
|
|
var cancelResp map[string]any
|
|
mustDecodeJSON(t, cancelOut, &cancelResp)
|
|
if status := nestedString(t, cancelResp, "data", "thread", "status"); status != "cancelled" {
|
|
t.Fatalf("expected cancelled thread, got %q", status)
|
|
}
|
|
if kind := nestedString(t, cancelResp, "data", "message", "kind"); kind != "control" {
|
|
t.Fatalf("expected control message, got %q", kind)
|
|
}
|
|
}
|
|
|
|
func TestCancelPersistsReasonAndArtifact(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tempDir := t.TempDir()
|
|
dbPath := filepath.Join(tempDir, "coord.db")
|
|
cancelPath := filepath.Join(tempDir, "cancel.md")
|
|
if err := os.WriteFile(cancelPath, []byte("Cancelled by product decision"), 0o644); err != nil {
|
|
t.Fatalf("write cancel artifact: %v", err)
|
|
}
|
|
|
|
runInboxCommand(t, "--db", dbPath, "--json", "init")
|
|
|
|
sendOut := runInboxCommand(
|
|
t,
|
|
"--db", dbPath,
|
|
"--json",
|
|
"send",
|
|
"--from", "leader",
|
|
"--to", "worker-a",
|
|
"--subject", "Implement cancellation",
|
|
"--summary", "Initial request",
|
|
)
|
|
|
|
var sendResp map[string]any
|
|
mustDecodeJSON(t, sendOut, &sendResp)
|
|
threadID := nestedString(t, sendResp, "data", "thread", "thread_id")
|
|
|
|
runInboxCommand(
|
|
t,
|
|
"--db", dbPath,
|
|
"--json",
|
|
"cancel",
|
|
"--agent", "leader",
|
|
"--thread", threadID,
|
|
"--reason", "Task superseded by a larger refactor",
|
|
"--artifact", cancelPath,
|
|
"--artifact-kind", "brief",
|
|
)
|
|
|
|
showOut := runInboxCommand(
|
|
t,
|
|
"--db", dbPath,
|
|
"--json",
|
|
"show",
|
|
"--thread", threadID,
|
|
)
|
|
var showResp map[string]any
|
|
mustDecodeJSON(t, showOut, &showResp)
|
|
|
|
messages, ok := nestedValue(t, showResp, "data", "messages").([]any)
|
|
if !ok || len(messages) == 0 {
|
|
t.Fatalf("expected non-empty message history, got %#v", nestedValue(t, showResp, "data", "messages"))
|
|
}
|
|
|
|
lastMessage, ok := messages[len(messages)-1].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("expected message object, got %#v", messages[len(messages)-1])
|
|
}
|
|
if got := lastMessage["summary"]; got != "Task superseded by a larger refactor" {
|
|
t.Fatalf("expected cancel summary, got %#v", got)
|
|
}
|
|
if got := lastMessage["body"]; got != "Task superseded by a larger refactor" {
|
|
t.Fatalf("expected cancel body, got %#v", got)
|
|
}
|
|
artifacts, ok := lastMessage["artifacts"].([]any)
|
|
if !ok || len(artifacts) != 1 {
|
|
t.Fatalf("expected one cancel artifact, got %#v", lastMessage["artifacts"])
|
|
}
|
|
artifact, ok := artifacts[0].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("expected artifact object, got %#v", artifacts[0])
|
|
}
|
|
if got := artifact["path"]; got != cancelPath {
|
|
t.Fatalf("expected artifact path %q, got %#v", cancelPath, got)
|
|
}
|
|
if got := artifact["kind"]; got != "brief" {
|
|
t.Fatalf("expected artifact kind brief, got %#v", got)
|
|
}
|
|
}
|
|
|
|
func TestCancelRejectsWhenThreadMissing(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dbPath := filepath.Join(t.TempDir(), "coord.db")
|
|
runInboxCommand(t, "--db", dbPath, "--json", "init")
|
|
|
|
stdout, _, exitCode := executeInboxCommand(
|
|
"--db", dbPath,
|
|
"--agent", "leader",
|
|
"--json",
|
|
"cancel",
|
|
"--thread", "thr_missing",
|
|
)
|
|
if exitCode != 40 {
|
|
t.Fatalf("expected not-found exit code 40, got %d with %s", exitCode, stdout)
|
|
}
|
|
assertErrorJSON(t, stdout, "not_found")
|
|
}
|
|
|