feat(graph): add diagnosis routing skeleton

This commit is contained in:
zhuyongxin
2026-07-17 11:17:13 +08:00
parent 581daffdad
commit 42ba204532
26 changed files with 2455 additions and 0 deletions
+1
View File
@@ -4,6 +4,7 @@
| 日期 | slug | 说明 | 领域 | 关键词 | 关联 OpenSpec | 状态 |
|---|---|---|---|---|---|---|
| 2026-07-17 | chat-diagnosis-stategraph-routing-skeleton | 实现未接生产入口的 Diagnosis StateGraph 骨架、有限路由和 Fake Node 测试。 | Chat diagnosis orchestration/graph | StateGraph, fake node, conditional edge, retry counter, orchestration events, trace builder | openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-routing-skeleton | archived |
| 2026-07-17 | chat-diagnosis-stategraph-design-freeze | 冻结 ISS-011 的 Graph State、条件边、有限重试、安全降级、审计和测试迁移边界。 | Chat diagnosis orchestration/design | StateGraph, runId, Gatekeeper, verified evidence, fallback, orchestration trace, test migration | openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-design-freeze | archived |
| 2026-07-10 | session-run-trace-isolation | 拆分会话态和运行态,引入 runId 隔离 Trace、Feedback、AIOps 和 demo 链路。 | Trace/session/run isolation | chat_session, diagnosis_run, runId, trace exact run, feedback fallback, AIOps SSE metadata, baseline drift | openspec/changes/archive/2026-07-10-session-run-trace-isolation | archived |
| 2026-07-09 | interview-demo-quality-audit | 增加面试演示前置质量审计,覆盖 prompt、Gatekeeper 和评测基线。 | Agent eval/demo/Prompt audit | interview demo preflight, prompt_audit, gatekeeper rules, diagnosis baseline, 12 fixtures | openspec/changes/archive/2026-07-09-interview-demo-quality-audit | archived |
@@ -0,0 +1,69 @@
# Chat Diagnosis StateGraph Routing Skeleton Acceptance
## 结果
已接受。阶段 1 完成未接生产入口的 Graph 骨架和 Fake Node 路由体系。
## 验证
### 静态验证
- 命令:`git diff --check`
- 结果:passed。
- 检查:production refs、forbidden deps、23 changed paths 白名单。
- 结果:passed,outside refs=0,forbidden refs=0,out-of-scope=0。
### 脚本验证
- 命令:`mvn -q "-Dtest=DiagnosisGraphRoutingTest,DiagnosisOrchestrationTraceBuilderTest" test`
- 结果:passed,35 tests(29 routing + 6 trace),0 failure/error。
- 覆盖:正常、三类技术 retry、Executor 不重试、Gatekeeper、evidence retry、Composer、unknown fail-closed、threadId、Append events 和 trace。
- 命令:`mvn -q "-DskipTests" test`
- 结果:passed。
- 覆盖:main/test compilation。
- 命令:`openspec validate chat-diagnosis-stategraph-routing-skeleton --type change --strict --json`
- 结果:passed,1/1。
- 命令:`openspec validate --specs --strict --json`
- 结果:passed,12/12(归档前)。
### 浏览器/人工验证
- 结果:not run。
- 原因:无 UI 或生产入口变化。
### 未验证
- Maven E2E:not run,用户要求仅阶段 5 全部实现后统一执行。
- `logs/`:not inspected,保留到阶段 5。
- 数据库:not queried,保留到阶段 5。
- 真实模型/Agent:not invoked,属于阶段 2。
## 已完成范围
- 显式 Graph Core direct dependency。
- 26 state keys、typed status、topology/route/reason constants。
- 八个 config-aware action ports 和真实 CompiledGraph factory。
- Planner/Verifier/Composer 技术计数、一次 evidence retry、recursion limit 32。
- fail-closed router、events Append 和 trace builder。
- 35 个 Fake Node/trace tests。
## 已知限制
- Skeleton 没有生产消费者,阶段 3 才切换 ChatService。
- Fake Node 只证明控制流,不证明真实 Agent JSON、Gatekeeper 或安全输入映射。
- orchestration trace 尚未持久化或通过 API 暴露。
## Bug 修复和诊断
- 架构审计发现并修正 Graph Core 传递依赖所有权,改为 BOM 管理的直接依赖。
- 自查补齐全部正常节点 threadId、Verifier REJECT 和缺失 effective verdict 场景。
## 交接
- 下一步:阶段 1 Git commit;完成后才能创建阶段 2 change。
- Delta sync:新增 `chat-diagnosis-stategraph-routing-skeleton` 主 spec,共 6 requirements。
- OpenSpec 归档确认:用户已要求每阶段 archive,授权已存在。
- OpenSpec 归档结果:已同步主 spec,并归档到 `openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-routing-skeleton/`。
@@ -0,0 +1,21 @@
# Chat Diagnosis StateGraph Routing Skeleton Brief
## 背景
- 用户目标:ISS-011 阶段 1 独立完成 Graph 骨架和 Fake Node 路由测试,archive/commit 后才能进入真实 Node 阶段。
- 当前问题:阶段 0 只有设计基线,仓库此前没有可编译 StateGraph 或条件边验证。
- 关联 OpenSpec:`openspec/changes/chat-diagnosis-stategraph-routing-skeleton/`
- devflow 分档:complex
- 前置基线:`openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-design-freeze/`
## 范围
- 本次要做:Graph Core 直接依赖、状态/枚举、config-aware action ports、deterministic router、Graph factory、有限计数、events/trace builder、Fake Node tests。
- 本次不做:真实 Agent/Gatekeeper、ChatService、Hook、DB、Trace API、旧实现清理、Maven E2E。
- 影响区域:`pom.xml`、`com.superbiz.agent.graph.diagnosis`、对应 test 包。
## OpenSpec 对齐
- proposal 覆盖状态:已覆盖 skeleton-only 目标、L2 边界、测试与 E2E 非目标。
- specs 覆盖状态:6 个 requirements 覆盖编译、Planner、Executor/Gatekeeper、Verifier、Composer、trace。
- tasks 覆盖状态:12/12 完成。
@@ -0,0 +1,112 @@
# Chat Diagnosis StateGraph Routing Skeleton Decisions
## Question Pool
| # | 维度 | 问题 | 模式 | 状态 |
|---|---|---|---|---|
| Q1 | 术语 | 阶段 1 的 Graph State、event、trace 含义从哪里继承? | evidence-driven | 已解决 |
| Q2 | 边界 | 阶段 1 是否接入 ChatService 或真实 Agent/Service? | evidence-driven | 已解决 |
| Q3 | 技术 | 锁定 1.1.2.0 是否支持所需 Node/Edge、策略和 recursion limit? | evidence-driven | 已解决 |
| Q4 | 技术 | Node action port 是否需要 RunnableConfig? | evidence-driven | 已解决 |
| Q5 | 验收 | 阶段 1 是否有必要添加单元测试? | evidence-driven + user rule | 已解决 |
| Q6 | 接口 | 新骨架的接口影响等级与消费者是什么? | evidence-driven | 已解决 |
| Q7 | 循环 | recursion limit 应取多少,是否替代业务计数? | evidence-driven | 已解决 |
| Q8 | 阶段 | 是否在本 change 实现真实 nodes、DB、Trace API 或旧代码清理? | user-interview(已由六阶段口径确认) | 已解决 |
## Evidence-driven
| 结论 | 证据来源 | 是否已汇报用户 |
|---|---|---|
| 阶段 1 必须完整继承阶段 0 baseline | archived design/spec/ADR | 已汇报 |
| 本阶段只做 Fake Node 骨架,不接真实模型 | ISS-011 阶段 1/2 边界 | 已汇报 |
| 1.1.2.0 支持 AsyncNodeActionWithConfig、AsyncEdgeActionWithConfig、conditional edges、Replace/Append、recursionLimit 和 threadId | 本地 JAR `javap` / `javap -c` | 已汇报 |
| AppendStrategy 将 list/collection 追加为有序列表,可用于 node terminal events | 本地 AppendStrategy bytecode | 已汇报 |
| 路由是新增行为且分支多,单元测试有必要 | 阶段 1 完成标准与用户“必要则加”规则 | 已汇报 |
| 最坏合法路径少于 20 次 Node 执行,limit 32 有安全余量 | 冻结路由矩阵的路径计数 | 已汇报 |
| 当前仓库没有 Graph 包或实现 | `rg` / package 目录核查 | 已汇报 |
| 生产代码将直接 import Graph Core,必须从传递依赖提升为 BOM 管理的直接依赖 | pom 与 dependency tree / 架构审计 | 已汇报 |
## User-interview
| 问题原文 | 用户原话 | 确认状态 | OpenSpec 回写 |
|---|---|---|---|
| 阶段 1 是否应独立执行 sm-flow? | “iss-011里每个阶段,都是一个sm-flow” | 已确认 | 本 change 独立边界 |
| 阶段 1 是否执行 E2E? | “端到端只在最后阶段全部完成后才验证” | 已确认 | Out of Scope / Acceptance |
| 阶段 1 是否添加单元测试? | “如果有必要添加单元测试验收的话,就加” | 已确认规则;本阶段判定必要 | Acceptance |
| 是否可提前实现阶段 2–5? | “每个阶段需要归档完并提交才能进入下一个阶段” | 已确认不可提前 | Out of Scope |
## Context And Handoff
- 前置 archive:`openspec/changes/archive/2026-07-17-chat-diagnosis-stategraph-design-freeze/`
- 前置 commit:`581daff`
- 当前 change:`chat-diagnosis-stategraph-routing-skeleton`
- 后续 change:`chat-diagnosis-stategraph-real-nodes`,只能在本阶段 archive + commit 后创建。
## Technical Decisions
### Package and API
- 新包:`com.superbiz.agent.graph.diagnosis`。
- `pom.xml` 显式声明 Graph Core,版本继续由现有 BOM 管理。
- Graph 工厂接收 config-aware Node action ports,不依赖 Spring Bean 或真实 Agent。
- Fake actions 只放 `src/test`。
- 状态读取集中在 typed helper/router,避免各 edge 复制字符串解析。
### Retry ownership
- Planner/Verifier/Composer Node wrapper 根据进入节点前的上次技术失败状态增加各自 retry count。
- 第一次失败时 count=0,允许 self-loop;重入后 count=1,第二次失败直接 Fallback。
- Evidence Retry Node 将 run-level evidence count 增加一次并重置 planner retry count。
- Edge 只选择 route,不隐式修改状态。
### Event and trace
- 每个 Fake/后续真实 Node 返回一个 event list,AppendStrategy 负责累积。
- event 包含 node/outcome/reasonCode/attempt,不包含 payload。
- trace builder 由相邻 events 生成 transition;final node/reason 来自最后 event。
- events 为空时拒绝构造 trace,避免伪造路径。
### Interface impact
- 等级:L2 internal interface。
- 新消费者:阶段 2 Node adapters、阶段 3 ChatService orchestrator、阶段 4 tests。
- 外部 API/DB/运行路径:无变化。
- 回滚:revert 本阶段提交即可;因为未接生产入口,没有数据迁移。
- 兼容:后续 action adapters 必须实现已冻结 ports,不得传递父 State 全量数据。
## Risks Accepted
- Stage 1 skeleton 会暂时存在但未被生产调用,这是阶段边界要求,不是死代码最终状态。
- 真实 Agent 状态映射尚未验证,由阶段 2 独立 change 负责。
- Maven E2E 不运行,生产路径完全未改变。
## Apply Evidence
- Task 1.1:显式声明 BOM 管理的 Graph Core;新增 26 个 state keys、状态枚举、拓扑/route/reason 常量、默认 Replace + events Append 策略和安全 typed reads。
- Task 1.2:新增不可变 event/transition/trace records,构造期拒绝空 routing metadata 和非法计数,map 输出只有冻结字段。
- Task 2.1:新增八个 non-null config-aware action ports,Fake/真实 Node 共用同一 Graph 接入面。
- Task 2.2:新增纯 router;所有未知/缺失状态 fail closed,LOW_CONFID guard 只读 facts_checked,不构造 retry context。
- Task 2.3:Graph Factory 注册八节点和全部条件边;wrapper 独占 retry/evidence control state,compile recursion limit=32。
- 首模块 Maven compile:passed(31s),锁定 1.1.2.0 API 假设成立。
- Task 3.1:trace builder 从 event 单向派生 transitions/final reason/degraded/evidence count,空或异类 events 显式失败。
- Task 4.1:新增严格 FIFO Fake Node fixture,记录 sequence/calls/threadId,每 attempt 只追加一个 terminal event,意外调用立即失败。
- Task 4.2:真实 CompiledGraph normal/Planner/Executor/Gatekeeper focused tests 首轮通过(Maven exit 0,约 67s)。
- Task 4.3:Verifier/evidence/Composer 路由与独立计数测试通过(Maven exit 0,约 12s)。
- Task 4.4:routing + trace focused suite 通过(Maven exit 0,约 28s),覆盖事件顺序、degraded、map 白名单、不可变性和非法输入。
- Task 5.1:35 tests(29 routing + 6 trace)全通过;Maven test compilation、change strict 1/1、主 specs 12/12、diff check 均通过。
- Task 5.2:现有 production refs=0,新 Graph 对真实 Service/DB/Trace refs=0,23 个 changed paths 全部命中阶段白名单;Maven E2E/log/DB 按用户口径保留到阶段 5。
- Review:补齐所有正常节点 threadId 传播、Verifier REJECT→Composer 和 completed-without-verdict fail-closed 用例;增强后 focused suite exit 0。
## Cross-Artifact 对齐检查
| 上游 → 下游 | 检查内容 | 状态 |
|---|---|---|
| brief/prd → proposal | 阶段 1 目标、Fake Node 边界、测试口径和 E2E 非目标 | 已对齐 |
| proposal → 设计产物 | direct dependency、状态、ports、router、counter、trace、测试架构 | 已对齐 |
| 设计产物 → specs/tasks | 所有可观察路由、终止、安全默认和实现模块 | 已对齐 |
| specs → tasks | 编译、全路由、trace、focused tests、生产隔离检查 | 已对齐 |
Gap:无。
## Architecture Audit
输入是 run-scoped 初始 state 与 `RunnableConfig`,处理链是 CompiledGraph → config-aware action ports → deterministic router/counters,输出是最终 state 与纯路由 trace;阶段 1 没有 Controller/Service/DB 消费者。Graph State 由单次 invoke 所有,events 只由 Node append,transitions 只由 builder 派生,避免双写。阶段 2 只实现 action ports,阶段 3 才将 orchestrator 交给 ChatService,因此当前未接生产入口是刻意生命周期边界。审计发现的唯一缺口是 Graph Core 直接依赖所有权,已回写 proposal/design/tasks。与阶段 0 archive 无冲突,L2 风险可由 Fake Node CompiledGraph tests 和 revert 单提交控制。
@@ -0,0 +1,31 @@
# Chat Diagnosis StateGraph Routing Skeleton Evidence
## 证据
| 来源 | 证据 | 结论 | 是否已汇报 |
|---|---|---|---|
| 阶段 0 archive/ADR | 冻结 26 个 state keys、完整路由、四类计数、run audit | 阶段 1 实现未偏离基线 | 是 |
| 本地 Graph Core 1.1.2.0 `javap` | config-aware Node/Edge、conditional edge、recursion limit、threadId 存在 | 使用公共锁定 API 可编译 | 是 |
| AppendStrategy bytecode | list/collection 按顺序追加 | 每 Node 返回单 event list 可形成实际路径 | 是 |
| Maven compile | `mvn -q "-DskipTests" compile` exit 0 | direct dependency 和 Factory API 编译成立 | 是 |
| Fake Node CompiledGraph tests | 29 routing tests,0 failure/error | 全条件边、retry、threadId、unknown fail-closed 成立 | 是 |
| Trace tests | 6 tests,0 failure/error | transitions、degraded、map 白名单、不可变和非法输入成立 | 是 |
| Test compilation | `mvn -q "-DskipTests" test` exit 0 | 全测试源可编译 | 是 |
| OpenSpec validation | change 1/1、主 specs 12/12 strict | artifacts 与既有规格无回归 | 是 |
| 生产隔离检查 | outside Graph refs=0,Graph 对真实 Service/DB/Trace refs=0 | 阶段 1 未接生产入口 | 是 |
| Git 路径白名单 | 23 changed paths,out-of-scope=0 | 无跨阶段文件混入 | 是 |
## Evidence-driven 结论
- 结论:直接声明 Graph Core 是正确依赖所有权。
- 证据:生产代码直接 import Graph Core;依赖原先仅由 Agent Framework 传递。
- 风险:BOM 升级仍需重新跑真实 Graph tests。
- 用户确认:不需要,属于构建稳健性。
- 结论:recursion limit 32 足够且没有替代业务计数。
- 证据:最坏合法路径低于 20;第二次技术失败和第二次 LOW_CONFID tests 均终止。
- 风险:未来新增循环必须重算。
- 用户确认:不需要,冻结业务上限未变。
- 结论:单元测试必要,E2E 不必要。
- 证据:阶段新增条件边行为但未接生产入口;35 tests 直接验证 Graph。
- 风险:真实 Agent 映射仍留给阶段 2。
- 用户确认:符合用户按必要性和最终阶段 E2E 规则。