diff --git a/.doc/ops/CURRENT.md b/.doc/ops/CURRENT.md index 18e4118e..8bb9875a 100644 --- a/.doc/ops/CURRENT.md +++ b/.doc/ops/CURRENT.md @@ -5,7 +5,7 @@ ## 焦点 -1. **TRACK-S**: [D7a intent 解绑](./short-term/2026-09-15-intent-bizdev-boundary.md)(D6 已合入。下一波 D5/D4/D7b) +1. **TRACK-S**: [D5 stageflow](./short-term/2026-09-15-stageflow-type-ownership.md)(D6/D7a 已合入。D4 getter 仍开放) 2. **CHAT-INTENT**: [对话意图运行时状态](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md)(双标签 busy 已签:项目 **6275** / `DOC_BUSY` 单 run;不删 `sess-p143-u9` 探针) 3. **CHAT**: [对话历史刷新活验已补](../test-reports/2026-09-13-chat-history-refresh-test-report.md)(项目 6252 闲聊刷新同集 + guest 403;编制任务链仍开放) @@ -65,7 +65,8 @@ | Cursor | event-e1c-projection-cutover | fix/event-projection-cutover | - | events | done | | Cursor | event-e2-hook-guard | fix/event-e2-hook-guard | - | events | done | | Cursor | doccontent-canonical-boundary | fix/doccontent-canonical-boundary | - | docgov | done | -| Cursor | intent-bizdev-boundary | fix/intent-bizdev-boundary | - | intent | in_progress | +| Cursor | intent-bizdev-boundary | fix/intent-bizdev-boundary | - | intent | done | +| Cursor | stageflow-type-ownership | fix/stageflow-type-ownership | - | stageflow | in_progress | > 新任务开始前登记。`branch` 必须为 `feature/` 或 `fix/`,**禁止** `dev` / `test` / `main`。同一 `mutex` 同时仅一个 `in_progress`。 @@ -77,7 +78,7 @@ | holder | phase | since | scope | queue | |--------|-------|-------|-------|-------| -| Cursor | merging | 2026-09-15 | D6 doccontent canonical;mode=off | - | +| Cursor | merging | 2026-09-15 | D5 stageflow types;mode=off | - | **phase**: `idle` | `merging` | `smoke` | `e2e` diff --git a/.doc/ops/short-term/2026-09-15-stageflow-type-ownership.md b/.doc/ops/short-term/2026-09-15-stageflow-type-ownership.md new file mode 100644 index 00000000..4f3a141c --- /dev/null +++ b/.doc/ops/short-term/2026-09-15-stageflow-type-ownership.md @@ -0,0 +1,40 @@ +--- +title: "D5 stageflow 类型归属与 D7b chatflow 首批" +status: in_progress +created: 2026-09-15 +updated: 2026-09-15 +owner: Cursor +branch: fix/stageflow-type-ownership +worktree: "-" +mutex: stageflow +--- + +# D5 stageflow 类型归属与 D7b chatflow 首批 + +## 目标 + +coordinator 生产代码不再 import bizdev;task/stage 请求走 stageflow 类型;chatflow assembler 改用 maturity。 + +## 范围 + +- stageflow 类型别名与状态常量 +- coordinator 构造改为 StageTaskRunner + ContextServices +- chatflow 去掉 bizdev import + +## 非目标 + +- 不复制行为方法成 DTO(身份别名 + token golden) +- 不删除 bizdev 八个 getter(D4) +- 不搬空 chat 包 + +## 步骤 + +1. [x] 类型边界与 coordinator 解绑 +2. [x] chatflow assembler +3. [x] 表征测试与 arch-check +4. [x] 报告 + +## 验收标准 + +- [x] coordinator 生产 import 无 bizdev +- [x] [S2/S4b 报告](../../test-reports/2026-09-15-stageflow-type-ownership-test-report.md) diff --git a/.doc/status/FEATURE-MATRIX.md b/.doc/status/FEATURE-MATRIX.md index 9520bd0a..c0ec8ac4 100644 --- a/.doc/status/FEATURE-MATRIX.md +++ b/.doc/status/FEATURE-MATRIX.md @@ -27,7 +27,7 @@ | PI Runner / 配置链 | pi-agent + MiniMax 真实链路 | done | [test piagent](../test-reports/2026-09-13-codex-audit-p0-remediation-test-report.md);[container-env](../test-reports/2026-09-13-container-env-configuration-test-report.md) | — | `pi-agent` | | 三环境运维 | dev/test/main + 共享 KB | done | [PROJECT.md](../../PROJECT.md) §4;四环境 healthy | — | `infra` | | CI / E2E | PG 集成 + 真实 PI E2E | partial | [gap-matrix BUG-08](../remediation/gap-matrix.md);[test pg-ci](../test-reports/2026-09-12-pg-ci-soak-e2e-test-report.md);[运行时 UI Round20](../test-reports/2026-09-14-document-revision-runtime-ui-test-report.md) | CI `TEST_DATABASE_URL` 隔离库仍缺;文档运行时真实 UI 已按 UI_PHASE 分文件且 post-restart 断言最终 A1 正文。`-race` 全包并行 TempDir flake 为基建残留 | `ci` | -| 模块解耦与可靠事件 | 文档可靠性纵向试点、PG 持久事件交付与选择性模块化 | partial | [架构](../system-design/2026-09-14-module-decoupling-architecture.md);[ADR](../adr/2026-09-14-modular-monolith-decoupling.md);[Phase 1](../remediation/2026-09-14-module-decoupling-refactor-plan.md);[Phase 2 审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md);[Phase 2 修订计划](../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md);[E0A](../test-reports/2026-09-15-event-e0a-production-scope-contract-test-report.md);[E0B](../test-reports/2026-09-15-event-e0b-dispatcher-pg-test-report.md);[E1A](../test-reports/2026-09-15-event-e1a-notify-cutover-test-report.md);[E1B](../test-reports/2026-09-15-event-e1b-workflow-advance-test-report.md);[E1C](../test-reports/2026-09-15-event-e1c-projection-test-report.md);[E2](../test-reports/2026-09-15-event-e2-hook-guard-test-report.md);[复盘](../ops/research/2026-09-15-track-e-retrospective.md);[D6](../test-reports/2026-09-15-doccontent-canonical-boundary-test-report.md) | E0A–E2 隔离库已过;dispatcher 默认 off。删除闭包 API 须等 live。D6 canonical 已抽出。Track S 其余与 Track P/FAV 另列 | `architecture-docs` | +| 模块解耦与可靠事件 | 文档可靠性纵向试点、PG 持久事件交付与选择性模块化 | partial | [架构](../system-design/2026-09-14-module-decoupling-architecture.md);[ADR](../adr/2026-09-14-modular-monolith-decoupling.md);[Phase 1](../remediation/2026-09-14-module-decoupling-refactor-plan.md);[Phase 2 审阅](../audit/2026-09-15-module-decoupling-phase2-plan-review.md);[Phase 2 修订计划](../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md);[E0A](../test-reports/2026-09-15-event-e0a-production-scope-contract-test-report.md);[E0B](../test-reports/2026-09-15-event-e0b-dispatcher-pg-test-report.md);[E1A](../test-reports/2026-09-15-event-e1a-notify-cutover-test-report.md);[E1B](../test-reports/2026-09-15-event-e1b-workflow-advance-test-report.md);[E1C](../test-reports/2026-09-15-event-e1c-projection-test-report.md);[E2](../test-reports/2026-09-15-event-e2-hook-guard-test-report.md);[复盘](../ops/research/2026-09-15-track-e-retrospective.md);[D6](../test-reports/2026-09-15-doccontent-canonical-boundary-test-report.md);[D7a](../test-reports/2026-09-15-intent-bizdev-boundary-test-report.md);[D5](../test-reports/2026-09-15-stageflow-type-ownership-test-report.md) | E0A–E2 隔离库已过;dispatcher 默认 off。D5/D6/D7a/D7b-chatflow 已合入。删除闭包 API 须等 live。D4 getter 原子删除与 Track P 实现、FAV 另列。HTTP/PI 已有独立 remediation(Phase 2 只立项) | `architecture-docs` | --- diff --git a/.doc/system-design/module-boundaries.yaml b/.doc/system-design/module-boundaries.yaml index 34d1c718..60a78a54 100644 --- a/.doc/system-design/module-boundaries.yaml +++ b/.doc/system-design/module-boundaries.yaml @@ -42,11 +42,12 @@ imports: config: [] coordinator: - agent - - bizdev + - app/stageflow - ctxmgr - docgov - intent - kb + - maturity - projectinstance - squad - stream @@ -83,9 +84,9 @@ imports: - workflowdef - workspace app/chatflow: - - bizdev - coordinator - ctxmgr + - maturity - projectinstance app/docnotify: - docgov diff --git a/.doc/test-reports/2026-09-15-stageflow-type-ownership-test-report.md b/.doc/test-reports/2026-09-15-stageflow-type-ownership-test-report.md new file mode 100644 index 00000000..cd7e2d3a --- /dev/null +++ b/.doc/test-reports/2026-09-15-stageflow-type-ownership-test-report.md @@ -0,0 +1,52 @@ +# D5 stageflow 类型归属与 D7b chatflow 首批测试报告 + +## 一、 测试背景 (Background) + +coordinator 通过 bizdev DTO 与 locator 调用编排根。D5 要求 use-case 请求/结果归 stageflow,coordinator 最终不 import bizdev。D7b 允许按用例收紧 import;本批只迁 `app/chatflow` assembler 的阶段常量。 + +## 二、 测试目标 (Test Objectives) + +- coordinator 生产包 import 无 bizdev。 +- StageTaskRunner / UseCase 使用 stageflow 类型;token `failed` / `pending_author_confirmation` 不变。 +- chatflow assembler 使用 `maturity.StageV01_Triage`。 +- 顾问案例推荐仍能通过注入的 ContextManager 填充。 + +## 三、 测试方案与环境 (Test Plan & Environment) + +| 项 | 值 | +|----|-----| +| OS | Linux 7.0.0-31-generic | +| Go | go1.27.1 linux/amd64 | +| 分支 | `fix/stageflow-type-ownership` | +| 层级 | 表征/短测 + arch-check | + +## 四、 预期结果 (Expected Results) + +既有 ADVANCE_STAGE / pending confirmation / chat session 表征仍过;arch-check 收紧 coordinator 与 chatflow allowlist。 + +## 五、 实际测试结果与判定 (Actual Results & Evaluation) + +### 5.1 表征 + +- **测试输入 (Input)**:`go test -short -count=1 ./internal/coordinator ./internal/app/stageflow ./internal/app/chatflow ./internal/app ./internal/chat ./internal/bizdev ./internal/archtest ./cmd/bizdev-cli` +- **实际输出 (Actual Output)**:上述包全部 `ok`(cli 2.3s,其余 <0.15s) +- **评价判定 (Evaluation / Verdict)**:**PASS** +- **性能与耗时 (Duration & Latency)**:约 3.6s + +### 5.2 arch-check + +- **测试输入 (Input)**:`./scripts/arch-check.sh --mode block` +- **实际输出 (Actual Output)**:`arch-check block: production gate passed` +- **评价判定 (Evaluation / Verdict)**:**PASS** +- **性能与耗时 (Duration & Latency)**:~0.12s + +## 六、 自动化测试套件汇总 (Test Suite Execution) + +| 命令 | 结果 | +|------|------| +| coordinator/stageflow/chatflow/app/chat/bizdev/cli | PASS | +| arch-check | PASS | + +## 七、 测试结论与后续优化建议 (Conclusion & Next Steps) + +D5 与 D7b **首批 PASS**。类型仍是 bizdev 结构的别名,未机械复制方法。D4 八个 getter 仍在;`internal/chat` 仍 import bizdev 跑任务。下一步:no-new-callers 门禁后原子删除 getter。 diff --git a/cmd/bizdev-cli/main.go b/cmd/bizdev-cli/main.go index f40a8fc1..b37ba3ea 100644 --- a/cmd/bizdev-cli/main.go +++ b/cmd/bizdev-cli/main.go @@ -662,7 +662,7 @@ func handleChatMode( } rec := intent.NewRecognizer() - engine := coordinator.NewCoordinatorEngine(svc) + engine := coordinator.NewCoordinatorEngine(stageflow.New(svc)) session := chat.NewSession("cli_chat_sess", userCtx, rec, engine) session.CtxMgr = svc.ContextManager() diff --git a/internal/app/app.go b/internal/app/app.go index aefc2024..c8058b16 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -88,7 +88,7 @@ func Assemble(cfg *config.Config, svc *bizdev.Service) (*Runtime, error) { rec := intent.NewRecognizer() dialogueBackend := agent.NewBackend(cfg.AgentBackend, cfg) - coordEngine := coordinator.NewCoordinatorEngineWithDialogue(svc, dialogueBackend, cfg.DataDir) + coordEngine := coordinator.NewCoordinatorEngineWithDialogue(nil, dialogueBackend, cfg.DataDir) pool := svc.Pool() stores, storeErr := auth.NewStores(context.Background(), pool, cfg) if storeErr != nil { @@ -130,6 +130,7 @@ func Assemble(cfg *config.Config, svc *bizdev.Service) (*Runtime, error) { stages := stageflow.New(svc) coordEngine.SetStageTaskRunner(stages) + coordEngine.SetContextServices(svc.ContextManager(), svc.KB()) if instSvc != nil && instSvc.Available() { coordEngine.SetInstanceService(instSvc) } diff --git a/internal/app/chatflow/assembler.go b/internal/app/chatflow/assembler.go index 59254a43..55f9f1de 100644 --- a/internal/app/chatflow/assembler.go +++ b/internal/app/chatflow/assembler.go @@ -6,9 +6,9 @@ import ( "strings" "time" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/coordinator" "chat-agent-system/internal/ctxmgr" + "chat-agent-system/internal/maturity" ) // Assembler adapts coordinator.ContextAssembler and ChatLog so prompt context @@ -43,10 +43,10 @@ func (a *Assembler) Assemble(ctx context.Context, p Principal, req AssembleReque WorkDir: req.WorkDir, Project: req.Fallback, BlackboardFacts: make(map[string]string), - AvailableActions: coordinator.ComputeAvailableActions(bizdev.StageV01_Triage, req.User.ProjectRole), + AvailableActions: coordinator.ComputeAvailableActions(maturity.StageV01_Triage, req.User.ProjectRole), } if userCtx.Project.CurrentStage == "" { - userCtx.Project.CurrentStage = bizdev.StageV01_Triage + userCtx.Project.CurrentStage = maturity.StageV01_Triage } if userCtx.Project.CurrentWorkflow == "" { userCtx.Project.CurrentWorkflow = "intake" diff --git a/internal/app/stageflow/types.go b/internal/app/stageflow/types.go new file mode 100644 index 00000000..54bef9f0 --- /dev/null +++ b/internal/app/stageflow/types.go @@ -0,0 +1,23 @@ +package stageflow + +import "chat-agent-system/internal/bizdev" + +// Use-case request/result types live at the stageflow boundary. +// They alias bizdev domain structs so mapping stays identity until a later +// contract commit copies fields; characterization tests lock the tokens. +type ( + TaskRunRequest = bizdev.TaskRunRequest + TaskRunResult = bizdev.TaskRunResult + StageRunRequest = bizdev.StageRunRequest + StageRunResult = bizdev.StageRunResult + MaterialInput = bizdev.MaterialInput + StageMeta = bizdev.StageMeta + TaskMeta = bizdev.TaskMeta +) + +const ( + TaskStatusCompleted = bizdev.TaskStatusCompleted + TaskStatusFailed = bizdev.TaskStatusFailed + TaskStatusQualityFailed = bizdev.TaskStatusQualityFailed + TaskStatusPendingAuthorConfirmation = bizdev.TaskStatusPendingAuthorConfirmation +) diff --git a/internal/app/stageflow/usecase.go b/internal/app/stageflow/usecase.go index e0a34a82..ca99091b 100644 --- a/internal/app/stageflow/usecase.go +++ b/internal/app/stageflow/usecase.go @@ -3,8 +3,6 @@ package stageflow import ( "context" "errors" - - "chat-agent-system/internal/bizdev" ) var ErrClosed = errors.New("stageflow: executor not configured") @@ -12,8 +10,8 @@ var ErrClosed = errors.New("stageflow: executor not configured") // Executor is the unique application owner for task and stage runs. // HTTP, CLI and coordinator must call this instead of bizdev directly. type Executor interface { - ExecuteTask(ctx context.Context, req bizdev.TaskRunRequest) (*bizdev.TaskRunResult, error) - ExecuteStage(ctx context.Context, req bizdev.StageRunRequest) (*bizdev.StageRunResult, error) + ExecuteTask(ctx context.Context, req TaskRunRequest) (*TaskRunResult, error) + ExecuteStage(ctx context.Context, req StageRunRequest) (*StageRunResult, error) } // UseCase adapts bizdev orchestration without moving domain tables. @@ -25,14 +23,14 @@ func New(biz Executor) *UseCase { return &UseCase{Biz: biz} } -func (u *UseCase) ExecuteTask(ctx context.Context, req bizdev.TaskRunRequest) (*bizdev.TaskRunResult, error) { +func (u *UseCase) ExecuteTask(ctx context.Context, req TaskRunRequest) (*TaskRunResult, error) { if u == nil || u.Biz == nil { return nil, ErrClosed } return u.Biz.ExecuteTask(ctx, req) } -func (u *UseCase) ExecuteStage(ctx context.Context, req bizdev.StageRunRequest) (*bizdev.StageRunResult, error) { +func (u *UseCase) ExecuteStage(ctx context.Context, req StageRunRequest) (*StageRunResult, error) { if u == nil || u.Biz == nil { return nil, ErrClosed } diff --git a/internal/app/stageflow/usecase_test.go b/internal/app/stageflow/usecase_test.go index efe370d1..28e4d20a 100644 --- a/internal/app/stageflow/usecase_test.go +++ b/internal/app/stageflow/usecase_test.go @@ -23,7 +23,16 @@ func (s *stubBiz) ExecuteStage(_ context.Context, req bizdev.StageRunRequest) (* return &bizdev.StageRunResult{Success: true, StageTitle: string(req.Stage)}, nil } -func TestUseCaseDelegates(t *testing.T) { +func TestUseCaseTypeIdentity(t *testing.T) { + var req TaskRunRequest + req.TaskKey = "intake" + if req.TaskKey != "intake" { + t.Fatal("alias lost fields") + } + if TaskStatusFailed != "failed" || TaskStatusPendingAuthorConfirmation != "pending_author_confirmation" { + t.Fatalf("status tokens drifted") + } +} biz := &stubBiz{} httpUC := New(biz) cliUC := New(biz) diff --git a/internal/bizdev/case_recommend_e2e_test.go b/internal/bizdev/case_recommend_e2e_test.go index 30858225..07ec6ed7 100644 --- a/internal/bizdev/case_recommend_e2e_test.go +++ b/internal/bizdev/case_recommend_e2e_test.go @@ -101,6 +101,7 @@ func TestBizDev_CaseRecommendation_FullLink_E2E(t *testing.T) { rec := intent.NewRecognizer() engine := coordinator.NewCoordinatorEngine(svc) + engine.SetContextServices(svc.ContextManager(), svc.KB()) userCtx := &coordinator.UserProjectContext{ SnapshotID: "ctx_new_consult", diff --git a/internal/chat/longtask_quality_e2e_test.go b/internal/chat/longtask_quality_e2e_test.go index 8f02ab2c..c2c7db28 100644 --- a/internal/chat/longtask_quality_e2e_test.go +++ b/internal/chat/longtask_quality_e2e_test.go @@ -22,8 +22,8 @@ import ( "chat-agent-system/internal/agent" "chat-agent-system/internal/bizdev" "chat-agent-system/internal/chat" - "chat-agent-system/internal/coordinator" "chat-agent-system/internal/config" + "chat-agent-system/internal/coordinator" "chat-agent-system/internal/intent" ) @@ -101,6 +101,7 @@ func TestLongTaskGovernance_QualityE2E(t *testing.T) { svc := bizdev.MustNewService(t, cfg) dialogueBackend := agent.NewBackend("pi-agent", cfg) engine := coordinator.NewCoordinatorEngineWithDialogue(svc, dialogueBackend, cfg.DataDir) + engine.SetContextServices(svc.ContextManager(), svc.KB()) rec := intent.NewRecognizer() reportRoot := qualityReportDir(t) ctx := context.Background() @@ -112,12 +113,12 @@ func TestLongTaskGovernance_QualityE2E(t *testing.T) { _ = os.MkdirAll(scenarioADir, 0o755) userCtx := &coordinator.UserProjectContext{ - User: coordinator.UserInfo{ID: "1", Name: "张工", Role: "engineer", ProjectRole: "composer"}, + User: coordinator.UserInfo{ID: "1", Name: "张工", Role: "engineer", ProjectRole: "composer"}, Project: coordinator.ProjectInfo{ Name: "掌上无线超声系统", CustomerName: "华西医院微创神经外科", DeviceType: "超声软组织手术吸引设备", - IntendedUse: "脑组织空化乳化与同轴吸引", + IntendedUse: "脑组织空化乳化与同轴吸引", TargetMarket: "中国 NMPA 三类", CurrentStage: bizdev.StageV01_Triage, }, @@ -290,4 +291,3 @@ func qualityVerdict(res *bizdev.TaskRunResult) string { } return fmt.Sprintf("⚠️ 未完全通过(评分 %.0f,违规: %s)", res.QualityReport.Score, strings.Join(res.QualityReport.Violations, "; ")) } - diff --git a/internal/chat/session_test.go b/internal/chat/session_test.go index 8c52b352..a8f6bd3b 100644 --- a/internal/chat/session_test.go +++ b/internal/chat/session_test.go @@ -278,6 +278,7 @@ func TestChatSession_AdvisorCaseRecommendation(t *testing.T) { // 2. 发起新会话咨询 rec := intent.NewRecognizer() engine := coordinator.NewCoordinatorEngine(svc) + engine.SetContextServices(svc.ContextManager(), svc.KB()) userCtx := &coordinator.UserProjectContext{ Project: coordinator.ProjectInfo{ Name: "超声软组织刀研发咨询", @@ -626,7 +627,3 @@ func TestChatSession_QueryRewrite_EllipsisAndPronoun(t *testing.T) { t.Errorf("expected pronoun resolution to project name, got: %s", session.UserCtx.RewrittenQuery) } } - - - - diff --git a/internal/coordinator/action_planner_test.go b/internal/coordinator/action_planner_test.go index 79034a28..1cacb525 100644 --- a/internal/coordinator/action_planner_test.go +++ b/internal/coordinator/action_planner_test.go @@ -5,9 +5,9 @@ import ( "strings" "testing" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/coordinator" "chat-agent-system/internal/intent" + "chat-agent-system/internal/maturity" ) func TestEngine_IntentPlan_QueryThenQuery(t *testing.T) { @@ -27,7 +27,7 @@ func TestEngine_IntentPlan_QueryThenQuery(t *testing.T) { userCtx := &coordinator.UserProjectContext{ User: coordinator.UserInfo{ID: "1", Name: "用户"}, - Project: coordinator.ProjectInfo{Name: "测试项目", CurrentStage: bizdev.StageV01_Triage}, + Project: coordinator.ProjectInfo{Name: "测试项目", CurrentStage: maturity.StageV01_Triage}, BlackboardFacts: map[string]string{}, } @@ -51,7 +51,7 @@ func TestEngine_ExpectationPlusNew_ExecutesQueryKeepsConfirm(t *testing.T) { engine := coordinator.NewCoordinatorEngine(nil) ctx := &intent.ContextSnapshot{ - CurrentStage: string(bizdev.StageV01_Triage), + CurrentStage: string(maturity.StageV01_Triage), PendingExpectation: &intent.PendingExpectation{ ExpectedIntent: intent.IntentAdvanceStage, AllowAffirmative: true, @@ -68,8 +68,8 @@ func TestEngine_ExpectationPlusNew_ExecutesQueryKeepsConfirm(t *testing.T) { } userCtx := &coordinator.UserProjectContext{ - User: coordinator.UserInfo{ID: "1", Name: "用户"}, - Project: coordinator.ProjectInfo{Name: "项目", CurrentStage: bizdev.StageV01_Triage}, + User: coordinator.UserInfo{ID: "1", Name: "用户"}, + Project: coordinator.ProjectInfo{Name: "项目", CurrentStage: maturity.StageV01_Triage}, PendingExpectation: ctx.PendingExpectation, BlackboardFacts: map[string]string{}, } diff --git a/internal/coordinator/card_policy_test.go b/internal/coordinator/card_policy_test.go index 74e6af3e..ce2e3125 100644 --- a/internal/coordinator/card_policy_test.go +++ b/internal/coordinator/card_policy_test.go @@ -77,7 +77,7 @@ func TestResolveRejectCard_AuthorExecuteDenied(t *testing.T) { func TestHandleDocGovReject_UnauthorizedAuthor(t *testing.T) { engine := NewCoordinatorEngine(nil) userCtx := &UserProjectContext{ - User: UserInfo{ID: "u1", Name: "张工", Role: "author", ProjectRole: "author"}, + User: UserInfo{ID: "u1", Name: "张工", Role: "author", ProjectRole: "author"}, Project: ProjectInfo{Name: "NeuroPulse"}, } recRes := &intent.IntentRecognitionResult{ diff --git a/internal/coordinator/context.go b/internal/coordinator/context.go index 7472cee6..3bf4e30f 100644 --- a/internal/coordinator/context.go +++ b/internal/coordinator/context.go @@ -11,10 +11,10 @@ import ( "sync" "time" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/ctxmgr" "chat-agent-system/internal/intent" "chat-agent-system/internal/kb" + "chat-agent-system/internal/maturity" "chat-agent-system/internal/squad" ) @@ -28,18 +28,18 @@ type UserInfo struct { // ProjectInfo 项目与工作流当前基准 type ProjectInfo struct { - ID string `json:"id"` - Name string `json:"name"` - CustomerName string `json:"customer_name"` - DeviceType string `json:"device_type"` - IntendedUse string `json:"intended_use"` - TargetMarket string `json:"target_market"` - CreatorUserID int64 `json:"creator_user_id,omitempty"` - ActiveWorkflowKey string `json:"active_workflow_key,omitempty"` - WorkflowSelectionVersion int `json:"workflow_selection_version,omitempty"` - CurrentWorkflow string `json:"current_workflow"` - CurrentStage bizdev.MaturityStage `json:"current_stage"` - StageRules []string `json:"stage_rules,omitempty"` + ID string `json:"id"` + Name string `json:"name"` + CustomerName string `json:"customer_name"` + DeviceType string `json:"device_type"` + IntendedUse string `json:"intended_use"` + TargetMarket string `json:"target_market"` + CreatorUserID int64 `json:"creator_user_id,omitempty"` + ActiveWorkflowKey string `json:"active_workflow_key,omitempty"` + WorkflowSelectionVersion int `json:"workflow_selection_version,omitempty"` + CurrentWorkflow string `json:"current_workflow"` + CurrentStage maturity.MaturityStage `json:"current_stage"` + StageRules []string `json:"stage_rules,omitempty"` } // UserDocsInfo 用户相关文档清单与认领状态 @@ -78,20 +78,20 @@ type DocumentSummaryReader func(ctx context.Context, target string) (*ReadableDo // UserProjectContext 用户项目级全量统一上下文 (对话系统与执行系统共同消费) type UserProjectContext struct { mu sync.Mutex - Version int64 `json:"version"` - SnapshotID string `json:"snapshot_id"` - AssembledAt time.Time `json:"assembled_at"` - User UserInfo `json:"user"` - Project ProjectInfo `json:"project"` - UserDocs UserDocsInfo `json:"user_docs"` - Pending PendingItems `json:"pending"` - BlackboardFacts map[string]string `json:"blackboard_facts"` - LatestAdvisorBrief *squad.AdvisorBriefing `json:"latest_advisor_brief,omitempty"` - PendingExpectation *intent.PendingExpectation `json:"pending_expectation,omitempty"` + Version int64 `json:"version"` + SnapshotID string `json:"snapshot_id"` + AssembledAt time.Time `json:"assembled_at"` + User UserInfo `json:"user"` + Project ProjectInfo `json:"project"` + UserDocs UserDocsInfo `json:"user_docs"` + Pending PendingItems `json:"pending"` + BlackboardFacts map[string]string `json:"blackboard_facts"` + LatestAdvisorBrief *squad.AdvisorBriefing `json:"latest_advisor_brief,omitempty"` + PendingExpectation *intent.PendingExpectation `json:"pending_expectation,omitempty"` InteractiveCard *intent.InteractiveCardPayload `json:"interactive_card,omitempty"` - AvailableActions []string `json:"available_actions"` - RecentEvents []string `json:"recent_events,omitempty"` - WorkDir string `json:"work_dir,omitempty"` + AvailableActions []string `json:"available_actions"` + RecentEvents []string `json:"recent_events,omitempty"` + WorkDir string `json:"work_dir,omitempty"` // RecentDialogue 近轮对话(供 Phase A 对话 LLM 使用,不序列化到快照) RecentDialogue []DialogueTurn `json:"-"` // DialogueSummary 早期对话滚动压缩摘要(由 ctxmgr 维护生成,不序列化到快照) @@ -124,20 +124,20 @@ func NewContextAssembler() *ContextAssembler { } // ComputeAvailableActions 根据当前成熟度阶段与角色计算允许执行的操作集合 -func ComputeAvailableActions(stage bizdev.MaturityStage, pRole string) []string { +func ComputeAvailableActions(stage maturity.MaturityStage, pRole string) []string { actions := []string{"QUERY_PROGRESS", "SUPPLEMENT_INFO", "VIEW_DOC"} switch stage { - case bizdev.StageV01_Triage: + case maturity.StageV01_Triage: actions = append(actions, "TRIGGER_TASK:intake", "ADVANCE_STAGE:V0.5_feasibility") - case bizdev.StageV05_Feasibility: + case maturity.StageV05_Feasibility: actions = append(actions, "TRIGGER_TASK:research", "TRIGGER_TASK:feasibility_reg", "TRIGGER_TASK:prelim_design", "ADVANCE_STAGE:V1.0_quoting", ) - case bizdev.StageV10_Quoting: + case maturity.StageV10_Quoting: actions = append(actions, "TRIGGER_TASK:cdo_quote", "LOCK_COMMERCIAL") default: actions = append(actions, "ADVANCE_STAGE:V0.1_triage") @@ -147,7 +147,7 @@ func ComputeAvailableActions(stage bizdev.MaturityStage, pRole string) []string } // ComputeAvailableActionsWithWorkflow 结合激活工作流、成熟度阶段与角色权限计算可用操作集合 -func ComputeAvailableActionsWithWorkflow(stage bizdev.MaturityStage, pRole string, activeWorkflow string, isCreator bool) []string { +func ComputeAvailableActionsWithWorkflow(stage maturity.MaturityStage, pRole string, activeWorkflow string, isCreator bool) []string { actions := ComputeAvailableActions(stage, pRole) actions = appendUniqueCapability(actions, "QUERY_WORKFLOW") if isCreator { @@ -208,7 +208,7 @@ func (ctx *UserProjectContext) ToSnapshot() *intent.ContextSnapshot { } // BuildNextExpectation 根据当前成熟度阶段与项目名构造参谋下一步建议选项草稿 -func BuildNextExpectation(stage bizdev.MaturityStage, projectName string) *intent.PendingExpectation { +func BuildNextExpectation(stage maturity.MaturityStage, projectName string) *intent.PendingExpectation { if projectName == "" { projectName = "本项目" } @@ -217,7 +217,7 @@ func BuildNextExpectation(stage bizdev.MaturityStage, projectName string) *inten var snippet string switch stage { - case bizdev.StageV01_Triage: + case maturity.StageV01_Triage: snippet = fmt.Sprintf("项目「%s」当前处于初始摸底期,基准产品画像已梳理完成。", projectName) options = []intent.ExpectationOption{ { @@ -226,7 +226,7 @@ func BuildNextExpectation(stage bizdev.MaturityStage, projectName string) *inten Description: "自动比选技术路线,并梳理分类路径与型检标准", Intent: intent.IntentAdvanceStage, Slots: map[string]string{ - intent.SlotTargetStage: string(bizdev.StageV05_Feasibility), + intent.SlotTargetStage: string(maturity.StageV05_Feasibility), }, }, { @@ -246,7 +246,7 @@ func BuildNextExpectation(stage bizdev.MaturityStage, projectName string) *inten }, } - case bizdev.StageV05_Feasibility: + case maturity.StageV05_Feasibility: snippet = fmt.Sprintf("项目「%s」已完成方案成型与法规对齐,具备进入商务核算的条件。", projectName) options = []intent.ExpectationOption{ { @@ -255,7 +255,7 @@ func BuildNextExpectation(stage bizdev.MaturityStage, projectName string) *inten Description: "生成精细化 CDO 工时与成本核算表,锁定立项商务方案", Intent: intent.IntentAdvanceStage, Slots: map[string]string{ - intent.SlotTargetStage: string(bizdev.StageV10_Quoting), + intent.SlotTargetStage: string(maturity.StageV10_Quoting), }, }, { @@ -275,7 +275,7 @@ func BuildNextExpectation(stage bizdev.MaturityStage, projectName string) *inten }, } - case bizdev.StageV10_Quoting: + case maturity.StageV10_Quoting: snippet = fmt.Sprintf("项目「%s」已完成商务锁定,报价核算表已就绪。", projectName) options = []intent.ExpectationOption{ { @@ -307,7 +307,7 @@ func BuildNextExpectation(stage bizdev.MaturityStage, projectName string) *inten Description: "快速沉淀第一版立项画像并为您准备沟通话术", Intent: intent.IntentAdvanceStage, Slots: map[string]string{ - intent.SlotTargetStage: string(bizdev.StageV01_Triage), + intent.SlotTargetStage: string(maturity.StageV01_Triage), }, }, } @@ -381,15 +381,15 @@ func (a *ContextAssembler) AssembleFromWorkspace(workDir string, user UserInfo) ctx.Project.CurrentWorkflow = ctx.Project.ActiveWorkflowKey } if strings.HasPrefix(ctx.Project.CurrentWorkflow, "V0.1") || ctx.Project.CurrentWorkflow == "intake" { - ctx.Project.CurrentStage = bizdev.StageV01_Triage + ctx.Project.CurrentStage = maturity.StageV01_Triage } else if strings.HasPrefix(ctx.Project.CurrentWorkflow, "V0.5") { - ctx.Project.CurrentStage = bizdev.StageV05_Feasibility + ctx.Project.CurrentStage = maturity.StageV05_Feasibility } else if strings.HasPrefix(ctx.Project.CurrentWorkflow, "V1.0") { - ctx.Project.CurrentStage = bizdev.StageV10_Quoting + ctx.Project.CurrentStage = maturity.StageV10_Quoting } if ctx.Project.CurrentStage == "" { - ctx.Project.CurrentStage = bizdev.StageV01_Triage + ctx.Project.CurrentStage = maturity.StageV01_Triage } isCreator := false diff --git a/internal/coordinator/context_test.go b/internal/coordinator/context_test.go index 846ec72b..a7de6335 100644 --- a/internal/coordinator/context_test.go +++ b/internal/coordinator/context_test.go @@ -5,13 +5,13 @@ import ( "path/filepath" "testing" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/coordinator" "chat-agent-system/internal/intent" + "chat-agent-system/internal/maturity" ) func TestComputeAvailableActions(t *testing.T) { - actionsV01 := coordinator.ComputeAvailableActions(bizdev.StageV01_Triage, "composer") + actionsV01 := coordinator.ComputeAvailableActions(maturity.StageV01_Triage, "composer") foundAdvance := false for _, a := range actionsV01 { if a == "ADVANCE_STAGE:V0.5_feasibility" { @@ -22,7 +22,7 @@ func TestComputeAvailableActions(t *testing.T) { t.Errorf("expected V0.1 actions to contain advance to V0.5: %v", actionsV01) } - actionsV05 := coordinator.ComputeAvailableActions(bizdev.StageV05_Feasibility, "composer") + actionsV05 := coordinator.ComputeAvailableActions(maturity.StageV05_Feasibility, "composer") foundAdvanceQuote := false for _, a := range actionsV05 { if a == "ADVANCE_STAGE:V1.0_quoting" { diff --git a/internal/coordinator/dialogue_llm_test.go b/internal/coordinator/dialogue_llm_test.go index 7a722e93..c1b68836 100644 --- a/internal/coordinator/dialogue_llm_test.go +++ b/internal/coordinator/dialogue_llm_test.go @@ -8,8 +8,8 @@ import ( "testing" "chat-agent-system/internal/agent" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/intent" + "chat-agent-system/internal/maturity" ) type scriptedDialogueBackend struct { @@ -49,7 +49,7 @@ func TestDialogueLLM_CasualChatUsesBackend(t *testing.T) { Project: ProjectInfo{ ID: "p-dialogue-1", Name: "CUSA-Dialogue-Test", - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, }, BlackboardFacts: map[string]string{}, RecentDialogue: []DialogueTurn{ @@ -128,7 +128,7 @@ func TestDialogueLLM_AmbiguousFallbackUsesBackend(t *testing.T) { } engine := NewCoordinatorEngineWithDialogue(nil, backend, t.TempDir()) userCtx := &UserProjectContext{ - Project: ProjectInfo{Name: "CUSA", CurrentStage: bizdev.StageV01_Triage}, + Project: ProjectInfo{Name: "CUSA", CurrentStage: maturity.StageV01_Triage}, } rec := &intent.IntentRecognitionResult{ RawInput: "请详细解释压电换能器的逆压电效应与变幅杆阻抗匹配。", @@ -158,7 +158,7 @@ func TestDialogueLLM_FallbackToTemplateOnBackendFailure(t *testing.T) { backend := &scriptedDialogueBackend{fail: true} engine := NewCoordinatorEngineWithDialogue(nil, backend, t.TempDir()) userCtx := &UserProjectContext{ - Project: ProjectInfo{Name: "CUSA", CurrentStage: bizdev.StageV01_Triage}, + Project: ProjectInfo{Name: "CUSA", CurrentStage: maturity.StageV01_Triage}, } rec := &intent.IntentRecognitionResult{ RawInput: "你好", @@ -190,7 +190,7 @@ func TestDialogueLLM_PersonalizedGuidanceAndWarmPersona(t *testing.T) { User: UserInfo{Name: "张工", Role: "engineer", ProjectRole: "composer"}, Project: ProjectInfo{ Name: "CUSA-Warm", - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, }, PersonalizedGuidance: "【用户个性化工作习惯与偏好指导 (Memory Injection)】\n• 沟通风格:该用户偏好【结构精炼、结论先行】\n• 重点关注:该用户较关心【法规标准合规与审评审批风险】\n", Pending: PendingItems{ @@ -236,7 +236,7 @@ func TestDialogueLLM_QueryProgressNoBriefUsesBackend(t *testing.T) { engine := NewCoordinatorEngineWithDialogue(nil, backend, t.TempDir()) userCtx := &UserProjectContext{ User: UserInfo{Name: "张工", ProjectRole: "composer"}, - Project: ProjectInfo{Name: "医疗器械研发项目", CurrentStage: bizdev.StageV01_Triage}, + Project: ProjectInfo{Name: "医疗器械研发项目", CurrentStage: maturity.StageV01_Triage}, } rec := &intent.IntentRecognitionResult{ RawInput: "简单分析一下这个项目有什么风险", @@ -269,7 +269,7 @@ func TestDialogueLLM_QueryProgressNoBriefFallsBackToSynthesizedTemplate(t *testi backend := &scriptedDialogueBackend{fail: true} engine := NewCoordinatorEngineWithDialogue(nil, backend, t.TempDir()) userCtx := &UserProjectContext{ - Project: ProjectInfo{Name: "医疗器械研发项目", CurrentStage: bizdev.StageV01_Triage}, + Project: ProjectInfo{Name: "医疗器械研发项目", CurrentStage: maturity.StageV01_Triage}, } rec := &intent.IntentRecognitionResult{ RawInput: "简单分析一下这个项目有什么风险", diff --git a/internal/coordinator/engine.go b/internal/coordinator/engine.go index 82a676be..ff274860 100644 --- a/internal/coordinator/engine.go +++ b/internal/coordinator/engine.go @@ -13,11 +13,12 @@ import ( "time" "chat-agent-system/internal/agent" - "chat-agent-system/internal/bizdev" + "chat-agent-system/internal/app/stageflow" "chat-agent-system/internal/ctxmgr" "chat-agent-system/internal/docgov" "chat-agent-system/internal/intent" "chat-agent-system/internal/kb" + "chat-agent-system/internal/maturity" "chat-agent-system/internal/projectinstance" "chat-agent-system/internal/squad" "chat-agent-system/internal/stream" @@ -72,19 +73,19 @@ type CoordinationResult struct { // CoordinatorEngine L2 协调引擎 type CoordinatorEngine struct { - bizdevSvc bizdev.BizdevService stageTasks StageTaskRunner instSvc *projectinstance.Service assembler *ContextAssembler dialogueBackend agent.Backend dataDir string + ctxMgr *ctxmgr.ContextManager + kbClient *kb.Client } // StageTaskRunner is the application owner for ExecuteTask / ExecuteStage. -// Wired from app/stageflow; tests may leave it nil and fall back to bizdevSvc. type StageTaskRunner interface { - ExecuteTask(ctx context.Context, req bizdev.TaskRunRequest) (*bizdev.TaskRunResult, error) - ExecuteStage(ctx context.Context, req bizdev.StageRunRequest) (*bizdev.StageRunResult, error) + ExecuteTask(ctx context.Context, req stageflow.TaskRunRequest) (*stageflow.TaskRunResult, error) + ExecuteStage(ctx context.Context, req stageflow.StageRunRequest) (*stageflow.StageRunResult, error) } func (e *CoordinatorEngine) SetStageTaskRunner(r StageTaskRunner) { @@ -97,10 +98,14 @@ func (e *CoordinatorEngine) tasks() StageTaskRunner { if e == nil { return nil } - if e.stageTasks != nil { - return e.stageTasks + return e.stageTasks +} + +func (e *CoordinatorEngine) SetContextServices(ctxMgr *ctxmgr.ContextManager, kbClient *kb.Client) { + if e != nil { + e.ctxMgr = ctxMgr + e.kbClient = kbClient } - return e.bizdevSvc } // SetInstanceService 注入项目工作流实例服务(对话推进与实例门禁合流)。 @@ -110,17 +115,17 @@ func (e *CoordinatorEngine) SetInstanceService(svc *projectinstance.Service) { } } -func NewCoordinatorEngine(bizdevSvc bizdev.BizdevService) *CoordinatorEngine { +func NewCoordinatorEngine(runner StageTaskRunner) *CoordinatorEngine { return &CoordinatorEngine{ - bizdevSvc: bizdevSvc, - assembler: NewContextAssembler(), + stageTasks: runner, + assembler: NewContextAssembler(), } } // NewCoordinatorEngineWithDialogue 注入对话 LLM 后端(Phase A:CASUAL / AMBIGUOUS) -func NewCoordinatorEngineWithDialogue(bizdevSvc bizdev.BizdevService, dialogueBackend agent.Backend, dataDir string) *CoordinatorEngine { +func NewCoordinatorEngineWithDialogue(runner StageTaskRunner, dialogueBackend agent.Backend, dataDir string) *CoordinatorEngine { return &CoordinatorEngine{ - bizdevSvc: bizdevSvc, + stageTasks: runner, assembler: NewContextAssembler(), dialogueBackend: dialogueBackend, dataDir: dataDir, @@ -324,10 +329,10 @@ func (e *CoordinatorEngine) ProcessIntent( // enrichAdvisorBriefWithCases 结合上下文与意图槽位检索相似标杆案例并注入参谋锦囊 func (e *CoordinatorEngine) enrichAdvisorBriefWithCases(ctx context.Context, brief *squad.AdvisorBriefing, userCtx *UserProjectContext, slots map[string]string) { - if brief == nil || e.bizdevSvc == nil { + if brief == nil || e.ctxMgr == nil { return } - ctxMgr := e.bizdevSvc.ContextManager() + ctxMgr := e.ctxMgr if ctxMgr == nil { return } @@ -414,7 +419,7 @@ func (e *CoordinatorEngine) handleAmbiguousConsult(ctx context.Context, cand *in var sb strings.Builder sb.WriteString(fmt.Sprintf("完全理解您想再掂量一下。针对「%s」目前的节点,我帮您快速对照一下:\n\n", projName)) - if currentStage == bizdev.StageV01_Triage { + if currentStage == maturity.StageV01_Triage { sb.WriteString("• 若推进 V0.5(方案成型与法规对齐):\n") sb.WriteString(" 我可帮您梳理初步架构与注册分类路径,并预估型检成本,便于与客户深入沟通;\n") sb.WriteString("• 若先放一放 / 多做调研:\n") @@ -761,9 +766,9 @@ func (e *CoordinatorEngine) handleAdvanceStage(ctx context.Context, cand *intent } targetStageStr := cand.FilledSlots[intent.SlotTargetStage] - targetStage := bizdev.MaturityStage(targetStageStr) + targetStage := maturity.MaturityStage(targetStageStr) if targetStage == "" { - targetStage = bizdev.StageV05_Feasibility + targetStage = maturity.StageV05_Feasibility } streamer := stream.FromContext(ctx) @@ -835,7 +840,7 @@ func (e *CoordinatorEngine) handleAdvanceStage(ctx context.Context, cand *intent } // 3. 调用底层 L3 调度器执行阶段跃迁 - stageRes, err := e.tasks().ExecuteStage(ctx, bizdev.StageRunRequest{ + stageRes, err := e.tasks().ExecuteStage(ctx, stageflow.StageRunRequest{ Stage: targetStage, ProjectName: userCtx.Project.Name, CustomerName: userCtx.Project.CustomerName, @@ -929,7 +934,7 @@ func (e *CoordinatorEngine) handleTriggerTask(ctx context.Context, cand *intent. fmt.Sscanf(userCtx.User.ID, "%d", &userID) } - taskRes, err := e.tasks().ExecuteTask(ctx, bizdev.TaskRunRequest{ + taskRes, err := e.tasks().ExecuteTask(ctx, stageflow.TaskRunRequest{ TaskKey: taskKey, ProjectName: userCtx.Project.Name, CustomerName: userCtx.Project.CustomerName, @@ -999,9 +1004,9 @@ func (e *CoordinatorEngine) handleTriggerTask(ctx context.Context, cand *intent. // formatTriggerTaskReply builds sync coordinator copy for a TaskRunResult. // Pending high-risk candidates must not claim "正文已保存 / 已完成". -func formatTriggerTaskReply(taskRes *bizdev.TaskRunResult, outPath string) (reply string, taskStatus string) { +func formatTriggerTaskReply(taskRes *stageflow.TaskRunResult, outPath string) (reply string, taskStatus string) { if taskRes == nil { - return "任务执行失败。", bizdev.TaskStatusFailed + return "任务执行失败。", stageflow.TaskStatusFailed } taskStatus = taskRes.TerminalStatus() if taskRes.AwaitsAgentConfirmation() { @@ -1019,7 +1024,7 @@ func formatTriggerTaskReply(taskRes *bizdev.TaskRunResult, outPath string) (repl return sb.String(), taskStatus } -func attachTaskRunProjection(res *CoordinationResult, taskRes *bizdev.TaskRunResult) { +func attachTaskRunProjection(res *CoordinationResult, taskRes *stageflow.TaskRunResult) { if res == nil || taskRes == nil { return } @@ -1072,12 +1077,12 @@ func (e *CoordinatorEngine) handleTriggerAdhocTask(ctx context.Context, cand *in // 任务简报材料化:作为首要输入材料注入工作区(context/materials_text/task_brief.md), // 供 organizer 专员在容器内直接读到用户原始诉求(否则首步将报"无材料可整理") - briefMaterial := bizdev.MaterialInput{ + briefMaterial := stageflow.MaterialInput{ Filename: "task_brief.md", Content: []byte(fmt.Sprintf("# 任务简报(用户原始诉求,权威等级:primary_evidence)\n\n%s\n", brief)), } - taskRes, err := e.tasks().ExecuteTask(ctx, bizdev.TaskRunRequest{ + taskRes, err := e.tasks().ExecuteTask(ctx, stageflow.TaskRunRequest{ TaskKey: taskKey, Title: title, ProjectName: userCtx.Project.Name, @@ -1086,7 +1091,7 @@ func (e *CoordinatorEngine) handleTriggerAdhocTask(ctx context.Context, cand *in IntendedUse: userCtx.Project.IntendedUse, TargetMarket: userCtx.Project.TargetMarket, Fields: userCtx.BlackboardFacts, - Materials: []bizdev.MaterialInput{briefMaterial}, + Materials: []stageflow.MaterialInput{briefMaterial}, AutoRepair: true, ProjectID: projectID, UserID: userID, @@ -1671,7 +1676,7 @@ func (e *CoordinatorEngine) handleQueryRegulations(ctx context.Context, cand *in } var hits []kb.HitItem - if e != nil && e.bizdevSvc != nil && e.bizdevSvc.KB() != nil && strings.TrimSpace(searchQuery) != "" { + if e != nil && e.kbClient != nil && strings.TrimSpace(searchQuery) != "" { cacheKey := ctxmgr.HashKey("regulatory_search", searchQuery) cache := ctxmgr.GetGlobalCache() if cached, ok := cache.Get(ctxmgr.LayerC1Search, cacheKey); ok { @@ -1679,7 +1684,7 @@ func (e *CoordinatorEngine) handleQueryRegulations(ctx context.Context, cand *in hits = ch } } else { - kbHits, err := e.bizdevSvc.KB().Search(ctx, searchQuery, kb.SearchOptions{ + kbHits, err := e.kbClient.Search(ctx, searchQuery, kb.SearchOptions{ Domains: []kb.KnowledgeDomain{kb.DomainRegulatory}, Limit: 5, }) diff --git a/internal/coordinator/engine_clarification_test.go b/internal/coordinator/engine_clarification_test.go index 9b4d454c..488e03f6 100644 --- a/internal/coordinator/engine_clarification_test.go +++ b/internal/coordinator/engine_clarification_test.go @@ -5,9 +5,9 @@ import ( "strings" "testing" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/coordinator" "chat-agent-system/internal/intent" + "chat-agent-system/internal/maturity" ) // TestEngine_ClarificationBeforeAmbiguousConsult 缺驳回理由必须返回定向澄清,不得进入参谋模糊咨询 @@ -17,7 +17,7 @@ func TestEngine_ClarificationBeforeAmbiguousConsult(t *testing.T) { ctx := &intent.ContextSnapshot{ SnapshotID: "ctx_engine_clarify", - CurrentStage: string(bizdev.StageV05_Feasibility), + CurrentStage: string(maturity.StageV05_Feasibility), ActiveDocID: "doc-002", DocLifecycleState: "reviewing", UserDocRole: "reviewer", @@ -38,7 +38,7 @@ func TestEngine_ClarificationBeforeAmbiguousConsult(t *testing.T) { User: coordinator.UserInfo{ID: "user_102", Name: "李审核", Role: "reviewer", ProjectRole: "reviewer"}, Project: coordinator.ProjectInfo{ Name: "智能内窥镜项目", - CurrentStage: bizdev.StageV05_Feasibility, + CurrentStage: maturity.StageV05_Feasibility, }, BlackboardFacts: map[string]string{}, } @@ -75,8 +75,8 @@ func TestEngine_ClaimQueryMustNotExecuteWrite(t *testing.T) { } userCtx := &coordinator.UserProjectContext{ - User: coordinator.UserInfo{ID: "user_101", Name: "张工", Role: "engineer", ProjectRole: "composer"}, - Project: coordinator.ProjectInfo{Name: "测试项目"}, + User: coordinator.UserInfo{ID: "user_101", Name: "张工", Role: "engineer", ProjectRole: "composer"}, + Project: coordinator.ProjectInfo{Name: "测试项目"}, BlackboardFacts: map[string]string{}, } diff --git a/internal/coordinator/engine_run_test.go b/internal/coordinator/engine_run_test.go index fa1e95d6..0ff41618 100644 --- a/internal/coordinator/engine_run_test.go +++ b/internal/coordinator/engine_run_test.go @@ -19,9 +19,9 @@ func TestEngine_RunStatusQuery_WithWorkDir(t *testing.T) { } userCtx := &coordinator.UserProjectContext{ - User: coordinator.UserInfo{ID: "1", Name: "用户"}, - Project: coordinator.ProjectInfo{Name: "项目"}, - WorkDir: "/data/dev/ws-123", + User: coordinator.UserInfo{ID: "1", Name: "用户"}, + Project: coordinator.ProjectInfo{Name: "项目"}, + WorkDir: "/data/dev/ws-123", BlackboardFacts: map[string]string{}, } diff --git a/internal/coordinator/engine_test.go b/internal/coordinator/engine_test.go index 3780ac5d..6776105d 100644 --- a/internal/coordinator/engine_test.go +++ b/internal/coordinator/engine_test.go @@ -4,9 +4,9 @@ import ( "context" "testing" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/coordinator" "chat-agent-system/internal/intent" + "chat-agent-system/internal/maturity" "chat-agent-system/internal/squad" "strings" ) @@ -75,7 +75,7 @@ func TestCoordinatorEngine_QueryProgress_NoBrief_SubstantiveReply(t *testing.T) Name: "医疗器械研发项目", CustomerName: "北京水木东方", CurrentWorkflow: "intake", - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, }, BlackboardFacts: map[string]string{}, } @@ -156,7 +156,7 @@ func TestCoordinatorEngine_AdvanceStage(t *testing.T) { userCtx := &coordinator.UserProjectContext{ Project: coordinator.ProjectInfo{ Name: "超声测试项目", - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, }, User: coordinator.UserInfo{ ProjectRole: "composer", @@ -167,7 +167,7 @@ func TestCoordinatorEngine_AdvanceStage(t *testing.T) { TopIntent: &intent.CandidateIntent{ Intent: intent.IntentAdvanceStage, FilledSlots: map[string]string{ - intent.SlotTargetStage: string(bizdev.StageV05_Feasibility), + intent.SlotTargetStage: string(maturity.StageV05_Feasibility), }, }, } @@ -180,7 +180,7 @@ func TestCoordinatorEngine_AdvanceStage(t *testing.T) { if res.Status != coordinator.StatusAccepted { t.Errorf("expected status ACCEPTED, got %s", res.Status) } - if userCtx.Project.CurrentStage != bizdev.StageV05_Feasibility { + if userCtx.Project.CurrentStage != maturity.StageV05_Feasibility { t.Errorf("expected stage V0.5_feasibility, got %s", userCtx.Project.CurrentStage) } } @@ -190,9 +190,9 @@ func TestCoordinatorEngine_DeclineExpectation(t *testing.T) { userCtx := &coordinator.UserProjectContext{ Project: coordinator.ProjectInfo{ Name: "超声测试项目", - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, }, - PendingExpectation: coordinator.BuildNextExpectation(bizdev.StageV01_Triage, "超声测试项目"), + PendingExpectation: coordinator.BuildNextExpectation(maturity.StageV01_Triage, "超声测试项目"), } recRes := &intent.IntentRecognitionResult{ @@ -225,7 +225,7 @@ func TestCoordinatorEngine_AmbiguousConsult(t *testing.T) { userCtx := &coordinator.UserProjectContext{ Project: coordinator.ProjectInfo{ Name: "超声测试项目", - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, }, } @@ -255,7 +255,7 @@ func TestCoordinatorEngine_AdvanceStageWithPatch(t *testing.T) { userCtx := &coordinator.UserProjectContext{ Project: coordinator.ProjectInfo{ Name: "超声测试项目", - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, }, BlackboardFacts: make(map[string]string), } @@ -266,8 +266,8 @@ func TestCoordinatorEngine_AdvanceStageWithPatch(t *testing.T) { Intent: intent.IntentAdvanceStage, Branch: intent.BranchExpectationHit, FilledSlots: map[string]string{ - intent.SlotTargetStage: string(bizdev.StageV05_Feasibility), - "target_market": "欧洲CE", + intent.SlotTargetStage: string(maturity.StageV05_Feasibility), + "target_market": "欧洲CE", }, PatchSlots: map[string]string{ "target_market": "欧洲CE", @@ -580,9 +580,9 @@ func TestCoordinatorEngine_RejectExpectationAndAffirmativeChain(t *testing.T) { TopIntent: &intent.CandidateIntent{ Intent: intent.IntentDocGovReviewReject, FilledSlots: map[string]string{ - intent.SlotTargetDoc: "doc_cardio_01", - intent.SlotRejectReason: "第3节缺少血液相容性溶血试验评价指标", - intent.SlotTargetSection: "第3节", + intent.SlotTargetDoc: "doc_cardio_01", + intent.SlotRejectReason: "第3节缺少血液相容性溶血试验评价指标", + intent.SlotTargetSection: "第3节", }, }, } @@ -982,5 +982,3 @@ func TestCoordinatorEngine_TestingAnalysis(t *testing.T) { t.Errorf("reply must not contain commercial triage boilerplate, got: %s", res.NaturalReply) } } - - diff --git a/internal/coordinator/engine_workflow.go b/internal/coordinator/engine_workflow.go index 985b1496..6e27f315 100644 --- a/internal/coordinator/engine_workflow.go +++ b/internal/coordinator/engine_workflow.go @@ -36,9 +36,9 @@ func (e *CoordinatorEngine) handleSwitchWorkflow(_ context.Context, cand *intent if userCtx.Project.ActiveWorkflowKey == targetWF { return &CoordinationResult{ - Status: StatusAccepted, - Intent: intent.IntentSwitchWorkflow, - NaturalReply: fmt.Sprintf("当前项目已激活工作流「%s」,无需重复切换。", targetWF), + Status: StatusAccepted, + Intent: intent.IntentSwitchWorkflow, + NaturalReply: fmt.Sprintf("当前项目已激活工作流「%s」,无需重复切换。", targetWF), UpdatedContext: userCtx, }, nil } @@ -83,9 +83,9 @@ func (e *CoordinatorEngine) handleTriggerWorkflow(_ context.Context, cand *inten targetWF, workflowDisplayName(targetWF), ) return &CoordinationResult{ - Status: StatusAccepted, - Intent: intent.IntentTriggerWorkflow, - NaturalReply: msg, + Status: StatusAccepted, + Intent: intent.IntentTriggerWorkflow, + NaturalReply: msg, UpdatedContext: userCtx, }, nil } @@ -107,9 +107,9 @@ func (e *CoordinatorEngine) handleQueryWorkflowStatus(_ context.Context, _ *inte } } return &CoordinationResult{ - Status: StatusAccepted, - Intent: intent.IntentQueryWorkflowStatus, - NaturalReply: sb.String(), + Status: StatusAccepted, + Intent: intent.IntentQueryWorkflowStatus, + NaturalReply: sb.String(), UpdatedContext: userCtx, }, nil } @@ -129,9 +129,9 @@ func (e *CoordinatorEngine) handleQueryDocStatus(ctx context.Context, cand *inte defaultStr(lifecycle, "请在工作台文档面板查看详情"), ) return &CoordinationResult{ - Status: StatusAccepted, - Intent: intent.IntentQueryDocStatus, - NaturalReply: reply, + Status: StatusAccepted, + Intent: intent.IntentQueryDocStatus, + NaturalReply: reply, UpdatedContext: userCtx, }, nil } @@ -149,18 +149,18 @@ func (e *CoordinatorEngine) handleHelpCapabilities(_ context.Context, _ *intent. } sb.WriteString("\n高风险操作(工作流切换、文档审批、阶段推进)需要明确确认后才会执行。") return &CoordinationResult{ - Status: StatusAccepted, - Intent: intent.IntentHelpCapabilities, - NaturalReply: sb.String(), + Status: StatusAccepted, + Intent: intent.IntentHelpCapabilities, + NaturalReply: sb.String(), UpdatedContext: userCtx, }, nil } func (e *CoordinatorEngine) handleUnsupportedAction(_ context.Context, _ *intent.CandidateIntent, userCtx *UserProjectContext) (*CoordinationResult, error) { return &CoordinationResult{ - Status: StatusAccepted, - Intent: intent.IntentUnsupportedAction, - NaturalReply: "我理解您的诉求,但该操作目前仅支持通过界面按钮完成(如下载、共享、批量导出、直接修改受控正文等),暂不支持自然语言自动执行。", + Status: StatusAccepted, + Intent: intent.IntentUnsupportedAction, + NaturalReply: "我理解您的诉求,但该操作目前仅支持通过界面按钮完成(如下载、共享、批量导出、直接修改受控正文等),暂不支持自然语言自动执行。", UpdatedContext: userCtx, }, nil } @@ -244,8 +244,8 @@ func buildWorkflowSwitchExpectation(targetWF string, userCtx *UserProjectContext }, }, Payload: map[string]string{ - intent.SlotTargetWorkflow: targetWF, - "selection_version": fmt.Sprintf("%d", userCtx.Project.WorkflowSelectionVersion), + intent.SlotTargetWorkflow: targetWF, + "selection_version": fmt.Sprintf("%d", userCtx.Project.WorkflowSelectionVersion), }, } } diff --git a/internal/coordinator/engine_workflow_test.go b/internal/coordinator/engine_workflow_test.go index 853f13ec..b9b49b46 100644 --- a/internal/coordinator/engine_workflow_test.go +++ b/internal/coordinator/engine_workflow_test.go @@ -5,9 +5,9 @@ import ( "strings" "testing" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/coordinator" "chat-agent-system/internal/intent" + "chat-agent-system/internal/maturity" ) func TestEngine_SwitchWorkflow_NonCreatorRejected(t *testing.T) { @@ -24,11 +24,11 @@ func TestEngine_SwitchWorkflow_NonCreatorRejected(t *testing.T) { userCtx := &coordinator.UserProjectContext{ User: coordinator.UserInfo{ID: "42", Name: "张工", ProjectRole: "composer"}, Project: coordinator.ProjectInfo{ - Name: "测试项目", - CreatorUserID: 1, - ActiveWorkflowKey: "main", + Name: "测试项目", + CreatorUserID: 1, + ActiveWorkflowKey: "main", WorkflowSelectionVersion: 1, - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, }, AvailableActions: []string{"SWITCH_WORKFLOW"}, BlackboardFacts: map[string]string{}, @@ -61,7 +61,7 @@ func TestEngine_QueryWorkflowStatus(t *testing.T) { Name: "测试项目", ActiveWorkflowKey: "product_manager", WorkflowSelectionVersion: 2, - CurrentStage: bizdev.StageV05_Feasibility, + CurrentStage: maturity.StageV05_Feasibility, }, AvailableActions: []string{"QUERY_WORKFLOW", "TRIGGER_WORKFLOW:product_manager"}, BlackboardFacts: map[string]string{}, @@ -89,10 +89,10 @@ func TestEngine_HelpCapabilities(t *testing.T) { } userCtx := &coordinator.UserProjectContext{ - User: coordinator.UserInfo{ID: "1", Name: "用户"}, - Project: coordinator.ProjectInfo{Name: "项目"}, + User: coordinator.UserInfo{ID: "1", Name: "用户"}, + Project: coordinator.ProjectInfo{Name: "项目"}, AvailableActions: []string{"QUERY_PROGRESS", "SWITCH_WORKFLOW"}, - BlackboardFacts: map[string]string{}, + BlackboardFacts: map[string]string{}, } res, err := engine.ProcessIntent(context.Background(), recRes, userCtx) diff --git a/internal/coordinator/instance_advance_governance_test.go b/internal/coordinator/instance_advance_governance_test.go index b2bd74d2..89c58892 100644 --- a/internal/coordinator/instance_advance_governance_test.go +++ b/internal/coordinator/instance_advance_governance_test.go @@ -4,11 +4,12 @@ import ( "context" "testing" - "chat-agent-system/internal/bizdev" + "chat-agent-system/internal/app/stageflow" "chat-agent-system/internal/ctxmgr" "chat-agent-system/internal/docgov" "chat-agent-system/internal/intent" "chat-agent-system/internal/kb" + "chat-agent-system/internal/maturity" "chat-agent-system/internal/projectinstance" "chat-agent-system/internal/squad" "chat-agent-system/internal/storage" @@ -18,14 +19,14 @@ type countingBizdev struct { stageCalls int } -func (c *countingBizdev) ListTasks() []bizdev.TaskMeta { return nil } -func (c *countingBizdev) ListStages() []bizdev.StageMeta { return nil } -func (c *countingBizdev) ExecuteTask(_ context.Context, _ bizdev.TaskRunRequest) (*bizdev.TaskRunResult, error) { - return &bizdev.TaskRunResult{}, nil +func (c *countingBizdev) ListTasks() []stageflow.TaskMeta { return nil } +func (c *countingBizdev) ListStages() []stageflow.StageMeta { return nil } +func (c *countingBizdev) ExecuteTask(_ context.Context, _ stageflow.TaskRunRequest) (*stageflow.TaskRunResult, error) { + return &stageflow.TaskRunResult{}, nil } -func (c *countingBizdev) ExecuteStage(_ context.Context, _ bizdev.StageRunRequest) (*bizdev.StageRunResult, error) { +func (c *countingBizdev) ExecuteStage(_ context.Context, _ stageflow.StageRunRequest) (*stageflow.StageRunResult, error) { c.stageCalls++ - return &bizdev.StageRunResult{StageTitle: "legacy"}, nil + return &stageflow.StageRunResult{StageTitle: "legacy"}, nil } func (c *countingBizdev) InspectWorkspace(_ context.Context, _ string) (*squad.WorkspaceState, error) { return nil, nil @@ -58,14 +59,14 @@ func TestDialogueAdvanceStage_LiveInstanceDoesNotUseBizdev(t *testing.T) { engine.SetInstanceService(instSvc) userCtx := &UserProjectContext{ - Project: ProjectInfo{ID: "55", CreatorUserID: 1, CurrentStage: bizdev.StageV01_Triage}, + Project: ProjectInfo{ID: "55", CreatorUserID: 1, CurrentStage: maturity.StageV01_Triage}, User: UserInfo{ID: "1", ProjectRole: "owner"}, } recRes := &intent.IntentRecognitionResult{ TopIntent: &intent.CandidateIntent{ Intent: intent.IntentAdvanceStage, FilledSlots: map[string]string{ - intent.SlotTargetStage: string(bizdev.StageV05_Feasibility), + intent.SlotTargetStage: string(maturity.StageV05_Feasibility), }, }, } diff --git a/internal/coordinator/memory_composer_test.go b/internal/coordinator/memory_composer_test.go index 1029470c..cf4b592c 100644 --- a/internal/coordinator/memory_composer_test.go +++ b/internal/coordinator/memory_composer_test.go @@ -5,11 +5,11 @@ import ( "testing" "time" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/coordinator" "chat-agent-system/internal/ctxmgr" "chat-agent-system/internal/intent" "chat-agent-system/internal/kb" + "chat-agent-system/internal/maturity" ) func TestMemoryComposer_HierarchyAndPriority(t *testing.T) { @@ -33,7 +33,7 @@ func TestMemoryComposer_HierarchyAndPriority(t *testing.T) { Name: "超声切割止血系统", DeviceType: "有源手术器械", TargetMarket: "国内+CE", - CurrentStage: bizdev.StageV01_Triage, + CurrentStage: maturity.StageV01_Triage, CurrentWorkflow: "立项摸底", }, TaskState: taskState, diff --git a/internal/coordinator/pending_confirmation_reply_test.go b/internal/coordinator/pending_confirmation_reply_test.go index 09c67372..628e5d62 100644 --- a/internal/coordinator/pending_confirmation_reply_test.go +++ b/internal/coordinator/pending_confirmation_reply_test.go @@ -6,25 +6,26 @@ import ( "testing" "time" - "chat-agent-system/internal/bizdev" + "chat-agent-system/internal/app/stageflow" "chat-agent-system/internal/ctxmgr" "chat-agent-system/internal/docgov" "chat-agent-system/internal/intent" "chat-agent-system/internal/kb" + "chat-agent-system/internal/maturity" "chat-agent-system/internal/squad" "chat-agent-system/internal/storage" ) type pendingReplyBizdev struct { - res *bizdev.TaskRunResult + res *stageflow.TaskRunResult } -func (p *pendingReplyBizdev) ListTasks() []bizdev.TaskMeta { return nil } -func (p *pendingReplyBizdev) ListStages() []bizdev.StageMeta { return nil } -func (p *pendingReplyBizdev) ExecuteTask(_ context.Context, _ bizdev.TaskRunRequest) (*bizdev.TaskRunResult, error) { +func (p *pendingReplyBizdev) ListTasks() []stageflow.TaskMeta { return nil } +func (p *pendingReplyBizdev) ListStages() []stageflow.StageMeta { return nil } +func (p *pendingReplyBizdev) ExecuteTask(_ context.Context, _ stageflow.TaskRunRequest) (*stageflow.TaskRunResult, error) { return p.res, nil } -func (p *pendingReplyBizdev) ExecuteStage(_ context.Context, _ bizdev.StageRunRequest) (*bizdev.StageRunResult, error) { +func (p *pendingReplyBizdev) ExecuteStage(_ context.Context, _ stageflow.StageRunRequest) (*stageflow.StageRunResult, error) { return nil, nil } func (p *pendingReplyBizdev) InspectWorkspace(_ context.Context, _ string) (*squad.WorkspaceState, error) { @@ -39,7 +40,7 @@ func (p *pendingReplyBizdev) DocGov() *docgov.GovernanceEngine { return ni func (p *pendingReplyBizdev) KB() *kb.Client { return nil } func TestSyncTriggerTask_PendingConfirmation_NotSavedCompleted(t *testing.T) { - pending := &bizdev.TaskRunResult{ + pending := &stageflow.TaskRunResult{ Success: true, TaskKey: "intake", ArtifactTitle: "用户初始需求收集表", @@ -55,7 +56,7 @@ func TestSyncTriggerTask_PendingConfirmation_NotSavedCompleted(t *testing.T) { eng := NewCoordinatorEngine(&pendingReplyBizdev{res: pending}) userCtx := &UserProjectContext{ User: UserInfo{ID: "1", Name: "u", ProjectRole: "author"}, - Project: ProjectInfo{ID: "9", Name: "P", CurrentStage: bizdev.StageV01_Triage}, + Project: ProjectInfo{ID: "9", Name: "P", CurrentStage: maturity.StageV01_Triage}, } cand := &intent.CandidateIntent{ Intent: intent.IntentTriggerTask, @@ -78,7 +79,7 @@ func TestSyncTriggerTask_PendingConfirmation_NotSavedCompleted(t *testing.T) { if !strings.Contains(res.NaturalReply, "文档候选已生成") || !strings.Contains(res.NaturalReply, "待编制人确认") { t.Fatalf("sync reply missing pending wording: %s", res.NaturalReply) } - if res.TaskStatus != bizdev.TaskStatusPendingAuthorConfirmation { + if res.TaskStatus != stageflow.TaskStatusPendingAuthorConfirmation { t.Fatalf("TaskStatus=%q", res.TaskStatus) } if res.DocID != "doc_proj9_intake" || res.PendingAgentCandidateID != 99 || res.PendingChangeReportID != 12 { @@ -87,7 +88,7 @@ func TestSyncTriggerTask_PendingConfirmation_NotSavedCompleted(t *testing.T) { } func TestSyncTriggerTask_Committed_KeepsSavedWording(t *testing.T) { - ok := &bizdev.TaskRunResult{ + ok := &stageflow.TaskRunResult{ Success: true, TaskKey: "intake", ArtifactTitle: "用户初始需求收集表", @@ -98,7 +99,7 @@ func TestSyncTriggerTask_Committed_KeepsSavedWording(t *testing.T) { eng := NewCoordinatorEngine(&pendingReplyBizdev{res: ok}) userCtx := &UserProjectContext{ User: UserInfo{ID: "1", ProjectRole: "author"}, - Project: ProjectInfo{ID: "1", Name: "P", CurrentStage: bizdev.StageV01_Triage}, + Project: ProjectInfo{ID: "1", Name: "P", CurrentStage: maturity.StageV01_Triage}, } cand := &intent.CandidateIntent{ Intent: intent.IntentTriggerTask, @@ -115,13 +116,13 @@ func TestSyncTriggerTask_Committed_KeepsSavedWording(t *testing.T) { if !strings.Contains(res.NaturalReply, "正文已保存") { t.Fatalf("committed sync reply should mention saved body: %s", res.NaturalReply) } - if res.TaskStatus != bizdev.TaskStatusCompleted { + if res.TaskStatus != stageflow.TaskStatusCompleted { t.Fatalf("TaskStatus=%q", res.TaskStatus) } } func TestFormatTriggerTaskReply_PendingUsesCompletionSummary(t *testing.T) { - pending := &bizdev.TaskRunResult{ + pending := &stageflow.TaskRunResult{ Success: true, ArtifactTitle: "法规对齐报告", PendingAgentCandidateID: 1, @@ -129,7 +130,7 @@ func TestFormatTriggerTaskReply_PendingUsesCompletionSummary(t *testing.T) { DocRecord: &docgov.DocumentRecord{DocID: "doc_x"}, } reply, status := formatTriggerTaskReply(pending, "/tmp/out") - if status != bizdev.TaskStatusPendingAuthorConfirmation { + if status != stageflow.TaskStatusPendingAuthorConfirmation { t.Fatalf("status=%q", status) } if strings.Contains(reply, "正文已保存") { diff --git a/internal/coordinator/router.go b/internal/coordinator/router.go index ce0eda7e..46d3e8e9 100644 --- a/internal/coordinator/router.go +++ b/internal/coordinator/router.go @@ -298,4 +298,3 @@ func sanitizeAdhocTaskKey(title string) string { } return "adhoc_" + key } - diff --git a/internal/coordinator/router_test.go b/internal/coordinator/router_test.go index 2ebb32bb..47690836 100644 --- a/internal/coordinator/router_test.go +++ b/internal/coordinator/router_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" - "chat-agent-system/internal/bizdev" "chat-agent-system/internal/intent" + "chat-agent-system/internal/maturity" ) // ============================================================================ @@ -109,8 +109,8 @@ func TestUpgradeFlow_AttachCooldownAndRedeem(t *testing.T) { engine := NewCoordinatorEngine(nil) newCtx := func() *UserProjectContext { return &UserProjectContext{ - User: UserInfo{Name: "张工", ProjectRole: "composer"}, - Project: ProjectInfo{Name: "掌上超声项目", CurrentStage: bizdev.StageV01_Triage}, + User: UserInfo{Name: "张工", ProjectRole: "composer"}, + Project: ProjectInfo{Name: "掌上超声项目", CurrentStage: maturity.StageV01_Triage}, BlackboardFacts: map[string]string{}, } } @@ -119,7 +119,7 @@ func TestUpgradeFlow_AttachCooldownAndRedeem(t *testing.T) { // 1. 模糊分支命中复杂画像 → 初答 + 升级建议挂载 rec := &intent.IntentRecognitionResult{ RawInput: complexInput, - Branch: intent.BranchAmbiguousFallback, + Branch: intent.BranchAmbiguousFallback, TopIntent: &intent.CandidateIntent{Intent: intent.IntentCasualChat, Confidence: 0.2, Branch: intent.BranchAmbiguousFallback}, } res, err := engine.ProcessIntent(context.Background(), rec, newCtx()) @@ -187,11 +187,11 @@ func TestUpgradeFlow_NoHintForSimpleInputs(t *testing.T) { for _, input := range []string{"这个先放放,你觉得呢", "好的知道了", "今天天气不错"} { userCtx := &UserProjectContext{ User: UserInfo{Name: "张工", ProjectRole: "composer"}, - Project: ProjectInfo{Name: "智能输注泵项目", CurrentStage: bizdev.StageV01_Triage}, + Project: ProjectInfo{Name: "智能输注泵项目", CurrentStage: maturity.StageV01_Triage}, } rec := &intent.IntentRecognitionResult{ RawInput: input, - Branch: intent.BranchAmbiguousFallback, + Branch: intent.BranchAmbiguousFallback, TopIntent: &intent.CandidateIntent{Intent: intent.IntentCasualChat, Confidence: 0.2, Branch: intent.BranchAmbiguousFallback}, } res, err := engine.ProcessIntent(context.Background(), rec, userCtx) @@ -206,4 +206,3 @@ func TestUpgradeFlow_NoHintForSimpleInputs(t *testing.T) { } } } -