Files

47 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Why
当前 Chat/AIOps 通过 `SessionContextHolder`、`VerifierContextHolder` 和 `TokenUsageHolder` 等 ThreadLocal 隐式传播 session/run/token/retry 状态,且 Run 终态、取消、预算和重试分散在业务循环与 SDK 默认行为中。阶段 3A 的 Tool boundary、后续 Agent/Guard 和最终入口需要先共同依赖一个显式、可跨同步/异步边界传递的 Harness RunContext,否则会继续耦合旧 ChatService 并产生重复状态机。
## What Changes
- 新增结构不可变的 `RunContext`,显式携带 `sessionId`、`runId`、deadline、取消信号、线程安全预算、类型化重试策略和 first-terminal-wins 生命周期。
- 新增 `DiagnosisHarnessCore` 负责 Run 创建、deadline 检查、模型/Tool/Token/容量预算门禁、取消传播和唯一终态,不承担业务推理或持久化。
- 新增 caller-supplied `RunBudgetLimits`、线程安全 `RunBudget` 与单 Run 字节容量计数器;Core 不硬编码尚未校准的预算默认值。
- 新增 `HarnessRetryPolicies` 与 `HarnessRetryExecutor`,只允许 Router/SemanticGuard 的类型化技术失败最多两次 attempt;Diagnosis Agent、Tool 和 Evidence repair 固定一次 attempt。
- 将 Spring AI 1.1.7 全局底层重试 `spring.ai.retry.max-attempts` 从默认 10 压为 1,避免与 Harness 形成隐藏嵌套重试。
- 新增 Redis Tool Call Key Factory,只负责安全构造固定前缀下的 `runId + toolCallId` Key,不访问 Redis、不生成 Tool Call ID。
- 使用 Fake Model/Tool 和可控 Clock 验证显式异步传播、deadline、客户端取消、预算耗尽、重试记录、Key/容量边界和唯一 Run 终态。
- 本阶段不改 Controller/HTTP/SSE,不接入或临时适配旧 ChatService,不修改 `diagnosis_run` 持久化,也不实现 Tool-specific 投影或 Redis store。
## Capabilities
### New Capabilities
- `diagnosis-harness-run-context`: 提供显式 RunContext、Harness Core、预算、取消、deadline、类型化重试、唯一终态和后续 Tool store 所需的 Key/容量基础。
### Modified Capabilities
- None. 本阶段不声明旧 Chat/AIOps 运行路径已迁移;公开运行和数据库状态映射在后续 change 接入。
## Context Constraints
- 新代码不得读取或写入任何 ThreadLocal;RunContext 只能通过参数或框架受控 context 显式传播。
- RunContext 的结构不可变,但其 cancellation、budget 和 lifecycle 是线程安全的单 Run 状态句柄。
- 同一 Run 只允许第一个终态生效;取消、deadline、预算和异常之间的竞态不得覆盖先到终态。
- 同步模型/Tool 调用的取消只保证阻止后续执行并触发已注册资源取消回调,不虚假承诺无法证明的立即线程中断。
- `NO_EVIDENCE`、业务拒绝、取消和预算耗尽不是可重试技术失败。
- Tool Call Key 使用框架 `tool_call_id`;Key Factory 不生成、替换或回退到其他 ID。
## Interface Impact
- 等级:L2(内部 Harness 基础接口)。新增 Core 类型将被后续 3A-7 阶段消费,但本 change 不修改现有调用方。
- `application.yml` 的 Spring AI retry 从默认 10 attempts 变为 1 attempt,属于有意的内部运行配置变化;当前旧调用若遇到瞬时模型失败将不再由 SDK 隐式重试,避免未记录 attempts。Harness 允许的 Router/SemanticGuard 重试要到后续接入后显式执行和记录。
- 不改变 Controller、SSE、DTO、数据库 Schema 或公开错误码。
## Risks
- 旧运行路径在切换前会失去 SDK 隐式重试但尚未使用 Harness retry;这是为保证“所有 attempt 可观测”接受的短期行为变化,focused tests 需证明启动配置正确。
- RunContext 内含线程安全可变句柄,若被误解为纯值对象可能错误复制;设计和测试必须明确同一 Run 共享同一状态句柄。
- Budget 在模型调用后才能取得实际 Token,可能在记录实际消耗时才发现超限;Core 必须保留实际 usage 并立即终止后续执行。
- 本阶段不写数据库,内存生命周期只服务一次调用链;持久化终态映射由 Chat application use case 阶段负责。