6.7 KiB
ADR-0165:Trusted Tool 失败与超时终态完成协议
- 状态:Accepted
- 日期:2026-07-26
- 关联:ADR-0156、ADR-0158、ADR-0162 至 ADR-0164;RFC D-152 至 D-154
背景
ADR-0163/0164 已关闭 Trusted Tool 的成功持久化与 Profile-neutral 成功协调,
但 adapter 明确失败和 deadline 到期仍会让 StepRun 停留在 running。如果每个
Profile 自行解释异常,低配路由设备和集群节点会产生不同的终态、重试和敏感信息
持久化语义;若把异常对象、stack 或未知 output 写进 RunEvent,又会扩大泄露面。
失败终态还必须与成功 completion 竞争收敛。仅在应用层先查一次成功记录不能证明 互斥:并发调用、事务提交响应丢失和 PostgreSQL 主库切换都可能让调用者观察到未知 结果。
决策
1. 失败完成只保存固定低敏事实
runtime-core 新增显式 subpath
@qinglong/runtime-core/tool-execution-failure-completion。v1 只接受:
failed:tool_adapter_failed/Trusted Tool execution failed;timed_out:tool_deadline_exceeded/Trusted Tool execution deadline exceeded。
completion 必须绑定 exact start、Project、Run、StepRun、Tool、adapter、Run version、 event sequence、mutation 和 event identity。它不保存 raw error、stack、adapter output, 也不创建 Result Artifact 或取得 result key authority。
2. 成功与失败 completion 必须原子互斥
SQLite 与 PostgreSQL 各增加 append-only failure completion 表和 repository。失败提交 必须在一个事务内完成:
- 复验 start barrier、当前
runningTool StepRun、非 terminal Run; - 拒绝同一 start 已存在的成功 completion;
- 将 StepRun 原子迁移到
failed或timed_out,保持outputRef=null; - 推进 Run version/event sequence;
- 写入固定低敏 RunEvent、StepRunMutation 与 failure completion。
成功 repository 同样必须在事务内拒绝同一 start 的失败 completion。SQLite 使用
BEGIN IMMEDIATE 串行化双方竞争;PostgreSQL 使用 serializable transaction,并锁定
exact StepRun/Run。两侧都只允许完整命令 exact replay,任何部分身份复用、跨表镜像
漂移或同时存在成功/失败记录都失败关闭。
SQLite capability 推进到 v32,共 55 张受管表;PostgreSQL control-core capability
推进到 v33。PostgreSQL runtime role 对 failure completion 只取得 SELECT, INSERT,
admin、Package manager、Package executor、Worker ingress 与 PUBLIC 默认拒绝。
3. 一个协调器裁决所有 Tool 终态
runtime-core 新增显式 subpath
@qinglong/runtime-core/trusted-tool-completion,由
executeAndCompleteTrustedTool 固定编排:
- 执行 adapter 前同时读取 durable success/failure winner;
- 只有两者均不存在才调用既有 Trusted Tool execution;
- adapter 抛错后再次读取 durable winner,先收敛并发或未知提交结果;
- 只把明确的
TrustedToolExecutionFailedError归类为failed; - 只把明确的
TrustedToolExecutionDeadlineExceededError归类为timed_out; - Artifact、key、binding、snapshot、storage 等缺失或损坏继续保持非终态并失败关闭;
- failure commit 响应丢失后只读取 durable winner,同一次调用不得重新执行 adapter。
返回值是 succeeded | failed | timed_out 的判别联合。固定 system actor、start-derived
dedupe、mutation 和 event identity 均由协调器生成,不接受 transport 注入。
4. 保持双 Profile 的资源边界
现有 LocalSqliteTrustedToolStorage 与 ClusterTrustedToolStorage 增加
failureCompletions port,不新增 workspace package或第三方依赖:
- edge/standalone 仍使用首次请求才动态加载的 SQLite 单例 bundle,不新增连接、 timer、watcher 或 socket;
- cluster-control 仍只通过受审
@qinglong/cluster-postgres/runtime组合入口, 在现有单一 Pool 上装配同构 bundle; - runtime-core root、PostgreSQL root/admin/ingress 和生产 transport 不获得执行
authority;生产 allowlist 仍只有
run.get与run.cancel。
被否决方案
- 把异常序列化进 Artifact 或 RunEvent:扩大敏感信息面,且失败终态不需要解封。
- 只有失败 repository 检查成功记录:晚到的成功事务仍可穿透,无法证明互斥。
- 用任意异常自动终态化:会把 key 丢失、binding 漂移或数据库不可用误报为业务失败。
- 协调器捕获后重跑全部流程:会重复 adapter 副作用。
- 为两个 repository 各拆一个 package:没有独立部署或依赖边界,只会加重 路由设备安装、构建与审计成本。
- 因终态闭环而开放生产 route:result key 生命周期、人工恢复和专属故障注入 尚未完成。
验证
- runtime-core:331/331,覆盖成功、失败、超时、固定事实、并发 winner、响应丢失、 adapter-call-count=1、前置条件缺失保持非终态和显式 subpath;
- local-sqlite:119/119,真实 SQLite 覆盖原子失败提交、exact replay、成功/失败双向 排斥、固定事实与 lazy storage bundle;
- cluster-postgres:181 pass / 1 条件 skip,覆盖事务 SQL、双向排斥、typed schema、 migration checksum、readiness、六角色权限和 composition entrypoint;
- cluster-control:139 pass / 2 条件 skip,覆盖单 Pool storage 装配与依赖边界;
- 21 个 QL3 workspace package 全量 build/test 为 0 fail,package 数量和第三方依赖 均未增加;edge import、cluster dependency、cluster deployment 审计无 finding;
- 全新 PostgreSQL 18 六角色真库 integration:42 pass / 1 条件 skip / 0 fail,直接
覆盖
timed_out原子提交、exact replay、晚到成功拒绝、固定低敏事实与无 output 明文; - PostgreSQL 18.4 arm64 物理 HA 总门
passed=true:remote_apply、timeline 1→2、 旧主 fencing、双 control replica 重新 activation、pg_rewind只读同步重加入及 既有领域 COMMIT-response-loss 门全部通过。该 HA fixture 尚未注入 Trusted Tool failure completion 专属 COMMIT-response-loss,不能用通用事务门替代该证据。
后续门禁
- 在真实 PostgreSQL 上执行新增 terminal completion integration,并给 Tool completion 注入 COMMIT-response-loss、主库晋升后 durable winner 和 adapter-call-count=1;
- 给 SQLite 增加 adapter 返回后、failure/success 事务提交前后的进程 crash 矩阵;
- 建立 result key catalog、rotation、retention/rekey 与 key-lost 人工恢复;
- 按 Project current snapshot 构造短生命周期 adapter registry,再评审产品 use-case/transport 入口。