60 lines
2.8 KiB
Go
60 lines
2.8 KiB
Go
package domain
|
|
|
|
import (
|
|
"fmt"
|
|
"git.cin.su/m/Assistant/contracts/work"
|
|
"testing"
|
|
)
|
|
|
|
func TestSolutionSearchDoesNotDeadEndAfterBudgetedWave(t *testing.T) {
|
|
decision, err := DecideSolutionSearch(work.SolutionSearchInput{GoalID: "goal-1", GoalState: work.GoalInProgress, SearchRound: 3, MaxRound: 3, Unresolved: true})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !decision.ContinueSearching || decision.State != work.OrchestrationWaiting || decision.NextSearchRound != 4 {
|
|
t.Fatalf("unexpected exhausted-wave decision: %#v", decision)
|
|
}
|
|
if len(decision.Options) != 5 || decision.Options[4] != work.SearchOptionHuman {
|
|
t.Fatalf("all search avenues were not retained: %#v", decision.Options)
|
|
}
|
|
}
|
|
|
|
func TestSolutionSearchStopsOnlyForCancelOrVerifiedCompletion(t *testing.T) {
|
|
completed, err := DecideSolutionSearch(work.SolutionSearchInput{GoalID: "goal-1", GoalState: work.GoalCompleted, VerificationReady: true, MaxRound: 1})
|
|
if err != nil || completed.ContinueSearching || completed.State != work.OrchestrationCompleted {
|
|
t.Fatalf("verified completion was not terminal: %#v %v", completed, err)
|
|
}
|
|
cancelled, err := DecideSolutionSearch(work.SolutionSearchInput{GoalID: "goal-1", GoalState: work.GoalInProgress, CancelRequested: true, MaxRound: 1})
|
|
if err != nil || cancelled.ContinueSearching || cancelled.State != work.OrchestrationCancelled {
|
|
t.Fatalf("cancel was not terminal: %#v %v", cancelled, err)
|
|
}
|
|
}
|
|
|
|
func TestBuildSolutionSearchWaveMaterializesParallelAgentDirections(t *testing.T) {
|
|
decision, err := DecideSolutionSearch(work.SolutionSearchInput{GoalID: "goal-1", GoalState: work.GoalInProgress, MaxRound: 1})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
options := []work.SearchOptionKind{work.SearchOptionAgents, work.SearchOptionCapability, work.SearchOptionResearch, work.SearchOptionReflection}
|
|
dispatches := make([]work.SolutionSearchDispatch, 0, len(options))
|
|
for i, option := range options {
|
|
dispatches = append(dispatches, work.SolutionSearchDispatch{Option: option, Intent: work.AgentDispatchIntent{DispatchID: workDispatchID(i), IdempotencyKey: workDispatchID(i) + ":idem"}})
|
|
}
|
|
graph, intents, err := BuildSolutionSearchWave(decision, work.SolutionSearchWaveRequest{GraphID: "graph-1", IdempotencyPrefix: "goal-1", Dispatches: dispatches, Budget: work.GraphBudget{MaxParallel: 4, MaxAttempts: 2}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(graph.Nodes) != 4 || len(intents) != 4 || graph.State != work.GraphDraft {
|
|
t.Fatalf("unexpected materialized wave: %#v %#v", graph, intents)
|
|
}
|
|
for i, node := range graph.Nodes {
|
|
if node.State != work.GraphNodeBlocked || intents[i].SpecialistPurpose != string(options[i]) {
|
|
t.Fatalf("wave direction not preserved: node=%#v intent=%#v", node, intents[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func workDispatchID(index int) string {
|
|
return fmt.Sprintf("dispatch-%d", index)
|
|
}
|