Files
T

133 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Context
阶段 2-5 已形成内部 Harness 核心:`RunContext`、canonical evidence tools、唯一 Diagnosis Agent、EvidenceGuard/SemanticGuard 和 release policy。当前生产 Chat 仍由旧 `ChatService`/Controller 创建 Run、选择 Agent、维护历史并生成答案,新的组件没有统一入口,也没有 `intent/release_outcome/published_result` 持久化,阶段 6B 无法只做协议切换。
阶段 6A 建立同步的内部 application use case 和 typed output。阶段 6B 将在受控任务执行器中调用它并把 observer 转成 SSE;本阶段不触碰 HTTP、前端或旧公开行为。
## Goals / Non-Goals
**Goals:**
- 应用用例拥有 session/run 创建、路由、固定 executor dispatch、最终终态和安全持久化。
- Router 只看最小输入并按 Harness policy 进行最多两次技术 attempt。
- SYSTEM_CHAT、KNOWLEDGE_QUERY、DIAGNOSIS 三条路径接收同一个未改写 Query,能力严格隔离。
- 从 MySQL `diagnosis_run` 确定性读取有界 PreviousTurn。
- 提供 protocol-neutral observer/run control,使阶段 6B 能发送 metadata/status 和处理断开取消。
- 新增可前向迁移、可回滚的 L3 数据库契约。
**Non-Goals:**
- 不修改 Controller、SSE endpoint、前端消费者和 HTTP DTO。
- 不删除旧 ChatService、多 Agent、ThreadLocal 或旧 session storage。
- 不实现 token streaming、事件 schema 或 Controller 线程池。
- 不执行 live E2E;阶段 7 统一启动项目验证。
## Decisions
### 1. Application Use Case 是唯一业务入口
`ChatApplicationUseCase.execute(request, observer)` 固定流程:
```text
resolve session
-> read prior safe routing/diagnosis context
-> start one RunContext and persist RUNNING
-> observer.onStarted(run control)
-> IntentRouter
-> persist intent
-> fixed executor
-> complete Harness lifecycle
-> persist release outcome/public content/published result
-> typed ChatApplicationResult
```
它通过构造器接收 Router、三个 executor、Run store、Core 和 session ID supplier,不接收 Controller 注入的 ChatModel/Tool。Controller 在阶段 6B 只调用这一接口。
读取 prior context 必须早于当前 Run 持久化,避免 latest query 命中当前 PENDING/RUNNING 行。替代在 Controller 中先查历史;拒绝,因为会拆散生命周期所有权并制造 session/run 竞态。
### 2. Protocol-neutral observer 与取消控制
Observer 只接收 `ChatRunControl(sessionId, runId, cancelClientDisconnect)` 和固定 `ChatApplicationStatus`,不依赖 Spring MVC/SSE 类型。应用用例先成功写入 Run,再发送 started;阶段 6B 将 started 映射为 metadata,将 status 映射为安全状态事件。
Run control 只暴露客户端断开取消,不暴露 Core/RunContext。Observer 异常按执行失败处理并进入 Run 终态,避免协议层静默丢失连接后继续运行。
### 3. Router 是直接单轮模型调用
`IntentRouterInput` 只含原始 query、可选 last intent 和 last user query。Router 使用新的 system prompt 和共享 `GuardModelCall`,无 Tool/记忆/ReactAgent;严格解析唯一字段 `intent`。timeout/transport/任何非法输出映射到 `HarnessRetryPolicies.intentRouter()` 支持的失败类型,最多两次使用同一 JSON 输入。
两次失败抛出稳定 `ChatApplicationException(ROUTING_UNAVAILABLE)`;不得默认 DIAGNOSIS。取消/预算耗尽继续传播为 Run 终态。
### 4. 固定执行器与 typed public content
- SYSTEM_CHAT:一次 `GuardModelCall`,system prompt 只含受控产品能力说明;不接历史、Tool 或 evidence guard。
- KNOWLEDGE_QUERY:生成当前 direct invocation 的唯一 ID,调用 `HarnessEvidenceTools.lookup_knowledge` 一次。`NO_EVIDENCE` 返回固定安全说明;正证据只调用模型一次并严格解析 `KnowledgeAnswerDraft`,校验 exact call ID 和 document ID subset,再发布移除 Tool ID 的 `KnowledgeContent`。
- DIAGNOSIS:调用 `DiagnosisAgentUseCase(query, previousTurn)`,再调用 `DiagnosisReleaseUseCase`。SUCCESS 发布 `SemanticDraftView + verified sources`,Fallback 只发布 `SafeFallback`。
`ChatApplicationResult` 使用 `ChatContentType` 与 sealed typed content,不使用 Map/Object payload。阶段 6B 可直接序列化 content;Diagnosis public view 不含 Tool Call ID 或完整 evidence snapshot。
### 5. PreviousTurn policy 同时负责写入和读取边界
`PublishedResultPolicy` 从 SUCCESS Diagnosis 的 Query、Conclusion、Limitations/Scope 和 verified RAG metadata 构造有界 `PublishedResult`,并从持久化结果构造 `PreviousTurn`。每个字符串、list 和 source document 都按集中 limits 在字段边界截断;不调用 LLM。
只有 conclusion 非空才写 `published_result`。Repository 查询必须精确为同一 Session、`intent=DIAGNOSIS`、`release_outcome=SUCCESS`、JSON 非空,按 `created_at,id` 倒序一条。解析失败或字段无效时 fail closed 为 `previousTurn=null`。
### 6. Run store 和数据库契约
`DiagnosisRun` 新增:
- `intent VARCHAR(32)`,枚举 `SYSTEM_CHAT|KNOWLEDGE_QUERY|DIAGNOSIS`;
- `release_outcome VARCHAR(16)`,枚举 `SUCCESS|FALLBACK|FAILED|CANCELLED`;
- `published_result JSON`,只存固定安全结构。
V012 添加三列及索引 `session_id,intent,release_outcome,created_at,id`。`JpaChatRunStore` 负责 ensure ChatSession、start、markIntent、finish、latest routing context 和 safe PreviousTurn;JSON 使用注入的 ObjectMapper,禁止 Java serialization。
Run `status` 保持既有字符串:安全 SUCCESS/FALLBACK 都标记 `SUCCESS`,技术失败 `FAILED`,客户端/用户取消 `CANCELLED`;`release_outcome` 保留精确发布语义。finish 同时写安全 public content、budget tokens/tool count 和 duration。
### 7. 异常与 first-terminal-wins
应用用例 catch 所有执行异常后先读取 Run lifecycle:CANCELLED 映射 `release_outcome=CANCELLED`,其余未完成异常调用 `core.completeFailure` 并写 FAILED。成功/Fallback 都调用 `core.completeSuccess`。持久化错误不伪造成功;异常只通过稳定 `ChatFailureCode` 向阶段 6B 暴露,不携带供应商/JPA/Prompt 详情。
## Module and Ownership Audit
```text
ChatApplicationRequest
-> ChatApplicationUseCase (session/run/dispatch/terminal owner)
-> ChatRunStore (MySQL truth)
-> IntentRouter (minimal direct ChatModel)
-> SystemChatExecutor | KnowledgeQueryExecutor | DiagnosisChatExecutor
-> GuardModelCall | HarnessEvidenceTools | DiagnosisAgent/Release
-> ChatApplicationResult + Observer statuses
```
- Core owns deadline/cancel/budget/lifecycle;Application owns business dispatch and persistence;Store owns MySQL mapping;executors own path-specific behavior;Controller remains protocol-only.
- 最大风险是应用终态和 DB 写入分离;用例使用单一 finish path 和 first-terminal-wins lifecycle,focused tests 覆盖 success/fallback/failure/cancel。
- 最大兼容风险是 V012;Entity/migration/repository query 必须同步,阶段 6B 前不读取新入口不会改变公开行为。
- 不复用旧 `ChatService` 私有 routing/session helpers,避免新用例依赖旧多 Agent 结构。
## Interface Impact
- Level: L3 collaboration/database contract。
- Consumers: 阶段 6B Controller/SSE adapter、DiagnosisRunRepository、MySQL schema。
- Public HTTP/frontend: 本阶段无变化。
- Independent contract: 本 design 的 Database Contract/Migration Plan 章节作为独立接口说明。
## Risks / Trade-offs
- [Router hallucinated value] -> exact one-field JSON + enum parser + two-attempt policy + fail closed。
- [Knowledge model fabricates reference] -> exact invocation ID/document subset validation before public projection。
- [Current Run shadows previous context] -> prior reads before start/persist current Run。
- [PublishedResult leaks evidence] -> dedicated typed contract/policy and serialized-field negative tests。
- [Observer disconnect leaves work running] -> run control directly cancels shared Core context。
- [DB/entity drift] -> V012 migration + entity/repository/static schema tests + compile。
## Migration Plan
1. Apply V012 additive columns/index; all new columns nullable, old writers remain compatible。
2. Deploy stage 6A code while public Controller continues using old path;new fields remain unused except internal tests。
3. Stage 6B wires new application use case and begins writing fields atomically per Run。
4. Rollback: switch Controller back to old path, then optionally drop V012 index and three columns;V011 data and old writers remain valid。
## Open Questions
- None。具体模型/byte/PreviousTurn 数值由构造配置提供默认值,阶段 7 根据真实 Trace 校准。