Files
weichenandCursor 3f42149457 feat(bizdev): snapshot collaborators onto Runtime and Server ports
Composition roots copy Parts once so HTTP/CLI handlers stop calling locator getters on every request.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 13:00:33 +00:00

128 lines
4.1 KiB
Go

package bizdev
import (
"context"
"os"
"path/filepath"
"strings"
"testing"
"time"
"chat-agent-system/internal/config"
"chat-agent-system/internal/docrevision"
)
func activityTitles(t *testing.T, svc *Service, projectID int64) []string {
t.Helper()
pCtx, err := svc.ctxMgr.GetProjectContext(context.Background(), projectID)
if err != nil {
t.Fatalf("GetProjectContext: %v", err)
}
var titles []string
for _, a := range pCtx.AllActivities {
titles = append(titles, a.Title)
}
return titles
}
func TestExecuteTask_MaterializeFailure_DoesNotRecordCompletedActivity(t *testing.T) {
svc := MustNewService(t, &config.Config{DataDir: t.TempDir(), AgentBackend: "stub"})
ctx := context.Background()
svc.docRev.AgentCommit = false
projectID := int64(5601)
res, err := svc.ExecuteTask(ctx, TaskRunRequest{
TaskKey: "research", ProjectID: projectID, ProjectName: "P",
CustomerName: "C", DeviceType: "医疗器械", Backend: "stub",
Timeout: 10 * time.Second, DocID: "doc-act-fail", UserID: 1,
})
if err == nil || res == nil || res.Success {
t.Fatalf("want materialize failure, err=%v res=%+v", err, res)
}
for _, title := range activityTitles(t, svc, projectID) {
if strings.Contains(title, "完成交付物") {
t.Fatalf("must not record completion activity on materialize failure: %q", title)
}
if strings.Contains(title, "待编制人确认") {
t.Fatalf("must not record pending activity on materialize failure: %q", title)
}
}
}
func TestExecuteTask_PendingConfirmation_RecordsAwaitingNotCompleted(t *testing.T) {
dataDir := t.TempDir()
svc := MustNewService(t, &config.Config{DataDir: dataDir, AgentBackend: "stub"})
ctx := context.Background()
projectID := int64(5602)
docID := "doc_act_pending"
workDir := filepath.Join(dataDir, "ws-act-pending")
if err := os.MkdirAll(workDir, 0o755); err != nil {
t.Fatal(err)
}
base := "# base\n\n法规引用 GB9706\n"
if _, err := svc.docRev.OpenTemplateVersion(ctx, docID, base, docrevision.ActorSnapshot{DisplayName: "t"}, projectID, workDir); err != nil {
t.Fatal(err)
}
if _, err := svc.docGov.CreateOrGetDocument(ctx, docID, projectID, "research", "调研报告", "V0.5", workDir, 1, "a", 2, "r", 3, "p"); err != nil {
t.Fatal(err)
}
// Stub output omits 法规 → deterministic high risk → needs_confirmation.
res, err := svc.ExecuteTask(ctx, TaskRunRequest{
TaskKey: "research", ProjectID: projectID, ProjectName: "P",
CustomerName: "C", DeviceType: "医疗器械", Backend: "stub",
Timeout: 10 * time.Second, DocID: docID, UserID: 1, WorkDir: workDir,
})
if err != nil {
t.Fatalf("ExecuteTask: %v", err)
}
if res == nil || !res.AwaitsAgentConfirmation() {
t.Fatalf("want pending confirmation, got success=%v pending=%d reason=%s",
res != nil && res.Success, res.PendingAgentCandidateID, res.ErrorReason)
}
titles := activityTitles(t, svc, projectID)
foundPending, foundCompleted := false, false
for _, title := range titles {
if strings.Contains(title, "待编制人确认") {
foundPending = true
}
if strings.Contains(title, "完成交付物") {
foundCompleted = true
}
}
if !foundPending {
t.Fatalf("expected pending activity, titles=%v", titles)
}
if foundCompleted {
t.Fatalf("pending must not record 完成交付物, titles=%v", titles)
}
}
func TestExecuteTask_Committed_RecordsCompletedActivity(t *testing.T) {
svc := MustNewService(t, &config.Config{DataDir: t.TempDir(), AgentBackend: "stub"})
ctx := context.Background()
projectID := int64(5603)
res, err := svc.ExecuteTask(ctx, TaskRunRequest{
TaskKey: "intake", ProjectID: projectID, ProjectName: "P",
CustomerName: "C", DeviceType: "医疗器械", Backend: "stub",
Timeout: 10 * time.Second, DocID: "doc_act_ok", UserID: 1,
})
if err != nil {
t.Fatalf("ExecuteTask: %v reason=%v", err, res)
}
if res.AwaitsAgentConfirmation() {
t.Fatal("first-gen intake should auto-commit, not pending")
}
found := false
for _, title := range activityTitles(t, svc, projectID) {
if strings.Contains(title, "完成交付物") {
found = true
break
}
}
if !found {
t.Fatal("expected 完成交付物 after committed materialize")
}
}