summaryrefslogtreecommitdiff
path: root/internal/storage/events_test.go
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-05-23 08:10:03 +0000
committerClaude <noreply@anthropic.com>2026-05-23 08:10:03 +0000
commitb72978f4454235a00a2e5c92b5332b985cc08fa9 (patch)
tree71b0917d0ba8393173498b1792a13e8a353ad5c6 /internal/storage/events_test.go
parentdc97d7ae00bd25668ba495fba249ceade0c6b100 (diff)
feat(storage): dual-write question/summary/interaction flows to events
The legacy task columns (question_json, summary, interactions_json) now also emit events in the same transaction as the column update: - UpdateTaskQuestion(non-empty) -> clarification_request (agent); the empty-string clear-on-answer emits nothing - UpdateTaskSummary -> summary (agent) - AppendTaskInteraction -> clarification_answer (user) This populates the event stream from the existing Q&A and summary paths without removing the old columns yet, setting up their eventual deletion in the cleanup phase. https://claude.ai/code/session_01SESwn7kQ7oP62trWw6pc39
Diffstat (limited to 'internal/storage/events_test.go')
-rw-r--r--internal/storage/events_test.go103
1 files changed, 103 insertions, 0 deletions
diff --git a/internal/storage/events_test.go b/internal/storage/events_test.go
index 1f03aeb..3ce79ab 100644
--- a/internal/storage/events_test.go
+++ b/internal/storage/events_test.go
@@ -266,6 +266,109 @@ func TestRejectTask_WritesUserStateChangeEvent(t *testing.T) {
}
}
+func TestUpdateTaskQuestion_EmitsClarificationRequest(t *testing.T) {
+ db := testDB(t)
+ makeTaskForEvent(t, db, "task-1")
+
+ q := `{"text":"which env?","options":["dev","prod"]}`
+ if err := db.UpdateTaskQuestion("task-1", q); err != nil {
+ t.Fatalf("UpdateTaskQuestion: %v", err)
+ }
+
+ events, err := db.ListEvents("task-1", 0)
+ if err != nil {
+ t.Fatalf("ListEvents: %v", err)
+ }
+ if len(events) != 1 {
+ t.Fatalf("expected 1 event, got %d", len(events))
+ }
+ e := events[0]
+ if e.Kind != event.KindClarificationRequest || e.Actor != event.ActorAgent {
+ t.Errorf("got kind=%v actor=%v want clarification_request/agent", e.Kind, e.Actor)
+ }
+ if string(e.Payload) != q {
+ t.Errorf("payload: got %s want %s", e.Payload, q)
+ }
+}
+
+func TestUpdateTaskQuestion_ClearEmitsNothing(t *testing.T) {
+ db := testDB(t)
+ makeTaskForEvent(t, db, "task-1")
+
+ if err := db.UpdateTaskQuestion("task-1", ""); err != nil {
+ t.Fatalf("UpdateTaskQuestion clear: %v", err)
+ }
+ events, err := db.ListEvents("task-1", 0)
+ if err != nil {
+ t.Fatalf("ListEvents: %v", err)
+ }
+ if len(events) != 0 {
+ t.Fatalf("clearing question should emit no event, got %d", len(events))
+ }
+}
+
+func TestUpdateTaskSummary_EmitsSummaryEvent(t *testing.T) {
+ db := testDB(t)
+ makeTaskForEvent(t, db, "task-1")
+
+ if err := db.UpdateTaskSummary("task-1", "Did the thing."); err != nil {
+ t.Fatalf("UpdateTaskSummary: %v", err)
+ }
+ events, err := db.ListEvents("task-1", 0)
+ if err != nil {
+ t.Fatalf("ListEvents: %v", err)
+ }
+ if len(events) != 1 {
+ t.Fatalf("expected 1 event, got %d", len(events))
+ }
+ e := events[0]
+ if e.Kind != event.KindSummary || e.Actor != event.ActorAgent {
+ t.Errorf("got kind=%v actor=%v want summary/agent", e.Kind, e.Actor)
+ }
+ var payload struct {
+ Text string `json:"text"`
+ }
+ if err := json.Unmarshal(e.Payload, &payload); err != nil {
+ t.Fatalf("unmarshal: %v", err)
+ }
+ if payload.Text != "Did the thing." {
+ t.Errorf("payload text: got %q want %q", payload.Text, "Did the thing.")
+ }
+}
+
+func TestAppendTaskInteraction_EmitsClarificationAnswer(t *testing.T) {
+ db := testDB(t)
+ makeTaskForEvent(t, db, "task-1")
+
+ interaction := task.Interaction{
+ QuestionText: "which env?",
+ Options: []string{"dev", "prod"},
+ Answer: "prod",
+ }
+ if err := db.AppendTaskInteraction("task-1", interaction); err != nil {
+ t.Fatalf("AppendTaskInteraction: %v", err)
+ }
+
+ events, err := db.ListEvents("task-1", 0)
+ if err != nil {
+ t.Fatalf("ListEvents: %v", err)
+ }
+ if len(events) != 1 {
+ t.Fatalf("expected 1 event, got %d", len(events))
+ }
+ e := events[0]
+ if e.Kind != event.KindClarificationAnswer || e.Actor != event.ActorUser {
+ t.Errorf("got kind=%v actor=%v want clarification_answer/user", e.Kind, e.Actor)
+ }
+ var payload task.Interaction
+ if err := json.Unmarshal(e.Payload, &payload); err != nil {
+ t.Fatalf("unmarshal: %v", err)
+ }
+ if payload.Answer != "prod" || payload.QuestionText != "which env?" {
+ t.Errorf("payload: got %+v", payload)
+ }
+}
+
func TestCreateEvent_RequiresFields(t *testing.T) {
db := testDB(t)