package squad import ( "encoding/json" "testing" "time" ) func TestAgentSpecEnhancements(t *testing.T) { spec := AgentSpec{ Role: "biocompatibility_expert", Name: "生物相容性评估专员", Source: RoleSourceAdHoc, BaseRole: "engineer", Model: "MiniMax-M3", Tools: []string{"read", "write", "edit"}, BashPermission: "deny", Responsibilities: []string{"生物相容性风险评估"}, ForbiddenActions: []string{"严禁越权发布正式检验报告"}, } data, err := json.Marshal(spec) if err != nil { t.Fatalf("marshal AgentSpec failed: %v", err) } var parsed AgentSpec if err := json.Unmarshal(data, &parsed); err != nil { t.Fatalf("unmarshal AgentSpec failed: %v", err) } if parsed.Source != RoleSourceAdHoc { t.Errorf("expected source %s, got %s", RoleSourceAdHoc, parsed.Source) } if parsed.BaseRole != "engineer" { t.Errorf("expected base_role engineer, got %s", parsed.BaseRole) } } func TestStepSpecDynamicAdjustment(t *testing.T) { step := StepSpec{ ID: "step_01_search", Role: "searcher", Title: "文献与标准检索", SubWorkspace: "tasks/01_search", Mode: "execute", AllowDynamicAdjustment: true, } data, err := json.Marshal(step) if err != nil { t.Fatalf("marshal StepSpec failed: %v", err) } var parsed StepSpec if err := json.Unmarshal(data, &parsed); err != nil { t.Fatalf("unmarshal StepSpec failed: %v", err) } if !parsed.AllowDynamicAdjustment { t.Errorf("expected AllowDynamicAdjustment to be true") } } func TestWorkflowPlanPlanningMode(t *testing.T) { wf := WorkflowPlan{ WorkflowID: "wf_test_123", TaskKey: "cleanroom_design", Title: "洁净厂房设计方案", PlanningMode: PlanModeAutonomousAdhoc, Status: "pending", Steps: []StepSpec{ { ID: "step_01", Role: "organizer", }, }, } data, err := json.Marshal(wf) if err != nil { t.Fatalf("marshal WorkflowPlan failed: %v", err) } var parsed WorkflowPlan if err := json.Unmarshal(data, &parsed); err != nil { t.Fatalf("unmarshal WorkflowPlan failed: %v", err) } if parsed.PlanningMode != PlanModeAutonomousAdhoc { t.Errorf("expected planning mode %s, got %s", PlanModeAutonomousAdhoc, parsed.PlanningMode) } if parsed.TaskKey != "cleanroom_design" { t.Errorf("expected task_key cleanroom_design, got %s", parsed.TaskKey) } } func TestBlackboardAssumptions(t *testing.T) { bb := BlackboardState{ Facts: []FactItem{ {ID: "f1", Claim: "产品为无菌二类导管", Verified: true}, }, Assumptions: []AssumptionItem{ { ID: "a1", Topic: "sterilization_method", Statement: "基准假设灭菌方式采用环氧乙烷(EO)灭菌,解析期设定为14天", Rationale: "客户未明确灭菌方式,依据二类无源无菌高分子导管临床通行工程惯例设定", Source: "inferred", }, }, UpdatedAt: time.Now(), } data, err := json.Marshal(bb) if err != nil { t.Fatalf("marshal BlackboardState failed: %v", err) } var parsed BlackboardState if err := json.Unmarshal(data, &parsed); err != nil { t.Fatalf("unmarshal BlackboardState failed: %v", err) } if len(parsed.Assumptions) != 1 { t.Fatalf("expected 1 assumption, got %d", len(parsed.Assumptions)) } if parsed.Assumptions[0].Source != "inferred" { t.Errorf("expected assumption source 'inferred', got '%s'", parsed.Assumptions[0].Source) } } func TestEvaluationResult(t *testing.T) { res := EvaluationResult{ StepID: "step_01_search", Action: StepActionAddStep, Reason: "检测到产品使用动物源牛心包,需动态追加生物相容性专题调研", NewAssumptions: []AssumptionItem{ { ID: "a2", Topic: "animal_origin", Statement: "需执行GB/T 16886及ISO 22442动物源医疗器械病毒灭活评价", Source: "inferred", }, }, DynamicStepsToAdd: []StepSpec{ { ID: "step_01_biocompatibility", Role: "biocompatibility_expert", Title: "动物源生物相容性与病毒灭活专项评估", SubWorkspace: "tasks/01_biocompatibility", Mode: "execute", }, }, StepsToSkip: []string{"step_02_market"}, } data, err := json.Marshal(res) if err != nil { t.Fatalf("marshal EvaluationResult failed: %v", err) } var parsed EvaluationResult if err := json.Unmarshal(data, &parsed); err != nil { t.Fatalf("unmarshal EvaluationResult failed: %v", err) } if parsed.Action != StepActionAddStep { t.Errorf("expected action %s, got %s", StepActionAddStep, parsed.Action) } if len(parsed.DynamicStepsToAdd) != 1 { t.Errorf("expected 1 dynamic step to add, got %d", len(parsed.DynamicStepsToAdd)) } if len(parsed.StepsToSkip) != 1 || parsed.StepsToSkip[0] != "step_02_market" { t.Errorf("expected steps to skip ['step_02_market'], got %v", parsed.StepsToSkip) } }