package exec_test import ( "context" "errors" "testing" iexec "github.com/mathiasbq/supervisor/internal/exec" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // stubRunFn returns preset results sequentially. type stubRunFn struct { calls []stubCall callIdx int } type stubCall struct { result iexec.Result err error } func (s *stubRunFn) Run(_ context.Context, _ iexec.Request) (iexec.Result, error) { if s.callIdx >= len(s.calls) { return iexec.Result{}, errors.New("unexpected call") } c := s.calls[s.callIdx] s.callIdx++ return c.result, c.err } // stubVerifier returns preset verdicts sequentially. type stubVerifier struct { verdicts []iexec.Verdict idx int } func (s *stubVerifier) Verify(_ context.Context, _, _ string, _ iexec.Result) (iexec.Verdict, error) { if s.idx >= len(s.verdicts) { return iexec.Verdict{}, errors.New("unexpected verify call") } v := s.verdicts[s.idx] s.idx++ return v, nil } func okResult(skill string) iexec.Result { return iexec.Result{Status: "pass", Phase: "review", Skill: skill, Message: "ok", ModelUsed: "m"} } func TestOrchestratorSingleLocalAccept(t *testing.T) { local := &stubRunFn{calls: []stubCall{{result: okResult("review")}}} verifier := &stubVerifier{verdicts: []iexec.Verdict{{Accept: true}}} var attempts []iexec.AttemptRecord orch := iexec.NewOrchestrator( []iexec.ChainEntry{{Model: "ollama/devstral", Tier: "local", IsCloud: false}}, local.Run, nil, verifier, "", &attempts, ) result, err := orch.Run(context.Background(), iexec.Request{TaskPrompt: "review"}) require.NoError(t, err) assert.Equal(t, "pass", result.Status) require.Len(t, attempts, 1) assert.Equal(t, "local", attempts[0].Tier) assert.Equal(t, "accept", attempts[0].Verdict) } func TestOrchestratorEscalatesOnVerifierReject(t *testing.T) { local := &stubRunFn{calls: []stubCall{ {result: iexec.Result{Status: "fail", Phase: "review", Skill: "review", Message: "weak"}}, {result: okResult("review")}, }} verifier := &stubVerifier{verdicts: []iexec.Verdict{ {Accept: false, Feedback: "missing line refs"}, {Accept: true}, }} var attempts []iexec.AttemptRecord orch := iexec.NewOrchestrator( []iexec.ChainEntry{ {Model: "ollama/devstral", Tier: "local", IsCloud: false}, {Model: "ollama/gemma4", Tier: "local", IsCloud: false}, }, local.Run, nil, verifier, "", &attempts, ) result, err := orch.Run(context.Background(), iexec.Request{TaskPrompt: "review"}) require.NoError(t, err) assert.Equal(t, "pass", result.Status) require.Len(t, attempts, 2) assert.Equal(t, "escalate", attempts[0].Verdict) assert.Equal(t, "missing line refs", attempts[0].Feedback) assert.Equal(t, "accept", attempts[1].Verdict) } func TestOrchestratorEscalatesOnLocalError(t *testing.T) { local := &stubRunFn{calls: []stubCall{ {err: errors.New("network failure")}, {result: okResult("review")}, }} verifier := &stubVerifier{verdicts: []iexec.Verdict{{Accept: true}}} var attempts []iexec.AttemptRecord orch := iexec.NewOrchestrator( []iexec.ChainEntry{ {Model: "ollama/devstral", Tier: "local", IsCloud: false}, {Model: "ollama/gemma4", Tier: "local", IsCloud: false}, }, local.Run, nil, verifier, "", &attempts, ) _, err := orch.Run(context.Background(), iexec.Request{TaskPrompt: "review"}) require.NoError(t, err) require.Len(t, attempts, 2) assert.Equal(t, "error", attempts[0].Verdict) assert.Equal(t, "accept", attempts[1].Verdict) } func TestOrchestratorCloudTierSelfCertifies(t *testing.T) { cloud := &stubRunFn{calls: []stubCall{{result: okResult("review")}}} verifier := &stubVerifier{} // no verdicts — must not be called var attempts []iexec.AttemptRecord orch := iexec.NewOrchestrator( []iexec.ChainEntry{{Model: "claude-sonnet-4-6", Tier: "subagent", IsCloud: true}}, nil, cloud.Run, verifier, "", &attempts, ) result, err := orch.Run(context.Background(), iexec.Request{TaskPrompt: "review"}) require.NoError(t, err) assert.Equal(t, "pass", result.Status) require.Len(t, attempts, 1) assert.Equal(t, "subagent", attempts[0].Tier) assert.Equal(t, "accept", attempts[0].Verdict) assert.Equal(t, 0, verifier.idx) // verifier never called } func TestOrchestratorAllTiersExhausted(t *testing.T) { local := &stubRunFn{calls: []stubCall{{err: errors.New("unavailable")}}} var attempts []iexec.AttemptRecord orch := iexec.NewOrchestrator( []iexec.ChainEntry{{Model: "ollama/devstral", Tier: "local", IsCloud: false}}, local.Run, nil, &stubVerifier{}, "", &attempts, ) _, err := orch.Run(context.Background(), iexec.Request{TaskPrompt: "review"}) assert.ErrorContains(t, err, "all tiers exhausted") }