docs(openspec): archive stategraph design freeze

This commit is contained in:
zhuyongxin
2026-07-17 10:24:13 +08:00
parent a36fe72639
commit 581daffdad
15 changed files with 1167 additions and 57 deletions
@@ -0,0 +1,3 @@
ready_at: 2026-07-17
devflow: devflow/projects/2026-07-17-chat-diagnosis-stategraph-design-freeze
authorization: user-requested-per-stage-archive
@@ -0,0 +1,3 @@
committed_at: 2026-07-17
scope: iss-011-stage-0-design-freeze
validation: openspec-strict-pass
@@ -0,0 +1,226 @@
## Context
复杂 Chat 当前由 `ChatController -> ChatService.executeChatWithStrategy -> executeChatComplex` 驱动。`executeChatComplex` 同时负责 Run 生命周期、外层 LOW_CONFID round、`SequentialAgent` 构造、Verifier 解析、Composer、Fallback、持久化和评估;`VerifierInputHook` 又解析 Executor 输出、读取当前 Run 工具摘要、执行 `ExecutorGatekeeperService` 并通过 `VerifierContextHolder` 回传隐式状态。这些职责形成无法精确表达失败恢复位置、条件边和审计路径的隐式状态机。
阶段 0 不改变运行时,只冻结后续五个独立 change 必须遵守的架构契约。当前 change 的运行时影响为 L1;冻结目标最终涉及状态机语义、数据库与 Trace API,属于 L4。
| 区域 | 当前职责 | 冻结后的职责 |
|---|---|---|
| `ChatController` | 调用 ChatService | 请求/响应协议不变 |
| `ChatService` | Run 生命周期和细粒度隐式状态机 | 只维护 Run 生命周期并调用 Graph orchestrator |
| `SequentialAgent` | 固定跨 Agent 顺序 | 不再用于复杂 Chat 编排 |
| `VerifierInputHook` / `VerifierContextHolder` | 隐式 Gatekeeper、输入构造和跨层回传 | Gatekeeper/投影迁入显式 Node;旧隐式入口删除 |
| `ExecutorGatekeeperService` | 确定性 binding 校验 | 原规则复用,由显式 Gatekeeper Node 单次调用 |
| `DiagnosisRun` / `DiagnosisTraceService` | Run 与 self evaluation 聚合 | 增加 run-scoped orchestration trace |
## Goals / Non-Goals
**Goals:**
- 冻结最小 Graph State 的字段、所有权和更新策略。
- 冻结完整、有界且可终止的条件边与 retry 语义。
- 冻结 verified-input、Fallback、Run 状态与审计安全边界。
- 冻结旧测试替换范围和后续五个独立 change 的交付边界。
- 提供可被后续 OpenSpec Commit gate 机械对照的设计基线。
**Non-Goals:**
- 本 change 不实现或编译任何 Java/SQL/Prompt/配置变更。
- 不修改当前主运行时 specs 来宣称 StateGraph 已上线。
- 不运行 Maven E2E、日志或数据库验收。
- 不引入 SupervisorAgent、持久 Checkpointer、HITL、并行执行或 AIOps 公共 Graph。
- 不保留 Sequential/StateGraph 双轨开关。
## Decisions
### 1. StateGraph 只拥有跨节点控制状态
StateGraph 负责顺序、条件边、重试、终止和降级;现有 ReactAgent 继续完成语义任务;Gatekeeper、verified-input builder、evidence retry prepare 和固定 Fallback 使用确定性 Java Node。
替代方案:
- 继续在 ChatService 外层叠加 if/for:无法精确恢复失败节点和审计条件边,拒绝。
- 使用 SupervisorAgent:固定诊断 Pipeline 不需要动态选择专科 Agent,拒绝。
- 直接把父 State 交给 `ReactAgent.asNode(...)`:存在 messages/outputKey/私有状态泄漏风险,首版拒绝。
### 2. 最小 Graph State
默认 Replace;只有有界 `orchestration_events` 使用 Append。
| 字段 | 所有者/用途 | 策略 |
|---|---|---|
| `diagnosis_context` | query、history、sessionId、runId | Replace |
| `planner_plan` | Planner 结构化计划 | Replace |
| `planner_status` | COMPLETED / INVALID_OUTPUT / RETRYABLE_FAILED / NON_RETRYABLE_FAILED | Replace |
| `planner_retry_count` | 当前 Planner 阶段技术重试次数 | Replace |
| `planner_mode` | NORMAL / EVIDENCE_GAP_ONLY | Replace |
| `executor_output` | 完整 `executor_evidence_v2` | Replace |
| `executor_status` | COMPLETED / INVALID_OUTPUT / TOOL_BLOCKED / FAILED | Replace |
| `gatekeeper_result` | 原始确定性校验结果 | Replace |
| `gatekeeper_status` | PASS / LOW_CONFID / REJECT | Replace |
| `verified_executor_output` | 只保留通过 binding 的 claim 投影 | Replace |
| `verified_evidence` | 从通过 binding 的 `matched_text` 构造 | Replace |
| `verified_binding_count` | 当前可信 binding 数 | Replace |
| `verifier_verdict_ceiling` | PASS 或 LOW_CONFID | Replace |
| `verifier_output` | Verifier 结构化结果 | Replace |
| `verifier_status` | COMPLETED / INVALID_OUTPUT / RETRYABLE_FAILED / NON_RETRYABLE_FAILED | Replace |
| `verifier_retry_count` | 固定 verified input 技术重试次数 | Replace |
| `verifier_model_verdict` | 模型 PASS / LOW_CONFID / REJECT | Replace |
| `effective_verdict` | 应用 Gatekeeper ceiling 后的 verdict | Replace |
| `composer_output` | Composer 结构化输出 | Replace |
| `composer_status` | COMPLETED / INVALID_OUTPUT / RETRYABLE_FAILED / NON_RETRYABLE_FAILED | Replace |
| `composer_retry_count` | 固定安全输入技术重试次数 | Replace |
| `evidence_retry_count` | 诊断补证据轮次 | Replace |
| `retry_context` | evidence gaps、prior verified data、completed queries、约束 | Replace |
| `orchestration_events` | 每个 node attempt 的有界终态事件 | Append |
| `final_answer` | 最终安全用户表达 | Replace |
| `failure_reason` | 确定性失败 reason code | Replace |
不保存 Prompt、模型思考、完整工具原文、完整 Graph State 快照或其他 Run 数据。
### 3. 完整路由矩阵
| From | Outcome / Guard | To | 计数与约束 |
|---|---|---|---|
| START | always | Planner | Planner 阶段 retry count=0 |
| Planner | COMPLETED | Executor | 不增加 retry |
| Planner | INVALID_OUTPUT / RETRYABLE_FAILED 且 count=0 | Planner | 同业务输入重试一次,count=1 |
| Planner | NON_RETRYABLE_FAILED 或技术重试耗尽 | Fallback | 不执行后续 Agent |
| Executor | COMPLETED | Gatekeeper | 合法 no-evidence 也属于 COMPLETED |
| Executor | INVALID_OUTPUT / TOOL_BLOCKED / FAILED | Fallback | Executor 永不重试 |
| Gatekeeper | PASS | Verified Input Builder | ceiling=PASS |
| Gatekeeper | LOW_CONFID 且 verified binding > 0 | Verified Input Builder | ceiling=LOW_CONFID |
| Gatekeeper | REJECT、未知状态或 LOW_CONFID 且 binding=0 | Fallback | 不执行 Verifier |
| Verified Input Builder | completed | Verifier | 只投影通过 binding |
| Verifier | INVALID_OUTPUT / RETRYABLE_FAILED 且 count=0 | Verifier | 相同 verified input 重试一次 |
| Verifier | NON_RETRYABLE_FAILED 或技术重试耗尽 | Fallback | 不输出 Executor claim |
| Verifier | PASS / REJECT | Composer | 使用 effective verdict |
| Verifier | LOW_CONFID,非 ceiling 导致,存在有效 gaps,evidence count=0 | Prepare Evidence Retry | evidence count 增加一次 |
| Verifier | LOW_CONFID 且任一补查条件不满足 | Composer | 不补查 |
| Prepare Evidence Retry | completed | Planner | mode=EVIDENCE_GAP_ONLY;新 Planner 阶段 retry count 重置 |
| Composer | COMPLETED | END | 返回 Composer 安全表达 |
| Composer | INVALID_OUTPUT / RETRYABLE_FAILED 且 count=0 | Composer | 相同 allowed material 重试一次 |
| Composer | NON_RETRYABLE_FAILED 或技术重试耗尽 | Fallback | 可使用 Verifier 已允许材料 |
| Fallback | deterministic answer produced | END | degraded=true |
| 未处理异常/持久化失败/无法生成安全答案 | failure | outer failure handling | Run=FAILED,best-effort 保存已有 events |
Graph compile 必须设置 recursion limit 作为最终保险;业务循环仍由独立计数显式限制。
### 4. 四类计数互相独立
- `planner_retry_count`:每次进入 Planner 阶段最多一次;evidence retry 重新进入时重置。
- `verifier_retry_count`:同一 verified input 最多一次。
- `composer_retry_count`:同一 allowed material 最多一次。
- `evidence_retry_count`:整个 Run 最多一次。
技术重试不增加 evidence retry,也不得重新执行前序节点或工具。
### 5. Executor 状态按输出契约定义
合法 `executor_evidence_v2`(包括 no-evidence、空查询结果或工具限制说明)均为 COMPLETED。只有工具层明确禁止且没有合法结构时为 TOOL_BLOCKED;空/非法结构为 INVALID_OUTPUT;其他未形成合法结构的异常为 FAILED。只有 COMPLETED 进入 Gatekeeper,其余直接 Fallback 且不重试。
补证据轮只执行增量查询,但输出包含应保留 prior verified claims 的完整快照;Java 不做 claim 文本语义合并,完整快照重新经过 Gatekeeper。
### 6. Gatekeeper 与 Verifier 输入边界
Gatekeeper 保留原始结果并 fail-closed 标准化为 PASS / LOW_CONFID / REJECT;未知、缺失或无法识别结果映射为 REJECT。
PASS 与可继续 LOW_CONFID 都经过 Verified Input Builder。Builder 复用 `checked_bindings`,仅从通过项投影 `claim_id`、`source_invocation_id`、`tool_name`、`raw_path`、`matched_text`;不得传递完整 `tool_trace_summary`、失败 binding 或 Executor 自由文本。LOW_CONFID ceiling 不得被模型 PASS 提升。
### 7. 两类安全 Fallback
**前置验证失败:** Planner/Executor/Verifier 无法形成可信材料,或 Gatekeeper REJECT/零可信 binding。固定表达只包含校验状态、工具执行概况、诊断限制和人工查看 Trace 建议,不含任何 Executor claim。
**Composer 后置降级:** 已有 Verifier 允许材料,但 Composer 技术重试耗尽。确定性模板可以使用 allowed claims/missing info/recommended actions,仍不得读取 raw output。
成功生成安全答案时 Run=SUCCESS,并用 verdict 或 `orchestrationTrace.degraded=true` 表达质量;只有未处理异常、持久化失败或无法生成安全答案时为 FAILED,不新增 DEGRADED 状态。
### 8. Run-scoped 编排审计
每个 Node attempt 最多追加一个 `{node,outcome,reason_code,attempt}` 终态 event。按事件顺序压缩为 version、transitions、final_node、termination_reason、degraded、evidence_retry_count。
只持久化到当前 `diagnosis_run.orchestration_trace`;`RunnableConfig.threadId=runId`。Trace API 只在 `run.orchestrationTrace` 返回解析对象,不复制到顶层/session/raw 字段。它不替代 self evaluation、AgentStep、ToolInvocation 或 Graph checkpoint。
### 9. 测试替换边界
| 测试 | 处理 |
|---|---|
| `ChatServiceSequentialAgentTest` | 用 Graph 路由、Node 契约和 Chat 集成测试替换;删除固定顺序断言 |
| `VerifierInputHookTest` | 删除或改写为显式 Gatekeeper/Input Builder 契约测试 |
| `ExecutorGatekeeperServiceTest` | 保留并扩展 checked binding 与未知状态 fail-closed |
| `ChatControllerTest` | 保留,证明 `/api/chat` 兼容 |
| `DiagnosisTraceServiceTest` / Repository tests | 保留并扩展 run-scoped orchestration trace |
| Eval/Composer 安全测试 | 保留,证明 allowed-material、no-evidence 和 REJECT 不退化 |
阶段 0 无运行时行为,不新增单元测试。阶段 1–4 按风险建立上述测试;阶段 5 统一执行 Maven E2E、日志和数据库验收。
### 10. 六个独立 OpenSpec change
| 阶段 | Change | 唯一交付边界 |
|---|---|---|
| 0 | `chat-diagnosis-stategraph-design-freeze` | 冻结本设计,不改运行时 |
| 1 | `chat-diagnosis-stategraph-routing-skeleton` | Graph State、拓扑、Fake Node 路由与 trace builder |
| 2 | `chat-diagnosis-stategraph-real-nodes` | Agent Adapter、Gatekeeper、verified input、retry prepare、Fallback |
| 3 | `chat-diagnosis-stategraph-chatservice-cutover` | ChatService 生产入口、DB migration、Run/Trace API |
| 4 | `chat-diagnosis-stategraph-test-suite` | 新测试体系与旧测试替换 |
| 5 | `chat-diagnosis-stategraph-cleanup-docs` | 旧编排清理、最终回归、Maven E2E、日志/DB、文档 |
后续 change 必须先读取阶段 0 archive;若发现设计不准,必须在当阶段 OpenSpec 中显式记录和解决。
## Interface Impact
### Classification
- 当前阶段 0 change:L1。只交付设计、术语和决策档案,不改变运行时。
- 最终冻结目标:L4。状态机语义和 Run 终态判断变化,Trace API 与数据库契约扩展,旧内部调用路径将被删除。
### Changed contracts and consumers
| 契约 | 目标变化 | 消费者 |
|---|---|---|
| `/api/chat` | 请求/响应结构保持不变,内部路径改由 Graph 驱动 | ChatController、前端/demo 客户端 |
| Agent 输出协议 | `executor_evidence_v2`、Verifier、Composer 输出保持不变 | Agent adapters、Eval |
| Verifier 输入 | 改为 `verified_executor_output + verified_evidence`,不再提供完整 tool trace | Verifier adapter、Prompt binding |
| Run 状态 | 安全 Fallback 为 SUCCESS + degraded;只有无法安全响应的未处理失败为 FAILED | Trace、Feedback、Eval、运维审计 |
| Trace API | 仅 `run.orchestrationTrace` 新增解析对象 | Trace DTO/Service、demo 脚本、Trace UI |
| 数据库 | 仅新增 nullable JSON `diagnosis_run.orchestration_trace` | Flyway、DiagnosisRun repository |
| 内部编排 | 删除复杂 Chat Sequential、外层 round、Gatekeeper-in-Hook/ThreadLocal 入口 | ChatService、Hook、测试 |
### Compatibility, migration, and rollback
- 兼容消费者不需要修改 `/api/chat` 调用;Trace 消费者按加法字段处理。
- 新 StateGraph Chat Run 必须写非空 orchestration trace;历史 Run 不回填、不增加兼容读取。
- 数据库迁移先加 nullable 列,再切换代码;nullable 只服务于安全部署,不降低新 Run 应用契约。
- 每阶段可 Git revert;阶段 3 后回滚代码时允许保留无害 nullable 列。
- 不以 feature flag 或配置恢复长期双轨;若切换失败,回滚完整阶段提交。
### Interface acceptance
- Controller 契约测试证明 `/api/chat` 不变。
- Node/集成测试证明 Verifier 输入与安全 Fallback 边界。
- Repository/Trace 测试证明 run ownership 和唯一 API 投影。
- 阶段 5 Maven E2E、`logs/` 和数据库查询证明跨层最终行为。
## Risks / Trade-offs
- [阶段性 spec 与运行时差异] 阶段 0 只新增设计基线 capability,不修改运行时 specs。
- [六个 change 漂移] 每个 Discover/Commit gate 强制引用阶段 0 archive。
- [Graph API 漂移] 后续只使用本地 `1.1.2.0` JAR 已验证签名,并由阶段 1 编译测试锁定。
- [Gatekeeper 双执行] 阶段 2 迁移显式 Node,阶段 5 删除旧 Hook/ThreadLocal,不形成长期双轨。
- [安全降级泄漏] Fallback 输入类型分离并用 Node/集成测试证明。
- [Trace 无限增长或泄密] event 每 attempt 一条,受业务次数与 recursion limit 限制,字段白名单禁原文。
## Migration Plan
1. 阶段 0 archive 本设计基线并提交。
2. 阶段 1 引入未接生产入口的 Graph 骨架和路由测试。
3. 阶段 2 接入真实节点但不切换 ChatService。
4. 阶段 3 切换 ChatService,增加 nullable JSON 列和 run Trace 投影。
5. 阶段 4 用新测试体系覆盖路由和安全契约。
6. 阶段 5 删除旧编排并执行最终 Maven E2E、`logs/` 与数据库验收。
回滚按阶段 Git revert。阶段 3 后回滚运行时代码时允许保留 nullable 列;不通过配置重新启用长期双轨。历史 Run 不回填。
## Open Questions
无。若后续发现本设计与锁定 API 或安全契约冲突,必须在当阶段 sm-flow 中分类并按门禁处理。
@@ -0,0 +1,77 @@
# Chat Diagnosis StateGraph Design Freeze
## Why
ISS-011 将复杂 Chat 诊断从 `SequentialAgent + ChatService` 隐式状态机迁移到 Spring AI Alibaba `StateGraph`。在进入任何运行时代码实现前,需要先把跨节点状态、全部条件边、有限重试、安全降级、审计边界和旧测试替换范围冻结为单一、可引用的设计契约,避免后续五个独立 sm-flow 对同一行为产生不同解释。
## What Changes
本 change 只交付阶段 0 的设计冻结:
- 冻结最小 Graph State 及 Replace/Append 更新策略。
- 冻结 Planner、Executor、Gatekeeper、Verifier、Composer、Evidence Retry、Fallback 的全部条件边和终止路径。
- 冻结 Planner/Verifier/Composer 技术重试与 evidence retry 的独立计数和最大次数。
- 冻结 Gatekeeper 后的 Verifier 白名单输入、安全 Fallback 和 Run 状态语义。
- 冻结 `orchestration_events -> diagnosis_run.orchestration_trace -> run.orchestrationTrace` 的审计边界。
- 冻结旧 Sequential 测试的替换范围和必须保留的安全回归边界。
- 形成供阶段 1–5 各自独立 OpenSpec change 引用的长期决策记录。
本 change 不修改 Java、SQL、Prompt、配置或运行时行为。
## Capabilities
### New Capabilities
- `chat-diagnosis-stategraph-design-freeze`:为阶段 1–5 提供版本化、可审计的 StateGraph 设计基线,覆盖状态、路由、重试、安全降级、审计和测试迁移边界。
### Modified Capabilities
- 无。当前运行时 capabilities 只在对应实现阶段修改,避免阶段 0 归档后主规格提前宣称代码已切换。
## Scope
### In Scope
- `mvp/issues/active/ISS-011-chat-diagnosis-stategraph-orchestration.md` 中阶段 0 的设计结论。
- `devflow/glossary/CONTEXT.md` 中 Diagnosis Orchestration Trace 和 Verifier verified-evidence 边界。
- 阶段 0 的 OpenSpec 设计、设计验收 spec、可执行文档任务和 devflow/ADR 档案。
- 对最终目标的 L4 接口影响、迁移、回滚、兼容性与消费者边界做设计级记录。
### Out of Scope
- 创建 StateGraph、Node、Adapter、路由或测试代码。
- 修改 ChatService、Hook、Gatekeeper、Agent、Prompt 或工具。
- 数据库迁移和 Trace DTO/API 修改。
- 运行 Maven E2E、日志核验或数据库核验。
- 把阶段 1–5 的实现任务放入本 change。
- SupervisorAgent、持久 Checkpointer、HITL、并行 Agent/工具或 AIOps 公共 Graph。
## Context Constraints
- `runId` 是一次 Diagnosis Run 与 Trace 的所有权边界;编排摘要不得写入 session 级数据。
- Gatekeeper 引用真实性检查和 `checked_bindings` 是 verified evidence 的唯一事实来源,不得在 Verifier Input Builder 重复实现另一套验真规则。
- Composer 只能消费 Verifier 允许材料;前置验证失败的固定 Fallback 不得泄漏 Executor claim。
- `/api/chat`、`executor_evidence_v2`、Verifier 输出协议和 Composer 输出协议保持兼容。
- 最终 Trace API 只在 `run.orchestrationTrace` 增加解析对象;数据库只新增 nullable JSON `diagnosis_run.orchestration_trace`。
- 不保留长期 Sequential/StateGraph 双轨或运行时切换开关。
- 锁定依赖版本 `spring-ai-alibaba-graph-core:1.1.2.0` 已通过本地 JAR API 核验,后续实现不得使用未经锁定版本验证的示例签名。
## Acceptance
- 最小 Graph State 中每个字段都有所有权、用途和更新策略。
- 每个节点状态都有唯一条件边;所有循环均有显式上限和终止路径。
- Planner、Verifier、Composer 技术重试各自最多一次,且与最多一次 evidence retry 分开计数。
- Executor 不重试;Gatekeeper REJECT 与零可信 binding 直接进入不泄漏 claim 的固定 Fallback。
- PASS 与可继续的 LOW_CONFID 都经过 verified-input builder;Verifier 不接收完整 `tool_trace_summary`。
- `orchestration_trace`、`self_evaluation`、`agent_step`、`tool_invocation` 和 Graph checkpoint 的职责不重叠。
- 旧测试替换清单明确区分应替换的实现测试与必须保留/扩展的契约测试。
- 不存在“待讨论决策”、未定义循环或没有终止路径的分支。
- 本阶段无运行时变化,因此不新增或运行单元测试;使用 OpenSpec strict validation、结构检查与文档一致性检查验收。
## Risks
- 阶段 0 只冻结设计,主分支运行时仍是 Sequential;后续阶段不得把设计文档状态误认为已实现状态。
- 六个独立 changes 可能发生契约漂移;每个后续 Discover 必须读取本 change 的 archive 和 devflow 决策,并在 Commit gate 对照冻结契约。
- 现有主 OpenSpec 仍描述旧 `tool_trace_summary` 和外层 LOW_CONFID round;只有对应运行时切换阶段才能修改并归档这些运行时 specs。
- 最终设计属于 L4 影响;阶段 0 必须记录迁移/回滚,但不能以文档完成替代后续代码和最终 E2E 证据。
@@ -0,0 +1,121 @@
## ADDED Requirements
### Requirement: StateGraph design baseline SHALL be versioned and authoritative
The project SHALL maintain an archived ISS-011 design baseline that defines Graph State, routing, retry limits, fallback classes, audit boundaries, migration stages, and test replacement scope without claiming runtime cutover is complete.
#### Scenario: Later stage starts implementation
- **WHEN** an ISS-011 stage 1–5 OpenSpec change is proposed
- **THEN** its context and design SHALL reference the archived stage 0 baseline
- **AND** any intentional deviation SHALL be resolved through that stage's OpenSpec before implementation
#### Scenario: Stage zero is accepted
- **WHEN** the design-freeze change is archived
- **THEN** no Java, SQL, Prompt, configuration, or runtime behavior SHALL have been changed by this change
- **AND** runtime specs SHALL NOT claim StateGraph cutover is already implemented
### Requirement: Graph State design SHALL use explicit bounded control state
Every cross-node field SHALL have one purpose, owner, and update strategy. Fields SHALL use Replace semantics except bounded `orchestration_events`, which SHALL use Append.
#### Scenario: Node state is designed
- **WHEN** an Agent or Java Node reads or writes parent Graph State
- **THEN** its allowed input projection and output fields SHALL be explicit
- **AND** Prompt text, model reasoning, complete tool output, and complete State snapshots SHALL NOT be control state
#### Scenario: Orchestration event is designed
- **WHEN** a node attempt reaches a handled terminal outcome
- **THEN** at most one event SHALL be appended for that attempt
- **AND** it SHALL contain only stable node, outcome, reason code, and attempt data
### Requirement: Routing design SHALL be complete and terminating
Every Planner, Executor, Gatekeeper, Verifier, Composer, evidence-retry, and Fallback outcome SHALL map to one next node or terminal result. Every loop SHALL have an explicit business limit and the Graph SHALL use a recursion limit.
#### Scenario: Technical retry is eligible
- **WHEN** Planner, Verifier, or Composer first returns INVALID_OUTPUT or RETRYABLE_FAILED with the same allowed input
- **THEN** only that node SHALL be retried once
- **AND** no preceding Agent, Gatekeeper, or tool SHALL be rerun
#### Scenario: Technical retry is exhausted
- **WHEN** Planner, Verifier, or Composer returns NON_RETRYABLE_FAILED or exhausts its retry
- **THEN** the route SHALL terminate through the defined safe Fallback
- **AND** no unbounded loop SHALL remain
#### Scenario: Executor cannot produce a legal contract
- **WHEN** Executor returns INVALID_OUTPUT, TOOL_BLOCKED, or FAILED without legal `executor_evidence_v2`
- **THEN** the route SHALL go directly to pre-verification Fallback
- **AND** Executor SHALL NOT be retried
#### Scenario: Evidence retry is eligible
- **WHEN** effective verdict is LOW_CONFID, it was not caused by Gatekeeper ceiling, valid evidence gaps exist, and the Run has not retried evidence
- **THEN** one EVIDENCE_GAP_ONLY retry SHALL return to a new Planner stage
- **AND** technical retry counters SHALL remain independent from evidence retry count
### Requirement: Verified evidence and fallback boundaries SHALL fail closed
PASS and eligible LOW_CONFID Gatekeeper outcomes SHALL pass through a verified-input builder. Verifier SHALL receive only claims and evidence projected from passed checked bindings, not complete `tool_trace_summary` or unverified Executor text.
#### Scenario: Gatekeeper result is unsafe or unknown
- **WHEN** Gatekeeper returns REJECT, unknown, or LOW_CONFID with zero verified bindings
- **THEN** the route SHALL enter pre-verification Fallback without Verifier
- **AND** the final answer SHALL NOT contain any Executor claim
#### Scenario: Gatekeeper permits verification
- **WHEN** Gatekeeper returns PASS or eligible LOW_CONFID
- **THEN** the builder SHALL project evidence only from passed bindings
- **AND** a LOW_CONFID ceiling SHALL NOT be upgraded to PASS
#### Scenario: Composer fails after verification
- **WHEN** Composer exhausts retry after receiving Verifier-allowed material
- **THEN** deterministic fallback MAY use only that allowed material
- **AND** it SHALL NOT read raw Executor or tool output
### Requirement: Orchestration audit design SHALL preserve Run ownership
Orchestration audit SHALL remain separate from self evaluation, AgentStep, ToolInvocation, and Graph checkpoint data. A compact summary SHALL be derived from bounded events and persisted only to the current Run.
#### Scenario: A safe response is produced
- **WHEN** Graph reaches Composer or handled Fallback and produces a safe answer
- **THEN** Run status SHALL be SUCCESS
- **AND** degradation SHALL be represented by verdict or `orchestrationTrace.degraded`
#### Scenario: Trace is exposed
- **WHEN** an exact new StateGraph Chat Run is queried
- **THEN** parsed audit SHALL appear only at `run.orchestrationTrace`
- **AND** it SHALL NOT be duplicated at top level, session projection, or raw field
#### Scenario: Audit ownership is evaluated
- **WHEN** events or summaries are persisted
- **THEN** `runId` SHALL be the ownership and Graph thread boundary
- **AND** no data SHALL include Prompt, reasoning, complete tool output, or another Run
### Requirement: Test migration design SHALL preserve safety behavior
The baseline SHALL identify Sequential/Hook implementation tests to replace and public/security contract tests to retain or extend. Fixed Agent call order SHALL NOT remain a correctness criterion.
#### Scenario: Old tests are replaced
- **WHEN** StateGraph tests become authoritative
- **THEN** `ChatServiceSequentialAgentTest` SHALL be replaced by route, node-contract, and Chat integration coverage
- **AND** `VerifierInputHookTest` SHALL be removed or rewritten for explicit nodes
#### Scenario: Safety tests are retained
- **WHEN** the new suite is assembled
- **THEN** Gatekeeper, Controller, Run/Trace, Repository, Composer, no-evidence, REJECT, and Eval safety contracts SHALL remain covered
- **AND** fixed-order-only assertions SHALL be removed
@@ -0,0 +1,15 @@
## 1. Freeze Source Documents
- [x] 1.1 Compare ISS-011 sections 3–14 against the committed state, routing, retry, fallback, audit, and test-migration design; resolve every drift without editing runtime code.
- [x] 1.2 Verify `devflow/glossary/CONTEXT.md` defines Diagnosis Orchestration Trace and the Verifier verified-evidence boundary without implementation-detail leakage.
## 2. Record Durable Architecture Decisions
- [x] 2.1 Create a project ADR that records the StateGraph control boundary, explicit Gatekeeper Node, run-scoped orchestration trace, rejected alternatives, compatibility, migration, and rollback decisions.
- [x] 2.2 Record the six independent sm-flow handoff boundaries and require stages 1–5 to reference the archived stage 0 baseline.
## 3. Validate The Design Freeze
- [x] 3.1 Run strict OpenSpec validation and cross-artifact checks for proposal, design, specs, and tasks; resolve every validation or alignment gap.
- [x] 3.2 Verify the stage 0 diff contains no Java, SQL, Prompt, configuration, or runtime behavior changes.
- [x] 3.3 Record that unit tests and Maven E2E are intentionally not run because stage 0 changes only design artifacts; reserve Maven E2E, logs, and database evidence for stage 5.
@@ -0,0 +1,124 @@
# chat-diagnosis-stategraph-design-freeze Specification
## Purpose
为 ISS-011 阶段 1–5 提供已归档、可审计的 StateGraph 设计基线,规范跨节点状态、条件边、有限重试、安全降级、Run 级编排审计和测试迁移边界,同时明确阶段 0 不代表运行时已经切换。
## Requirements
### Requirement: StateGraph design baseline SHALL be versioned and authoritative
The project SHALL maintain an archived ISS-011 design baseline that defines Graph State, routing, retry limits, fallback classes, audit boundaries, migration stages, and test replacement scope without claiming runtime cutover is complete.
#### Scenario: Later stage starts implementation
- **WHEN** an ISS-011 stage 1–5 OpenSpec change is proposed
- **THEN** its context and design SHALL reference the archived stage 0 baseline
- **AND** any intentional deviation SHALL be resolved through that stage's OpenSpec before implementation
#### Scenario: Stage zero is accepted
- **WHEN** the design-freeze change is archived
- **THEN** no Java, SQL, Prompt, configuration, or runtime behavior SHALL have been changed by this change
- **AND** runtime specs SHALL NOT claim StateGraph cutover is already implemented
### Requirement: Graph State design SHALL use explicit bounded control state
Every cross-node field SHALL have one purpose, owner, and update strategy. Fields SHALL use Replace semantics except bounded `orchestration_events`, which SHALL use Append.
#### Scenario: Node state is designed
- **WHEN** an Agent or Java Node reads or writes parent Graph State
- **THEN** its allowed input projection and output fields SHALL be explicit
- **AND** Prompt text, model reasoning, complete tool output, and complete State snapshots SHALL NOT be control state
#### Scenario: Orchestration event is designed
- **WHEN** a node attempt reaches a handled terminal outcome
- **THEN** at most one event SHALL be appended for that attempt
- **AND** it SHALL contain only stable node, outcome, reason code, and attempt data
### Requirement: Routing design SHALL be complete and terminating
Every Planner, Executor, Gatekeeper, Verifier, Composer, evidence-retry, and Fallback outcome SHALL map to one next node or terminal result. Every loop SHALL have an explicit business limit and the Graph SHALL use a recursion limit.
#### Scenario: Technical retry is eligible
- **WHEN** Planner, Verifier, or Composer first returns INVALID_OUTPUT or RETRYABLE_FAILED with the same allowed input
- **THEN** only that node SHALL be retried once
- **AND** no preceding Agent, Gatekeeper, or tool SHALL be rerun
#### Scenario: Technical retry is exhausted
- **WHEN** Planner, Verifier, or Composer returns NON_RETRYABLE_FAILED or exhausts its retry
- **THEN** the route SHALL terminate through the defined safe Fallback
- **AND** no unbounded loop SHALL remain
#### Scenario: Executor cannot produce a legal contract
- **WHEN** Executor returns INVALID_OUTPUT, TOOL_BLOCKED, or FAILED without legal `executor_evidence_v2`
- **THEN** the route SHALL go directly to pre-verification Fallback
- **AND** Executor SHALL NOT be retried
#### Scenario: Evidence retry is eligible
- **WHEN** effective verdict is LOW_CONFID, it was not caused by Gatekeeper ceiling, valid evidence gaps exist, and the Run has not retried evidence
- **THEN** one EVIDENCE_GAP_ONLY retry SHALL return to a new Planner stage
- **AND** technical retry counters SHALL remain independent from evidence retry count
### Requirement: Verified evidence and fallback boundaries SHALL fail closed
PASS and eligible LOW_CONFID Gatekeeper outcomes SHALL pass through a verified-input builder. Verifier SHALL receive only claims and evidence projected from passed checked bindings, not complete `tool_trace_summary` or unverified Executor text.
#### Scenario: Gatekeeper result is unsafe or unknown
- **WHEN** Gatekeeper returns REJECT, unknown, or LOW_CONFID with zero verified bindings
- **THEN** the route SHALL enter pre-verification Fallback without Verifier
- **AND** the final answer SHALL NOT contain any Executor claim
#### Scenario: Gatekeeper permits verification
- **WHEN** Gatekeeper returns PASS or eligible LOW_CONFID
- **THEN** the builder SHALL project evidence only from passed bindings
- **AND** a LOW_CONFID ceiling SHALL NOT be upgraded to PASS
#### Scenario: Composer fails after verification
- **WHEN** Composer exhausts retry after receiving Verifier-allowed material
- **THEN** deterministic fallback MAY use only that allowed material
- **AND** it SHALL NOT read raw Executor or tool output
### Requirement: Orchestration audit design SHALL preserve Run ownership
Orchestration audit SHALL remain separate from self evaluation, AgentStep, ToolInvocation, and Graph checkpoint data. A compact summary SHALL be derived from bounded events and persisted only to the current Run.
#### Scenario: A safe response is produced
- **WHEN** Graph reaches Composer or handled Fallback and produces a safe answer
- **THEN** Run status SHALL be SUCCESS
- **AND** degradation SHALL be represented by verdict or `orchestrationTrace.degraded`
#### Scenario: Trace is exposed
- **WHEN** an exact new StateGraph Chat Run is queried
- **THEN** parsed audit SHALL appear only at `run.orchestrationTrace`
- **AND** it SHALL NOT be duplicated at top level, session projection, or raw field
#### Scenario: Audit ownership is evaluated
- **WHEN** events or summaries are persisted
- **THEN** `runId` SHALL be the ownership and Graph thread boundary
- **AND** no data SHALL include Prompt, reasoning, complete tool output, or another Run
### Requirement: Test migration design SHALL preserve safety behavior
The baseline SHALL identify Sequential/Hook implementation tests to replace and public/security contract tests to retain or extend. Fixed Agent call order SHALL NOT remain a correctness criterion.
#### Scenario: Old tests are replaced
- **WHEN** StateGraph tests become authoritative
- **THEN** `ChatServiceSequentialAgentTest` SHALL be replaced by route, node-contract, and Chat integration coverage
- **AND** `VerifierInputHookTest` SHALL be removed or rewritten for explicit nodes
#### Scenario: Safety tests are retained
- **WHEN** the new suite is assembled
- **THEN** Gatekeeper, Controller, Run/Trace, Repository, Composer, no-evidence, REJECT, and Eval safety contracts SHALL remain covered
- **AND** fixed-order-only assertions SHALL be removed