feat(ql3): compare bounded task run outcomes

This commit is contained in:
whyour
2026-08-14 17:18:25 +08:00
parent a55613afaa
commit 828370c60b
22 changed files with 1802 additions and 22 deletions
+8 -2
View File
@@ -11,6 +11,7 @@
最新增量证据(2026-08-13):
- D-310/ADR-0402(已接受):新增 `qinglong.task.runs.compare@1.0.0`,把“最近成功/失败 Run”的选择从模型无界分页收回服务端。输入只接受 Task ID,固定读取按 created/id 倒序的 64 条 Project-scoped Task Run,第 65 条仅证明窗口截断且协议不返回 cursor;选择 succeeded baseline 与 failed candidate 后按固定顺序执行最多两个低敏点查并复用共享差值算法,输出明确区分 complete 与窗口内未找到,consistency 固定为 `bounded_task_window_then_ordered_point_reads`。实现没有扩大 CRITICAL/HIGH 的通用 SQLite/PostgreSQL Run Reader,而是在双方既有 `run/outcome-comparison/` 中提供窄 adapter;不新增 package、依赖、migration、索引、连接、timer、listener、watcher 或 cache,默认 Edge/Standalone 制品字节数保持 2,589,812。定向 Runtime Core 10/10、SQLite 1/1(真实 query plan 命中既有 Task 时间索引)、PostgreSQL adapter 2/2、Local MCP 47/47、dependency firewall 53/53;最终 18-package clean build/test 与 backend 1,206 pass/2 条件 skip/0 failpackage/dependency/Edge/Cluster deployment 审计零 finding。Edge-MCP 为 7,237,187 bytes/795 files/220 modules/RSS 38,699,008 bytesStandalone-MCP 为 7,237,295 bytes/795 files/220 modules/RSS 38,600,704 bytes,均在门内。PostgreSQL 18.4 arm64 HA 125/125 Gate、timeline `1→2`,报告 SHA-256 为 `229c7cac328ee960f667f92868374264a10cb75090ef93d644da1326385d8774`
- D-309/ADR-0401(已接受):`qinglong.run.compare@1.0.0` 进入可选 `ql3-mcp` stdio 产品入口,复用 Runtime Core 的共享 Definition/projection 和既有 MCP 静态注册循环。每次调用重新执行 Owner credential 认证、`tool.call:qinglong.run.compare` + `run.read` Policy、durable allowed audit、credential fence confirm,再按 baseline→candidate 串行执行两个 Project-scoped SQLite 点查;错误稳定收敛为 `run_compare_unavailable`。该入口是 ADR-0347 的交互式只读 surface,只持久化安全 admission,不冒充 StepRun、encrypted Tool completion 或模型 Trace;内部 Copilot 的受信执行仍必须走完整 completion 链。实现不新增 package、依赖、migration、表、索引、连接、timer、listener、watcher、cache 或网络 endpoint,默认 Edge/Standalone 继续裁掉 MCP package,仅显式 `edge-mcp|standalone-mcp` 承担调用成本。Local MCP 46/46、最终 18-package clean build/test 退出 0、backend 1,206 pass/2 条件 skip/0 failpackage/dependency/Edge/Cluster deployment 审计零 finding;默认 Edge 为 2,589,812 bytes/315 files/56 modules/RSS 11,091,968 bytesEdge-MCP 为 7,219,977 bytes/792 files/217 modules/RSS 38,649,856 bytesStandalone-MCP 为 7,220,085 bytes/792 files/217 modules/RSS 38,043,648 bytes,均在各自门内。
- D-308/ADR-0400(已接受):首个只读 Copilot 的“最近成功/失败运行对比”不再依赖 Prompt 自由拼接两个查询。`qinglong.run.compare@1.0.0` 作为第二个受信内建 Tool,固定 `read/low``run.read``database.read` 和 5 秒 deadline;只有当前 Project Tool snapshot 显式包含 reviewed Definition、产品 composition 显式绑定 adapter 后才可执行。它按 baseline→candidate 串行复用两次有界 Run 点查,absent 与 cross-Project 均为 `found:false`,只输出低敏 Run projection、固定 changed fields 和可证明的 queue/execution/total duration delta;任一时间戳不完整或结束早于开始时不生成对应差值。输出明确标记 `ordered_independent_point_reads`,不冒充数据库事务快照。实现位于既有 `runtime-core/tool-execution/builtin-run-compare/`,只提供两个显式 subpath,不从 package root 导出,不新增 workspace package、依赖、表、migration、连接、timer、listener、watcher、cache 或低配设备常驻开销。最终 18-package clean build/test 退出 0backend 1,208 项为 1,206 pass/2 条件 skip/0 failpackage/dependency/Edge/Cluster deployment 审计零 finding。Edge、Edge AI、Edge MCP 制品为 2,589,812 / 3,121,108 / 7,209,862 bytes,均低于各自上限且未装配 subpath 被发布投影裁掉。
- D-307/ADR-0399(已接受):物理 Edge release archive Gate 使用外部 Ed25519 签发、QingLong verify-only 的两阶段协议。`prepare` exact 重建 owner-private 统一物理报告,要求 direct release service start 已通过,并把 repository、40 位 Git revision、设备/boot、物理报告、release archive、实机 artifact tree/metadata/entrypoint 与 Node digest/version 编入无换行 canonical payload;私钥始终位于 HSM/KMS/离线 operator。`finalize` 以 operator-pinned SPKI 公钥重算 fingerprint,稳定读取并复核所有输入后验证 64-byte detached signature,任一 source/archive/evidence 漂移均失败关闭,输出 `0600` no-replace envelope。通过只把 `release_archive_signature` 替换为 `release_archive_signature_or_attestation``supported:false` 与其余 firmware、整机 flash、migration、断电、固定实机采集和 Cluster 容量 Gate 全部保留。基础 importer 同时把 Edge、SQLite 与 Plugin Package 三个 workload 的 platform/architecture 精确绑定到统一物理观测,release verifier 再要求 observed/Edge/SQLite 为完整 recorder shape 且 Node identity 相同,拒绝跨主机拼接与重算外层摘要后的最小伪造。实现不新增 package、依赖、daemon、listener、timer、watcher 或设备常驻负担;18-package clean build/test 退出 0backend 1,208 项为 1,206 pass/2 条件 skip/0 failpackage/dependency/Edge/service bridge/Cluster deployment 审计零 finding。
@@ -6906,8 +6907,13 @@ Copilot 默认不能直接提交修改或运行命令。写操作通过 Tool Reg
credential 后才可发现,并且每次调用都经过 Tool Policy、durable Security Audit 和 credential
fence confirm;它没有进入默认 Edge/Standalone application,也未向 HTTP、Cluster 或任意模型
授予 ambient capability。该交互式 MCP 读取不冒充内部 Trusted Tool 的 StepRun/encrypted
completion。“最近成功与失败”的有界选择、日志 range/redaction 和最终 Copilot Prompt 仍需
后续产品 Gate。
completion。ADR-0402 已完成“最近成功与失败”的有界选择
`qinglong.task.runs.compare@1.0.0` 只接受 Task ID,在一次固定 64+1 的 Project-scoped
Task Run 窗口中选择最新 succeeded/failed,并复用共享低敏对比算法。协议没有 cursor;
窗口截断且缺少任一 outcome 时必须返回 `complete=false`,禁止模型把局部缺失解释成全历史
不存在。可选本机 MCP 已接入同一认证/Policy/Audit/confirm 链;PostgreSQL 仅提供窄 adapter
Cluster 产品入口和完整 Trusted Tool completion 仍需独立门禁。日志 range/redaction 和最终
Copilot Prompt 仍需后续产品 Gate。
## 17. Tool Registry
@@ -0,0 +1,103 @@
# ADR-0402:有界的 Task 最近成功/失败 Run 对比
- 状态:Accepted
- 日期:2026-08-14
- 关联 RFCQL-RFC-0001 D-310、Phase 2
- 关联 ADRADR-0347、ADR-0400、ADR-0401
## 问题
ADR-0400/0401 已提供按两个显式 Run ID 对比的共享受信 Tool 和可选本机 MCP 入口,但“选择
最近一次成功与失败运行”仍可能被留给模型。模型如果循环调用 `run.list`、翻页并自行过滤,
搜索次数、历史范围和停止条件都不可证明;在低配路由设备上会形成不可控 SQLite I/O,在
Cluster 上也会放大数据库读取和模型上下文,同时给 Prompt 注入制造更大的输入面。
直接把 Task/status 过滤继续塞入通用 Run Reader 也不合理。GitNexus 显示
`LocalSqliteRunReader` 为 CRITICAL(14 个直接、29 个总影响、1 条产品启动流程),
`PostgresRunReader` 为 HIGH(7 个直接、15 个总影响)。为了一个 AI 只读用例扩大这两个基础
Reader 的职责,会让本地恢复、API、Cluster recovery 和写事务继承树承担无关回归风险。
## 决策
1. 增加 `qinglong.task.runs.compare@1.0.0`。输入精确为一个不超过 255 字符的 `taskId`
没有 `limit`、cursor、status、SQL、排序或 Project 参数;Project 只来自受信 composition。
Definition 固定为 `read/low``run.read`、5 秒 deadline。
2. Runtime Core 在 `run/outcome-comparison/` 定义窄
`TaskRunOutcomeWindowReader`。repository 一次只返回按
`(created_at_ms DESC, id DESC)` 排列的最小五字段记录:Run/Project/Task identity、status 和
created time。Tool 固定请求 65 条,其中前 64 条是搜索窗口,第 65 条只证明还有更老记录;
协议永远不返回 cursor,模型不能扩大窗口。
3. 前 64 条中第一个 `succeeded` 是 baseline,第一个 `failed` 是 candidate。两者都找到,
或存储明确返回不超过 64 条时,`selection.complete=true`;如果窗口已满且缺少任一结果,
输出 `complete=false`,不能把“窗口内未找到”伪装成历史上不存在。
4. 选择后按 succeeded → failed 固定顺序执行最多两个既有 Project-scoped Run 点查,并复用
ADR-0400 的低敏 projection、changed fields 和时长差值算法。选择出的 Run 如果消失、变更
Task/outcome、跨 Project 或损坏,整个调用稳定 unavailable;不回退到继续搜索。
5. 输出携带
`consistency=bounded_task_window_then_ordered_point_reads`。它明确表示一次有界选择查询后跟
两次独立点查,不声称数据库事务快照。baseline 永远代表 succeededcandidate 永远代表
failed,差值方向固定为 failed succeeded。
6. SQLite 与 PostgreSQL 各自新增独立、二级目录内的窄 adapter,不修改现有通用 Run Reader
或 Repository 继承树。SQLite 真实 `EXPLAIN QUERY PLAN` 必须命中既有
`ql3_local_runs_task_created_idx`PostgreSQL adapter 使用同样的 Project/Task/order/`LIMIT 65`
查询。复用既有索引避免新增 migration、索引空间和每次 Run 写放大。
7. 可选 `ql3-mcp` 复用既有逐调用 Owner credential → Tool Policy → durable allowed audit →
credential confirm 链,审计理由固定为 `tool_qinglong_task_runs_compare`。默认 Edge/Standalone
仍不装载 MCPCluster 只获得显式 PostgreSQL adapter subpath,不开放 ambient MCP/HTTP
endpoint,内部 Copilot 仍须走完整 Trusted Tool completion 链。
## 低配、集群与 package 布局
- 默认低配设备没有新增进程、连接、timer、listener、watcher、cache、migration 或索引;启用
MCP 时每次调用固定为一个 65 行上限的最小列查询和最多两个串行点查。
- Cluster adapter 复用调用方现有 queryable/Pool,不创建第二连接池;driver 错误收敛为稳定
repository operation error,畸形 bigint/status 收敛为 constraint error。
- package 数保持 18。能力落入 Runtime Core 既有 `run/outcome-comparison/`
`tool-execution/builtin-run-compare/`,持久化实现落入两端既有
`run/outcome-comparison/`;不为一两个文件创建微型 package,也不回到 package `src` 根平铺。
- Runtime Core、Local SQLite、Cluster PostgreSQL 只提供显式 subpathpackage 根入口不扩大;
Local MCP dependency firewall 只放行两个新 Runtime Core 精确 subpath。
## 被否决方案
1. **让模型分页 `run.list`**:查询次数、停止条件和上下文大小不可证明。
2. **把 task/status/cursor 加入通用 Run list**:会把 AI 用例扩散到 HTTP/API 和基础 Reader
且仍允许模型无界翻页。
3. **分别查询所有成功和失败历史**:即使只返回一条,缺少固定窗口时存储扫描和语义仍无界。
4. **为两种 outcome 新增索引**:会增加所有设备的磁盘与 Run 写放大;固定 64 条窗口可复用
已有 Task 时间索引,当前收益不足以支付 migration 和低配常驻成本。
5. **修改 `LocalSqliteRunReader`/`PostgresRunReader`**GitNexus 已证明 HIGH/CRITICAL blast
radius,独立 reader 能用更小权限和故障域完成目标。
6. **只返回两个 Run ID**:仍迫使调用方再次自由组合字段和差值;本 Tool 应交付完整的有界
低敏对比结果。
## 当前验证
1. Runtime Core 定向 10/10:覆盖成功/失败选择顺序、差值、固定 64+1 窗口、无 cursor、
incomplete 语义、跨 Project/乱序/畸形/消失/存储失败、Definition/binding 漂移、显式
subpath 和根入口零导出。
2. Local SQLite 1/1fresh production migration 后写入多 Project/Task/状态 Run,经 MCP 的
单 authority 读取精确窗口,并用真实 `EXPLAIN QUERY PLAN` 证明命中既有 Task 时间索引。
PostgreSQL adapter 2/2:精确 SQL/参数/顺序/上限、bigint 映射、畸形状态和 driver 错误
收敛全部通过。
3. Local MCP 47/47:新增 Tool discovery、固定 read-only annotations、双 permission、durable
audit reason、credential confirm、真实 stdio + fresh SQLite 的选择和两次点查均通过。
4. dependency firewall 53/53,完整 dependency audit 与 package boundary audit 零 finding
package 保持 18 个,`singleSourcePackages=[]``shallowSourcePackages=[]`
5. 最终 18-package clean build/test 退出 0backend 1,208 项为 1,206 pass、2 条平台条件
skip、0 fail。Edge import 与 Cluster deployment 审计零 finding。Runtime Core 为 165/164
nested、Local SQLite 为 197/196 nested、Cluster PostgreSQL 为 168/167 nested,三者 package
根入口均未增长。
6. 默认 Edge artifact 保持 2,589,812 bytes/315 files/56 modules,证明未装配能力被完全裁掉;
RSS 增量 11,173,888 bytes,低于 16 MiB 门。Edge-MCP 为 7,237,187 bytes/795 files/
220 modules/RSS 38,699,008 bytesStandalone-MCP 为 7,237,295 bytes/795 files/
220 modules/RSS 38,600,704 bytes,均低于 16 MiB/1,536 files/48 MiB 门。
7. PostgreSQL 18.4 arm64 HA 125/125 Gate 通过,timeline `1→2`,报告 SHA-256 为
`229c7cac328ee960f667f92868374264a10cb75090ef93d644da1326385d8774`;容器、网络与卷零残留。
## 后续门禁
1. Cluster 产品 composition 装配 Definition/binding,并以真实 PostgreSQL 完成加密结果和
StepRun/Trace completion
2. 日志解释另建 Artifact range、redaction、prompt-injection 和字节预算协议;
3. 固定物理 Edge MCP 单次选择/点查延迟与 RSS,并验证撤权竞态。
+1
View File
@@ -405,6 +405,7 @@
| [ADR-0399](./ADR-0399-external-release-attestation-for-physical-edge-evidence.md) | 物理 Edge 证据的外部发布归档证明 | Acceptedexact recorder 重建与离线验签已实现;固定实机 ceremony 待执行) |
| [ADR-0400](./ADR-0400-bounded-trusted-run-comparison-tool.md) | 有界、受信的 Run 对比 Tool | Accepted |
| [ADR-0401](./ADR-0401-optional-local-mcp-run-comparison-surface.md) | 可选本机 MCP Run 对比产品入口 | Accepted |
| [ADR-0402](./ADR-0402-bounded-latest-task-run-outcome-comparison.md) | 有界的 Task 最近成功/失败 Run 对比 | Accepted |
## 规则