8.9 KiB
8.9 KiB
Decisions: single-react-harness-run-context
规模与入口
- 分档:complex。
- 入口:ISS-014 阶段 2;阶段 0/1 已分别由 Git commit
58c3910、4274f33固化并 Archive。 - 目标:建立后续 Tool、Agent、Guard 和入口共同依赖的显式 Harness 运行边界,不接旧 ChatService。
Context
devflow/index.md命中 design freeze、ACI contracts 和 session/run trace isolation。- 当前
SessionContextHolder、VerifierContextHolder、TokenUsageHolder使用 ThreadLocal;新 Harness 禁止复用。 - 当前 ChatService 自行生成 runId、写
diagnosis_run、执行两轮 retry loop 并在 finally 清理 ThreadLocal,职责与新 Harness 边界冲突。 DiagnosisRun.status当前是字符串PENDING/RUNNING/SUCCESS/FAILED;本阶段不修改实体或迁移,由后续应用用例映射。- Spring AI 1.1.7
SpringAiRetryProperties的配置前缀是spring.ai.retry,默认maxAttempts=10。
Question Pool
| 维度 | 问题 | 模式 | 证据与结论 | 状态 |
|---|---|---|---|---|
| 术语 | “不可变 RunContext”是否意味着预算/取消也不能变化? | evidence-driven | ISS 要求上下文不可变同时要求计数/取消/终态;采用结构不可变 record + 线程安全单 Run 状态句柄。 | 已解决并汇报 |
| 术语 | Run 与 DiagnosisRun 是否在阶段 2 直接持久化绑定? | evidence-driven | 阶段 2 只建 Core,阶段 6A 才接应用用例;本阶段生命周期为内存执行真理,不改 JPA。 | 已解决并汇报 |
| 边界 | 是否迁移旧 ThreadLocal/ChatService 调用? | evidence-driven | ISS 1109-1111 明确禁止 ThreadLocal 和旧 ChatService 临时适配;只新增零消费者 Core。 | 已解决并汇报 |
| 边界 | 取消是否承诺立即中断同步模型调用? | evidence-driven | 阶段 0 已确认分层取消;阻止后续边界并执行资源回调,不承诺不可证明的硬中断。 | 已解决并汇报 |
| 验收 | 唯一终态如何证明? | evidence-driven | atomic first-terminal-wins lifecycle,并用取消/预算/异常/成功竞态测试证明后续终态不能覆盖。 | 已解决并汇报 |
| 验收 | 异步传播如何证明不依赖 ThreadLocal? | evidence-driven | Fake Tool 在 CompletableFuture 线程只接收显式 RunContext,并验证相同 session/run/state handles。 |
已解决并汇报 |
| 技术 | 隐藏重试如何关闭? | evidence-driven | 本地依赖 SpringAiRetryProperties 证实 spring.ai.retry.max-attempts 默认 10;配置改为 1 并加配置测试。 |
已解决并汇报 |
| 技术 | 尚未校准的预算默认值如何处理? | evidence-driven | ISS 要求集中配置且不伪造数值;Core 接受显式 limits,不内置默认预算,后续 Spring wiring 决定配置值。 | 已解决并汇报 |
| 技术 | Tool Call Key 是否生成 Tool ID? | evidence-driven | 阶段 0/1 冻结框架 ID;Factory 仅验证安全 segment 并拼接,不生成或改写。 | 已解决并汇报 |
Grill 结论
- 术语、边界、验收和技术问题均可由已确认 ISS、现有代码和本地依赖 API 证明。
- 没有新的产品偏好、公开协议或风险接受度问题需要
user-interview;短期关闭旧 SDK retry 的影响已在 proposal 明示。 grill-with-docs的代码可证问题已先查证并向用户汇报;所有结论均已回写 proposal。
能力与工具限制
- Discover 能力来源:
sm-flow+grill-with-docs。 - 当前工具集没有
codebase-retrieval和 LSP;使用rg、源码阅读、本地依赖jar/javap、编译和 focused tests 补足调用链与 API 核对。
Cross-artifact 对齐
| 链路 | 状态 | 结论 |
|---|---|---|
| brief 目标/范围/非目标 -> proposal | 已对齐 | 显式 context、Core、预算/取消/终态、retry、key/capacity、隐藏 retry 和不接旧 runtime 全部覆盖。 |
| proposal 范围/约束/承诺 -> design | 已对齐 | 类职责、并发语义、first-wins、配置变化、迁移和回滚均有明确设计。 |
| design 决策/接口影响/风险 -> specs/tasks | 已对齐 | 每个状态边界都有 scenario,配置行为变化和 zero-consumer 边界有独立任务与验证。 |
| specs 可观察行为 -> tasks | 已对齐 | 8 条 requirements 分解为 primitives、budget、Core、retry、key、配置和三层验证。 |
Architecture Audit
- 能力来源:
zoom-out,使用 glossary 的 RunContext、Run Lifecycle、Run Budget、Harness Retry Policy 和 Diagnosis Run 术语。 - 输入链路为未来 application use case 创建 RunContext,处理链路由 Core/Retry/Key/Capacity 通过显式参数消费,输出为唯一 RunTermination;当前 runtime 不接入。
- RunContext 拥有单 Run 内存状态,应用用例拥有数据库映射,Tool store 拥有 Redis invocation;数据所有权没有重叠。
- Core 不保存全局 Run map、不调用 Agent/数据库/Redis、不实现循环编排,因此不会演变为工作流引擎。
- 最大风险是关闭 SDK retry 对旧路径的短期行为影响;已作为显式配置变更进入 proposal/spec/test 和回滚说明,无 ADR 冲突。
Commit Gate Preflight
- proposal、design、specs、tasks 完整,OpenSpec status complete,strict validation 通过。
- question pool 无未汇报 evidence-driven 结论、无未确认 user-interview 问题。
- 接口影响 L2;
spring.ai.retry.max-attempts=1的有意内部行为变化已明确影响和回滚边界。 - cross-artifact 四段对齐无 gap,架构审计约束已进入 design/spec/tasks。
- Apply 持续授权已存在;执行范围严格限制为新 Harness foundation、配置 override 和 focused tests。
Pre-apply Research
参考实现与反例
SessionContextHolder:ThreadLocal session/run fallback,新 Harness 明确禁止复用。TokenUsageHolder/TokenTrackingChatModel:当前只记录 total token 且依赖 ThreadLocal,后续 model boundary 应改为显式 RunBudget;本阶段不改旧类。ChatService.executeChatComplex:当前业务方法内创建 Run、两轮 retry、写终态和清理 ThreadLocal,是后续替换对象,不是 Core 参考实现。DiagnosisRun:现有持久化字段和字符串状态;本阶段只确认映射边界,不修改实体或 Repository。- Spring AI 1.1.7
SpringAiRetryProperties:spring.ai.retry前缀、默认maxAttempts=10,支持精确配置 override。
技术栈清单
- Java 17 record 表达结构不可变 context/limits/snapshot/policy/attempt。
AtomicReference实现 first-reason/first-terminal-wins;AtomicLong实现 capacity CAS;同步临界区维护复合预算一致性。Clock和Supplier<String>注入保证 deadline/ID 可测试,不引入 scheduler 或全局 registry。- SLF4J 只记录取消 callback 异常,不记录用户输入、Tool payload 或凭据。
- SnakeYAML 直接解析 classpath
application.yml验证 retry override,不启动外部 MySQL/Redis/Milvus/模型。
新建基础设施
harness.core:RunContext、Cancellation、Lifecycle、Budget、Capacity、Core 和类型化异常/状态。harness.retry:RetryFailure/Policy/Policies/Attempt/Executor/Exception 与函数接口。harness.tool.store.ToolCallKeyFactory:纯 Key 构造,不访问 Redis。- focused unit tests 与 Fake Model/Tool;无需新 Maven 依赖。
影响半径
- 新生产包在本阶段保持零消费者。
- 唯一现有运行配置变化为
spring.ai.retry.max-attempts=1;Model 路由、provider、Controller、JPA 和 Redis 配置保持不变。
Apply 结果
- 冲突分类:未发现 OpenSpec 遗漏、代码偏离或方向不确定项;一次自审发现 RetryExecutor 需要无条件拦截预算/取消异常,已回写代码并通过回归测试。
- 新增
RunContext、Cancellation、Lifecycle、Budget、Capacity、DiagnosisHarnessCore、typed Retry 和 ToolCallKeyFactory;未接旧 Chat/AIOps/Controller/Redis/JPA。 - Spring AI 全局 retry 已由默认 10 压为 1;Harness strict policies 只允许 Router/SemanticGuard 技术失败一次显式重试。
- 首模块对齐:Run state/budget/Core/retry/key/config 与 design/tasks 全部完成;Tool interceptor/store/Agent/应用用例仍留给后续阶段。
Apply 验证
- 编译:
mvn -q -DskipTests compile:通过。 - Core focused:
mvn -q '-Dtest=RunContextTest,RunBudgetTest,DiagnosisHarnessCoreTest,HarnessRetryExecutorTest,ToolCallKeyFactoryTest,SpringAiRetryConfigurationTest' test:通过(加固后复跑通过)。 - 综合回归:
mvn -q '-Dtest=HarnessContractTest,RagToolContractTest,QueryLogsToolContractTest,MysqlToolContractTest,RunContextTest,RunBudgetTest,DiagnosisHarnessCoreTest,HarnessRetryExecutorTest,ToolCallKeyFactoryTest,SpringAiRetryConfigurationTest,ChatControllerTest' test:通过。 - 静态 scope:新 Harness 包无 ThreadLocal/current-holder/Redis 引用;旧 Chat/AIOps/Controller/JPA 调用链 diff 为空;模型路由/provider 未改。
- OpenSpec:
openspec validate single-react-harness-run-context --strict:通过。