# Chat Diagnosis StateGraph Real Nodes Decisions ## Question Pool | # | 维度 | 问题 | 模式 | 状态 | |---|---|---|---|---| | Q1 | 边界 | 阶段 2 是否切换 ChatService/DB/Trace? | user-interview(六阶段已确认) | 已解决 | | Q2 | 复用 | 新 Nodes 如何避免复制 Hook/ChatService 解析与安全渲染? | evidence-driven | 已解决 | | Q3 | Agent | Adapter 如何调用真实 ReactAgent 并保留 Hook/ToolCallback/run config? | evidence-driven | 已解决 | | Q4 | Gatekeeper | 显式 Node 如何保证当前 run、单次调用和 fail-closed 标准化? | evidence-driven | 已解决 | | Q5 | 安全 | passed checked bindings 如何投影为 verified output/evidence? | evidence-driven | 已解决 | | Q6 | 补证据 | 哪些 facts 可触发 evidence retry,completed queries 如何表达? | evidence-driven | 已解决 | | Q7 | Fallback | 前置验证失败与 Composer 后置失败可分别使用哪些材料? | evidence-driven | 已解决 | | Q8 | Prompt | 阶段 2 是否立即修改共享 Verifier Prompt? | evidence-driven | 已解决 | | Q9 | 验收 | 阶段 2 是否需要单元/集成测试与 E2E? | evidence-driven + user rule | 已解决 | ## Evidence-driven | 结论 | 证据来源 | 是否已汇报用户 | |---|---|---| | ReactAgent.call(input, config) 返回 AssistantMessage,现有 AgentLoggingHook 从 config metadata 读取 sessionId/runId | 本地 1.1.2.0 javap、AgentLoggingHook | 已汇报 | | Executor parser 当前在 VerifierInputHook,Verifier/Composer parser 与 renderer 当前在 ChatService | 定向源码阅读和 references | 已汇报 | | checked_bindings 提供 claim_id/tool_name/source_invocation_id/raw_path/matched_text/status | ExecutorGatekeeperService | 已汇报 | | Gatekeeper.validateRun 使用 run-scoped ToolInvocation repository | ExecutorGatekeeperService tests/code | 已汇报 | | Graph path不能注册旧 VerifierInputHook,否则 Gatekeeper 会双执行且输入包含 full tool trace | 阶段 0 ADR、Hook 源码 | 已汇报 | | evidence retry 只允许 critical no_evidence/indirect_support | 阶段 0 design/ISS-011 | 已汇报 | | 阶段 1 router 未检查 is_critical,属于实现偏离 | Router 源码与阶段 0 baseline 对照 | 已汇报 | | 共享 Prompt 暂时仍服务旧 Sequential path,本阶段直接修改会提前破坏生产 payload | ChatService agent builder + VerifierInputHook + prompt | 已汇报 | | Node 输入/安全边界新增且旧解析会重构,单元和 focused regression 必要;E2E 不必要 | 阶段边界和用户规则 | 已汇报 | ## User-interview | 问题原文 | 用户原话 | 确认状态 | OpenSpec 回写 | |---|---|---|---| | 阶段 2 是否独立 sm-flow? | “iss-011里每个阶段,都是一个sm-flow” | 已确认 | 独立 change | | 是否可提前切生产入口? | “每个阶段需要归档完并提交才能进入下一个阶段” | 已确认不可提前阶段 3 | Out of Scope | | 阶段 2 是否执行 E2E? | “端到端只在最后阶段全部完成后才验证” | 已确认不执行 | Acceptance | | 是否添加单元测试? | “如果有必要添加单元测试验收的话,就加” | 已确认规则;本阶段判定必要 | Acceptance | ## Context And Handoff - 阶段 0 archive/commit:design baseline / `581daff` - 阶段 1 archive/commit:routing skeleton / `42ba204` - 当前 change:`chat-diagnosis-stategraph-real-nodes` - 后续 change:`chat-diagnosis-stategraph-chatservice-cutover`,只能在本阶段 archive + commit 后创建。 ## Technical Decisions ### Shared protocol components - 抽取 Executor、Verifier、Composer 解析器,旧 Hook/ChatService 委托新组件。 - 抽取 Composer safe input builder / renderer,旧 ChatService 保持相同输出。 - JSON sanitization 只存在一份共享实现,不在每个 Node copy。 - 抽取过程是行为保持 refactor;现有 focused tests 是回归门禁。 ### Agent adapter boundary - `DiagnosisAgentInvoker` 是最小 port:`invoke(String, RunnableConfig) -> String`。 - `ReactAgentDiagnosisInvoker` 只包装 `ReactAgent.call(...).getText()`。 - Planner/Executor/Verifier/Composer adapters 各自拥有白名单 input projector、parser 和 status event。 - tests 使用 fake invoker,另有 ReactAgent wrapper test。 ### Legacy Hook coexistence - 旧 Sequential path 在阶段 3 前仍通过 VerifierInputHook 执行 Gatekeeper。 - Graph Verifier Agent 不注册该 Hook;显式 Gatekeeper Node 是 Graph 中唯一 validation 入口。 - Parser/enricher 可共享,但 Hook 的 legacy payload/prompt 暂不改变。 - 阶段 3 切换生产入口并同步 Verifier Prompt;阶段 5 删除旧隐式结构。 ### Gatekeeper normalization - raw pass → PASS。 - raw fail + severity low_confid → LOW_CONFID。 - raw fail + severity reject → REJECT。 - 缺失、unknown、异常或不一致 → REJECT。 - verified_binding_count 只统计 checked_bindings.status=pass。 ### Verified projection - 通过项按 claim_id + source_invocation_id + tool_name + raw_path 与原 binding 精确匹配。 - verified_executor_output 只包含 answer_version 与至少一条 passed binding 的 filtered claims;合法零 claim 保持空列表。 - verified_evidence 只含 claim_id/source_invocation_id/tool_name/raw_path/matched_text。 - hypotheses、失败 binding、未引用 ToolInvocation、raw Executor output 不投影。 ### Evidence retry - extractor 要求 `is_critical=true` 且 verification 为 no_evidence/indirect_support。 - gap 字段:claim_id(从 `claim-id: text` 提取或空)、fact、verification、reason。 - completed queries 由 verified evidence 的 tool/invocation/path 去重生成。 - prior verified output/evidence 原样只读进入 retry_context。 - 约束固定:max_retry=1、do_not_repeat_successful_queries、only_execute_incremental_queries、preserve_prior_verified_claims。 - Executor 输入声明“增量执行、完整输出”,Java 不合并 claims。 ### Interface impact - 等级:L2 internal interface;共享 parser 委托保持旧行为。 - 新消费者:阶段 3 Graph orchestrator/Agent factory。 - 当前外部 API/DB/生产路由:无变化。 - 回滚:revert 本阶段提交;旧 Sequential path仍完整。 - 有意修正:Router 只允许 critical gap,属于对冻结基线的代码修复。 ## Risks Accepted - 真实模型尚未执行;Node contract 通过 fake invoker/real service tests证明,阶段 5 才 E2E。 - Prompt 输入说明与 Graph input 的最终同步推迟到阶段 3,避免当前旧生产 Hook 提前不兼容。 - 旧 Hook 暂时仍存在,但不进入 Graph action graph;阶段 5 必须删除。 ## Architecture Audit ### Module and ownership map `Diagnosis Context + RunnableConfig` → Agent adapters / deterministic Nodes → owned Graph State fields → `DiagnosisGraphRouter` → next Node or END → `final_answer + orchestration_events`。阶段 2 只提供这条可构造链,阶段 3 才由 `ChatService` 创建 Run、构造 Agent 实例并调用 Graph。 | 模块 | 数据所有权 | 允许依赖 | |---|---|---| | `diagnosis.protocol` | JSON contract、纯解析结果、安全 input/rendering | Jackson 与纯 DTO;不依赖 Graph/Hook/ChatService/ThreadLocal | | `graph.diagnosis` Agent adapters | 白名单输入、Agent attempt status/event | protocol、注入的 invoker、Graph API | | Gatekeeper Node | raw Gatekeeper result、normalized status/count | ExecutorGatekeeperService、当前 run config | | Verified Input / Retry Prepare | verified projection、critical gaps、retry context | raw result 的只读投影与 protocol DTO | | Router / Factory | 条件边、有限计数、调用次序 | Graph State;不解析 Agent raw output | | legacy Hook / ChatService | 阶段 3 前的生产 Sequential 流程 | 只委托 protocol;不得消费真实 Graph action set | ### Lifecycle and coupling audit Graph State 和 events 都是 invocation-scoped,runId 只从当前 RunnableConfig 获取,Nodes 不持有跨 Run 可变状态。旧路径与 Graph 路径阶段性共享的只有无状态 protocol 组件和 Gatekeeper service,不共享 ThreadLocal 或 Agent output。ReactAgent/invoker 必须构造注入,阶段 2 不复制 ChatService Prompt/Agent factory。唯一有意的阶段性耦合是 legacy consumers 改为委托 protocol,这由旧 focused tests 和完整 revert 保护。阶段 3 前生产入口、DB、Trace、Prompt 均保持隔离。 ### Cross-artifact alignment | 对齐链 | 结果 | 证据 | |---|---|---| | brief/proposal 目标、范围、非目标 → proposal | 已对齐 | 独立阶段边界、真实 Nodes、无生产切换均明确 | | proposal 承诺与约束 → design | 已对齐 | invoker、共享组件、Gatekeeper、投影、retry、Fallback、L2 均有决策 | | design 架构/接口结论 → specs/tasks | 已对齐 | 中立 protocol 包、构造注入、fail-closed 和生产隔离均有任务/行为 | | specs 可观察行为 → tasks 可执行切片 | 已对齐 | 每个 requirement 至少由一个实现任务和一个测试/验收任务覆盖 | ### Audit result 审计发现共享协议组件包所有权与 Agent 实例装配边界需要显式化,已回写 design/tasks。未发现状态字段、路由计数、run 生命周期或阶段边界的新冲突。接口影响维持 L2,消费者都在本 change 与下一阶段明确范围内。剩余风险是共享抽取的旧行为漂移和 binding 投影泄漏,均有 focused regression 与 mixed-binding tests。架构风险可接受,无未解决问题。 ## Commit Gate - proposal/design/specs/tasks:全部存在,OpenSpec status `isComplete=true`。 - 当前 change strict validation:通过。 - 主 specs strict validation:13 passed,0 failed。 - 规格结构:9 requirements、22 scenarios;tasks:27 个 checkbox 切片。 - Cross-artifact:4/4 已对齐,gap=0。 - 接口影响:L2,已在 design 独立章节记录消费者、兼容和回滚。 - Question pool:所有 evidence-driven 已汇报;所有 user-interview 已确认;无未决项。 - Preflight scope:`git diff --check` 通过;Commit checkpoint 未修改业务代码。 - 结论:Draft OpenSpec 达到可执行状态,创建 `.committed`。 ## Apply Authorization - 用户原话:“直接实现吧,不用找我授权了”。 - 解释:阶段 2–5 后续 checkpoint 可在前置门禁通过后直接继续,不再因 Apply 或 Archive 授权暂停。 - 不扩大范围:每阶段仍须独立 OpenSpec、验收归档、Git commit;阶段 0–4 不做 E2E,阶段 5 才统一执行。 ## Pre-apply Research ### Reference implementations read - `src/main/java/com/superbiz/agent/hook/VerifierInputHook.java`:Executor JSON sanitization、parse status、tool-name normalization、唯一 invocation 回填与 legacy Gatekeeper payload。 - `src/main/java/com/superbiz/agent/service/ChatService.java`:Verifier claim/fact parser、Gatekeeper ceiling、Composer allowed-material builder、Composer parser/safe renderer、旧 retry context。 - `src/main/java/com/superbiz/agent/service/ExecutorGatekeeperService.java`:`validateRun`、severity normalization source、checked binding 与 matched_text 结构。 - `src/main/java/com/superbiz/agent/graph/diagnosis/DiagnosisGraphFactory.java`:config-aware action ports、technical retry/evidence retry counter 所有权和 recursion limit。 - `src/main/java/com/superbiz/agent/graph/diagnosis/OrchestrationEvent.java` 与 `src/test/java/com/superbiz/agent/graph/diagnosis/ScriptedDiagnosisGraphActions.java`:每 attempt 单 event 形态。 - `src/main/java/com/superbiz/agent/hook/AgentLoggingHook.java`:RunnableConfig metadata 中 sessionId/runId 的审计读取方式。 - `src/test/java/com/superbiz/agent/hook/VerifierInputHookTest.java`、`ChatServiceSequentialAgentTest.java`、`DiagnosisGraphRoutingTest.java`:JUnit 5、Mockito 边界替身和 CompiledGraph observable behavior 测试风格。 - 本地 `1.1.2.0` JAR `javap`:`ReactAgent.call(String,RunnableConfig)` 与 `RunnableConfig.threadId/metadata` 公共 API。 ### Technology inventory | 类别 | 项目标准 / 本阶段使用 | |---|---| | JSON contract | Jackson `ObjectMapper`、`LinkedHashMap` 保持稳定字段顺序;共享 sanitization 只存在一份 | | Graph Node | `AsyncNodeActionWithConfig` 返回 `CompletableFuture>`;state 默认 Replace、events Append | | Agent boundary | 构造注入的 `DiagnosisAgentInvoker`;ReactAgent wrapper 透传同一个 RunnableConfig | | Run scope | `config.metadata("runId")` 为 Gatekeeper 唯一运行边界;缺失即 fail closed | | Error handling | 合法 contract/invalid output/temporary/permanent 分离;unknown exception 不推断为可重试 | | Tests | JUnit 5;只在 ReactAgent、repository 等系统边界使用 fake/mock;Node/CompiledGraph 走公开 action/graph 接口 | | Request/response | 本阶段不改 Controller/DTO/API,不适用 | | MQ/Consumer | 本阶段不涉及,不适用 | | DB/Trace/Prompt | 本阶段禁止修改,阶段 3 处理 | ### Reuse and new infrastructure - 新建中立 `com.superbiz.agent.diagnosis.protocol`:`JsonPayloadSupport`、Executor/Verifier/Composer protocol、safe input/rendering、`EvidenceGapExtractor`;不得依赖 Graph/Hook/ChatService/ThreadLocal。 - 新建 `graph.diagnosis` Node 层:invoker wrapper、failure classifier、四个 Agent adapters、Gatekeeper、Verified Input、Retry Prepare、Fallback 和 action assembly。 - 不新建 Prompt/Agent factory;阶段 3 通过构造注入已有 ReactAgent 实例。 - 不新增 Maven dependency、数据库迁移、配置项或生产 consumer。 ### Pre-apply conclusion 参考实现、API 签名、异常和测试标准已足以指导实现;未发现 devflow/OpenSpec 冲突。进入 TDD tracer bullet,先锁定共享 Executor parser 的合法 no-evidence 与 malformed 行为。 ## Apply Completion And Verification ### Assembly alignment - 首个共享 protocol 模块与最终真实 Graph action assembly 均逐项对照 design/specs:invoker 显式透传 RunnableConfig,Gatekeeper 单次 fail-closed,Verified Input 精确投影,Verifier/Composer 固定输入重试,critical evidence retry 与两类 Fallback 边界全部落地。 - `DiagnosisGraphFactory` 继续独占技术重试计数、evidence retry 计数和 Planner mode/reset;Node 不重复拥有编排计数。 - 新增源码中无 `ThreadLocal`、`VerifierInputHook`、`tool_trace_summary`、`raw_executor`、TODO 或 FIXME;protocol 包无 Graph/Hook/ChatService 反向依赖。 - `ChatService` 无 Diagnosis Graph/CompiledGraph 引用,生产切换保持在阶段 3;DB migration、Trace DTO/entity/repository 和 prompts 均无 diff。 ### Automated verification - 新 protocol/Node/真实 CompiledGraph/Router/Trace focused suite:通过。 - 旧 `ChatServiceSequentialAgentTest`、`VerifierInputHookTest`、`ExecutorGatekeeperServiceTest` 回归:通过。 - 合计 100 tests,0 failures,0 errors,0 skipped。 - `mvn -q -DskipTests test-compile`:通过。 - `openspec validate chat-diagnosis-stategraph-real-nodes --strict`:通过。 - `openspec validate --specs --strict`:13 passed,0 failed。 - `git diff --check`:通过;仅报告 Git 既有 LF/CRLF 转换提示,无 whitespace error。 ### Deferred final verification - 阶段 2 按用户确认不运行 Maven live E2E,不启动应用,不检查 `logs/`,不查询数据库。 - 上述端到端、日志和 `scripts/query_mysql.py` 数据库核验统一保留到阶段 5 全部实现完成后执行。