Chat Diagnosis StateGraph ChatService Cutover Decisions
Entry Summary
- 问题:复杂 Chat 仍使用 SequentialAgent + ThreadLocal/Hook 隐式状态机,真实 Graph 尚未成为生产入口,也没有 Run 级 orchestration trace 持久化和 API 投影。
- 期望:阶段 3 独立完成生产 cutover、Run/Trace 映射和必要测试,归档并提交后才进入阶段 4。
- 分档:complex。
- Change:
chat-diagnosis-stategraph-chatservice-cutover。
- 授权:用户已要求后续阶段直接实现,不再逐 checkpoint 等待;阶段门禁、独立 archive/commit 与阶段 5 才 E2E 约束不变。
Context Sources
mvp/issues/active/ISS-011-chat-diagnosis-stategraph-orchestration.md 阶段 3、协议影响、Run 状态和验收章节。
- 阶段 0–2 OpenSpec archives、devflow acceptance/decisions 与当前四份 Graph 主 specs。
devflow/glossary/CONTEXT.md 中 Chat Session、Diagnosis Run、Diagnosis Trace、Diagnosis Orchestration Trace 的边界。
ChatService 生产调用链、四个 Agent builder、Run persistence/self-evaluation/metrics 逻辑。
DiagnosisRun、V011 migration、DiagnosisTraceResponse、DiagnosisTraceService 与相关 tests。
DiagnosisGraphFactory、真实 action factory、Node adapters、final trace builder 和本地 CompiledGraph API。
Question Pool
| # |
维度 |
问题 |
模式 |
状态 |
| Q1 |
术语 |
orchestration trace 是否属于 self-evaluation 或完整 Trace event log? |
evidence-driven |
已解决 |
| Q2 |
边界 |
阶段 3 是否改变 /api/chat,以及 Trace 字段出现在哪一层? |
user-interview(既有冻结决策) |
已确认 |
| Q3 |
生命周期 |
LOW_CONFID/REJECT/Fallback 是否应使用 FAILED 或新增 DEGRADED? |
user-interview(既有冻结决策) |
已确认 |
| Q4 |
错误处理 |
Graph 异常时如何 best-effort 保存已有编排事实而不伪造 event? |
evidence-driven |
已解决 |
| Q5 |
技术实现 |
是否复用现有 Agent factory/Hook/ToolCallback 与真实 Node assembly? |
evidence-driven |
已解决 |
| Q6 |
安全 |
Graph Verifier Prompt/self-evaluation 是否可继续使用 raw Executor 和完整 tool trace? |
evidence-driven |
已解决 |
| Q7 |
验收 |
阶段 3 是否需要新增测试,是否现在运行 live E2E? |
user-interview(用户最新规则) |
已确认 |
Evidence-driven Findings
- Q1:glossary 与阶段 0 spec 已定义 orchestration trace 为 Run 级紧凑编排摘要,与 self-evaluation、AgentStep/ToolInvocation 和 checkpoint 分离;无需新增术语或 ADR。
- Q4:所有已定义 Agent/Java 失败应由 Graph 路由到 handled Fallback 并返回 final state;只有真实可取得的 final/partial state 才可构造 trace。无法取得 state 的未处理异常标记 Run FAILED,不得生成虚假 transition。
- Q5:
DiagnosisRealGraphActionsFactory 已提供真实 Node assembly;ChatService 现有四个 builder、AgentLoggingHook、Skills hooks、method tools 和 ToolCallbacks 可直接构造 ReactAgent,再通过 ReactAgentDiagnosisInvoker 注入,不得复制 Prompt/Agent factory。
- Q6:阶段 2 spec 已禁止 Graph Verifier 使用 raw Executor/full tool trace;当前
chat-verifier-prompt.md 仍描述旧 Hook payload,是阶段 3 必须同步的明确 gap。self-evaluation 可保存 Graph 的 verified output、Gatekeeper audit 和 Composer audit,但不能重新引入 raw 输入。
User-interview Confirmations
| 问题 |
用户原话/既有确认 |
确认状态 |
OpenSpec 回写 |
| Q2 外部协议与 Trace 层级 |
ISS-011 已冻结 /api/chat 不变,Trace 只在 run.orchestrationTrace 增解析对象 |
已确认 |
proposal |
| Q3 Run 生命周期 |
ISS-011 已冻结安全 Fallback 为 SUCCESS,不新增 DEGRADED;只有无法生成安全响应的未处理失败为 FAILED |
已确认 |
proposal |
| Q7 验收节奏 |
“端到端只在最后阶段全部完成后才验证;每个阶段如果有必要添加单元测试验收的话,就加” |
已确认 |
proposal |
Interface Impact
- 等级:L4。
- 原因:复杂 Chat 内部状态机正式切换;DiagnosisRun 增加数据库 JSON 契约;Trace run 对象新增字段;旧固定顺序消费者/测试不再成立。
- 保持兼容:
/api/chat request/response、sessionId/runId、Executor/Verifier/Composer 输出契约不变。
- 加法变化:只新增
diagnosis_run.orchestration_trace 和 run.orchestrationTrace。
- 回滚:revert 阶段 3 代码/Prompt/spec,数据库列可保留 nullable;不保留运行时双轨开关。
Discover Status
devflow/index.md:命中阶段 0–2 archives 和 Run/Trace 历史项目。
- Glossary:相关术语已存在且无冲突,不需更新。
- ADR:阶段 0 已记录难以逆转的状态机/Trace 决策,本阶段没有新的三条件 ADR。
- 未解决问题:0。
- Draft 产物:当前只创建 proposal + decisions;design/specs/tasks 留到 Commit checkpoint。
Grill-with-docs Review
Domain model stress test
- 同一 session 连续两个复杂 Chat run:每次编译/执行使用自己的 runId threadId 和 metadata;orchestration trace 只写各自 DiagnosisRun,session 投影不复制,符合 Session/Run/Trace 领域边界。
- Gatekeeper REJECT 或 Planner/Executor 技术失败:Graph 进入确定性 Fallback,返回安全非空答案;Run 为 SUCCESS,trace
degraded=true,不会把诊断质量塞进 Run status。
- Composer 成功但 verdict=LOW_CONFID/REJECT:Run 仍为 SUCCESS;self-evaluation 保存 effective verdict,orchestration trace 保存实际路径,两者职责不混合。
- Graph 未处理异常:使用流式 NodeOutput 捕获最后一个真实 state,只有其中已有 events 时才 best-effort 构造 partial trace;没有 event 时不伪造 transition,Run 标记 FAILED。
- 历史/AI_OPS run:新增列 nullable,Trace DTO 对旧 run 可返回 null;不增加历史回填或跨 flow 假数据。
Design tree conclusions
- 生产切换采用单轨,不增加 feature flag 或保留 Sequential/Graph 双运行;回滚依靠 Git revert,nullable 列可保留。
- ChatService 负责 Run 生命周期和调用一个专用 Graph runtime/orchestrator;复杂 Agent 构造从旧 Sequential 私有流程中搬移或封装复用,不复制第二套 builder。
- Graph 执行优先使用可观察的
CompiledGraph.stream(..., config) 收集最后真实 state,以支持异常时 best-effort trace;正常终止仍以 END state 的 final_answer 为唯一答案来源。
- Graph result mapping 形成独立组件:final answer、Verifier evaluation、Composer audit、Gatekeeper audit、trace JSON 均从显式 final state读取,不再访问 VerifierContextHolder。
- Verifier Prompt 必须更新为
diagnosis_context、verified_executor_output、verified_evidence、gatekeeper_audit、verdict_ceiling 和可选 retry context;删除 raw Executor/full tool trace/Hook Gatekeeper 说明。
- 阶段 3 必须有 production cutover 与 Trace DTO/Service tests;阶段 4 再做测试体系全面改名、夹具收敛和旧测试删除。
Documentation result
- 术语与
devflow/glossary/CONTEXT.md 完全一致,无需修改 glossary。
- 状态机、Run status 和 orchestration trace 隔离均来自阶段 0 已归档 ADR/规格,不创建重复 ADR。
- proposal 已反映单轨切换、L4 接口影响、流式 partial-state 处理、Prompt 安全边界和阶段 5 E2E 延期。
- Grill question pool 全部关闭;无需要再次询问用户的产品取舍。
Architecture Audit
Module and caller map
ChatController 的 normal/SSE 两个入口都调用 ChatService.executeChatWithStrategy,复杂分支进入 executeChatComplex;对外仍只消费 ChatResult(answer, sessionId, runId)。阶段 3 将内部链路变为 ChatService Run lifecycle -> complex Chat Graph runtime/Agent assembly -> real Diagnosis Nodes -> Graph result mapper -> DiagnosisRun persistence -> DiagnosisTraceService。Trace UI/Eval 当前读取兼容 session.selfEvaluation,它仍由 Run self-evaluation 投影;新增 orchestration trace 只属于 run。AIOps、Feedback、CaseLibrary 和 Run list 继续使用 DiagnosisRun 既有字段,不消费新增 orchestration trace。
| 模块 |
所有权 |
允许的依赖/影响 |
| ChatController |
/api/chat normal/SSE 协议 |
继续只依赖 ChatResult;无字段变化 |
| ChatService |
Chat Session/Diagnosis Run 生命周期、成功/失败保存、metrics、Eval、finally cleanup |
调用一个 Graph runtime/result mapper;不再拥有条件边/重试/Gatekeeper/Composer 路由 |
| Complex Chat Graph runtime |
每请求 Agent assembly、initial state、RunnableConfig、CompiledGraph stream |
复用现有 Prompt/tool/skill/logging;不持久化跨 Run 状态 |
| Diagnosis Graph |
Node status、verified material、events、final answer |
保持阶段 1/2 路由和 counter 所有权 |
| Graph result mapper |
final/partial state 到安全 evaluation/trace DTO |
不读 ThreadLocal,不查询其他 run,不持久化 raw material |
| DiagnosisRun/Flyway |
当前 Run 的 orchestration JSON |
仅一个 nullable JSON 列;历史/AIOps 可为 null |
| DiagnosisTraceService/DTO |
exact/latest Run 查询和 API 投影 |
只在 RunTrace 加 parsed map;session/top-level/run-list 不重复 |
Lifecycle and coupling audit
ReactAgent 与 CompiledGraph 都按请求构造,因为 Planner/Executor system Prompt 含本次 history/knowledge map;Graph State 和 runtime last-state holder 也是 invocation-scoped,不进入 singleton 可变字段。SessionContextHolder 仍只包围当前请求并在 finally 清理;Graph Node config 以 runId threadId + metadata 绑定 AgentStep、ToolInvocation 和 Gatekeeper。success persistence 在 Eval 之前完成,EvaluationService 再按 runId 合并 rule channel;handled Fallback 与 Composer 使用同一 SUCCESS 路径。Trace JSON 与 self-evaluation 分栏,避免把路线、质量和完整 Agent/tool 明细耦合到一个容器。
Consumer impact audit
- ChatController normal/SSE:ChatResult 协议不变,L4 内部切换不要求调用方迁移。
- Trace UI/demo:继续读取兼容
session.selfEvaluation;新的 run.orchestrationTrace 是加法字段,最终脚本断言留到阶段 5。
- DiagnosisTraceEvaluator:现有 fixtures 不变;工具覆盖仍可从
toolInvocations 读取,兼容 executor_structured_output 保存 verified projection。pre-verification Fallback 质量未来应以 trace degraded 而非伪 verdict 判断,属于阶段 4 测试体系/阶段 5文档收尾。
- AIOps/Feedback/CaseLibrary/Run list:实体新增 nullable 字段不改变 builder call sites或查询语义。
- 数据库:Hibernate validate 要求 V012 与 entity 同批;回滚代码可忽略保留列。
Cross-artifact alignment
| 对齐链 |
结果 |
证据 |
| brief/proposal 目标、范围、非目标 → proposal |
已对齐 |
单轨 cutover、Run/Trace、Prompt、阶段边界与 E2E 延期均明确 |
| proposal 承诺与约束 → design |
已对齐 |
10 项决策覆盖 runtime、state、config、partial state、result、persistence、DB/API/Prompt/tests |
| design 架构/接口结论 → specs/tasks |
已对齐 |
L4、单轨、Run status、verified-only、Trace 唯一投影和 schema whitelist 均有 requirement/task |
| specs 可观察行为 → tasks 可执行切片 |
已对齐 |
6 组 26 个切片覆盖数据、runtime、Prompt、cutover、tests、handoff |
Audit result
未发现与阶段 0–2、Run/Trace ADR 或 glossary 冲突。审计确认不能把 Agent factory 复制进 Node,也不能把 pre-verification Fallback 伪装为 Verifier verdict;两项已在 design/specs/tasks 固定。唯一跨阶段依赖是阶段 4 让测试/Eval 以 orchestration degraded 理解无 Verifier verdict 的安全 Fallback,已记录但不阻塞阶段 3 production correctness。架构风险可接受,cross-artifact gap=0,无未解决接口消费者。
Commit Gate
- schema:spec-driven;proposal/design/specs/tasks 全部 done,applyRequires=
tasks 已满足。
- OpenSpec:当前 change strict validation 通过;14 个主 specs 全部 strict pass。
- 规格结构:5 个 delta capabilities、23 条 requirements、72 个 scenarios;tasks 26 个可执行 checkbox。
- Cross-artifact:4/4 已对齐,gap=0。
- Interface impact:L4;design 已独立记录消费者、加法 DB/Trace 协议、单轨迁移和 Git revert 回滚。
- Question pool:所有 evidence-driven 已查证;所有 user-interview 已由 ISS-011/用户原话确认;无未决项。
- Preflight:
git diff --check 通过;Commit checkpoint 尚未修改 Java、SQL、Prompt 或测试。
- 结论:Draft OpenSpec 已达到可执行状态,创建
.committed,阶段 3 Apply 只能以这些产物为依据。
Apply Authorization
- 用户原话:“直接实现吧,不用找我授权了”。
- 本阶段在 Commit gate 后直接进入 Apply;不扩大到阶段 4 全面测试迁移或阶段 5 live E2E。
Pre-apply Research
Reference implementations read
ChatService.executeChatComplex、四个 complex Agent builders、Run start/save、metrics、Prompt audit、self-evaluation merge:迁移源实现和外部兼容基线。
DiagnosisGraphFactory、DiagnosisRealGraphActionsFactory、四个 Agent adapters、Gatekeeper/VerifiedInput/Fallback、DiagnosisOrchestrationTraceBuilder:Graph 路由/计数/安全材料唯一真理源。
DiagnosisRun、V011 migration、DiagnosisTraceResponse、DiagnosisTraceService、DiagnosisTraceServiceTest:Run JSON 字段和 exact/latest Trace 映射标准。
ChatController normal/SSE、DiagnosisTraceController:公开协议调用者与响应包装边界。
SelfEvaluationMergeService、EvaluationService、DiagnosisTraceEvaluator:evaluation container、异步 rule merge 和兼容消费者。
- 本地 graph-core 1.1.2.0
javap:CompiledGraph stream/invoke/state、NodeOutput state()、RunnableConfig threadId/metadata 的真实 API。
chat-*-prompt.md:现有 Prompt 组装与 Verifier 旧 Hook payload gap。
Technology inventory
| 类别 |
项目标准 / 本阶段使用 |
| Graph execution |
CompiledGraph.stream(initial, config) + NodeOutput.state,当前请求线程阻塞消费 |
| Run context |
SessionContextHolder + RunnableConfig threadId/metadata;runId 是唯一执行边界 |
| Agent assembly |
ReactAgent builder、AgentLoggingHook、PlannerSkillMetadataHook/SkillsAgentHook、现有 tools/callbacks |
| JSON persistence |
Jackson map serialization;实体 String + @JdbcTypeCode(SqlTypes.JSON);Flyway JSON column |
| Trace API |
Lombok DTO builder + DiagnosisTraceService parsed Map;exact/latest Run 查询 |
| Evaluation |
SelfEvaluationMergeService container;EvaluationService 按 runId 异步合并 rule channel |
| Tests |
JUnit 5,通过 public service/runtime/Trace API;只 mock repository/model/tool 外部边界 |
| MQ/Consumer |
不涉及 |
New infrastructure and reuse
- 新增一个深接口的 complex Chat Graph runtime/result mapper;复用既有 Graph/Node/Agent builders,不增加新依赖或第二套路由。
- 新增 V012、DiagnosisRun 字段和 RunTrace parsed map;不新增表、repository method 或历史 backfill。
- TDD tracer bullet 从 Trace DTO/Service 的唯一 Run 投影开始,再进入 runtime final-state mapping,最后切换 ChatService。
- 研究未发现 devflow/OpenSpec 冲突,技术清单足以开始实现。
Apply Progress
- TDD Trace slice RED:DiagnosisTraceServiceTest 明确缺少 DiagnosisRun builder 字段和 RunTrace getter。
- GREEN:V012、DiagnosisRun JSON 字段、RunTrace parsed map、DiagnosisTraceService mapping 完成;10 个 Trace service tests 通过。
- 失败分类:首次 GREEN 运行仅测试夹具用裸 ObjectMapper 无法序列化 LocalDateTime,属于 test harness 偏差;改为项目可用的
findAndRegisterModules() 后原始 focused loop 通过,未改业务协议。
- Trace API JSON 断言证明顶层/session 无重复字段、run 为解析对象、无 raw 字段;null/invalid JSON fail closed。
Apply Completion
- 复杂 Chat 已单轨切换到
ChatDiagnosisGraphRuntime;生产 ChatService 不再创建 SequentialAgent,不再读取 VerifierContextHolder,Graph Verifier 只保留 AgentLoggingHook。
- runtime 使用 query-only initial state、
threadId=runId 和 sessionId/runId metadata,流式保留最后真实 state;异常只保存真实 partial state/trace。
DiagnosisGraphResultMapper 只从 verified projection 构造兼容 self-evaluation;Verifier 未完成时不伪造 verdict,不持久化 full tool trace/raw Executor。
- Verifier Prompt 与 runtime payload 已统一为 verified-only,Prompt audit 更新为
chat-prompts-v2 / chat-verifier-v3。
- 旧
ChatServiceSequentialAgentTest 因绑定已删除的固定顺序/ThreadLocal/score retry 实现而移除,由 public service/runtime/route tests 替代。
- V012 schema 白名单测试确认只新增
diagnosis_run.orchestration_trace JSON NULL,无其他 schema object。
Verification Summary
- focused regression:27 suites / 119 tests,0 failures、0 errors、0 skipped。
- Maven test compilation:通过。
- OpenSpec:当前 change strict pass;主 specs 14/14 strict pass。
- 静态门禁:
git diff --check 通过;cutover 禁用引用 0;核心 TODO/placeholder 0;schema whitelist 为 1 ALTER / 1 ADD COLUMN / 0 CREATE / 0 DROP。
- 实现期唯一失败分类:no-answer service test 曾错误期待 inner cause 文本,属于测试断言偏差;按公开 wrapper error + FAILED/partial trace 契约修正后通过,OpenSpec 与生产代码无需变更。
- 按阶段门禁未运行 Maven live E2E、未检查
logs/、未执行 scripts/query_mysql.py;统一保留到阶段 5。
Archive Result
- 5 份 delta specs 已同步:新增 9、修改 13、删除 1 条 requirements。
- OpenSpec 已归档到
openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-chatservice-cutover/。
- CLI 对 proposal 结构给出非阻塞建议(大 change/delta 拆分与 SHALL/scenario 启发式);tasks 26/26、delta specs 和 strict validation 均通过,未形成验收阻塞。