diff --git a/.doc/ops/short-term/2026-09-15-event-shared-live-cutover.md b/.doc/archive/ops/2026-09-15-event-shared-live-cutover-task.md similarity index 52% rename from .doc/ops/short-term/2026-09-15-event-shared-live-cutover.md rename to .doc/archive/ops/2026-09-15-event-shared-live-cutover-task.md index a3d5075f..a759df1a 100644 --- a/.doc/ops/short-term/2026-09-15-event-shared-live-cutover.md +++ b/.doc/archive/ops/2026-09-15-event-shared-live-cutover-task.md @@ -1,6 +1,6 @@ --- title: "共享环境事件消费者 live 切换" -status: in_progress +status: done created: 2026-09-15 updated: 2026-09-15 owner: Cursor @@ -31,20 +31,24 @@ mutex: events ## 步骤 1. [x] L0 受控 SetMode 与 inventory -2. [ ] L1 notify -3. [ ] L2 workflow_advance -4. [ ] L3 projection + 授权页 -5. [ ] L4 删除生产 hook 注册 +2. [x] L1 notify +3. [x] L2 workflow_advance +4. [x] L3 projection + 授权页 +5. [x] L4 删除生产 hook 注册 ## 验收标准 -- [ ] fav / test / main 切模式失败 -- [ ] 每消费者独立 live 报告 -- [ ] 生产代码无 `OnOutbox =` / `AddOnApprovedHook(` +- [x] fav / test / main 切模式失败 +- [x] 每消费者独立 live 报告 +- [x] 生产代码无 `OnOutbox =` / `AddOnApprovedHook(` ## 相关链接 - Long-term: [.doc/archive/ops/2026-09-15-event-shared-live-cutover.md](../../archive/ops/2026-09-15-event-shared-live-cutover.md) -- Test report: (本波完成后补) +- Notify: [.doc/test-reports/2026-09-15-event-notify-shared-live-test-report.md](../../test-reports/2026-09-15-event-notify-shared-live-test-report.md) +- Advance: [.doc/test-reports/2026-09-15-event-workflow-advance-shared-live-test-report.md](../../test-reports/2026-09-15-event-workflow-advance-shared-live-test-report.md) +- Projection: [.doc/test-reports/2026-09-15-event-projection-shared-live-test-report.md](../../test-reports/2026-09-15-event-projection-shared-live-test-report.md) ## 证据 / 备注 + +已合入 `dev@39dc68d`。生产 hook 注册已删;方法本体保留一个窗口。 diff --git a/.doc/audit/2026-09-15-multi-intent-hitl-plan-review.md b/.doc/audit/2026-09-15-multi-intent-hitl-plan-review.md new file mode 100644 index 00000000..3b108a1b --- /dev/null +++ b/.doc/audit/2026-09-15-multi-intent-hitl-plan-review.md @@ -0,0 +1,122 @@ +--- +title: "多意图与 HITL 方案复核" +status: done +created: 2026-09-15 +updated: 2026-09-15 +severity: high +--- + +# 多意图与 HITL 方案复核 + +## 结论 + +提案方向合理,且可复用现有 IntentFrameV2、ActionRegistry、PendingExpectation、交互卡和可靠事件骨架。但初稿不能直接实施:它会让 LLM backend 进入 `internal/intent`、把跨模块执行继续堆入 coordinator,并以不足以抵御多实例竞态的 PlanID+StepID 代替状态机和动作幂等,存在解耦回退、越权和双执行风险。 + +已按审阅结果重写[系统设计](../system-design/2026-09-15-multi-intent-hitl-plan.md)与[任务总览](../ops/short-term/2026-09-15-multi-intent-hitl.md)。本次仅修改文档,没有实施业务代码。 + +## 已确认问题 + +### P1:原 LLM 接线破坏 intent 纯模块边界 + +初稿要求在 `internal/intent/segmenter.go` 经既有 `agent.Backend` 分段;当前边界只允许 `intent -> maturity`。照此实施必然新增 intent 到 agent/coordinator 的依赖。 + +**整改:** 规则分段留在 intent;可选 LLM 仅作为 `app/intentflow` 外围 adapter,返回不可信分段建议,每段重新走确定性识别、安全扫描和 ActionRegistry。任何阶段都禁止 intent import agent、PG、storage 或 coordinator。 + +### P1:计划持久化缺少权威状态机与并发协议 + +初稿两表只有宽泛 status/payload,PlanID+StepID 只是标识,不能防重复确认、确认/取消/过期竞态、两个 worker 同时执行,也不能处理业务成功而步骤 receipt 未落库的崩溃窗口。 + +**整改:** 增加 plan revision/digest、append-only decisions、expected revision、decision nonce、步骤 CAS、lease/fencing、动作级幂等 receipt 和恢复对账。PG 是唯一权威;UserProjectContext/消息只保存 plan 引用。 + +### P1:确认未与当前授权绑定 + +持久化 user/role 或用户曾经确认都不能证明执行时仍有权。原稿没有要求恢复、读取和每步执行重新检查当前项目成员、duty、资源生命周期与版本。 + +**整改:** 确认只记录意愿;所有读取/决策验证 user/session/project 四元作用域;每步由动作 owner 按当前 principal 和 expected resource version 重新授权。失败 fail closed,不以系统身份代执行。 + +### P1:执行器方案会让 coordinator 再次成为 service locator + +初稿拟扩展 `coordinator/action_planner.go` 的分发表来执行写动作,会把 docgov/taskrun/workflow 等具体实现重新聚集到 coordinator,抵消已完成的 chatflow/stageflow/bizdev 解耦。 + +**整改:** 新增深模块 `internal/app/intentflow` 作为计划生命周期 owner,通过消费者拥有的窄端口调用动作属主;coordinator/chat 仅保留兼容入口,组合根唯一装配。 + +### P1:事件与 SSE 被混为一条通道 + +现有 Track E 只处理注册的 PG 事件,不会自动把任意 delivery 变成 SSE。若只发 SSE,刷新丢失;若只写 outbox,浏览器不会自动得到状态。 + +**整改:** 计划状态同步落库;outbox 只发布版本化状态事实并驱动消息/read model 投影;SSE 是提交后的提示。刷新总是 GET PlanView。事件先登记 YAML、StaticContracts 和 payload allowlist。 + +### P1:不确定分段会退回单意图执行 + +“置信下降/指代补全失败就合并回单意图”与“不确定必须澄清、未确认零副作用”矛盾,仍可能执行 TopIntent 并丢弃其余任务。 + +**整改:** 只有确定为完整单意图连动时才合并;低置信、指代失败或无法证明完整一律澄清,保留候选理解但不执行。 + +### P1:数据复制与步骤传递缺少信任边界 + +初稿可能把原文、槽位、结果复制到 JSONB、日志、事件、SSE,再把查询摘要直接注入 task brief,扩大敏感数据面和提示注入路径。 + +**整改:** 计划保存消息引用/digest/allowlist display snapshot;事件和日志仅传 scope、状态与安全摘要引用;步骤间使用带 provenance/type/digest/sensitivity 的 ResultReference。结果只能进入隔离材料区,不能修改 action、target、tool 或 capability。 + +### P1:灰度开关顺序错误 + +现有 MULTI_INTENT_ENABLED 默认 true;初稿到最后一阶段才新增 tier,会让中间合入的行为缺少默认关闭门。 + +**整改:** U1 先建立默认 legacy 的新 tier;U2 只 shadow;auto_read 先维持两个查询的当前上限;确认和每个动作 adapter 分档开放。回滚必须继续支持已有计划读取/取消/收口。 + +## 重要产品修订 + +- 无活动写计划时单意图生成行为保持不变;多意图 generate 的确认/tier/adapter 能力由 intentflow BatchActionPolicy 管理,静态风险仍引用 ActionRegistry; +- 计划卡默认显示一句摘要和主动作,详细风险/步骤折叠展开,降低认知负担; +- 自然语言“确认”只有在当前会话恰有一个活动可见计划时才绑定;多计划或混入新任务时澄清; +- 聚合澄清不承诺一次自由文本必然填满所有槽位;只接受可唯一映射值,槽位依赖/冲突继续追问; +- 部分确认默认是分批批准,未选项保留待确认;只有显式排除才取消,部分完成提供重试/继续/关闭; +- 单意图生成兼容承诺只适用于当前没有活动写计划;有活动计划时统一冲突视图,避免双任务; +- 多意图价值必须用采用率、确认放弃率和拆单回退率证明;价值不足时停止写动作扩面,但保留“不静默丢任务”的安全改进。 +- 批量确认、tier 和 adapter 策略归 intentflow 的 BatchActionPolicy;ActionRegistry 只保留动作身份与静态风险,避免编排政策回灌 L1; +- 计划卡折叠态仍显示目标、最高风险、不可撤销副作用和非原子语义;技术元数据才可折叠; + +## 并发与权限检查表 + +- 同 turn 同 digest 返回原计划;同 turn 异 digest 冲突; +- decision 带 expected revision、nonce 与 digest; +- plan/step CAS 与单调 fencing; +- fencing 和幂等占位必须进入动作属主事务,只锁计划行不足以阻止旧 worker 副作用; +- confirm/cancel/expiry/edit 只有一个胜者; +- 部分确认必须依赖闭包; +- 双标签、双实例、worker 接管最多一次副作用; +- 跨 user/project/session 不可读、不可确认且不泄露存在性; +- 确认后成员/职责/资源状态变化仍会拒绝执行; +- SSE 重复、乱序、缺失由 GET reconcile; +- CSRF/Origin 沿用服务端认证策略,nonce 不冒充 CSRF。 +- active-plan discovery 是刷新必需入口,不能依赖消息投影中恰好保存 plan_id。 + +## 范围与任务修订 + +原 T1–T5 被重拆为核心 U1–U8、可选实验 U9 和属主扩面 U10–U12:契约门禁、纯规则 shadow、持久计划、事件投影、决策/授权、Web、只读执行、task generate 首版、LLM adapter、mutate/docgov/workflow-run 分项扩面。每个单元有独立依赖、文件范围、测试、停走门与真实 mutex。总览不长期占用 `intent`;每个 action 仍需独立 short-term。 + +## 评审覆盖 + +- 本地视角:coherence、feasibility、security、scope、product、design、adversarial; +- 独立 cross-model:Claude Opus 5/high 的 security、product、adversarial 与 whole-document sweep; +- cross-model 审的是初稿,其关于 LLM 输入、plan ACL、结果传递、幂等、产品价值和确认负担的有效意见已纳入修订;其余由当前代码与边界事实校正。 + +## 关联整改 + +- System design: [2026-09-15-multi-intent-hitl-plan.md](../system-design/2026-09-15-multi-intent-hitl-plan.md) +- Short-term: [2026-09-15-multi-intent-hitl.md](../ops/short-term/2026-09-15-multi-intent-hitl.md) + +## 证据 + +- `internal/intent/plan_builder.go`:首连接词、两段、写意图返回 nil; +- `internal/coordinator/action_planner.go`:pending confirm 仅文字提示; +- `internal/intent/registry.go`:task.run/adhoc 为 medium 且当前不全局 RequiresConfirm; +- `internal/intent/flags.go`:MULTI_INTENT_ENABLED 默认 true; +- `.doc/system-design/module-boundaries.yaml`:intent 只依赖 maturity,Track E/table owners 已登记; +- `internal/events/registry.go`:事件须静态注册; +- `internal/app/uow/uow.go`:不透明 TxScope; +- `web/src/App.tsx`:现有 card action 含前端本地业务状态路径。 + +## 开放问题 + +无阻塞性架构问题。各放量阈值必须在 U2 shadow 基线形成后预注册;这属于实施期量化,不授权跳过停走门。 diff --git a/.doc/audit/INDEX.md b/.doc/audit/INDEX.md index d959cf0a..1bd542a5 100644 --- a/.doc/audit/INDEX.md +++ b/.doc/audit/INDEX.md @@ -13,6 +13,15 @@ ## 核心文档(按阅读顺序推荐) +### 多意图与 HITL 方案复核(2026-09-15) + +**文件**: [2026-09-15-multi-intent-hitl-plan-review.md](./2026-09-15-multi-intent-hitl-plan-review.md) + +**结论**: 多意图方向可行,但必须以 `app/intentflow` 深模块、PG 权威状态机、逐动作即时授权和分波 mutex 防止 intent/coordinator 再耦合;确认、卡片和 SSE 均不能替代授权或权威状态。 + +**设计/计划**: [多意图持久计划与 HITL](../system-design/2026-09-15-multi-intent-hitl-plan.md) · [核心 U1–U8 与扩面 U9–U12](../ops/short-term/2026-09-15-multi-intent-hitl.md) + + ### 模块解耦 Phase 2 方案复核(2026-09-15) **文件**: [2026-09-15-module-decoupling-phase2-plan-review.md](./2026-09-15-module-decoupling-phase2-plan-review.md) diff --git a/.doc/ops/CURRENT.md b/.doc/ops/CURRENT.md index 29313de8..88b199ad 100644 --- a/.doc/ops/CURRENT.md +++ b/.doc/ops/CURRENT.md @@ -5,9 +5,9 @@ ## 焦点 -1. **TRACK-P**: HTTP 信封与 PI typed-result 已实施([信封](../test-reports/2026-09-15-http-error-envelope-h1-h3-test-report.md);[typed-result](../test-reports/2026-09-15-pi-typed-result-v1-test-report.md)) -2. **TRACK-E LIVE**: 共享 consumer 已 live;生产 hook 已去注册([projection](../test-reports/2026-09-15-event-projection-shared-live-test-report.md)) -3. **CHAT-INTENT**: [对话意图运行时状态](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md)(双标签 busy 已签:项目 **6275** / `DOC_BUSY` 单 run;不删 `sess-p143-u9` 探针) +1. **MULTI-INTENT HITL**:方案已复核,U1 契约未开工([设计](../system-design/2026-09-15-multi-intent-hitl-plan.md);[short-term](./short-term/2026-09-15-multi-intent-hitl.md)) +2. **发布门禁**:CI `TEST_DATABASE_URL`、真实 PI 三工作流 E2E、前端人工抽检仍开放([gap-matrix](../remediation/gap-matrix.md)) +3. **CHAT-INTENT**:双标签 busy 已签(项目 **6275**);不删 `sess-p143-u9`;项目 143 只读 ## 并行认领 @@ -72,6 +72,7 @@ | Cursor | phase2-closeout-inventories | feature/phase2-closeout-inventories | - | architecture-docs | done | | Cursor | event-shared-live-cutover | feature/event-shared-live-cutover | - | events | done | | Cursor | pi-typed-result | feature/pi-typed-result | - | pi-agent | done | +| Codex | multi-intent-hitl-plan-review | feature/phase2-session-close | - | architecture-docs | done | > 新任务开始前登记。`branch` 必须为 `feature/` 或 `fix/`,**禁止** `dev` / `test` / `main`。同一 `mutex` 同时仅一个 `in_progress`。 @@ -116,6 +117,7 @@ | 模块解耦整改计划 | [../remediation/2026-09-14-module-decoupling-refactor-plan.md](../remediation/2026-09-14-module-decoupling-refactor-plan.md) | | Phase 2 方案审阅 | [../audit/2026-09-15-module-decoupling-phase2-plan-review.md](../audit/2026-09-15-module-decoupling-phase2-plan-review.md) | | Phase 2 修订计划 | [../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md](../remediation/2026-09-15-module-decoupling-ipc-phase2-remediation-plan.md) | +| 多意图 HITL 复核方案 | [../system-design/2026-09-15-multi-intent-hitl-plan.md](../system-design/2026-09-15-multi-intent-hitl-plan.md) | | 文档可靠性 M1 报告 | [../test-reports/2026-09-14-document-reliability-pilot-test-report.md](../test-reports/2026-09-14-document-reliability-pilot-test-report.md) | | 文档可靠性 M1 活验 | [../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md](../test-reports/2026-09-14-document-reliability-pilot-live-test-report.md) | | 文档可靠性 M2 | [../test-reports/2026-09-14-document-reliability-m2-test-report.md](../test-reports/2026-09-14-document-reliability-m2-test-report.md) | diff --git a/.doc/ops/short-term/2026-09-15-multi-intent-hitl.md b/.doc/ops/short-term/2026-09-15-multi-intent-hitl.md new file mode 100644 index 00000000..7c0cd10a --- /dev/null +++ b/.doc/ops/short-term/2026-09-15-multi-intent-hitl.md @@ -0,0 +1,103 @@ +--- +title: "多意图持久计划与 HITL(核心 U1–U8,扩面 U9–U12)" +status: planned +created: 2026-09-15 +updated: 2026-09-15 +owner: "-(待逐单元认领)" +branch: feature/multi-intent-u1-contracts +worktree: "-" +mutex: architecture-docs +--- + +# 多意图持久计划与 HITL(核心 U1–U8,扩面 U9–U12) + +## 目标 + +不回退现有模块解耦、单意图行为和权限边界,交付可持久、可恢复、可并发裁决的 2–4 步计划;所有批量生成/写入/控制确认前零副作用,执行前逐动作重新授权。 + +## 权威文档 + +- [详细设计与计划](../../system-design/2026-09-15-multi-intent-hitl-plan.md) +- [复核审计](../../audit/2026-09-15-multi-intent-hitl-plan-review.md) +- [模块边界 SSOT](../../system-design/module-boundaries.yaml) + +## 强制约束 + +- `internal/intent` 继续只依赖 `maturity`;新生命周期归 `internal/app/intentflow`; +- 确认不是授权;每步由动作 owner 按当前主体、状态和版本重新鉴权; +- PG plan state 权威,卡片/SSE 仅投影; +- 每步一个业务事务,不做跨模块长事务; +- 中间结果不进 FAV; +- 新行为从 legacy/shadow 开始,回滚不丢已有计划。 + +## 波次 + +| 波次 | 单元 | 交付 | 依赖 | 主 mutex | go/no-go | +|------|------|------|------|----------|----------| +| W0 | U1 | 模块/API/状态/事件契约 | 无 | `intent`,`events` | arch/event/table owner 全绿 | +| W1 | U2 | 纯规则提案 shadow | U1 | `intent` | 不改路由,安全错误为 0 | +| W2 | U3 | intentflow + PG/CAS/lease | U1,U2 | `intent-plan` | 两 worker 无双 owner/执行 | +| W2 | U4 | outbox + 投影 | U3 | `events` | projection diff=0 | +| W3 | U5 | decision API + 授权端口 | U3 | `intent-plan`,`server/authz` | 权限负例全绿 | +| W3 | U6 | Web 卡片/刷新/a11y | U4,U5 | `web` | 双标签/reload 无假成功 | +| W4 | U7 | 低风险只读执行 | U4-U6 | `intent-plan`,`chat` | legacy 无回归 | +| W4 | U8 | task generate adapter | U7 | `taskrun`,`intent-plan` | 首版 real PI 闭环 | +| W5 | U9 | 可选 LLM adapter 实验 | U2,U7 | `intent-plan`,`pi-agent` | 不阻塞首版;达阈值才启用 | +| W5+ | U10 | low mutate 逐 action 扩面 | U8 | 实际 owner | 单 action 签署 | +| W5+ | U11 | docgov 逐 action 扩面 | U8 | `docgov`,`intent-plan` | 单 action 签署 | +| W5+ | U12 | workflow/run-control 分项扩面 | U8 | `workflow`/`taskrun` | 分项签署 | + +> 本文件仅是总览,不长期占用一个 mutex。实施时每个 U-ID 新建独立 short-term、分支和认领;U10–U12 还必须按 action 拆分。核心首版为 U1–U8,U9 与后续 owner 扩面不阻塞首版关闭。 + +## 步骤 + +1. [ ] U1 冻结边界、状态机、批量策略、错误码、事件和默认 legacy tier; +2. [ ] U2 characterization-first 建 golden/hard-negative 与 shadow 基线; +3. [ ] U3 建 intentflow owner、PG schema、CAS/lease/fencing/retention; +4. [ ] U4 接 Track E outbox/dispatcher,只投影状态事实; +5. [ ] U5 建统一 decision command 与动作 owner 授权端口; +6. [ ] U6 取消计划动作的前端本地成功路径,以 PlanView 恢复; +7. [ ] U7 只开放独立低风险查询; +8. [ ] U8 只接 task generate,完成首版 real PI 闭环; +9. [ ] U9 作为独立可选实验接语义分段; +10. [ ] U10–U12 分别按 mutate/docgov/workflow/run-control owner 扩面。 + +## 验收标准 + +- [ ] 含写/生成/控制时,确认前相关表、任务、文档和工作流零变化; +- [ ] 两标签确认/取消只产生一个决策和至多一次动作; +- [ ] 服务/worker 重启后 PG 恢复,成功步骤不重跑; +- [ ] 确认后权限或资源版本变化时 fail closed; +- [ ] 跨用户/项目/会话读取和决策被隐藏; +- [ ] 按钮与自然语言确认得到同一服务端 receipt; +- [ ] intent 边界、单一写者、UoW、事件静态契约和组合根无回退; +- [ ] 无活动计划时单意图生成保持;有活动计划时不创建第二任务;多意图生成需确认; +- [ ] 部分确认可稍后处理未选项,只有显式排除才取消;部分完成可重试、继续或关闭; +- [ ] 双标签/刷新/重开/SSE 重连真实页面通过; +- [ ] 适用的真实 PI E2E 通过,stub 不冒充验收。 + +## 非目标 + +- >4 步、并行 DAG、多活动写计划自动合并; +- 跨步骤 ACID/自动补偿; +- coordinator/chat 全量重构; +- FAV 启用或中间产物归档; +- 改变单意图生成策略。 + +## 交付纪律 + +- 每单元记录精确边界影响、适用测试、go/no-go、回滚、branch/commit/merge/push 状态; +- 每单元独立 test report、CURRENT 认领/集成槽和 FEATURE-MATRIX 回链; +- 安全、越权、双执行或刷新差异任一出现,停止当前 tier;dispatcher 故障只停投影;LLM 故障进入澄清。 + +## 相关链接 + +- Checklist: U1 实施时建立逐波 checklist +- Handoff: 每个 U-ID 独立建立 +- Test report: 每个 U-ID 独立归档 `.doc/test-reports/` + +## 证据 / 备注 + +- 当前 `plan_builder.go` 最多两段且写意图返回 nil;`action_planner.go` 的确认仍是文字提示。 +- 当前 `module-boundaries.yaml` 中 intent 仅依赖 maturity;Track E live,FAV off。 +- 本次只修订方案与任务文档,不实施、不提交、不推送。 diff --git a/.doc/status/FEATURE-MATRIX.md b/.doc/status/FEATURE-MATRIX.md index b4a4ac39..2c0b6493 100644 --- a/.doc/status/FEATURE-MATRIX.md +++ b/.doc/status/FEATURE-MATRIX.md @@ -15,7 +15,7 @@ | 模块 | 能力 | 状态 | 证据 | 缺口/后续 | mutex | |------|------|------|------|-----------|-------| -| 意图识别 L1 | 18 类 Intent + 三分支消解 | partial | [system-design/intent-recognition](../system-design/intent-recognition/);[现场专项审计](../audit/2026-09-13-conversation-intent-runtime-state.md);[运行态报告](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md);[双标签活验](../test-reports/assets/2026-09-15-conversation-intent-dual-tab/live.json) | 明确写动作与只读总结已分流;双标签 `DOC_BUSY` 已签(项目 6275)。完整 hard-negative/eval 集仍待补齐 | `intent` | +| 意图识别 L1 | 18 类 Intent + 三分支消解 | partial | [system-design/intent-recognition](../system-design/intent-recognition/);[现场专项审计](../audit/2026-09-13-conversation-intent-runtime-state.md);[运行态报告](../test-reports/2026-09-13-conversation-intent-runtime-state-test-report.md);[双标签活验](../test-reports/assets/2026-09-15-conversation-intent-dual-tab/live.json);[多意图复核方案](../system-design/2026-09-15-multi-intent-hitl-plan.md) | 明确写动作与只读总结已分流;双标签 `DOC_BUSY` 已签(项目 6275)。多意图持久计划仅完成方案复核,核心 U1–U8 与扩面 U9–U12 均未实施;intent 纯依赖边界不得回退 | `intent` | | 对话 / ctxmgr | 多轮上下文、记忆、摘要 | partial | [system-design/multi-turn-dialogue](../system-design/multi-turn-dialogue/);[刷新恢复专项审计](../audit/2026-09-13-chat-history-refresh-disappears.md);[U10 端口化](../archive/ops/2026-09-15-chatlog-contextasm-u10.md);[U10 报告](../test-reports/2026-09-15-chatlog-contextasm-u10-test-report.md) | `CHAT-HISTORY-REFRESH` 闲聊刷新活验已补。U10 原地端口 **停止扩面**(未物理拆包)。语义摘要(D5 backlog) | `chat` | | 智能体小队 | 角色-任务-工作区-黑板 | done | [system-design/agent-squad](../system-design/agent-squad/);[test 2026-09-07](../test-reports/2026-09-07-dynamic-squad-planning-test-report.md) | 非关键步骤降级(A5/A6 backlog) | `squad` | | 工作流治理 | 三正式工作流 + 阶段门禁 | partial | [remediation/three-workflows](../remediation/2026-09-12-three-workflows-strict-governance-remediation.md);[test 2026-09-12](../test-reports/2026-09-12-three-workflows-governance-remediation-test-report.md);[冻结态/职责可选整改](../remediation/2026-09-14-workflow-plan-409-frozen-and-optional-duties-remediation.md);[Wave 5 页面矩阵](../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md);[职责-动作鉴权](../test-reports/2026-09-14-governance-action-level-authz-test-report.md) | 设置页/DutyMode + 动作级鉴权/未激活 202-blocked/关闭创建直通已落地。后续:none 文档真实 PI 审批长链路、CI 三工作流 E2E | `workflow` | diff --git a/.doc/system-design/2026-09-15-multi-intent-hitl-plan.md b/.doc/system-design/2026-09-15-multi-intent-hitl-plan.md new file mode 100644 index 00000000..f858bb53 --- /dev/null +++ b/.doc/system-design/2026-09-15-multi-intent-hitl-plan.md @@ -0,0 +1,475 @@ +# 多意图多任务识别、持久计划与 HITL 统一确认方案 + +> 状态: planned(方案已复核,未实施) +> 日期: 2026-09-15 +> 作者: Cline(初稿)/ Codex(架构、安全与实施计划复核) +> 关联: [方案审计](../audit/2026-09-15-multi-intent-hitl-plan-review.md);[意图识别深读](./intent-recognition/01-意图识别框架-设计-架构-实现-难点-解决方案-亮点与优势.md);[模块化单体架构](./2026-09-14-module-decoupling-architecture.md);[任务总览](../ops/short-term/2026-09-15-multi-intent-hitl.md) + +--- + +## 一、结论与目标 + +方向可行,但原稿不能直接实施。需要先闭合计划生命周期、确认回路、授权、并发和模块归属。修订目标是: + +1. 一次输入可安全识别 2–4 个候选子任务,并让用户核对系统理解; +2. 只有确定的低风险只读组合可自动执行;批量生成、写入、控制、缺槽、冲突或不确定组合必须进入服务端持久化 HITL; +3. 刷新、双标签页、服务/worker 重启和 SSE 晚到时,计划与卡片从 PostgreSQL 权威状态恢复; +4. 确认只表达用户意愿,不授予权限。每一步执行前按当前主体、成员关系、资源状态和版本重新授权; +5. 不回退已完成的解耦:`internal/intent` 保持纯规则领域模块;跨属主写入继续使用端口、单一写者、`app/uow` 和静态事件契约。 + +第一版按显式依赖顺序执行,每步独立提交,不承诺跨步骤原子回滚或并行 DAG 调度。 + +这项能力的直接价值不是替代逐条对话,而是消除当前“用户已经明确给出多个任务,系统却只执行 TopIntent 且不告知”的不可信行为,并让有依赖的“先查再生成”在一次可审计确认中完成。逐条提交仍是低复杂度场景的有效入口;如果 shadow 期显示多意图采用率低、确认放弃率高或用户普遍主动拆单,U7 之后的写动作扩面应停止,而不是为了完成路线图继续建设。 + +--- + +## 二、当前事实与缺口 + +| 能力 | 当前事实 | 证据 | +|------|----------|------| +| 单意图识别 | 18+ Intent、四级漏斗、三分支已实现;FEATURE-MATRIX 仍为 `partial`,不能称“已成熟” | `internal/intent/recognizer.go`、`.doc/status/FEATURE-MATRIX.md` | +| V2 帧/动作表 | `IntentFrameV2`、ActionRegistry、风险、必填槽位、灰度开关已存在 | `internal/intent/types_v2.go`、`registry.go`、`flags.go` | +| 有限多意图 | 默认开启;只按首个连接词拆两段;写意图返回 `nil` | `internal/intent/plan_builder.go` | +| 有限执行 | 只读步骤顺序执行;需确认步骤只有文字提示 | `internal/coordinator/action_planner.go` | +| HITL 基础 | PendingExpectation、四类卡片和 ExpiresAt 已存在;前端仍有本地业务状态修改路径 | `internal/intent/types.go`、`web/src/App.tsx` | +| 可靠事件 | PG dispatcher、delivery、静态契约已 live;FAV 关闭 | `internal/events`、`.doc/ops/CURRENT.md` | +| 模块边界 | `intent` 只允许依赖 `maturity`;chatflow/stageflow/doccontent 等解耦已完成 | `.doc/system-design/module-boundaries.yaml` | + +关键缺口:分段不确定时可能退回 TopIntent 并静默丢任务;计划没有 revision、决策凭据、执行账本或可恢复状态机;确认没有统一服务端命令;ActionRegistry 风险容易被误当授权;未处理重复提交、双标签决策、过期竞态和 worker 抢占;卡片/SSE 不是权威状态;原稿把 agent backend 引入 L1 会破坏 intent 边界;T1–T5 全用 `intent` mutex 与实际跨模块范围不符;自由文本结果传递存在提示注入和数据泄露风险;固定样例数不能代替质量门槛。 + +--- + +## 三、硬约束与非目标 + +### 3.1 不可回退的解耦约束 + +| 约束 | 强制规则 | 验证 | +|------|----------|------| +| L1 纯度 | `internal/intent` 只做确定性分段、识别、帧和计划提案;不得访问网络、PG、文件或 agent backend | arch-check 保持 `intent -> maturity` | +| 应用编排 | 新增 `internal/app/intentflow` 作为计划生命周期唯一编排入口 | chat/server 只依赖深接口,不获得 store/engine | +| 单一写者 | `intent_plans*` 仅由 intentflow repository owner 写;业务动作仍写自己的表 | table owner + SQL write archtest | +| 跨属主一致性 | 计划、决策、投影请求和 outbox 需要一致时使用不透明 `app/uow.TxScope` | 不暴露 pool/pgx.Tx | +| 事件契约 | 新事件先登记 YAML 与 `events.StaticContracts`,再接 dispatcher | registry parity + 未注册 fail closed | +| 授权归属 | intentflow 不复制 docgov/taskrun/workflow 权限,调用动作属主用例端口 | 每个 adapter 有即时授权负例 | +| 组合根 | store、adapter、clock、ID generator、event sink 仅在 `internal/app/app.go` 装配 | server 不重新接线 | + +### 3.2 非目标 + +- 不拆微服务或新增 RPC;不支持 >4 步、并行 DAG、多个活动写计划自动合并; +- 不承诺跨步骤 ACID 或自动补偿; +- 当前作用域没有活动写/生成计划时,不改变单意图生成任务行为;已有活动计划时统一进入冲突/替换流程,禁止启动第二个写计划; +- 不让 LLM 决定风险、权限、槽位真值或执行顺序; +- 不启用 FAV,也不把中间结果归档到 FAV; +- 不借机全量重构 coordinator/chat action executor。 + +--- + +## 四、总体架构与权威性 + +```mermaid +flowchart LR + UI[Web 计划卡] --> API[server HTTP/SSE] + API --> FLOW[app/intentflow\n计划生命周期] + CHAT[chat/chatflow] --> FLOW + FLOW --> L1[intent\n纯规则提案] + FLOW --> STORE[(plan owner store)] + FLOW --> UOW[app/uow] + FLOW --> PORTS[动作属主端口] + FLOW --> EVENTS[events outbox] + EVENTS --> PROJ[projection/notify] + FLOW -.只建议分段.-> SEM[语义 adapter\nagent backend] +``` + +`app/intentflow` 对外只提供:处理一轮输入、提交计划决策、读取授权后的 PlanView、恢复/推进已有计划。不得向调用者暴露 PlanStore、事务、`docgov.Engine`、`taskrun.Manager` 或 pool。 + +权威性从高到低:当前认证主体与资源状态 → 动作属主的授权/业务不变量 → PG 计划/步骤/决策 → 消息卡片投影 → SSE/前端内存。下层不得覆盖上层。 + +### 4.1 端到端流 + +```mermaid +sequenceDiagram + participant U as 用户 + participant W as Web/server + participant F as app/intentflow + participant I as intent + participant D as PG plan store + participant A as 动作属主 + U->>W: input + client_turn_id + W->>F: HandleTurn(principal, context, input) + F->>I: 安全扫描、分段、逐段识别 + I-->>F: PlanProposal + evidence + digest + alt 独立低风险只读 + F->>A: 每步即时授权并执行 + F-->>W: 聚合结果 + else 需澄清/确认 + F->>D: 同事务写 plan/steps/outbox + F-->>W: 权威卡片 + U->>W: decision + nonce + expected_revision + W->>F: DecidePlan + F->>D: CAS 状态 + F->>A: 每步重新授权、执行 + F->>D: CAS step + receipt/ref + F-->>W: PlanView + end +``` + +--- + +## 五、领域模型与状态机 + +- `intent.PlanProposal`:L1 值对象,含规范化分段、候选帧、证据、缺槽和依赖建议;不含授权结论或 DB 状态; +- `intentflow.Plan`:应用实体,含主体/会话/项目作用域、请求摘要、revision、过期、决策与执行账本; +- `PlanView`:脱敏 UI 投影,不回传内部 payload、权限快照或完整中间结果; +- UserProjectContext/消息只保留 `plan_id + revision` 引用,不持久化第二份 PendingPlan。 + +### 5.1 计划状态 + +```mermaid +stateDiagram-v2 + [*] --> proposed + proposed --> awaiting_clarification + proposed --> awaiting_confirmation + proposed --> executing: 仅低风险只读 + awaiting_clarification --> awaiting_confirmation + awaiting_clarification --> executing + awaiting_clarification --> awaiting_clarification: 增量补槽形成新 revision + awaiting_clarification --> superseded + awaiting_confirmation --> executing + awaiting_confirmation --> cancelled + awaiting_confirmation --> expired + awaiting_confirmation --> superseded + executing --> partially_completed + executing --> completed + executing --> failed + executing --> cancelled: 仅未开始步骤 + partially_completed --> completed + partially_completed --> failed + partially_completed --> executing: 用户选择重试/继续 + partially_completed --> cancelled: 取消全部未开始步骤 +``` + +编辑产生新 revision/digest,旧卡片 `outdated`;取消不能回滚已完成业务副作用;`skip` 只允许独立低风险只读步骤;依赖失败阻塞所有后代;`confirm_retry` 暂停计划并对指定失败步骤重新确认。 + +### 5.2 步骤、部分确认与幂等 + +步骤状态:`pending -> eligible -> running -> succeeded | failed | denied | conflicted | blocked_dependency | skipped | cancelled`。 + +- `eligible -> running` 用条件更新和 fencing token; +- 动作幂等键:`plan_id:plan_revision:step_id:action_digest`;同键同摘要返回既有 receipt,同键异摘要冲突; +- 动作属主端口必须接收 idempotency key、action digest、expected resource version 和 fencing token,并能按同一身份查询 receipt。只有属主事务能原子提交幂等占位与业务副作用,或已证明原生机制等价时,该 action 才能放量;旧 fence 必须被属主拒绝; +- 部分确认必须是依赖闭包;选中步骤进入 eligible,未选独立步骤继续等待确认。只有用户显式“排除未选项”才写 `cancelled_by_user`,其后代取消或阻塞; +- 高风险步骤逐项可见;确认父步骤不自动确认新出现的高风险后代; +- “确认第 1 项并修改第 2 项”拆成决策和新 revision,不混为一个转移。 + +--- + +## 六、分段、识别与组合策略 + +### 6.1 确定性分段 + +`internal/intent` 内扩展纯规则分段器,支持连接词、句号、分号、换行、序号和“先/再/最后”,上限 4 段。输出包含规范化文本、原文 span、连接证据、结构置信类别和未解析指代。 + +1. 整句先做 Stage 0 安全扫描;分段规范化、槽位补丁、LLM 建议后再次逐段扫描;原文命中优先,整体拒绝; +2. “查询并总结”“阅读后概括”等单动作内部链不拆; +3. 只有确定为完整单意图时才合并回单意图;低置信、指代补全失败或无法证明完整时进入澄清,禁止退回 TopIntent 执行; +4. 逐段识别后检查同资源冲突、重复动作和依赖; +5. 超过 4 段不创建残缺计划,明确要求分批。 + +### 6.2 可选语义分段 + +LLM adapter 位于 intentflow 外围,不放进 `internal/intent`。它只能提出 `text span + connector + reason`,不能输出权限、风险、ActionKey、执行顺序或权威槽位。 + +- 只发送当前文本和必要的脱敏实体标签;不发送 secrets、完整历史、文档正文或权限表; +- 严格版本化 schema;超时、格式错、span 重叠、越界或安全冲突均 fail closed; +- 每段重新进入确定性 recognizer、ActionRegistry 和安全扫描;护栏优先,无法裁定就澄清; +- 以 `request_digest + segmenter_version + model_contract_version` 固化已展示分段;重试不得因模型漂移改变计划; +- shadow 日志只保留 digest、类别、差异和计数。 + +### 6.3 组合风险矩阵 + +ActionRegistry 提供动作身份、目标类别和静态风险提示,但不是授权或批量编排 SSOT。`app/intentflow` 拥有版本化 `BatchActionPolicy`,只记录 action key 的批量确认要求、可开放 tier、adapter 能力和 execution mode,并在启动时校验 key 存在于 ActionRegistry。它不得复制 Risk、RequiredSlots、CapabilityKey 或 AllowedStates。`task.run`/`task.run.adhoc` 的批量策略要求确认,同时保持其单意图 `RequiresConfirm` 不变。 + +| 条件 | 模式 | 行为 | +|------|------|------| +| 全部独立 RiskLow 查询、槽位齐、无冲突 | `auto_read` | 即时授权后执行 | +| 任一批量生成、mutate/control、中高风险或 BatchActionPolicy 要求确认 | `awaiting_confirmation` | 先持久化并出卡,确认前零副作用 | +| 缺槽、指代/分段/依赖不明 | `awaiting_clarification` | 聚合澄清;有槽位依赖时分组问 | +| 原文或变换结果命中红线 | `rejected` | 整体拒绝,不执行其他段 | +| >4 段 | `rejected_batch_size` | 要求分批 | + +V2 灰度不可绕过:只有 ActionRegistry 映射稳定、V2 shadow 达门槛且当前 multi-intent tier 允许的动作可进入 decision;其余走 legacy 或显式澄清。 + +--- + +## 七、HITL、授权与并发协议 + +### 7.1 服务端权威卡片 + +`PLAN_CONFIRM` 折叠态也必须显示任务数、受影响目标、生成/写入/控制类型、最高风险、不可撤销副作用和“逐步提交、后续失败不回滚”提示;高风险步骤始终逐项可见。只有 action key、revision、digest 等技术元数据和低风险细节可折叠。支持全部确认、依赖闭包内部分确认、编辑、取消。 + +`CLARIFY_AGGREGATE` 展示逐步缺槽、约束、已知值和冲突。回复形成 slot patch 后必须重新识别、重新计算 digest、风险和授权预检。 + +用户只回答部分问题时保存可唯一映射的增量 patch,产生新 revision 并继续停留在 awaiting_clarification;新卡同时显示已解决值和剩余问题,旧卡 stale。不会要求重填已经验证的值,也不会在缺槽未闭合时提前执行。 + +澄清字段按步骤和依赖分组,标记“已验证/待填写/冲突/无效”,显示剩余数量;提交文案为“保存已填写并继续”,提交后保留合法值并聚焦首个未解决字段。 + +卡片 metadata 是 PG 状态投影。按钮和自然语言“确认/取消/只做第 1 项”统一进入服务端 `DecidePlan`;前端不得本地修改业务资源或先标成功。 + +部分确认 UI 使用依赖层级列表:选择子步骤时立即勾选并解释必需前置;存在已选后代时不能取消前置;提交按钮显示本次确认的步骤数和目标。未选项标为“继续等待”,显式排除是独立次级动作,并在提交前列出会被取消或阻塞的后代。 + +自然语言决策采用确定性语法优先:明确 plan/步骤编号或当前会话只有一个活动可见计划时才可绑定;“确认”在多个活动计划、步骤引用不合法或同时包含新任务时不执行,改为定向澄清。聚合槽位优先使用结构化卡片字段;自由文本只把可唯一映射的 `label:value`/已有 PatchSlots 结果写入 patch,冲突值、依赖值无效或多义值保持未解析并再次提问,绝不猜测。 + +### 7.2 确认不等于授权 + +执行每一步前,动作属主重新校验当前认证用户与 plan session/project/user、当前成员/duty/capability、资源归属/lifecycle/stage、expected version/ETag、动作允许状态。计划中的角色/权限快照只用于审计。失败进入 `denied/conflicted`,不得换系统身份代执行。 + +### 7.3 并发规则 + +- 创建:`(session_id, client_turn_id, request_digest)` 唯一;同 turn 异 digest 冲突; +- 决策:必须带 `expected_revision`、`decision_nonce`、`decision_digest`;同 nonce 同摘要返回 receipt,异摘要冲突; +- 标识:plan_id、step_id、decision_nonce 使用不可预测的随机标识;安全性不依赖其保密,所有访问仍做四元作用域授权; +- 状态:当前 revision 且未过期的等待态才能 CAS;陈旧卡片返回 409 和当前安全视图; +- 过期:服务端 `expires_at` 权威,TTLTurns 只显示; +- 执行:短 lease + owner + lease_until + 单调 fencing;续租失败不再领步骤; +- 竞态:确认/取消/过期、编辑/确认只允许一个 CAS 胜出; +- SSE:允许重复/乱序/丢失,前端按 revision/step version 去重,发现缺口 GET 对账。 + +同一 user/session/project 同时只允许一个活动写/生成计划。新的低风险查询可独立处理;新的写计划必须让用户完成、取消或显式替换旧计划,不自动合并。计划锁不替代业务资源自己的 lease/version lock。 + +因此“单意图生成保持现状”仅适用于没有活动写/生成计划的作用域。有活动计划时,无论新输入是单意图还是多意图,都返回同一服务端冲突视图,禁止创建第二个 task/run;真实页面验收分别覆盖无活动计划兼容和有活动计划冲突。 + +`partially_completed` 必须提供前向收口卡:重试指定失败步骤、继续仍 eligible 的独立步骤、取消所有未开始步骤并关闭计划。已成功 receipt 永不回滚;running 步骤先由 lease/fencing 收口,卡片列明已发生且不可撤销的副作用。 + +--- + +## 八、持久化、事务、事件与数据治理 + +### 8.1 表与所有权 + +`intent_plans`:plan_id、environment/project/session/user/client_turn、request_digest、segmenter/policy version、status、revision、expires_at、timestamps、last_fencing_token。原始输入沿用 chat message 保留;计划表保存引用、digest 和脱敏展示快照。 + +`intent_plan_steps`:plan/step、action_key、规范化 slots、依赖、status、expected_resource_version、action_digest、idempotency_key、attempt、result_ref/digest、safe_summary、timestamps、version。 + +`intent_plan_decisions`:append-only decision id/nonce、plan revision、actor、kind、step selection、patch/request digest、outcome、created_at。关键 CAS、审计和查询字段必须类型化;JSONB 只用于版本化 slots/display snapshot。三表 owner 登记为 `app/intentflow`,其他包只能走端口。 + +### 8.2 事务与恢复 + +- 创建:plan + steps + card projection request + outbox 同一 UoW; +- 决策:decision append + plan CAS + eligible steps 同一 UoW; +- 业务副作用由动作属主事务提交,再以 idempotent receipt 更新步骤,不制造跨模块长事务; +- 业务成功但 receipt 写回失败时,通过动作幂等键查既有结果并对账,不盲跑; +- 消息投影失败不回滚权威计划,dispatcher 重试,刷新 GET 修复。 + +### 8.3 事件与作用域 + +只发布事实,不发布执行命令。候选事件 `intent.plan.awaiting_input`、`intent.plan.step_changed`、`intent.plan.completed` 必须同时登记 YAML、StaticContracts、schema/golden 和 parity test。 + +payload 仅含 plan/revision/step/status、environment/project/user/session scope 和安全摘要引用;不含原 prompt、完整 slots、权限快照或完整结果。消费者和 SSE 投递前按当前主体重新读取授权后的 PlanView;同项目不同用户不能互见。 + +### 8.4 留存与结果传递 + +- plan/decision 随会话和项目数据政策清理,不早于关联 chat/taskrun 审计窗口;删除由 owner 执行; +- 中间结果仅保存 `ResultReference`:producer、result/artifact ID、digest、类型、敏感级别、允许用途和长度受限 safe summary; +- 不把前序自由文本直接拼入权威槽位或后续指令区。后续生成只能把带来源的数据放入隔离材料区,不能扩大 action/target/tool/capability; +- 若结果导致动作、目标或范围变化,产生新 revision 并重新确认; +- 最终生成物仍归 taskrun/受控文档/FAV(启用后),计划库不充当成果仓。 + +--- + +## 九、API、刷新与前端 + +资源接口必须包括 `GET /api/v1/intent-plans/active`(按当前 principal/environment/project/session/user 发现活动计划)、`GET /api/v1/intent-plans/{plan_id}` 与 `POST /api/v1/intent-plans/{plan_id}/decisions`。页面 bootstrap、刷新和 SSE 缺口恢复先查询 active,再拉 PlanView;消息投影失败时仍能找回计划。 + +decision API 继承当前服务端认证方式、Origin/CSRF 策略和统一限流;nonce/幂等键只防重放与并发,不替代 CSRF 或身份认证。若当前认证方式不具备适用的 CSRF 防护,U1 必须把它列为 U5 的前置 blocker,而不是在计划端点单独发明一套弱机制。 + +统一错误码至少包括:`PLAN_NOT_FOUND_OR_HIDDEN`、`PLAN_STALE_REVISION`、`PLAN_EXPIRED`、`PLAN_DECISION_CONFLICT`、`PLAN_DEPENDENCY_INVALID`、`PLAN_ACTION_FORBIDDEN`、`PLAN_ACTION_VERSION_CONFLICT`。无权主体沿用资源隐藏策略,避免枚举 plan_id。 + +刷新时由 plan 表生成卡片/进度,不从旧按钮或 SSE 推断。页面刷新、重开、SSE 重连均以 GET 覆盖本地缓存。卡片需支持键盘/读屏、依赖说明、错误焦点、过期/陈旧状态;按钮提交后可显示 submitting,但只有服务端 receipt 能变为 executing/resolved。完整结果从 owning API 读取,SSE 只携安全摘要和版本。 + +状态恢复矩阵:submitting 锁定重复提交并保留选择;outdated/conflict 自动读取最新 PlanView、聚焦状态通知并提供“查看最新版”;expired 禁用原决策,保留只读摘要并提供“按当前上下文重建计划”;服务端字段错误保留未提交输入并聚焦对应字段。会话顶部提供可关闭但可重新发现的活动计划入口,无活动计划返回明确空态。 + +可访问性契约:步骤用有序列表和带 legend 的选择组;折叠控件暴露 `aria-expanded/aria-controls`;进度用 polite live region,阻断错误用 alert 并聚焦;状态不只靠颜色;键盘顺序为摘要、步骤、主/次动作;窄屏单列、无横向滚动、触控目标至少 44px,并支持 reduced-motion。 + +--- + +## 十、灰度、指标与回滚 + +保留 `MULTI_INTENT_ENABLED` 作为 legacy 开关;在任何行为变更前新增 `MULTI_INTENT_PLAN_TIER=legacy|shadow|auto_read|confirm|full`,默认 `legacy`。 + +- legacy:保持现有路径,但一旦可靠检测到未处理写/生成段,不得静默只执行 TopIntent,应澄清; +- shadow:只生成提案/指标,不建计划、不改路由; +- auto_read:先保持现状上限,仅开放 2 个低风险只读步骤;3–4 个只读步骤先进入确认/观察,达到单独门槛后再扩大; +- confirm:开放持久卡片;真实 adapter 未启用时只能产生 `validated_only` 预检。Plan、step、receipt 和 PlanView 显式携带 execution mode;`validated_only` 不能写 `succeeded/completed`,UI 必须显示“仅验证,未执行”; +- full:按 action key 逐项开放已验收 adapter。 + +LLM 分段独立开关且从 shadow 起步。关闭新计划创建后,已有计划仍能读取、取消和收口;不能回滚到无法处理已持久计划的版本。 + +| 指标 | 停走条件 | +|------|----------| +| 未确认/越权副作用 | 0 | +| 安全红线绕过 | 0 | +| hard-negative 反事实错误自动执行 | 0;shadow 必须计算“若处于 auto_read/confirm 会如何路由”,不能用实际未执行冒充零错误 | +| 重复确认导致重复动作 | 0 | +| refresh/restart 权威状态差异 | 0 | +| split precision/recall、澄清率、放弃率 | U2 先固定数据集与基线,再预注册阈值;未达不切档 | +| 用户采用与确认负担 | 记录多意图采用率、确认放弃率、拆单回退率;若价值不足,停止 U8/U9 而保留“识别后不静默丢弃”的安全改进 | +| projection backlog/dead letter | 不突破 Track E 既有预算 | + +观察窗口由样本量和流量决定,不能用固定“一周”代替证据。 + +--- + +## 十一、实施计划(核心 U1–U8、按属主扩面 U10–U12、可选实验 U9) + +### U1. 契约冻结与架构门禁 + +**目标:** 冻结 intentflow 边界、状态机、数据字典、错误码、事件和兼容策略。 +**依赖:** 无。 +**文件:** `.doc/system-design/module-boundaries.yaml`、`internal/events/registry.go`、API/schema 文档、arch/event tests。 +**做法:** 注册 app/intentflow allowlist 与 table owner;保持 intent->maturity;冻结 BatchActionPolicy,但不向 intent 回灌 HITL/tier/adapter 字段;先落默认 legacy tier;禁止 server/chat 直写计划表。 +**测试:** 新 import/SQL/event 违规 block;YAML/registry parity;未知 action/policy key fail closed;ActionRegistry 不出现批量执行策略;单意图生成策略不变。 +**停走门:** 架构测试全绿,授权/状态契约无待实现者猜测。 +**mutex:** 纯契约文档用 `architecture-docs`;事件注册变更串行占 `events`。U1 不修改 intent 业务类型,intent 代码变更从 U2 开始。 + +### U2. 确定性分段、PlanProposal 与 shadow 基线 + +**目标:** 不改变生产路由地生成 2–4 步提案和差异指标。 +**依赖:** U1。 +**文件:** `internal/intent/segmenter.go`、`plan_builder.go`、`types_v2.go`、`registry.go`、`internal/intent/testdata/*` 及 tests。 +**做法:** characterization-first;规则分段、span、指代/连动护栏、安全复扫、显式依赖、稳定 digest。 +**测试:** 连接词/句号/序号;查询并总结不拆;指代失败澄清;红线整体拒绝;5 段拒绝;同输入 digest 稳定;写段不静默丢弃。 +**停走门:** shadow 不改响应;对 golden、hard-negative 和真实抽样人工标签做 counterfactual evaluation,报告分母、误拆/漏段/错误自动执行率及置信区间;预注册阈值未达不得切档。 +**mutex:** `intent`。 + +### U3. intentflow、PG 状态机与 repository + +**目标:** 建立持久计划/步骤/决策与并发协议,不接真实写动作。 +**依赖:** U1、U2。 +**文件:** `internal/app/intentflow/*`、`deploy/postgres/goose/*intent_plan*`、`internal/app/app.go`、PG tests。 +**做法:** owner repository、UoW、CAS revision、decision nonce、绝对过期、lease/fencing、创建幂等、retention、组合根装配。 +**测试:** 双创建;nonce 同/异 digest;确认/取消/过期竞态;两 worker 抢占;租约接管;旧 fencing token 在动作属主处被拒绝;重启恢复;业务成功但 receipt 写回失败;环境隔离。 +**停走门:** 无双 owner/双执行,arch-check 无新例外。 +**mutex:** 新增 `intent-plan`,迁移窗口协调 `db/app`。 + +### U4. 事件、卡片与步骤投影 + +**目标:** 权威计划可靠投影;消息/SSE 丢失不影响恢复。 +**依赖:** U3。 +**文件:** 新增 intent-plan event registry/schema、intentflow projection subscriber、ctxmgr owner port、对应 parity/dispatcher integration tests。 +**做法:** 同 UoW outbox、事实事件、消费者幂等与最小 payload;复用 Track E 已有重试/dead letter/replay。禁止修改通用 claim、lease、delivery、retry 或 replay 语义;若确需修改,另立缺陷任务。 +**测试:** 重复/乱序;projection 暂停 replay;消息失败后 GET 修复;worker restart;伪造 producer/字段拒绝;同项目跨用户不可见。 +**停走门:** shadow projection 与 DB diff=0,delivery 可查。 +**mutex:** `events`;ctxmgr 写入只走 owner 端口。 + +### U5. 决策 API 与即时授权端口 + +**目标:** 按钮/自然语言走同一服务端命令,执行前重新授权。 +**依赖:** U3。 +**文件:** `internal/server/*intent_plan*`、`internal/app/intentflow/*`、授权端口契约、fake/dry-run adapter、auth integration tests。 +**做法:** active discovery/GET/decision、错误信封、四元作用域、expected revision、依赖闭包、资源版本;不在本单元接真实业务属主 adapter。 +**测试:** 投影缺失仍能发现活动计划;非成员/跨项目/跨 session;角色撤销;资源变更;stale revision;重复点击;非法部分确认;edit 使旧卡失效;按钮/自然语言同 receipt。 +**停走门:** 权限负例全绿;确认前零副作用;无系统身份绕过。 +**mutex:** `intent-plan` + `server/authz`;动作接入另占 owner mutex。 + +### U6. Web 卡片、刷新与可访问性 + +**目标:** UI 只呈现 PlanView,刷新和多标签一致。 +**依赖:** U4、U5。 +**文件:** `web/src/types/workbench.ts`、`web/src/components/chat/InteractiveCard.tsx`、API client、`web/src/App.tsx`、web/browser tests。 +**做法:** 两卡、步骤进度、依赖选择、submitting/outdated/expired/conflict、GET reconcile;计划动作不进入本地 AST/资源修改路径。 +**测试:** reload/reopen 与无投影 active discovery;双标签确认/取消;409 查看最新版;过期重建;字段输入保留;键盘/读屏/live-region;窄屏 44px/reduced-motion;SSE 重复乱序;慢请求;validated_only 明示未执行。 +**停走门:** 真实浏览器双标签/reload 无本地假成功。 +**mutex:** `web`。 + +### U7. 低风险只读执行与聚合 + +**目标:** 独立低风险查询从 proposal 安全推进到完成。 +**依赖:** U4、U5;可与 U6 并行,开放 auto_read tier 前两者都必须通过。 +**文件:** `internal/app/intentflow/*`、query adapters、coordinator/chatflow 兼容入口、integration tests。 +**做法:** 每步即时授权、显式依赖、ResultReference、失败/阻塞汇报;旧 executeIntentPlan 仅兼容,不扩成跨模块 switch。 +**测试:** 2–4 查询;独立失败继续;依赖失败阻塞;敏感字段脱敏;同 turn 重放;重启续跑。 +**停走门:** legacy 单意图无回归,重复执行为 0。 +**mutex:** `intent-plan`;触及入口时协调 `chat`。 + +### U8. 生成任务 adapter + +**目标:** 经确认后只开放 `task.run` 与 `task.run.adhoc`,形成第一版生成闭环。 +**依赖:** U7。 +**文件:** intentflow taskrun adapter、taskrun owner port/tests、real PI/browser tests。 +**做法:** shadow/dry-run 后开启;传稳定幂等键,保存 result reference/receipt;不改变无活动计划时的单意图行为。 +**测试:** 多意图生成需确认;活动计划冲突;权限撤销;重放;部分完成;receipt 丢失恢复;真实 PI 结果引用。 +**停走门:** taskrun owner/PG/auth/browser/real PI 分层证据全绿。 +**mutex:** `taskrun` + `intent-plan`。 + +### U9. LLM 分段 adapter 与全面灰度 + +**目标:** 仅为规则无法可靠判断的输入提供受控建议。 +**依赖:** U2、U7。 +**文件:** intentflow segment proposal port/adapter、版本化 schema、eval/real PI tests。 +**做法:** 最小输入、严格 schema、固定版本/digest、护栏优先、shadow、超时 fail closed。 +**测试:** malformed/timeout;重试稳定;模型改风险/权限无效;红线拆分逃逸失败;敏感内容不出站;冲突澄清。 +**停走门:** real PI eval 达预注册阈值且安全错误为 0。 +**mutex:** `intent-plan` + `pi-agent`,不得改变 intent imports。 + +U9 是核心首版之外的独立实验,不参与 U1–U8 的完成判定。未实施或未达阈值时,规则无法裁定的输入继续进入澄清。 + +### U10. 低风险 mutate adapters + +**目标:** 只接入经专项批准的 medium/low mutate action。 +**依赖:** U8。 +**文件:** 每个动作的 intentflow adapter 与 owner tests。 +**做法:** 每个 action 独立 short-term、flag、dry-run、权限负例和回滚;不打包发布。 +**停走门:** 单 action 证据齐全后才加入 full tier。 +**mutex:** 对应动作 owner + `intent-plan`。 + +### U11. 文档治理 adapters + +**目标:** 按 claim/submit/review/final 等 action 分项接入 docgov,不复制其 duty/lifecycle 规则。 +**依赖:** U8。 +**文件:** intentflow docgov adapters、docgov owner ports/tests、browser auth negatives。 +**做法:** 高风险动作逐个任务、逐个 go/no-go;必须带 expected document version。 +**停走门:** 各 action 的跨角色、生命周期和并发负例独立签署。 +**mutex:** `docgov` + `intent-plan`。 + +### U12. Workflow 与 run-control adapters + +**目标:** 分别接入 workflow switch/run 与 task run resume/restart/cancel。 +**依赖:** U8。 +**文件:** intentflow workflow/run adapters、owner ports/tests。 +**做法:** workflow 与 run-control 必须拆成独立 short-term,不共用发布开关或回滚点。 +**停走门:** 当前 stage/state、权限、幂等和冲突负例分别通过。 +**mutex:** `workflow` 或 `taskrun` + `intent-plan`。 + +--- + +## 十二、验收矩阵与 DoD + +必须覆盖:两个只读查询;查询+生成确认前零副作用;部分确认后未选项仍可稍后确认、显式排除才取消;增量补槽保留已验证值;部分完成可重试/继续/关闭;确认后权限撤销;双标签确认/取消只一方成功;确认/过期竞态;服务/worker 重启不重跑成功步骤;投影停机而 GET 正确;“查法规并总结”不误拆;红线混入整体拒绝;前序结果含提示注入仍只作材料;无活动计划时单意图生成不变、有活动计划时不创建第二任务、批量生成需确认;跨用户/项目/会话隐藏;同 turn/nonce 异摘要冲突;编辑后旧卡 stale。 + +Definition of Done: + +- [ ] 核心首版 U1–U8 按各自停走门独立验收;U9、U10–U12 未实施不阻塞首版,但任何已启用 adapter 必须满足自己的停走门; +- [ ] `intent -> maturity` 保持,intentflow 无 service locator、pool 或跨 owner SQL; +- [ ] 所有写/生成/控制在未确认和越权时副作用为 0; +- [ ] 双标签、刷新、服务/worker 重启、重复/乱序事件下无双执行且可恢复; +- [ ] 按钮与自然语言走同一命令,每步即时授权并校验资源版本; +- [ ] 中间结果不进 FAV,事件不携带敏感正文; +- [ ] arch-check、Go short、PG、web build/test、真实 browser 和适用 real PI 分别有报告; +- [ ] FEATURE-MATRIX、CURRENT、任务与必要时 gap-matrix 一致; +- [ ] 清除废弃实验、旧本地成功路径和临时开关;回滚版本仍能读取/取消已有计划。 + +--- + +## 十三、关键决策 + +1. 采用 `app/intentflow` 深模块,不继续膨胀 coordinator; +2. 单意图生成行为保持;多意图策略由 intentflow 的 BatchActionPolicy 管理并引用 ActionRegistry action key,不把应用编排政策回灌 L1; +3. 同步权威状态 + outbox 投影,不用纯事件驱动 plan state; +4. 服务端绝对过期,不用 TTLTurns 作权威; +5. 逐步骤事务,不制造跨 owner 长事务; +6. LLM 只建议分段且最后实施; +7. 新行为默认 legacy/shadow,现有 `MULTI_INTENT_ENABLED=true` 不是自动放量许可。 + +不采用:把完整 PendingPlan 塞进 UserProjectContext、扩展前端本地 cardActionEngine 执行业务、用 coordinator switch 持有所有具体 engine、LLM 直接生成可执行计划、跨模块大事务。它们会造成双真相、越权/假成功、service locator 回潮、不可信执行或解耦倒退。 + +长期维护归属按模块分开:intent owner 维护规则与评测;intentflow owner 维护状态机、schema 和 rollout;web owner 维护卡片交互;events owner 维护投影契约;各 action owner 维护自己的授权 adapter。上线后每次新增 ActionSpec 必须同时给出批量策略、计划适配能力和负例,不能让矩阵靠人工记忆同步。 diff --git a/.doc/system-design/README.md b/.doc/system-design/README.md index 4c88309f..6f41f87f 100644 --- a/.doc/system-design/README.md +++ b/.doc/system-design/README.md @@ -119,6 +119,19 @@ --- +### 7. 多意图持久计划与 HITL + +| 项 | 链接 | +|-----|------| +| 主方案 | [2026-09-15-multi-intent-hitl-plan.md](2026-09-15-multi-intent-hitl-plan.md) | +| 复核 | [../audit/2026-09-15-multi-intent-hitl-plan-review.md](../audit/2026-09-15-multi-intent-hitl-plan-review.md) | +| 任务总览 | [../ops/short-term/2026-09-15-multi-intent-hitl.md](../ops/short-term/2026-09-15-multi-intent-hitl.md) | +| 一句话总结 | intent 保持纯规则,intentflow 持久化计划并统一确认、授权、幂等、恢复和逐动作执行 | + +**硬边界**:确认不等于授权;PG 是计划真相,卡片/SSE 是投影;写动作按 owner 端口逐项接入;LLM 只能提出不可信分段建议。 + +--- + ## 🏗️ 在整体架构中的位置 ```