mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-23 03:18:09 +08:00
feat(ql3): audit legacy shadow terminal windows
This commit is contained in:
@@ -6,10 +6,24 @@
|
||||
- 目标版本:QingLong 3.x
|
||||
- 作者:QingLong Maintainers
|
||||
- 创建日期:2026-07-17
|
||||
- 最后更新:2026-08-18
|
||||
- 最后更新:2026-08-19
|
||||
- 讨论范围:架构与演进路线,不包含最终 UI 视觉方案
|
||||
|
||||
最新增量证据(2026-08-18):
|
||||
最新增量证据(2026-08-19):
|
||||
|
||||
- D-358/ADR-0450(已接受):新增显式、只读、一次性的 Legacy Shadow 闭合窗口终态审计。调用方必须提供 origin 与
|
||||
`[windowStartMs, windowEndMs)`,cohort 固定为窗口内创建的 legacy-owned Shadow Run;只有窗口经过默认五分钟 settling、候选 keyset 与
|
||||
Legacy evidence 都完整且分母非零时,才输出 terminal agreement/full comparability permille。关联只接受 direct Run/Attempt reference、同 Cron
|
||||
opaque log ID、PID 或唯一容差内 started time,任何多解或 evidence hard-limit 都归入 ambiguous/incomplete;报告按八类 outcome 与五个固定
|
||||
dimension 计数守恒,不含 Project/Run/Attempt/Cron/PID/log/task/user/error identity。edge 预算为 `8 × 1 page`,standalone 为
|
||||
`32 × 4 pages`;每页一次候选查询和一次 evidence 查询,无 N+1、timer、watcher、写入、schema/migration、package、生产依赖或部署对象。
|
||||
因 2.x RunningInstance 没有可信 execution origin,v1 明确只证明 `shadow_to_legacy`,将 `legacyWithoutShadow` 标为 `not_measured`,不把它单独
|
||||
冒充 Primary gate。阶段门已重跑:真实 SQLite/CLI 聚焦测试 `14/14`、Legacy/Shadow 串行扩展 `91/91`、`build:back`、完整 backend
|
||||
`1,455 pass / 0 fail / 2 conditional skip`、18-package clean build/test、14/14 static audit 与 14/14 artifact audit 全部通过。
|
||||
edge/standalone 产物字节保持 D-357 基线:base `2,589,998 / 2,590,076`、adopted `2,809,293 / 2,809,416`、application
|
||||
`3,632,877 / 3,632,997`、application-api `3,800,430 / 3,800,574`、AI `3,069,251 / 3,069,341`、application+AI
|
||||
`4,493,151 / 4,493,283`、MCP `7,315,930 / 7,316,038`。本切片不改 PostgreSQL、容器或 Kubernetes 部署面,因而不重跑物理
|
||||
PostgreSQL HA/K3s,也不把 D-357 的相邻结果冒充本阶段新证据;D-359 继续负责 edge/standalone 资源压力和 Shadow-off 回滚演练。
|
||||
|
||||
- D-357/ADR-0449(已接受):将 D-356 的进程内 startup summary 收紧为可供后续 origin-scoped gate 使用的版本化差异证据。每个候选只归入
|
||||
completed/cancelled/abandoned/markedLost/repaired/pending/ambiguous/skipped/failed 九个固定 outcome,总量与最多七条已配置 origin
|
||||
@@ -9115,7 +9129,7 @@ flowchart LR
|
||||
| PR-1 Run Schema | Incubating | Run/RunAttempt/RunEvent schema、nullable cancel request 与 Attempt deadline 字段及恢复索引、CancellationDispatch 状态/version/lease/backoff schema、Repository port、临时 Sequelize adapter、统一事件大小/分页上限、跨 adapter RunRepository contract suite(原子事务、回滚、Run/Attempt/RetryPolicy CAS、唯一错误、分页与取消恢复);ADR-0041 的 `pg-0003-run-retry-policy`、capability v2、driver-neutral PostgreSQL Run Repository 与真实 `pg.Pool` 上的共享 Repository/rollback/SQLSTATE contract;ADR-0063/0069/0071/0073/0074/0076 的独立 Node 24 local-sqlite typed schema、十二条 reviewed migration、capability v6、共享 operation authority、readiness/RunRepository/API credential repository/receipt journal/dispatch plan/encrypted Secret envelope/Project Policy/security audit/authorized mutation/stable Identity catalog、Drizzle↔真实 catalog table/column/index/CHECK/FK lockstep、base/adopted/application edge/standalone 产物门禁;ADR-0064 的 legacy baseline/plan digest、Online Backup recovery、side-by-side target migration、staged manifest、双库栅栏 activation、source 生命周期写栅栏、target stable identity 和重启语义;ADR-0065 的独立 cutover authority、外部副作用停机 evidence、append-only journal、start/restart/stop barrier 与 unknown→manual_required 收敛;ADR-0066 的 adopted storage→Run reconciliation→receipt maintenance→domain recovery→lifecycle→admission application gate、严格有界 recovery summary 与 admission-first reverse stop;ADR-0067 的 SQLite 事实驱动 Run 候选源、256 条硬上限、截断失败关闭和唯一 Repository authority;ADR-0068 的 receipt-first Reconciler、callback token/sequence fence、exact local-process identity、Attempt/Run/双 Event 原子终态推进和最终 verifier;ADR-0069 的 local-process 单向包边界、pre-spawn journal、受审 POSIX launcher、immutable receipt、exact identity 和 Profile-aware cleanup lifecycle;ADR-0070 的独立 local-execution、spawn 前后双 transaction CAS、callback digest、exact stop 补偿与 fail-closed starting 保留;ADR-0071 的独立 local-dispatch、不可变 revision/context、Secret-first materializer、Profile Artifact admission、4/64 MiB output hard quota 和窄 application facade;ADR-0073/0074 的 Project-bound SecretRef、AES-256-GCM、外置 keyring 生命周期、双 SQLite authority CAS、application preflight、强 Principal/Policy 和 envelope+audit 原子提交;ADR-0086 的本机 Owner provisioning/challenge/claim/delivery acknowledgement/credential recovery CLI;ADR-0377 的 Local/Cluster 同构、Profile-aware、Project-scoped Artifact range read | fresh database/pepper setup、credential rotation/GC 运维编排与 Secret/Project/Role/Approval 管理 CLI/API/UI、备份/rekey、2.x/target process controller、人工 recovery、target 写后 reconciliation 与完整 cutover/rollback 演练;retry 产品策略、Artifact retention/tombstone stack、具体本机 lifecycle 和 target executable;Linux x64/arm64、PID namespace、断电与固定路由设备门禁;PostgreSQL 16/18 双连接并发与 failover integration;Task revision/context 跨方言 contract/并发压力与引用感知 retention、Keyv 数据迁移 |
|
||||
| PR-2 Run 状态机 | Incubating | 纯转换表、终态/时间/错误/执行器元数据规则、Run version 与 event sequence CAS、事务性 RunCommandService、回滚测试 | 重复 Worker callback/fencing、并发数据库压力测试、Primary 执行链接入 |
|
||||
| PR-3 Executor 端口 | Incubating | ADR-0003、ExecutionSpec/Context/Handle/Result、Executor port、LocalProcessExecutor、进程组取消/超时升级、流式背压、Legacy Cron spec builder、真实进程 contract tests、可复现 edge 基准入口 | 固定 edge/多架构设备基线、Legacy builder 与 makeCommand 差异审计、Primary 生产流量接入 |
|
||||
| PR-4 Shadow Run | Incubating | origin 三态策略;默认关闭的 `QL3_SHADOW_ORIGINS`;manual、scheduled_node、boot、subscription、system 与 script 现有 ChildProcess 旁路观察;system crond 显式 origin marker、Shell execution ID、finish-only 准入、确定性 Run/Attempt 与 exact replay;`@once` 保持 manual、gRPC transport 不冒充 origin 的准入裁决;每个 worker 懒加载;Run/Attempt/Event 影子生命周期;稳定且不复制 caller 原文的 task identity/revision 与有界日志引用;同 worker 有界注册表和跨 worker 持久化候选关联;stop all/stop instance、Shell callback、乱序/迟到/歧义处理;监听前一次性、Profile-aware 的 keyset Startup Reconciler,终态证据补齐、lost/abandoned/pending 分流与 terminal Attempt response-loss 修复;origin-bounded 且逐级守恒的版本化 startup difference report、固定字段 metric batch 与一次性 collector;失败开放和契约测试 | 跨测量窗口终态差异查询、具体 exporter、资源压力、回滚演练和 Primary 门禁 |
|
||||
| PR-4 Shadow Run | Incubating | origin 三态策略;默认关闭的 `QL3_SHADOW_ORIGINS`;manual、scheduled_node、boot、subscription、system 与 script 现有 ChildProcess 旁路观察;system crond 显式 origin marker、Shell execution ID、finish-only 准入、确定性 Run/Attempt 与 exact replay;`@once` 保持 manual、gRPC transport 不冒充 origin 的准入裁决;每个 worker 懒加载;Run/Attempt/Event 影子生命周期;稳定且不复制 caller 原文的 task identity/revision 与有界日志引用;同 worker 有界注册表和跨 worker 持久化候选关联;stop all/stop instance、Shell callback、乱序/迟到/歧义处理;监听前一次性、Profile-aware 的 keyset Startup Reconciler,终态证据补齐、lost/abandoned/pending 分流与 terminal Attempt response-loss 修复;origin-bounded 且逐级守恒的版本化 startup difference report、固定字段 metric batch 与一次性 collector;显式、只读、闭合窗口且 Profile-bounded 的 Shadow→Legacy 终态差异审计;失败开放和契约测试 | Legacy→Shadow capture authority、具体 exporter、资源压力、回滚演练和 Primary 门禁 |
|
||||
| PR-5 Primary LocalExecutor | Incubating(默认不激活,仅 manifest-gated manual) | runtime-owned Run 创建器;持久化先于 spawn;Run/Attempt 完整成功、失败、取消、超时与 lost 闭环;Executor handle 身份校验;spawn 后激活写失败的 stop+lost 补偿;completion rejection 安全收敛;独立 Primary 幂等查询与唯一索引竞态裁决;durable `run.cancel_requested`、stop-before-signal、首次请求幂等、晚到完成裁决与待取消有界恢复查询;最多 64 条一页的 cross-worker cancellation source;独立 CancellationDispatch Repository 原子 claim/result、lease expiry 接管、owner/token/version fencing、指数退避与结果 RunEvent;最多 64 页的单周期 cancel supervisor;显式 start/stop、无重叠、错误隔离、停止等待有上限且 timer unref 的 lifecycle runner;Linux durable handle 的 PID/boot/start ticks/process-group 复验与 TERM/KILL controller;完整有界分页且 fail-closed 的 startup Reconcile supervisor;RunningInstance nullable `run_id/attempt_id` 关联;Primary 专用组合 Repository 在同一 SQLite 事务提交前投影 Crontab/RunningInstance,失败整体回滚;有界且防穿越的 legacy log output ref;manual owner seam、真实本机装配、单 spawn/fail-closed;严格 manual-only rollout manifest loader、短期审批/gate、配置哈希审计;HTTP worker 已接轻量 lazy bootstrap,accepted 后按 receipt-first reconcile→completion receipt lifecycle→timeout intent lifecycle→cancel dispatch lifecycle→router 顺序激活,失败撤销,监听失败和 shutdown 有界停止;Primary timeout 在 spawn 前持久化绝对 deadline,有界 source/requester/supervisor 只提交 timeout 意图并复用 CancellationDispatch;代码级 edge/standalone Profile 为各 lifecycle 提供不同 cadence 与页上限,cluster-control/worker 拒绝误装本机 SQLite Primary;统一 CompletionService 原子提交 Attempt/Run/双 Event,spawn 前保存 callback token hash、终态推进 sequence,实时回调与 receipt consumer 共享入口并覆盖两个清理 crash window;manual Primary 已接入受限 POSIX launcher、`0600` direct-file stdout/stderr、父进程退出后续写、不可覆盖 receipt 生产、回执环境清除、TERM 转发等待及 live transaction 后清理;Startup Reconciler receipt-first 双检查并在确定 exited 后执行 profile 化的单次 50/100 ms publish grace;`0007` 独立 CompletionReceiptJournal 在 spawn 前登记、为升级前 active Attempt 补登记并驱动周期扫描,使终态残留继续可发现;确定无效的已知 Attempt receipt 先持久化隔离状态,再进入确定性私有分片 quarantine;终态 missing 与 quarantine 按 edge/standalone retention 有界清理;非 Journal 文件具备只读优先、固定分片/条目上限、overflow fail-closed、显式同盘隔离的 Node 24 运维 CLI;扫描具备页上限、resume cursor、timer unref、无重叠、有界 stop 和低敏计数;ENOSPC 与 launcher receipt 存储失败有代码门禁 | 部署配置写入/审批入口与用户可见状态;PostgreSQL CancellationDispatch adapter;cluster-control 生产启动拓扑;固定 edge/Linux 多架构与真实磁盘压力基线、完整 2.x API 契约和回滚演练 |
|
||||
| PR-7 Worker Session、Run Lease 与启动协议基础 | Incubating(默认关闭,独立入口显式 opt-in) | ADR-0012/0013/0014/0021/0057–0061/0108–0121/0231–0239/0377;有界 capability/Placement/Dispatcher;SQLite 协议孵化与 PostgreSQL v9 Session/Run Lease/credential/attestation authority;immutable revision Placement、数据库时钟 keyset candidate、认证 Worker Pull、digest-only offer recovery;versioned capability-free ExecutionSpec response、stable claim 跨重启退避、单 owner 原子 inbox 准入与 TLS 1.3 mTLS/`ql3w` HTTPS client;同一 package journal 上 revision-fenced starting/spawn/started/running/completion 状态、callback digest、tagged no-spawn 与 ambiguous recovery;PostgreSQL starting/running/start-failure/completion 数据库权威事务、精确重放与 cancellation/timeout 优先终态;batch Secret delivery 在 Attempt advisory lock 下复验 Session/Lease/revision 完整围栏并复用单 Agent,Secret-before-Artifact materializer 将同一 log ID 交给 Executor/journal/running ACK;offer-scoped `wlog-*` 私有文件 spool、Edge/Node 容量策略、append/quota/path 防护、barrier 后 output ownership、受审 POSIX Executor、truncation fact、固定内存流式 source、认证 Artifact stream、共享 immutable store port、S3-compatible SSE/checksum/条件 promotion adapter、upload-before-completion 协调,以及 Local/Cluster 同构、Profile-aware、ETag-fenced range read;用户取消 run.stop mutation 以数据库时间写 intent/Event 并在事务内复验 Project/RoleBinding fence;非执行取消 convergence lifecycle、运行期 expiry 与安全 lost retry 已接入 cluster-control 单一全局 cadence;完整 generation/version/token/Attempt fencing;独立最小权限 Worker ingress、CA/CRL 与连接 generation 热重载;offer journal、spawn barrier、receipt-first recovery;独立 `@qinglong/worker-runtime` 的本地 P-256 CSR、key/chain/trust 验证、generation + active pointer 安装和持久退避;默认关闭的 production process 已装配具体 execution graph、完整 Session heartbeat/drain/offline、direct-file bootstrap、单 Agent/单 cadence、startup reconciliation、证书 maintenance、transport fail-close/recovery 与 Edge/Node 有界预算;真实 PostgreSQL 18 + Linux Node 合约已覆盖 Run completion、credential 和 CA 双轮换且保持同一 Session;真实 K3s 合约已覆盖 TLS/credential Secret 分权、双对象 CAS、Recreate 顺序、identity generation 与单节点 PVC recovery;所有能力默认不可达且受 edge/cluster import audit 约束 | 具体 cert-manager/Vault/SPIFFE/离线 CA adapter 与模板、ingress reload controller、生产 RBAC、证书到期告警和 `ql3w` credential recovery 产品面;具体 KMS/Vault Secret provider、对象存储 credential/temporary lifecycle 与 retention/tombstone;Worker 管理 API;真实 Kubernetes 多节点 CSI/node-loss/production 360 秒 drain 与固定 edge 文件系统 suspend/时钟/断电、x64/arm64 资源门禁 |
|
||||
| PR-8 Project/Policy/Approval Core | Incubating(默认拒绝、无生产业务执行入口) | ADR-0028;统一六类 ActorRef 与 exact-shape 校验;`0017` ownerless default Project 和 append-only versioned RoleBinding;owner/admin/operator/viewer 固定矩阵;Project 内 mutation 幂等、expected-version CAS、双 SQLite 连接竞争门禁;archived read-only、revocation、存储损坏 fail-closed;Agent 写/Secret/Tool `require_approval`;ADR-0047 把六类 subject、role/permission matrix 与 fence 抽到 runtime-core,`pg-0004-project-policy`/capability v3 建立 ownerless PostgreSQL baseline、严格 role/state CHECK、append-only runtime 权限、SERIALIZABLE Project lock、mutation replay、双连接单 winner 和 cluster admission authorizer;ADR-0049/`pg-0005` capability v4 建立 stable IdentitySubject、append-only digest-only API credential、真实 cluster bearer authenticator、write-only durable security audit 与最小权限 runtime role,且已验证 HTTP→credential→Policy→audit→handler 纵向链路;ADR-0051 建立 `/api/v3` 认证前 peer/global 双预算、transport-peer-only、无 timer 且有界内存的 overload shield;ADR-0027 Artifact authorizer adapter;ADR-0029 `AuthenticatedPrincipal` contract、`0018` digest-only versioned challenge、CSPRNG/TTL、同事务消费 challenge + 写首 owner、精确重放与双连接竞争/崩溃回滚门禁;ADR-0030 `0019` stable identity/binding、legacy HS384 + current-session membership、logout/platform/revoke/disable、single-factor 与损坏 fail-closed 门禁;ADR-0031 `0020` digest-bound ApprovalRequest、User-only decision、Project/Role version fence、精确 expiry/重放/并发裁决及同事务 immutable dispatch;ADR-0032 `0021` execution backfill、三表原子 consume、稳定 due keyset、claim/renew/start/result fencing、pre-start takeover/post-start recovery-required、attempt budget、handler inspect/digest barrier 和 bounded dispatcher;ADR-0033/`0022` control/resolution backfill、start/renew/completion 原子联动、稳定 recovery keyset、双 resolver claim/takeover、finding/result 精确重放、自动/人工终结、迟到 completion 单 winner 和 evidence-only bounded reconciler;ADR-0034/`0023` 首个 `run.create` canonical plan、Run/Attempt/Event/receipt 同事务、幂等 collision fail-closed、renew/终态 fence、真实 SQLite handler 与 automatic evidence provider;ADR-0035/`0024` 独立 `approval.recover` 矩阵、稳定 User + 五分钟强认证、Project/RoleBinding fence、human resolution + authorization fact 原子提交、撤权竞态与回滚门禁;ADR-0036 recovery-first 单 timer lifecycle、edge/standalone 独立 cadence/页预算、跨周期 cursor、非重叠与有界 stop;ADR-0074 以新的 Node 24 SQLite v5 ownerless Project/RoleBinding/audit authority 和独立 local-secret-admin 提供强 Principal、`secret.manage`、撤权 fence、envelope+allowed audit 原子提交及不回显语义;ADR-0086 以可信 POSIX console 和 staged delivery 完成本机首 Owner 产品 ceremony | fresh database/pepper setup 与安全迁移向导;`shareStore`/Express 到 authentication core 的 production migration;credential rotation/revocation API、mTLS/Worker enrollment、恢复码;Project/Role/Approval/Secret 管理 CLI/API/UI、audit retention/query/export/alert、preview Artifact/digest/immutable plan builder、真实 MFA/hardware adapter、人工 recovery API/UI/独立 rate limit 与审计事件、handler/provider registry、lifecycle startup/shutdown/指标/admission gate;PostgreSQL action/receipt/provider/recovery-authorization 与 OPA adapter、缓存 version 失效;Tool/Package/Secret/Shell 各自的 handler/evidence contract;Secret/Run/Tool/Workflow waiting_approval 全入口装配;完整回滚演练 |
|
||||
|
||||
@@ -239,7 +239,7 @@ Shadow Adapter 不得:
|
||||
|
||||
Shadow 转换仍必须遵守 ADR-0001。无法合法映射时追加 compat.transition_mismatch,不能强行覆盖终态。
|
||||
|
||||
当前 Alpha 切片对已审 Node worker origin 直接观察同一 ChildProcess 的 spawn、error 和 exit 事件,因此不依赖 Shell callback 才能形成基本终态。下述两级关联已补充 Shell callback、stop/cancel 和乱序/迟到回调;ADR-0448 又补充了监听前一次性启动恢复,ADR-0449 将其投影为 origin-bounded、版本化的差异报告与固定字段 metric batch。该 startup snapshot 仍不能替代跨测量窗口的历史终态对账与正式 Primary gate。
|
||||
当前 Alpha 切片对已审 Node worker origin 直接观察同一 ChildProcess 的 spawn、error 和 exit 事件,因此不依赖 Shell callback 才能形成基本终态。下述两级关联已补充 Shell callback、stop/cancel 和乱序/迟到回调;ADR-0448 又补充了监听前一次性启动恢复,ADR-0449 将其投影为 origin-bounded、版本化的差异报告与固定字段 metric batch。ADR-0450 再提供显式、只读、Profile-bounded 的闭合窗口终态审计;但 2.x RunningInstance 缺少可信 origin,因此它只证明已写 Shadow Run 到 Legacy evidence 的一致性,不能单独证明 Legacy→Shadow 捕获率或替代正式 Primary gate。
|
||||
|
||||
### 9.4 `next` Alpha callback 与 stop 关联
|
||||
|
||||
@@ -253,7 +253,7 @@ Shadow 转换仍必须遵守 ADR-0001。无法合法映射时追加 compat.trans
|
||||
6. 取消事实在 Legacy kill 前投递;同 worker 的后续 exit 排在取消之后。跨 worker 使用持久化定位器尽力关联,任何查询或写入失败都不能阻断 kill 或改变 2.x API 响应。
|
||||
7. 乱序 finished 可以从 queued/claimed 补齐 dispatching、starting、running 和终态;重复终态 callback、取消后的迟到成功 callback 不覆盖终态,也不追加重复完成事件。
|
||||
|
||||
这仍不是完整的 Shadow→Primary 门禁:ADR-0448 已提供启动后有界批量扫描、终态证据补齐、lost/abandoned 收敛和两事务 response-loss 修复;ADR-0449 已增加 startup 差异报表、固定低基数 metric batch 与可注入单次 collector,但尚未完成跨窗口终态差异查询、具体 exporter、资源/回滚演练和正式 Primary gate。后续能力不得让 edge 增加常驻 watcher 或无界内存队列。
|
||||
这仍不是完整的 Shadow→Primary 门禁:ADR-0448 已提供启动后有界批量扫描、终态证据补齐、lost/abandoned 收敛和两事务 response-loss 修复;ADR-0449 已增加 startup 差异报表、固定低基数 metric batch 与可注入单次 collector;ADR-0450 已完成不伪造反向捕获率的闭合窗口 Shadow→Legacy 终态差异查询。具体 exporter、Legacy→Shadow capture authority、资源/回滚演练和正式 Primary gate 尚未完成。后续能力不得让 edge 增加常驻 watcher 或无界内存队列。
|
||||
|
||||
### 9.3 Shadow 写失败
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# ADR-0450:闭合窗口的 Legacy Shadow 终态差异审计
|
||||
|
||||
- 状态:Accepted
|
||||
- 日期:2026-08-18
|
||||
- 关联 RFC:QL-RFC-0001 D-02、D-358、PR-4
|
||||
- 关联 ADR:ADR-0002、ADR-0448、ADR-0449
|
||||
- Amends:ADR-0449 的跨测量窗口待办
|
||||
|
||||
## 上下文
|
||||
|
||||
ADR-0448/0449 只证明一次启动时 active Shadow Run 的恢复结果,不能回答一个明确时间段内已经写入的 Shadow Run 是否与 Legacy 执行终态一致。
|
||||
直接用 startup scanned 计算比例会把未知尾页和未稳定执行混入分母;把全部 `RunningInstances` 当成 Shadow 应写集合也不成立,因为 QingLong 2.x
|
||||
表没有可信的 execution origin,manual、system crond 与其他 Legacy 路径可能复用同一 Cron。
|
||||
|
||||
部署跨度还要求同一能力既能在低性能路由设备运行,也能在 standalone 节点处理较大窗口。审计不能增加启动查询、常驻 timer、第二数据库 authority、
|
||||
无界数组或高基数指标,更不能为了“补齐”历史数据而改写 Run/Attempt/RunningInstance。
|
||||
|
||||
## 决策
|
||||
|
||||
1. 新增显式、只读、一次性的 `audit:legacy-shadow-terminal:ql3` 运维入口。调用方必须给出至少一个已支持 Shadow origin 以及
|
||||
`[windowStartMs, windowEndMs)`;窗口 cohort 以 `legacy-owned Shadow Run.created_at_ms` 为准,不自动选择“最近一段时间”。
|
||||
2. 窗口只有在 `windowEndMs <= observedAtMs - minimumSettlingAgeMs` 时闭合,默认 settling age 为五分钟。窗口未闭合、候选页未扫完或
|
||||
Legacy evidence 达到硬上限时,不输出任何比例。
|
||||
3. Source 使用 `(created_at_ms, run_id)` 稳定 keyset,复用现有 `Runs(project_id, created_at_ms)` 索引;Run 与 latest Attempt 在同一有界查询中读取。
|
||||
每页再执行一次有界 RunningInstance evidence 查询,不逐 candidate 发出 N+1 查询。单页候选硬上限 64、Legacy evidence 硬上限 512。
|
||||
4. Profile 默认预算保持与 startup recovery 一致:edge `8 × 1 page`,standalone `32 × 4 pages`。查询不安装 timer、watcher、线程、进程、连接池
|
||||
常驻生命周期或后台续扫;预算耗尽返回 `incomplete`,操作者缩小窗口后重试。
|
||||
5. 关联优先级固定为 direct Attempt/Run reference,其次同 Cron 下的 opaque log artifact ID、PID,最后才允许唯一且在容差内的 started time。
|
||||
多个候选或 evidence 截断一律归入 ambiguous,不用“最近一条”猜测。原始 log path 只在 adapter 内哈希,不进入 application/report。
|
||||
6. 每个 Shadow candidate 必须且只能归入八类之一:`matched`、`shadow_not_terminal`、`shadow_attempt_missing`、
|
||||
`shadow_attempt_ambiguous`、`legacy_evidence_missing`、`legacy_evidence_ambiguous`、`status_mismatch`、`field_mismatch`。
|
||||
aggregate 与按 origin matrix 都必须守恒。
|
||||
7. status、exit code、started time、finished time 与 log artifact 使用固定 dimension counters 记录 compared/matched/mismatched/unavailable。
|
||||
时间默认允许两秒精度差,硬上限一分钟;`terminalAgreementPermille` 与 `fullyComparablePermille` 只在窗口闭合、候选与 evidence 都完整且分母非零时出现。
|
||||
8. 报告 schema 为 `qinglong/legacy-shadow-terminal-difference-report@v1`。报告只包含 Profile、窗口、预算、固定计数、最多七条 origin matrix 和
|
||||
`matched/empty/differences_found/window_open/incomplete` assessment;不输出 Project/Run/Attempt/Cron/PID/log/task/user/error identity。
|
||||
9. 报告明确声明 `direction=shadow_to_legacy` 和 `legacyWithoutShadow=not_measured`。当前数据模型无法可靠证明“存在 Legacy 执行但 Shadow Run 未写入”,
|
||||
因而本报告不能单独作为 Primary gate;D-360 必须组合 observer failure/capture evidence,或先引入可信 origin-scoped admission ledger。
|
||||
10. 审计不写数据库、不修复差异、不启动 Executor、不改变 Legacy 返回值。`--fail-on-difference` 只把非 `matched` assessment 映射为进程退出码 1,
|
||||
供人工 rollout/CI gate 使用。
|
||||
|
||||
## 资源与部署影响
|
||||
|
||||
- 不新增 package、生产依赖、schema、migration、表、索引、数据库 authority、HTTP/gRPC 路由、timer、watcher、worker、容器或 Kubernetes 对象。
|
||||
- edge 默认最多读取 8 个 Shadow candidate 与 64 条 Legacy evidence;standalone 默认最多 128 个 candidate 与每页 256 条 evidence。
|
||||
- CLI 数据库连接固定只读、单连接池;报告为固定字段 aggregate,不保留 candidate identity,也不建立进程内累计 registry。
|
||||
- `Runs(project_id, created_at_ms)` 负责 cohort keyset;RunningInstance 查询每页一次且结果有硬上限。若未来固定设备证明表扫描 CPU 不可接受,应通过新 migration
|
||||
增加 `(cron_id, started_at, id)` 索引并单独评审升级写放大,而不是在本 ADR 中静默修改已发布 migration checksum。
|
||||
|
||||
## 被拒绝的替代方案
|
||||
|
||||
### 双向扫描所有 RunningInstances 并计算 Shadow 捕获率
|
||||
|
||||
拒绝。2.x `RunningInstances` 没有可信 execution origin,无法知道某条记录是否属于已开启 Shadow 的入口;把它们都放进分母会制造假阴性。
|
||||
|
||||
### 在每次 HTTP startup 自动审计历史窗口
|
||||
|
||||
拒绝。它会重复 D-356 的启动查询、延迟路由设备监听,并需要隐式选择时间窗口。历史证据必须由操作者显式触发。
|
||||
|
||||
### 为每个 Shadow candidate 单独查 RunningInstances
|
||||
|
||||
拒绝。即使 candidate 数有上限,N+1 仍会让低性能 SQLite 设备承担不必要的查询调度和重复表扫描。
|
||||
|
||||
### 只输出差异明细 ID 方便排障
|
||||
|
||||
拒绝。运维日志会泄露高基数任务身份;需要明细时应新增受认证、Project-scoped 的诊断产品面,而不是扩大默认 CLI 报告。
|
||||
|
||||
## 验证
|
||||
|
||||
- 真实 SQLite 覆盖完全一致、status/exit field 差异、missing/ambiguous evidence、active Shadow、窗口未闭合、edge 页预算耗尽、evidence overflow、
|
||||
双 origin 守恒、空分母和只读 CLI 脱敏输出。
|
||||
- 真实 SQLite/CLI 聚焦测试 `14/14`、Legacy/Shadow 串行扩展 `91/91`、`build:back`、完整 backend
|
||||
`1,455 pass / 0 fail / 2 conditional skip`、18-package clean build/test、14/14 static audit 与 14/14 artifact audit 全部通过。
|
||||
- edge/standalone 的 base、adopted、application、application-api、AI、application+AI、MCP 产物分别为
|
||||
`2,589,998 / 2,590,076`、`2,809,293 / 2,809,416`、`3,632,877 / 3,632,997`、
|
||||
`3,800,430 / 3,800,574`、`3,069,251 / 3,069,341`、`4,493,151 / 4,493,283`、
|
||||
`7,315,930 / 7,316,038` bytes,与 D-357 完全一致。
|
||||
- 本切片不修改 PostgreSQL、容器或 Kubernetes 部署面,因此物理 PostgreSQL HA/K3s 门不作为本切片的新证据;D-359 仍负责 edge/standalone 资源压力与
|
||||
Shadow-off 回滚演练。
|
||||
@@ -453,6 +453,7 @@
|
||||
| [ADR-0447](./ADR-0447-boot-shadow-and-non-origin-boundaries.md) | Boot Shadow 准入与 once/gRPC 非 Origin 边界 | Accepted |
|
||||
| [ADR-0448](./ADR-0448-bounded-legacy-shadow-startup-reconciliation.md) | 有界 Legacy Shadow 启动恢复 | Accepted |
|
||||
| [ADR-0449](./ADR-0449-versioned-legacy-shadow-startup-difference-report-and-metrics.md) | 版本化 Legacy Shadow 启动差异报告与指标批次 | Accepted |
|
||||
| [ADR-0450](./ADR-0450-closed-window-legacy-shadow-terminal-difference-audit.md) | 闭合窗口的 Legacy Shadow 终态差异审计 | Accepted |
|
||||
|
||||
## 规则
|
||||
|
||||
|
||||
Reference in New Issue
Block a user