Files
Agent-System/internal/projectinstance/rdev_pg_test.go
T
weichenandCursor 37b1aaa3ae feat(rdev): add medical design-control workflow (13 stages / 60 docs)
Seed rdev.v2.json, rd_ templates, catalog policy (order 40), squad
kind orchestration, and hard precheck requiring completed main (CDO).
Includes StageKey dynamicization from P0 and docs for P2–P4 skeleton.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 09:46:26 +00:00

124 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package projectinstance_test
import (
"context"
"testing"
"time"
"chat-agent-system/internal/projectinstance"
"chat-agent-system/internal/projectworkflow"
"chat-agent-system/internal/workflowdef"
)
// TestPG_RDevActivateWithNAClose 激活 rdev(60 任务)并将 rd_sw_plan 规划关闭。
func TestPG_RDevActivateWithNAClose(t *testing.T) {
pool := openPGPool(t)
defer pool.Close()
ctx := context.Background()
wfStore := workflowdef.NewStore(pool)
def, err := workflowdef.LoadManifestDefinition("rdev.v2.json")
if err != nil {
t.Fatalf("load rdev manifest: %v", err)
}
if err := wfStore.UpsertPublishedSeed(ctx, workflowdef.CreateDefinitionInput{
Key: workflowdef.OfficialKeyRDev,
Name: "研发设计控制流程",
Definition: def,
}, 1); err != nil {
t.Fatalf("seed rdev: %v", err)
}
pwStore := projectworkflow.NewStore(pool)
instStore := projectinstance.NewStore(pool)
svc := projectinstance.NewService(instStore, wfStore, pwStore, nil)
var projectID int64
code := "pg-rdev-" + time.Now().Format("150405.000")
err = pool.QueryRow(ctx, `
INSERT INTO projects (code, name, status, creator_user_id, lifecycle_status, active_workflow_key, workflow_selection_version, workflow_plan_revision)
VALUES ($1, 'PG RDev Activation', 'active', 1, 'planning', '', 1, 0) RETURNING id
`, code).Scan(&projectID)
if err != nil {
t.Fatalf("insert project: %v", err)
}
t.Cleanup(func() {
_, _ = pool.Exec(context.Background(), `DELETE FROM projects WHERE id = $1`, projectID)
})
plan, err := svc.BuildDefaultPlan(ctx, workflowdef.OfficialKeyRDev, 0)
if err != nil {
t.Fatalf("default plan: %v", err)
}
if len(plan.Stages) != 13 {
t.Fatalf("want 13 stages, got %d", len(plan.Stages))
}
taskCount := 0
for i := range plan.Stages {
for j := range plan.Stages[i].DocTasks {
taskCount++
plan.Stages[i].DocTasks[j].Duties = projectinstance.DocDuty{
AuthorUserID: 1, ReviewerUserID: 2, ApproverUserID: 3,
}
if plan.Stages[i].DocTasks[j].TaskKey == "rd_sw_plan" {
plan.Stages[i].DocTasks[j].Enabled = false
}
}
}
if taskCount != 60 {
t.Fatalf("want 60 tasks, got %d", taskCount)
}
if _, err := svc.SaveWorkflowPlan(ctx, projectID, 1, true, projectinstance.SavePlanInput{
Plan: *plan, ExpectedPlanRevision: 0, ExpectedSelectionVersion: 1,
}); err != nil {
t.Fatalf("save plan: %v", err)
}
preview, err := svc.ActivationPreview(ctx, projectID, 1, true)
if err != nil {
t.Fatalf("preview: %v", err)
}
activated, err := svc.Activate(ctx, projectID, 1, true, projectinstance.ActivateInput{
ConfirmationToken: preview.ConfirmationToken,
ExpectedProjectVersion: preview.ExpectedProjectVersion,
ExpectedPlanRevision: preview.ExpectedPlanRevision,
})
if err != nil {
t.Fatalf("activate: %v", err)
}
if activated.Instance.Status != projectinstance.InstanceActive {
t.Fatalf("expected active, got %q", activated.Instance.Status)
}
if activated.Instance.ConfigSnapshot.WorkflowDefinitionKey != workflowdef.OfficialKeyRDev {
t.Fatalf("key=%s", activated.Instance.ConfigSnapshot.WorkflowDefinitionKey)
}
var executorKey string
var enabled bool
err = pool.QueryRow(ctx, `
SELECT dti.executor_key, dti.enabled
FROM project_doc_task_instances dti
JOIN project_stage_instances si ON si.id = dti.stage_instance_id
WHERE si.workflow_instance_id = $1 AND dti.task_key = 'rd_proposal'
`, activated.Instance.ID).Scan(&executorKey, &enabled)
if err != nil {
t.Fatalf("query rd_proposal: %v", err)
}
if executorKey != "squad.rdev_doc.v1" || !enabled {
t.Fatalf("rd_proposal executor=%q enabled=%v", executorKey, enabled)
}
err = pool.QueryRow(ctx, `
SELECT dti.enabled
FROM project_doc_task_instances dti
JOIN project_stage_instances si ON si.id = dti.stage_instance_id
WHERE si.workflow_instance_id = $1 AND dti.task_key = 'rd_sw_plan'
`, activated.Instance.ID).Scan(&enabled)
if err != nil {
t.Fatalf("query rd_sw_plan: %v", err)
}
if enabled {
t.Fatal("rd_sw_plan should be disabled (N/A planning close)")
}
}