diff options
Diffstat (limited to 'internal/executor')
| -rw-r--r-- | internal/executor/agentmcp_test.go | 3 | ||||
| -rw-r--r-- | internal/executor/channel.go | 13 | ||||
| -rw-r--r-- | internal/executor/channel_test.go | 62 | ||||
| -rw-r--r-- | internal/executor/container_test.go | 1 |
4 files changed, 79 insertions, 0 deletions
diff --git a/internal/executor/agentmcp_test.go b/internal/executor/agentmcp_test.go index 18299e8..c45964d 100644 --- a/internal/executor/agentmcp_test.go +++ b/internal/executor/agentmcp_test.go @@ -48,6 +48,9 @@ func (c *recordingChannel) ProposeRoleConfig(_ context.Context, cfg role.RoleCon c.proposedRoleConfigs = append(c.proposedRoleConfigs, cfg) return c.roleConfigVersion, nil } +func (c *recordingChannel) ReportVerdict(_ context.Context, approved bool, reasoning string) error { + return nil +} func resultText(t *testing.T, res *mcp.CallToolResult) string { t.Helper() diff --git a/internal/executor/channel.go b/internal/executor/channel.go index 9392c77..55da7b1 100644 --- a/internal/executor/channel.go +++ b/internal/executor/channel.go @@ -273,4 +273,17 @@ func (c *storeChannel) ProposeRoleConfig(_ context.Context, config role.RoleConf return row.Version, err } return row.Version, nil +} + +func (c *storeChannel) ReportVerdict(_ context.Context, approved bool, reasoning string) error { + payload, _ := json.Marshal(struct { + Approved bool `json:"approved"` + Reasoning string `json:"reasoning"` + }{Approved: approved, Reasoning: reasoning}) + return c.store.CreateEvent(&event.Event{ + TaskID: c.taskID, + Kind: event.KindVerdictReported, + Actor: event.ActorAgent, + Payload: payload, + }) }
\ No newline at end of file diff --git a/internal/executor/channel_test.go b/internal/executor/channel_test.go index 84cad89..23f0661 100644 --- a/internal/executor/channel_test.go +++ b/internal/executor/channel_test.go @@ -607,3 +607,65 @@ func TestStoreChannel_ProposeRoleConfig_EmitsRoleConfigProposedEvent(t *testing. t.Errorf("payload mismatch: %+v (want role=evaluator_quality version=%d)", payload, version) } } + +// TestStoreChannel_ReportVerdict_EmitsVerdictReportedEvent proves calling +// ReportVerdict records a KindVerdictReported event attached to the +// *calling task's* own ID, payload {approved, reasoning} — +// internal/scheduler.StoryOrchestrator's finalizeArbitration later reads an +// arbitration task's own event stream for this to decide REVIEW_READY vs +// NEEDS_FIX. Mirrors TestStoreChannel_ProposeRoleConfig_EmitsRoleConfigProposedEvent. +func TestStoreChannel_ReportVerdict_EmitsVerdictReportedEvent(t *testing.T) { + store := &fakeChannelStore{} + ch := newStoreChannel(store, "arbitration-task-1") + + if err := ch.ReportVerdict(context.Background(), false, "the CSS change breaks the running-log panel"); err != nil { + t.Fatalf("ReportVerdict: %v", err) + } + + if len(store.createdEvents) != 1 { + t.Fatalf("expected 1 event, got %d", len(store.createdEvents)) + } + ev := store.createdEvents[0] + if ev.Kind != event.KindVerdictReported { + t.Errorf("expected KindVerdictReported, got %q", ev.Kind) + } + if ev.Actor != event.ActorAgent { + t.Errorf("expected ActorAgent, got %q", ev.Actor) + } + if ev.TaskID != "arbitration-task-1" { + t.Errorf("expected event attached to calling task ID, got %q", ev.TaskID) + } + + var payload struct { + Approved bool `json:"approved"` + Reasoning string `json:"reasoning"` + } + if err := json.Unmarshal(ev.Payload, &payload); err != nil { + t.Fatalf("unmarshal payload: %v", err) + } + if payload.Approved != false || payload.Reasoning != "the CSS change breaks the running-log panel" { + t.Errorf("unexpected payload: %+v", payload) + } +} + +// TestStoreChannel_ReportVerdict_Approved proves the approved=true case +// round-trips correctly too — not just the rejection path exercised above. +func TestStoreChannel_ReportVerdict_Approved(t *testing.T) { + store := &fakeChannelStore{} + ch := newStoreChannel(store, "arbitration-task-2") + + if err := ch.ReportVerdict(context.Background(), true, "meets all acceptance criteria"); err != nil { + t.Fatalf("ReportVerdict: %v", err) + } + + var payload struct { + Approved bool `json:"approved"` + Reasoning string `json:"reasoning"` + } + if err := json.Unmarshal(store.createdEvents[0].Payload, &payload); err != nil { + t.Fatalf("unmarshal payload: %v", err) + } + if !payload.Approved { + t.Error("expected approved=true to round-trip as true") + } +} diff --git a/internal/executor/container_test.go b/internal/executor/container_test.go index 6672dea..80b1996 100644 --- a/internal/executor/container_test.go +++ b/internal/executor/container_test.go @@ -855,3 +855,4 @@ func (noopChannel) ProposeEpic(_ context.Context, _ EpicProposal) (string, error func (noopChannel) ProposeRoleConfig(_ context.Context, _ role.RoleConfig) (int, error) { return 0, nil } +func (noopChannel) ReportVerdict(_ context.Context, _ bool, _ string) error { return nil } |
