mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
7.4 KiB
7.4 KiB
ADR-0402:有界的 Task 最近成功/失败 Run 对比
- 状态:Accepted
- 日期:2026-08-14
- 关联 RFC:QL-RFC-0001 D-310、Phase 2
- 关联 ADR:ADR-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 和写事务继承树承担无关回归风险。
决策
- 增加
qinglong.task.runs.compare@1.0.0。输入精确为一个不超过 255 字符的taskId, 没有limit、cursor、status、SQL、排序或 Project 参数;Project 只来自受信 composition。 Definition 固定为read/low、run.read、5 秒 deadline。 - 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,模型不能扩大窗口。 - 前 64 条中第一个
succeeded是 baseline,第一个failed是 candidate。两者都找到, 或存储明确返回不超过 64 条时,selection.complete=true;如果窗口已满且缺少任一结果, 输出complete=false,不能把“窗口内未找到”伪装成历史上不存在。 - 选择后按 succeeded → failed 固定顺序执行最多两个既有 Project-scoped Run 点查,并复用 ADR-0400 的低敏 projection、changed fields 和时长差值算法。选择出的 Run 如果消失、变更 Task/outcome、跨 Project 或损坏,整个调用稳定 unavailable;不回退到继续搜索。
- 输出携带
consistency=bounded_task_window_then_ordered_point_reads。它明确表示一次有界选择查询后跟 两次独立点查,不声称数据库事务快照。baseline 永远代表 succeeded,candidate 永远代表 failed,差值方向固定为 failed − succeeded。 - 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 写放大。 - 可选
ql3-mcp复用既有逐调用 Owner credential → Tool Policy → durable allowed audit → credential confirm 链,审计理由固定为tool_qinglong_task_runs_compare。默认 Edge/Standalone 仍不装载 MCP;Cluster 只获得显式 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,也不回到 packagesrc根平铺。 - Runtime Core、Local SQLite、Cluster PostgreSQL 只提供显式 subpath,package 根入口不扩大; Local MCP dependency firewall 只放行两个新 Runtime Core 精确 subpath。
被否决方案
- 让模型分页
run.list:查询次数、停止条件和上下文大小不可证明。 - 把 task/status/cursor 加入通用 Run list:会把 AI 用例扩散到 HTTP/API 和基础 Reader, 且仍允许模型无界翻页。
- 分别查询所有成功和失败历史:即使只返回一条,缺少固定窗口时存储扫描和语义仍无界。
- 为两种 outcome 新增索引:会增加所有设备的磁盘与 Run 写放大;固定 64 条窗口可复用 已有 Task 时间索引,当前收益不足以支付 migration 和低配常驻成本。
- 修改
LocalSqliteRunReader/PostgresRunReader:GitNexus 已证明 HIGH/CRITICAL blast radius,独立 reader 能用更小权限和故障域完成目标。 - 只返回两个 Run ID:仍迫使调用方再次自由组合字段和差值;本 Tool 应交付完整的有界 低敏对比结果。
当前验证
- Runtime Core 定向 10/10:覆盖成功/失败选择顺序、差值、固定 64+1 窗口、无 cursor、 incomplete 语义、跨 Project/乱序/畸形/消失/存储失败、Definition/binding 漂移、显式 subpath 和根入口零导出。
- Local SQLite 1/1:fresh production migration 后写入多 Project/Task/状态 Run,经 MCP 的
单 authority 读取精确窗口,并用真实
EXPLAIN QUERY PLAN证明命中既有 Task 时间索引。 PostgreSQL adapter 2/2:精确 SQL/参数/顺序/上限、bigint 映射、畸形状态和 driver 错误 收敛全部通过。 - Local MCP 47/47:新增 Tool discovery、固定 read-only annotations、双 permission、durable audit reason、credential confirm、真实 stdio + fresh SQLite 的选择和两次点查均通过。
- dependency firewall 53/53,完整 dependency audit 与 package boundary audit 零 finding;
package 保持 18 个,
singleSourcePackages=[]、shallowSourcePackages=[]。 - 最终 18-package clean build/test 退出 0;backend 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 根入口均未增长。
- 默认 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 bytes,Standalone-MCP 为 7,237,295 bytes/795 files/ 220 modules/RSS 38,600,704 bytes,均低于 16 MiB/1,536 files/48 MiB 门。
- PostgreSQL 18.4 arm64 HA 125/125 Gate 通过,timeline
1→2,报告 SHA-256 为229c7cac328ee960f667f92868374264a10cb75090ef93d644da1326385d8774;容器、网络与卷零残留。
后续门禁
- Cluster 产品 composition 装配 Definition/binding,并以真实 PostgreSQL 完成加密结果和 StepRun/Trace completion;
- 日志解释另建 Artifact range、redaction、prompt-injection 和字节预算协议;
- 固定物理 Edge MCP 单次选择/点查延迟与 RSS,并验证撤权竞态。