summaryrefslogtreecommitdiff
path: root/internal/executor/nativerunner_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/executor/nativerunner_test.go')
-rw-r--r--internal/executor/nativerunner_test.go59
1 files changed, 59 insertions, 0 deletions
diff --git a/internal/executor/nativerunner_test.go b/internal/executor/nativerunner_test.go
index afdb49d..89a7ab5 100644
--- a/internal/executor/nativerunner_test.go
+++ b/internal/executor/nativerunner_test.go
@@ -282,6 +282,65 @@ func TestNativeRunner_Run_ToolLoop_ProposeEpic(t *testing.T) {
}
}
+// TestNativeRunner_Run_ToolLoop_ProposeRoleConfig is an end-to-end-ish test
+// (fake LLM server, real agentloop.Loop/tools.go dispatch, real
+// storeChannel) proving a propose_role_config tool call reaches
+// AgentChannel.ProposeRoleConfig correctly through
+// internal/agentloop/tools.go's dispatchTool, and from there through
+// storeChannel.ProposeRoleConfig into a new draft role_configs row —
+// mirroring the propose_epic coverage above (Phase 7c) for this phase's
+// (Phase 8) new tool.
+func TestNativeRunner_Run_ToolLoop_ProposeRoleConfig(t *testing.T) {
+ srv := fakeChatServer(t, []fakeTurn{
+ {toolCalls: []llm.ToolCall{toolCall("c1", "propose_role_config", `{"role":"builder","system_prompt":"Be more careful.","escalation_ladder":[{"candidates":[{"provider":"anthropic","model":"claude-sonnet-4-6"}],"max_retries":1}]}`)}},
+ {content: "finished"},
+ })
+ defer srv.Close()
+
+ r := newLocalRunner(t, srv)
+ tt := localTask()
+ store := &fakeChannelStore{}
+ ch := newStoreChannel(store, tt.ID)
+ exec := &storage.Execution{ID: uuid.New().String(), TaskID: tt.ID}
+
+ if err := r.Run(context.Background(), tt, exec, ch); err != nil {
+ t.Fatalf("Run: %v", err)
+ }
+
+ rows := store.roleConfigs["builder"]
+ if len(rows) != 1 {
+ t.Fatalf("expected 1 created role_configs row, got %d", len(rows))
+ }
+ row := rows[0]
+ if row.Status != "draft" {
+ t.Errorf("expected status draft, got %q", row.Status)
+ }
+ var decoded struct {
+ Role string `json:"role"`
+ SystemPrompt string `json:"system_prompt"`
+ EscalationLadder []struct {
+ Candidates []struct {
+ Provider string `json:"provider"`
+ Model string `json:"model"`
+ } `json:"candidates"`
+ MaxRetries int `json:"max_retries"`
+ } `json:"escalation_ladder"`
+ }
+ if err := json.Unmarshal([]byte(row.ConfigJSON), &decoded); err != nil {
+ t.Fatalf("unmarshal config_json: %v", err)
+ }
+ if decoded.Role != "builder" || decoded.SystemPrompt != "Be more careful." {
+ t.Errorf("config fields not propagated: %+v", decoded)
+ }
+ if len(decoded.EscalationLadder) != 1 || len(decoded.EscalationLadder[0].Candidates) != 1 ||
+ decoded.EscalationLadder[0].Candidates[0].Provider != "anthropic" {
+ t.Errorf("escalation_ladder not propagated: %+v", decoded.EscalationLadder)
+ }
+ if len(store.createdEvents) != 1 || store.createdEvents[0].TaskID != tt.ID {
+ t.Errorf("expected 1 role_config_proposed event attached to the calling task, got %+v", store.createdEvents)
+ }
+}
+
func TestNativeRunner_Run_RecordProgress(t *testing.T) {
srv := fakeChatServer(t, []fakeTurn{
{toolCalls: []llm.ToolCall{toolCall("c1", "record_progress", `{"message":"halfway there"}`)}},