refactor(harness): freeze single-agent contracts

This commit is contained in:
zhuyongxin
2026-07-21 17:33:25 +08:00
parent 30d3296043
commit 58c39107c5
47 changed files with 2607 additions and 24 deletions
@@ -0,0 +1,36 @@
# Acceptance: single-react-design-freeze
## 实现结果
- 新增类型化 Harness contracts 和序列化契约测试。
- ISS-014 已调整为 11 个串行 changes,并补齐 Tool ID、双状态、previous turn 和安全切换决策。
- Python 查询脚本和 Spring 主配置改为环境变量 Secret。
- 集成测试和历史 handoff 中的旧 Secret 副本已删除或脱敏。
- devflow glossary 新增 Harness、EvidenceGuard、SemanticGuard、Invocation Status 和 Evidence Status。
## 静态验证
- OpenSpec strict validation:通过。
- Secret 扫描:通过,已知真实 Secret 模式零匹配。
- Diff whitespace 检查:通过。
## 脚本验证
- 4 个 contract tests:通过。
- ToolInvocationRecorder、ExecutorGatekeeperService、ChatController focused baseline:通过。
- 查询脚本缺失密码环境变量时 fail fast:通过。
## 浏览器/人工验证
- 不适用;阶段 0 未切换任何公开 UI/API。
## 未验证与后续门禁
- Provider 侧旧凭据轮换待凭据所有者完成。
- Live E2E 留到阶段 7。
- 阶段 1 只有在本 change Archive 和 Git commit 后才能开始。
## 状态
- Stage acceptance: accepted
- OpenSpec archive: authorized by standing user instruction
@@ -0,0 +1,31 @@
# Brief: single-react-design-freeze
## 背景
ISS-014 将 Chat 诊断从多 Agent、Hook、ThreadLocal 和外层重试编排收敛为单体 Diagnosis ReAct Agent、确定性 Harness 和隔离 SemanticGuard。阶段 0 先冻结后续实施共同依赖的契约和安全边界。
## 目标
- 提供可复用的 Diagnosis Draft、Knowledge Answer、Fallback、published result 和 previous turn 类型。
- 固定 framework Tool Call ID、调用生命周期和证据结果双状态。
- 固定取消、重试、no-evidence、阶段门禁和安全凭据策略。
- 保持当前公开 Chat 运行行为不变。
## 范围
- `com.superbiz.agent.harness.contract` 类型层和 focused tests。
- ISS-014 的 11 个串行 OpenSpec changes 台账。
- 主配置、查询脚本和集成测试中的明文 Secret 清理。
- OpenSpec、devflow glossary 和阶段验收基线。
## 非目标
- 不接入新 Harness、Agent 或 Guards。
- 不切换 `/api/chat`,不删除旧运行链。
- 不执行 live E2E。
## 元数据
- Scale: complex
- Parent issue: `ISS-014`
- OpenSpec: `openspec/changes/single-react-design-freeze`
@@ -0,0 +1,20 @@
# Decisions: single-react-design-freeze
## 已确认决策
- ISS-014 保留为总 Issue,实施拆成 11 个独立、串行 sm-flow changes。
- 每个 change 必须完成 Apply、阶段验收、OpenSpec Archive 和 Git commit 后才能进入下一项。
- Apply、Archive 和阶段 Git commit 已获得用户对整个目标的持续授权;仅方向性决策需要暂停。
- `tool_call_id` 使用框架协议 ID,Harness 不生成第二套 ID。
- `status=PROJECTING/READY/ERROR` 表示 invocation lifecycle;`evidence_status=EVIDENCE_FOUND/NO_EVIDENCE/ERROR` 表示结果语义。
- `NO_EVIDENCE` 只能支持限定范围的 `NEGATIVE_OBSERVATION`。
- KNOWLEDGE_QUERY 使用 answer items 绑定 `tool_call_id + document_id`,首版不进入 SemanticGuard。
- `diagnosis_run` 是 previous turn 的持久化真理源;只有最近的 `DIAGNOSIS + SUCCESS` 安全发布结果可用。
- 取消采用分层、可观测语义;同步模型调用不承诺无法证明的立即硬取消。
- 底层重试压为一次 attempt,Router/SemanticGuard 的允许重试只由 Harness 执行。
- 阶段 4 和 6A 不接管公开入口,阶段 6B 才执行原子 SSE 切换。
## 权衡
- contract types 提前落地会增加少量文件,但后续 output type、validator、持久化和 SSE 可以复用,避免多阶段字符串协议漂移。
- Provider 侧凭据轮换是外部前置,阶段 0 只证明工作树已清理,不伪造外部完成状态。
@@ -0,0 +1,25 @@
# Evidence: single-react-design-freeze
## 代码与框架证据
- `ChatController` 当前直接管理会话、模型、工具、执行和伪流式 SSE,证明公开切换必须延后到阶段 6B。
- `ChatService` 当前构建 Planner/Executor/Verifier/Composer 并依赖 ThreadLocal,证明阶段 0 只能创建无运行依赖的 contract types。
- Spring AI Alibaba `Builder` 提供 ToolInterceptor、output type、tool timeout 和调用限制扩展点;`ReactAgent` 提供 interrupt。
- Spring AI 1.1.7 `SpringAiRetryProperties` 构造器默认 `maxAttempts=10`,与 Harness 单一重试所有权冲突,阶段 2 必须压为一次底层 attempt。
- `DiagnosisRun` 当前只有通用 status 和文本 answer,不足以确定性恢复安全 previous turn,因此确认后续保存 `intent/release_outcome/published_result`。
- 历史 ISS-009 和 verifier evidence 归档证明 `NO_EVIDENCE` 只能表达限定范围内无匹配结果。
## 验证证据
- `mvn -q '-Dtest=HarnessContractTest' test`:通过。
- `mvn -q '-Dtest=ToolInvocationRecorderTest,ExecutorGatekeeperServiceTest,ChatControllerTest' test`:通过。
- `mvn -q '-Dtest=HarnessContractTest,ToolInvocationRecorderTest,ExecutorGatekeeperServiceTest,ChatControllerTest' test`:通过。
- `openspec validate single-react-design-freeze --strict`:通过。
- `git diff --check`:通过,仅有 Windows line-ending warning。
- 已知旧 Secret 模式扫描:零匹配。
- 缺少 `SUPERBIZ_MYSQL_PASSWORD` 时运行查询脚本:在连接前 fail fast,符合预期。
## 未验证
- 未运行模型、Redis、MySQL 或 Milvus live E2E;按阶段门禁留到阶段 7。
- Provider 侧旧凭据是否已经轮换无法由仓库证明,必须由凭据所有者完成,并在阶段 3C/7 前核验。