package squad_test import ( "os" "path/filepath" "strings" "testing" "chat-agent-system/internal/squad" ) func TestPrepareWorkspaceWritesDialogueContext(t *testing.T) { dir := t.TempDir() engine := squad.NewWorkspaceEngine(nil) ws, err := engine.PrepareWorkspace(squad.WorkspacePrepareRequest{ WorkDir: dir, TaskKey: "system_reqs", StageTitle: "系统需求", ProjectName: "Demo", CustomerName: "Acme", DialoguePackage: &squad.DialoguePackage{ DigestMD: "# 项目对话纪要\n\n- **2026-09-24**: 张工: 器械类型眼科OCT\n", TurnsMD: "# turns\n\n[2026-09-24 15:00] 张工(engineer/member) 用户: 器械类型:眼科OCT\n", FactsJSON: []byte(`[{"key":"device_type","value":"眼科OCT"}]`), ConfirmationsMD: "# 裁决\n\n无冲突\n", TurnCount: 2, ExcludedPrivate: 1, ExcludedNoAccess: 0, ExcludedNoise: 3, }, WorkflowSteps: []squad.StepSpec{{ ID: "s1", Title: "整理", Role: "organizer", Mode: "write", SubWorkspace: "tasks/01_organizer", Status: "pending", }}, }) if err != nil { t.Fatal(err) } if ws == nil { t.Fatal("nil workspace") } for _, name := range []string{"digest.md", "turns.md", "facts.json", "CONFIRMATIONS.md", "README.md"} { p := filepath.Join(dir, "context", "dialogue", name) if _, err := os.Stat(p); err != nil { t.Fatalf("missing %s: %v", name, err) } } readme, _ := os.ReadFile(filepath.Join(dir, "context", "README.md")) if !strings.Contains(string(readme), "collab_dialogue") { t.Fatalf("README missing collab_dialogue: %s", readme) } dlgReadme, _ := os.ReadFile(filepath.Join(dir, "context", "dialogue", "README.md")) if !strings.Contains(string(dlgReadme), "采集统计:保留 2 轮;滤除私密 1、阶段不可见 0、噪声 3") { t.Fatalf("dialogue README missing collection stats: %s", dlgReadme) } taskMD, _ := os.ReadFile(filepath.Join(dir, "tasks", "01_organizer", "TASK.md")) if !strings.Contains(string(taskMD), "context/dialogue/") { t.Fatalf("TASK.md missing dialogue nav: %s", taskMD) } } func TestPrepareWorkspaceExplainsMissingDialogue(t *testing.T) { t.Setenv("DIALOGUE_CTX_INJECTION", "") unbound := prepareDialogueWorkspace(t, squad.WorkspacePrepareRequest{}) readme, err := os.ReadFile(filepath.Join(unbound, "context", "dialogue", "README.md")) if err != nil { t.Fatal(err) } if !strings.Contains(string(readme), "任务未绑定项目") { t.Fatalf("unbound readme=%s", readme) } if _, err := os.Stat(filepath.Join(unbound, "context", "dialogue", "turns.md")); err == nil { t.Fatal("unbound project must not pretend turns were filtered") } bound := prepareDialogueWorkspace(t, squad.WorkspacePrepareRequest{ProjectID: 6022}) readme, err = os.ReadFile(filepath.Join(bound, "context", "dialogue", "README.md")) if err != nil { t.Fatal(err) } if !strings.Contains(string(readme), "没有对话包") { t.Fatalf("bound readme=%s", readme) } t.Setenv("DIALOGUE_CTX_INJECTION", "off") disabled := prepareDialogueWorkspace(t, squad.WorkspacePrepareRequest{ProjectID: 6022}) readme, err = os.ReadFile(filepath.Join(disabled, "context", "dialogue", "README.md")) if err != nil { t.Fatal(err) } if !strings.Contains(string(readme), "开关已关闭") { t.Fatalf("disabled readme=%s", readme) } } func prepareDialogueWorkspace(t *testing.T, req squad.WorkspacePrepareRequest) string { t.Helper() req.WorkDir = t.TempDir() req.TaskKey = "research" req.StageTitle = "调研报告" req.ProjectName = "测试项目" req.CustomerName = "客户" req.WorkflowSteps = []squad.StepSpec{{ ID: "s1", Title: "整理", Role: "organizer", Mode: "write", SubWorkspace: "tasks/01_organizer", Status: "pending", }} if _, err := squad.NewWorkspaceEngine(nil).PrepareWorkspace(req); err != nil { t.Fatal(err) } return req.WorkDir }