路径说明(2026-09-20): 本文成稿时
docker-compose-storage-only.yml/docker-compose-storage-only.auth-none.yml/docker-compose.test.yml位于仓库根;2026-09-20 起三者迁入docker/目录(commit1854cae)。文中根目录原路径为历史记录,不再逐一回改;实际使用时请替换为docker/前缀路径。
改名註記(2026-09-17): 本文成稿與執行時,Cargo 包名/二進制名為舊名,lib 為舊名
_core;2026-09-17 起全倉統一改名為 Mega2(mega2/mega2_core),本文中的命令、路徑、環境變量與服務名已同步更新,歷史提交記錄本身不變。
模板版本: v2(2026-07-29 起生效;本计划整份符合 docs/plan/plan-template.md v2)。
本文解决「monorepo 根树写入无序列化(并发写入互相覆盖、路径 ref 与根树视图分叉)」与「不接入用户系统、不使用 Issue 与 Change List 的 storage-only 部署形态下,Git 推送如何直接落入 main」两个问题,目标是交付:MonoWriteQueue 全局写入序列化(顺序 + 事务级 advisory lock + 根 ref CAS tripwire)、后代 ref 续接与墓碑、合成 commit 的真实归属与 provenance、push_policy = "trunk" 直推形态、无用户系统的静态 token 推送认证。
设计事实源是 docs/refactoring/trunk-push.md(2026-09-05 修订 66,经 Codex/Claude 双评审 PASS——Codex 第 59 轮、Claude 第 3 轮;事实校准 17 条、ADR-TP-01..20 含 15a、不变式 I1–I6 含 I2a、阶段 1 交付物 10 项、修订记录 66 条)。本计划不复制其设计论证,只把已决议设计落成可执行任务卡;实现时若需偏离 ADR,必须先修改 trunk-push.md 与本计划并说明原因。
与事实源的阶段对齐(2026-09-05 修订 2):trunk-push.md 在双评审中把基础静态 token 认证自阶段 5 前移至阶段 4 的 4.2a(push_policy=trunk 强制显式 push_auth),阶段 5 收窄为「多 token 运维与认证强化」且未给出可执行规范——本计划据此把 TP-19/TP-20 移入 Phase 4,阶段 5 的多 token 运维登记为 DEFER-TP-05(重启条件 = trunk-push.md 阶段 5 补齐规范)。另据同批评审修订:阶段 1 不可独立上线生产(其删除式后代处理违反 I1,生产部署以阶段 2/TP-14 为前置);B0 不做任何拒绝性 NFF 判定(遥测);pending_action 仅保留 requeue_conflict(根绕过判定由 B2.5 落库的 expected_* 基线 + reaper 通用 I3 修复承担);trunk 形态 LFS 不可用。
本文只规划任务,不宣称实现完成。落地时每个任务都必须先刷新源码锚点(GC-01),再按任务卡验收。
- 队列基础设施:新增
push_queue/queue_control实体与迁移、MonoWriteQueuestorage/service/router 四层(泛化自merge_queue)、B0–B4 算法、reaper、控制面。 - 根树写入路径:
src/ceres/api_service/mono_api_service.rs(merge_cl_unchecked/apply_update_result/process_ref_updates)、src/ceres/pack/import_repo.rs(attach)、src/ceres/pack/monorepo.rs(finalize_receive_pack/refs_with_head_hash/traverses_tree_and_update_filepath)、src/jupiter/storage/mono_storage.rs。 - 一致性机制:
mega_ref_tombstones墓碑表、blob_paths出现对索引表、B3 树哈希断言、物化插入校验、对账与周期巡检。 - 配置与认证:
[monorepo].push_policy、[monorepo].max_push_commits、[git].push_auth/[[git.push_tokens]]、src/server/http_server.rs启动门槛、src/contract/git_protocol/认证挂点。 - 测试与文档:
tests/integration_git_cli.rs、scripts/git_protocol_smoke.sh本地等价、docs/refactoring/trunk-push.md的同步、docs/monorepo.md反向声明、部署文档。
- 不改 review 形态的既有语义:阶段 1–3 的队列化与缺陷修复不得改变 CL 创建/检查/合并的判定、门控与拒绝面;既有测试用例期望值不得修改。两类登记在案的显式豁免:后代 ref 续接(缺陷修复本身)与 merge 的队列生命周期变化(背压、
wait_timeout、异步转同步)——见 trunk-push.md 硬约束 8。 - 不引入用户系统 / Issue / Change List:trunk 形态的认证只交付 git-over-HTTP 静态 token;SSH receive-pack 在 storage-only 形态下不暴露(TP-20)。
- 不做多分支单推送、merge commit 入链、根路径 clone:沿用 ADR-MC-04 / MC-03 的既有拒绝面;根路径推送不作为该形态假设。
- 不做 Redis 队列、不做乐观 CAS 并发模型:ADR-TP-01/02 已否决。
- 不承诺逐 commit GPG 签名验证:ADR-TP-15a,N=1 的签名保留是零改写副产物、非可依赖保证。
- 阶段 6 四项优化(group commit / LISTEN-NOTIFY / 实时进度 / 物化 TTL)不进入本计划执行:登记为 DEFER-TP-01..04,无实测压力证据不启动。
- 阶段 5 的多 token 运维与强化不进入本计划执行:登记为 DEFER-TP-05(trunk-push.md 阶段 5 收窄后未给出可执行规范;基础认证已随 4.2a 进阶段 4/TP-19)。
- trunk 形态 LFS 不可用:LFS 路由经
UserStorage认证(lfs_router.rs:205-213/235-250),静态 token 模型不覆盖 LFS 批/锁授权——trunk 形态关闭 LFS 写路由并在部署文档声明(TP-18);token-aware LFS 授权为独立议题。
- 全部根树与路径 ref 写入者(trunk 推送、CL merge、ImportRepo attach、两条惰性物化路径)要么经
MonoWriteQueue串行、要么被 ADR-TP-20 机制显式覆盖;根 ref CAS 断言恒不失败(不变式 I5)。 - 并发写入不再互相覆盖:根树在任一提交边界等于所有路径子树的一致快照(不变式 I3);已物化路径历史只增不改(I1);每次推送在每个受影响的层恰好前进一个 commit(I2a)。
push_policy = "trunk"下:N = 1 推送客户端 commit 原样落地(hash/作者/时间/message 逐字不变),N > 1 自动 squash 为一个 commit 且 tree 保真(I2),squash message 完整枚举全部 N 条不截断(I4);trunk 与cedar.enforcement != "off"互斥于启动期 fail-closed 拒绝。- 无用户系统部署可经静态 token 推送(
push_auth = "token",组件边界路径授权;push_auth = "none"需显式配置;push_auth ∈ {token,none}强制push_policy = "trunk",反向trunk强制显式push_auth——4.2a 随阶段 4 交付)。trunk 形态 LFS 不可用(TP-18)。 - 全部 23 张任务卡(TP-01..TP-23)
Lifecycle=done且Acceptance=complete;三门全绿;外部双评审(Codex/Claude)对本计划 PASS;docs/monorepo.md反向声明与部署文档同步完成。
所有行号和源码锚点必须在开工当天刷新(GC-01)。下列锚点核对日为 2026-09-04(
docs/refactoring/trunk-push.md事实校准日;该文档 2026-09-05 经 66 条修订与双评审 PASS,本表已按其终版对齐)。
| 类别 | 当前事实 | 证据 |
|---|---|---|
| 代码入口 | 分支命令经 finalize_receive_pack → persist_mono_branch_cl_mega_refs_transaction → apply_cl_mega_ref_for_push_command 落地为 refs/cl/<id>;run_mono_post_push_pipeline 调 update_or_create_cl;update_refs 只在 tag 命令时被 smart.rs:450 调用(拒绝 Tag) |
src/ceres/pack/monorepo.rs:205/676/863-877/913/916-939/975 |
| 代码入口 | 根树推进只发生在 CL merge 与 ImportRepo attach;attach 有 (ref_commit_hash, ref_tree_hash) 双条件 CAS + MAX_ATTACH_ATTEMPTS=64 重试;push/merge 路径无锁盲写 |
src/ceres/api_service/tree_ops.rs:263-271、src/jupiter/storage/mono_storage.rs:287/453-483、src/ceres/pack/import_repo.rs:507-513 |
| 代码入口 | RedLock 只接在 ImportRepo attach 路径 |
src/ceres/protocol/mod.rs:202、src/ceres/pack/import_repo.rs:513 |
| 代码入口 | 批量 ref 更新经 FuturesUnordered 并发执行、无法加入事务、对缺失行静默跳过;单 ref 的 save_refs/update_ref 已支持事务 |
src/jupiter/storage/mono_storage.rs:65-73/188-199/287-333 |
| 数据/状态 | merge_queue 四层齐备(storage/service/router/DTO);互斥 AtomicBool 仅进程内、claim 无 FOR UPDATE SKIP LOCKED、position 为毫秒时间戳;冲突失败重排队到队尾(Conflict → move_item_to_tail);QueueStatusEnum 是 CL 工作流状态机(Waiting/Testing/Merging/Merged/Failed) |
src/jupiter/service/merge_queue_service.rs:169、src/jupiter/storage/merge_queue_storage.rs:83/178、src/ceres/api_service/mono_api_service.rs:4419-4429、src/callisto/sea_orm_active_enums.rs:228-239 |
| 代码入口 | 子路径 main ref 懒生成无父 commit;两条物化路径(advertise/clone 与 code_edit)无锁、无 CAS、无版本检查 |
src/ceres/pack/monorepo.rs:121/129-135、src/ceres/code_edit/utils.rs:362-442、src/ceres/protocol/smart.rs:76-88 |
| 代码入口 | remove_none_cl_refs 删除后代 ref;starts_with 无组件边界且不转义 LIKE 元字符;唯一调用点 |
src/jupiter/storage/mono_storage.rs:77-84、src/ceres/api_service/mono_api_service.rs:2617-2622 |
| 代码入口 | 合成 commit 归属硬编码 mega <admin@mega.org>(git-internal 0.8.7 外部依赖);process_ref_updates 以路径自身旧 tip 为 parent(祖先方向已具备续接语义) |
git-internal 0.8.7 外部依赖的 src/internal/object/commit.rs:104-128;仓内 src/ceres/api_service/mono_api_service.rs:623-668 |
| 代码入口 | validate_incoming_push 执行 ADR-MC-04 单分支准入与 MC-03 PushChain::validate(拒绝 merge commit、拓扑连续、tip 匹配);链长硬编码 MAX_CL_CHAIN_COMMITS=250;ordered_commits tip 在前 |
src/ceres/pack/monorepo.rs:1153、src/ceres/pack/push_chain.rs:182-205/408-447/469-482、src/ceres/merge_checker/mod.rs:20-27 |
| 数据/状态 | mega_refs 唯一索引 uniq_mref_path(path, ref_name);列为 path/ref_name/ref_commit_hash/ref_tree_hash/is_cl/时间戳 |
src/jupiter/migration/m20250314_025943_init.rs:268-277 |
| 代码入口 | 文件路径索引 traverses_tree_and_update_filepath 从 tip 递归重建、成本与子树规模成正比、当前在临界区内;mega_blob.file_path 单列无出现对语义 |
src/ceres/pack/monorepo.rs:704/1051-1114、src/callisto/mega_blob.rs:6-22 |
| 代码入口 | 合并侧门控(UN-19 ACL 自提权、GPG ensure_gpg_check_passed)都在合并入口/processor,不在推送路径 |
src/ceres/api_service/mono_api_service.rs:2124/2135/2580-2592/4599 |
| 配置项 | [monorepo] 仅 import_dir/admin/root_dirs/object_format/rename,无直推字段;import_dir 属 restart_required_fields |
src/config/model.rs:141、src/config/reload.rs:697、src/config/validate.rs:522 |
| 代码入口 | HTTP 启动两道 OAuth 门槛(require_oauth_for_http_service + app() 内取用);git token 认证走 UserStorage;check_push_permission 在 cedar off 时仍要求非空 username;SSH 要求已认证用户 |
src/server/http_server.rs:424-425/627-650、src/config/validate.rs:162-169、src/contract/git_protocol/http.rs:60-65/105-149/354-365、src/contract/git_protocol/mod.rs:43-62、src/contract/git_protocol/ssh.rs:135-157 |
| 文档 | 设计事实源(ADR-TP-01..20 含 15a、不变式 I1–I6、阶段 1–6、验收清单) | docs/refactoring/trunk-push.md(2026-09-04 校准) |
| 测试 | 现有集成测试 target(8 个);git 协议 smoke 骨架 | tests/integration_git_cli.rs、scripts/git_protocol_smoke.sh、docs/refactoring/integration.md |
| 工作区前置 | 单 Cargo 包(plan-20260824 收口);版本面一处(Cargo.toml 的 version);测试栈 Postgres 15432 / Redis 16379 / Mailpit / RustFS |
Cargo.toml;docker-compose.test.yml;ER-01 |
| 代码入口 | 直连 merge 路由 /merge、/merge-no-auth(cl_router.rs:218-223/279-304)直接调 merge_cl(:2107-2128,入口预检拒绝 cl.from_hash != main、缺失 ref 拒绝 :2113-2118)在队列外执行 merge_cl_unchecked;/merge-queue/add 入队即返回依赖后台 processor |
src/api/router/cl_router.rs:203-304、src/api/router/merge_queue_router.rs:43-55、src/ceres/api_service/mono_api_service.rs:2107-2128 |
| 数据/状态 | mega_cl 无单调 revision 列;merge 状态更新与 rebase 均为无条件更新(cl_storage.rs:374-379/404-415),rebase/merge 反序竞态可把 Merged 改回 Open |
src/callisto/mega_cl.rs、src/jupiter/storage/cl_storage.rs:374-415、src/ceres/api_service/mono_api_service.rs:3293-3301/3441-3463 |
| 代码入口 | build_push_chain 对空链/全已知链返回 None(Noop 短路,validate_incoming_push 随即成功返回)——trunk 形态须改为继续入队 |
src/ceres/pack/monorepo.rs:1191-1247、src/ceres/pack/push_chain.rs:104-115 |
| 代码入口 | LFS 路由经 UserStorage 认证(静态 token 不覆盖 LFS 批/锁授权) |
src/api/router/lfs_router.rs:205-213/235-250 |
| 外部参照 | 本 checkout 的 .github/workflows/ 与 .github/workflow/ 均为空目录(2026-09-05 核对);D 组判定一律以开工时远端仓库的 workflow 现场读取为准 |
.github/workflows/ |
| ID | 缺口 | 影响 | 证据 | 计划动作 |
|---|---|---|---|---|
| GAP-01 | 根树写入无序列化(push/merge 路径无锁盲写,attach 仅有单路径 CAS) | 并发写入互相覆盖根树,路径 ref 与根树给出互相矛盾的视图且无报错 | tree_ops.rs:263-271、mono_storage.rs:287 |
TP-03/04/07 |
| GAP-02 | 批量 ref 更新无法加入事务、对缺失行静默跳过(首次向新路径推送会悄悄丢失 main@P) |
B3 单事务无法落地;创建语义缺失 | mono_storage.rs:287-333 |
TP-02/12 |
| GAP-03 | merge_queue 三互斥缺陷(进程内互斥、非原子 claim、时间戳序号)+ 异步执行模型 |
跨实例无全序;两个 processor 可取同一项;同毫秒入队顺序不确定 | merge_queue_service.rs:169、merge_queue_storage.rs:83/178 |
TP-03/07 |
| GAP-04 | remove_none_cl_refs 删除后代 ref(历史断裂,refusing to merge unrelated histories),且 LIKE 前缀无组件边界、不转义元字符 |
父路径推送后子路径 clone 者无法 pull/推送 | mono_storage.rs:77-84 |
TP-02/14 |
| GAP-05 | 合成 commit 归属硬编码 mega <admin@mega.org> + 常量 message |
根与祖先层历史不可审计 | git-internal 0.8.7(外部依赖)src/internal/object/commit.rs:104-128;仓内调用点 mono_api_service.rs:623-651 |
TP-16 |
| GAP-06 | 子路径懒生成无父 commit、无墓碑,删除后不可续接 | 路径复活即 unrelated history | monorepo.rs:121 |
TP-09/14 |
| GAP-07 | 两条惰性物化路径从各自根快照无锁写 mega_refs(本计划编号;勿与 trunk-push.md 的 GAP-07 CL 命名分歧混淆) |
物化行落后于根树;以它为基线的推送静默覆盖祖先改动(ADR-TP-19 失效链) | monorepo.rs:121、code_edit/utils.rs:362-442 |
TP-10/11 |
| GAP-08 | 无 push_policy 直推路径;review 形态推送只写 refs/cl/* |
storage-only 部署无法直推 main |
monorepo.rs:205/913/975、config/model.rs:141 |
TP-15/17 |
| GAP-09 | 推送认证强依赖 OAuth/UserStorage/SSH 用户,无静态 token 模型 | 无用户系统部署无推送通道 | http_server.rs:424-425、git_protocol/http.rs:105-149 |
TP-19/20 |
| GAP-10 | 文件路径索引重建在临界区内且无代际水位,删除的 blob 会被旧任务写回 | 大子树推送独占写入闸门;索引删除复活 | monorepo.rs:704/1051-1114 |
TP-13 |
| GAP-11 | 直连 merge 路由(/merge、/merge-no-auth、/merge-queue/add)在队列外执行 merge_cl_unchecked |
未覆盖的根树写入者,破坏队列全序前提(ADR-TP-09) | cl_router.rs:218-223/279-304、merge_queue_router.rs:43-55 |
TP-07 |
| GAP-12 | mega_cl 无单调 revision,merge 状态更新与 rebase 均无条件写 |
rebase/merge 反序竞态可把 Merged 改回 Open |
cl_storage.rs:374-415 |
TP-07 |
| GAP-13 | LFS 路由经 UserStorage 认证,静态 token 模型不覆盖 |
trunk 形态(cedar off + 静态 token)下 LFS 写通道无授权模型 | lfs_router.rs:205-213/235-250 |
TP-18(关闭) |
| GAP-17 | attach 路径的 RedLock(30s TTL Redis 互斥锁)在队列吸收后残留——跨系统锁缝正是 ADR-TP-02/03 否决的模式 |
残留的 Redis 锁在 advisory lock 序列化之外引入无 TTL 竞争面 | src/ceres/protocol/mod.rs:202、src/ceres/pack/import_repo.rs:513 |
TP-08 |
| GAP-14 | build_push_chain 对空链/全已知链返回 None(Noop 短路),validate_incoming_push 随即成功返回 |
trunk 形态下这类推送绕过 B1/B3、虚报成功(trunk-push.md 1.10 交付物 10) | monorepo.rs:1191-1247、push_chain.rs:104-115 |
TP-12 |
| GAP-15 | authz 快照屏障三件套(B3 事务内 outbox、published_version 单调 CAS 发布、按实例读取屏障)缺失,现状为内存 best-effort |
enforce 模式下 UN-19 重查可能读到陈旧快照;乱序发布覆盖新快照 | src/contract/policy/notify.rs:27-92、entitystore.rs:148-219 |
TP-22 |
| GAP-16 | 阶段 1.1 写入者审计(穷举 + 三类分法 + trunk-push.md 回写)无执行载体 | 写入者清单停留在散文,缺机器可核对条目与回写验收 | trunk-push.md 阶段 1.1、mono_service.rs:103-125 |
TP-23 |
| 计划/文档 | 关系 | 本计划处理 |
|---|---|---|
docs/refactoring/trunk-push.md |
设计事实源(ADR-TP-01..20、不变式、阶段 1–6、验收清单) | 全部任务卡从该文档的交付物清单派生;实现偏离必须先改该文档与本计划 |
plan-20260827.md(CL 多 commit push 放开) |
前置已完成;其 merge_queue 四层、PushChain、MC-03 校验、MC-09 ServerSigningContext、ADR-MC-04/07 是本计划消费的现成原语 |
复用不重做;MAX_CL_CHAIN_COMMITS 常量语义在 review 形态保持不变(TP-15 只新增 trunk 独立配置) |
plan-20260903.md(object-ID 配置) |
并行;改动面在配置与协议对象格式,与本计划写集基本不相交 | 开工时按 GC-01 核对收口状态;若写集相交补顺序边 |
plan-long.md |
无直接对应 PT 项 | 不触碰 |
docs/monorepo.md |
产品规则事实源;trunk-push.md 的反向声明(N 分流语义、I1–I6、墓碑续接、索引最终一致、ADR-TP-18 对齐约定)已由 TP-21 同步 | TP-21 已完成;见 docs/monorepo.md §8–11 与 ../deploy-trunk.md |
docs/refactoring/protocol.md |
receive-pack 分层事实源 | 协议层改造(TP-10/17)完成后同步 |
docs/refactoring/general.md / contract.md / config.md / integration.md / test-infra.md |
治理规范 / Cedar 与权限 / SecretRef / 测试栈 | 遵守;新增 e2e 用例登记进测试矩阵与 integration.md |
AGENTS.md / README.md |
工程约束基线(三门、ER-07、GC-12) | 遵守;trunk-push.md 的「文档概览 5a」登记在 docs/refactoring/README.md(非根 README.md),本计划不新增条目(TP-21 若需再同步) |
| 维度 | 结论 | 修订动作 |
|---|---|---|
| 合理性 | 高:写入序列化被论证为语义必然而非性能取舍(trunk-push.md 硬约束 1);storage-only 直推是明确的部署需求 | 无 |
| 可行性 | 中高:全部写入者类别已定位;队列可泛化自 merge_queue 四层;build_result_by_chain / apply_update_result / ServerSigningContext 均为现成原语;不足:B3 依赖的事务内 ref 更新原语需新增(GAP-02) |
TP-02 前置 |
| 任务卡粒度 | 23 卡全部单一行为轴、S/M;无 L/XL;无未登记合并发布(AC 均 ≤8,TP-21 docs 卡 10/12) | 见任务卡粒度审计表 |
| 依赖与顺序 | DAG 无环;阶段 1(队列 + 写入者接入 + authz 屏障)→ 阶段 2(后代续接)→ 阶段 3(归属)→ 阶段 4(trunk 接线 + 4.2a 认证,TP-19/20 先于 TP-17 e2e)→ 阶段 5(文档收口;阶段 5 多 token 运维延后 DEFER-TP-05) | 见实施顺序 |
| 完整性 | 测试/文档/迁移/回滚齐;新增 7 项迁移产物全部 forward-only(仓库无 migrate down 入口) |
无 |
| 安全性 | trunk 与 cedar enforce 互斥(启动 fail-closed);CAS tripwire + 对账巡检;静态 token 组件边界授权(先于且独立于 Cedar);push_auth="none" 需显式配置;push_auth ∈ {token,none} ⇔ push_policy=trunk 双向启动校验 |
无 |
| 功能正确性 | 不变式 I1–I6 全部可测;每个已知缺陷配回归;B3 单事务 + fencing + 意图两段式覆盖崩溃窗口 | 无 |
| 接口兼容 | push_policy 默认 review,既有部署行为不变;阶段 1–3 不改变 CL 可观察语义(硬约束 8 的豁免登记在案);新增配置全部 additive;trunk 形态 LFS 不可用(TP-18 关闭并声明) |
无 |
| 数据流与控制流 | B1 准入锁保证 FIFO;B2.5 认领先行 + expected_* 基线同事务落库 + queue_control 行锁串行化认领;reaper 持锁判定无 TOCTOU;1.11 幂等三态 + 收养/回放 |
无 |
| 性能与容量 | B3 成本以「已物化路径数」为界;索引重建移出临界区;message 25 KB 上限为已接受代价 | 见性能与容量摘要 |
| 可靠性与容错 | B3 单事务 + advisory lock 随连接释放 + reaper 按行比对 expected_* 基线并幂等补做重排意图 + 通用 I3 修复(按 kind 分语义)+ heartbeat 孤儿清理 + watchdog 升级路径 |
无 |
| 可维护性 | 队列是序列化闸门与生命周期台账而非作业执行器;写入者审计(1.1)为完备性第一依据 | 无 |
| 日期 | 触发 | 变更内容 | 原卡 → 新卡 | 受影响的引用 |
|---|---|---|---|---|
| 2026-09-05 | 成稿 | 初版,TP-01..TP-21(阶段 1×13、阶段 2×1、阶段 3×2、阶段 4×2、阶段 5×2、阶段 6×1 文档);DEFER-TP-01..04 登记阶段 6 优化;ADR-TP-01..20 引用 trunk-push.md | N/A | N/A |
| 2026-09-05 | 对齐 trunk-push.md 修订 66(双评审 PASS 后终版) | ①TP-19/TP-20 移入 Phase 4(4.2a 认证前移),Phase 5 改为文档收口(TP-21),阶段 5 多 token 运维登记 DEFER-TP-05;②TP-01 schema 对齐(pending_action 仅 requeue_conflict、queue_control.last_policy);③TP-03 补 B2.5 认领先行/expected_* 基线/双认领者并发、B0 NFF 预检降级遥测;④TP-04 移除 verify_root 预标记、改 expected_* 比对前置分支与 CAS 终态状态条件;⑤TP-05/TP-11 意图模型收敛(reaper 每行 Running 比对基线 + 通用 I3 修复按 kind);⑥TP-07 补直连入口入队/mega_cl revision 全量 CAS/存量端点映射/merge 缺行拒绝;⑦TP-08 补祖先/后代物化拒绝;⑧TP-09 补升级前删除回填/fail-closed;⑨TP-10 补重试绕过 heads_exist;⑩TP-11 断言先于 NFF、对账按 kind;⑪TP-12 创建 N=0 不可达、trunk 删除策略;⑫TP-13 隔离规则/收敛声明/版本来源分离;⑬TP-15 启动校验六条 + 水位重置置 NULL;⑭TP-18 LFS 关闭;⑮发布分组修正(阶段 1 不可独立上线生产,I1);⑯新增 TP-23(阶段 1.1 写入者审计卡,GAP-16)与 GAP-14/15/16/17(GAP-17 = attach 的 RedLock 退役);⑰TP-07 补单写者开关 [monorepo].merge_writer 配置定义 |
TP-01..TP-23(新增 TP-23) | 事实基线/GAP-11..16/成功定义/非目标/里程碑/测试矩阵 |
| 2026-09-09 | TP-21 文档收口 | 反向声明写入 docs/monorepo.md §8–11;新增 docs/deploy-trunk.md;trunk-push.md 头部「已同步」;integration.md 四条 e2e;errors.md N/A;crate 版本策略改为 只 patch、不 minor(TP-18 的 0.9.0 已回写 0.8.1) |
TP-21 done |
DEP-03、Phase 5、R28 |
| 2026-09-09 | 计划完成门 | source .env.test && cargo test --all EXIT:0(host git + git-lfs 3.7.1);补 ssh_receive_pack=false 与 rooted file_path 断言;TP-01/04/22/23 遗留勾选与 D 组 N/A |
N/A | 完成判据、R29 |
本计划的设计决策全部记录于 docs/refactoring/trunk-push.md 的「决策记录(ADR-TP)」一节(ADR-TP-01..20,另含 ADR-TP-15a),实现时若需偏离必须先修改该文档与本计划(G-05:不复制全文,以事实源为准)。下表为决策摘要与承接卡映射:
| ADR | 决策摘要 | 承接卡 |
|---|---|---|
| ADR-TP-01 | 全局单写入者,不做子树并行;乐观 CAS 已否决 | TP-04 |
| ADR-TP-02 | 队列基座选 Postgres,不选 Redis | TP-01/03 |
| ADR-TP-03 | 互斥用事务级 advisory lock(MONO_WRITE_LOCK),不用会话级/RedLock |
TP-04 |
| ADR-TP-04 | 推送同步阻塞等待轮次,队列不是异步作业队列 | TP-03 |
| ADR-TP-05 | 闸门粒度是「根树写入者」;merge_queue 被吸收而非并存(冲突关行重入队;attach 重试循环删除;全部 merge 入口统一入队——直连 /merge、/merge-no-auth、/merge-queue/add 同步化) |
TP-07/08 |
| ADR-TP-06 | FIFO 序号取 bigserial;trunk commit 保序但非一一对应(空洞) |
TP-01/03 |
| ADR-TP-07 | 轮次失败不冻结队列;CAS 失败(QueueBypassDetected)是显式例外 → 硬停 |
TP-04/05 |
| ADR-TP-08 | 背压 = 深度上限 + wait_timeout(只约束 B2 等待,到期放弃不取消共享行) |
TP-03 |
| ADR-TP-09 | 根 ref CAS 是 tripwire 断言而非并发控制,失败不重试 | TP-04 |
| ADR-TP-10 | 同一路径同时只允许一项「推送」在队(kind='push' 唯一部分索引) |
TP-01/03 |
| ADR-TP-11 | 文件路径索引移出临界区,接受最终一致(出现对表 + 行级水位 + 删除感知 reconciliation) | TP-13 |
| ADR-TP-12 | 按 N 分流:N=1 原样落地,N>1 在被推路径 squash 为一个 | TP-12/16 |
| ADR-TP-13 | roll-up 作者身份取链上 tip,其余作者进 Co-authored-by |
TP-16 |
| ADR-TP-14 | committer date = max(落地时刻, 前一 trunk commit 的 committer date);author date 原值 |
TP-16 |
| ADR-TP-15 | squash message 完整枚举全部 N 条不截断;祖先/后代带 Mono-Squash-Commit 指针 |
TP-16 |
| ADR-TP-15a | 逐 commit GPG 签名验证不作为受支持能力;合成 commit 由服务端签名 | TP-16 |
| ADR-TP-16 | 净零变更推送只推进被推路径(「受影响的层」判定) | TP-12 |
| ADR-TP-17 | 链长上限:review 保留 MAX_CL_CHAIN_COMMITS;trunk 引入 max_push_commits 可配(需参数化 PushChain) |
TP-15 |
| ADR-TP-18 | N>1 推送后客户端必须 git fetch && git reset --hard origin/main 对齐,服务端两处告知 |
TP-17 |
| ADR-TP-19 | 后代 ref 恒与 B3 同事务推进;I3 强一致不分层;惰性后代推进否决 | TP-14 |
| ADR-TP-20 | 惰性物化不入队:「插入时根身份对校验 + B3 树哈希断言与墓碑修复(SAVEPOINT 同事务,崩溃窗口由 B2.5 expected_* 基线 + reaper 通用 I3 修复兜底)+ 对账巡检」三层覆盖 |
TP-10/11 |
本节不重述 docs/plan/plan-template.md v2 的 GC-01..GC-12 全文,全部继承;以下为本计划特有补充:
- GC-TP-01 队列纪律(I5 前提): 任何改写根树或
refs/heads/main行的代码必须经MonoWriteQueue、在审计清单中登记为队列外并被 ADR-TP-20 覆盖、或属于服务接流前完成并持专属锁的 bootstrap(initialize_monorepo,mono_service.rs:103-125——trunk-push.md 硬约束 2 的第三类,I5 三分法)。不得在 B3 事务之外新增根 ref 写入点;新增写入者必须同步 trunk-push.md 硬约束 2 的清单与本计划。 - GC-TP-02 B3 单事务: 轮次的 ref/commit/tree/CL 状态写入必须在同一
&DatabaseTransaction内;禁止在 B3 内使用自建连接的原语(batch_update_by_path_concurrent原形、自建连接的remove_none_cl_refs等)。merge/rebase 的 CL 行更新一律携带单调 revision 全量 CAS(GAP-12,双向串行化);CL 创建/检查等其他状态写不受影响(trunk-push.md 1.11/1.9)。 - GC-TP-03 review 形态可观察行为不变(硬约束 8): 阶段 1–3 的任务不得改变 CL 创建/检查/合并的判定、门控与拒绝面;既有测试用例期望值不得修改。三类登记在案的豁免(trunk-push.md 登记在案,仅限其验收标准所列行为变化):①后代续接缺陷修复;②merge 队列生命周期变化(背压/
wait_timeout/异步转同步);③文件路径索引的形态隔离规则(队列轮次打水位后,review 推送的索引仅IS NULL行生效——trunk-push.md ADR-TP-11 登记为有意设计,索引不在写入判定链上)。 - GC-TP-04 失败可见性: 禁止沿袭「空 refs / capabilities-only / 静默跳过」的失败模式(
smart.rs:76-88把空 refs 编码为 capabilities-only、mono_storage.rs静默跳过缺失行);物化放弃、被拒轮次、CAS 失败都必须产生可诊断报错或显式终态。B0 的乐观 NFF 预检只作遥测不拒绝——拒绝权威唯一归属 B3(无锁的 B0 拒绝会在陈旧行修复前放逐客户端)。 - GC-TP-05 CAS 是 tripwire 不是完备性证明: 根 ref CAS 恒成功不等于不存在未登记写入者;完备性第一依据是写入者审计(Phase 0 登记、trunk-push.md 硬约束 2 清单),CAS 与巡检是兜底。
继承模板 ER-01..ER-12 全文。本计划无新增 ER 条目;强调以下与本文强相关的事项:
- 锚点刷新(ER-02): 本计划所有
file:line锚点核对日为 2026-09-04;每个任务开工时按 GC-01 重新核对,锚点漂移以现场为准并回写事实基线。 - 包名口径(ER-08): 全部命令使用
-p mega2(单包形态,-p mega2-core已失效)。 - ER-01 测试栈: 涉及 DB 的用例缺 Postgres 会 panic 而非跳过;开工前
docker compose -f docker-compose.test.yml up -d --wait。 - ER-04 A 组表面门: 命中「Git 协议」表面的卡(TP-10、TP-12、TP-17、TP-19、TP-20 等)按模板该行七步骨架执行
scripts/git_protocol_smoke.sh本地等价(含.env.test数据面覆盖与 token 播种;push 用例 401 不得判为协议回归)。 - D 组远端后置门: 本 checkout 的
.github/workflows/与.github/workflow/均为空目录(2026-09-05 核对);各卡 D 组判定一律以开工时远端仓库的 workflow 文件现场读取为准——命中paths:过滤器的卡登记remote-pending并跟踪远端结论,未命中的写N/A并说明,不得虚构远端门。 - ER-07 提交工作流: 本仓
commit.gpgSign=true、user.signingkey=7B2F49AE3A9E8BDC;每次提交后git cat-file -p HEAD | rg -q '^gpgsig'校验,失败不得推送。 - 迁移的 forward-only 口径(G-01): 本计划的迁移产物共 7 项(全部 forward-only,
down为空实现——仓库运行期无migrate down入口,runner.rs只暴露up与破坏性refresh;恢复靠前滚修复):①push_queue+queue_control+ 四枚举 + 索引 + 播种(TP-01);②mega_ref_tombstones(TP-09);③blob_paths(TP-13);④mega_cl.revision列(TP-07,GAP-12);⑤mega_refs_path_pattern部分索引(TP-14);⑥merge_queue 存量行一次性数据迁移(TP-07,随滚动部署交付);⑦authz outbox/published_version持久化(TP-22)。凡含迁移的卡(TP-01/07/09/13/14/22)Rollback mode = forward-only;TP-14 的索引迁移 additive,代码回滚后可重建。
依赖边格式:A -> B 表示 A 必须先于 B。编号顺序 ≠ 执行顺序,以本表与各卡 Dependencies 为准。
TP-01 -> TP-03(queue schema 是四层的表前提)TP-02 -> TP-04(B3 依赖事务内 ref 更新原语)TP-02 -> TP-10(物化插入校验依赖escape_like与事务内 upsert)TP-02 -> TP-14(后代候选查询依赖escape_like)TP-02 -> TP-09(墓碑查询依赖escape_like)、TP-04 -> TP-09(B3 修复挂点)、TP-09 -> TP-05(reaper 的 I3 修复复用 TP-09 的墓碑写原语)TP-03 -> TP-04、TP-03 -> TP-05、TP-03 -> TP-06TP-04 -> TP-05(reaper 依赖 B3 的意图/终态设计)TP-04 -> TP-07、TP-04 -> TP-08、TP-04 -> TP-11、TP-04 -> TP-12、TP-04 -> TP-13TP-07 -> TP-05(reaper 的requeue_conflict意图补做需 merge 冲突重排语义才可验收)、TP-05 -> TP-06(存量端点映射的push_queue数据面由轮次产生)TP-07 -> TP-11(merge 分支的树哈希断言)TP-07 -> TP-14(阶段 2 切换 merge 分支的后代处理,2.8)TP-09 -> TP-10、TP-09 -> TP-11、TP-09 -> TP-14(墓碑是插入校验/修复/续接的共同前提)TP-10 -> TP-11(ADR-TP-20 两层按序落地;写集在monorepo.rs/smart.rs相交)TP-11 -> TP-12(push 分支使用树哈希断言)TP-11 -> TP-13、TP-12 -> TP-13(C 段索引挂接 B3;写集在monorepo.rs相交)TP-12 -> TP-14(push 分支的后代处理在阶段 2 一并切换)TP-07 -> TP-12(push 分支后代处理复用交付物 5 的事务内删除变体)、TP-12 -> TP-16(provenance 升级 push 分支的合成 commit 构造)TP-14 -> TP-16(后代续接 commit 获得归属规则)TP-07 -> TP-15(merge_writer配置字段定义先于 TP-15 的跨字段校验)、TP-15 -> TP-16(枚举完整性三档验收依赖max_push_commits)TP-15 -> TP-17(finalize_receive_pack条件化读取push_policy)、TP-15 -> TP-18(router 条件挂载读取push_policy)TP-16 -> TP-17(trunk 落地使用 provenance 规则)TP-19 -> TP-20(token 认证在 OAuth 条件化之前)、TP-20 -> TP-17(trunk e2e 依赖认证载体就绪——4.2a 前移后的次序)、TP-17 -> TP-18(表面关闭依赖落地转正)——Phase 4 内序:TP-19 → TP-20 → TP-17 → TP-18TP-19 -> TP-20(OAuth 条件化在 token 认证之后)TP-13 -> TP-21、TP-18 -> TP-21、TP-20 -> TP-21(文档收口依赖全部代码卡)TP-04 -> TP-22、TP-07 -> TP-22(authz 屏障依赖 B3 事务挂点与 merge 的 UN-19 重查路径)TP-23 -> TP-01、TP-23 -> TP-04、TP-23 -> TP-07、TP-23 -> TP-08(写入者审计是 schema 与写入者接入卡的开工前置)TP-15 -> TP-19、TP-15 -> TP-20(认证配置与启动校验读取push_auth;TP-19/20 随 4.2a 前移至 Phase 4,见修订 2)
说明: 阶段 1 的 push 分支(TP-12)在「测试专用 push_policy 开关」(1.10 交付物 9)下实现与验收,不含阶段 4 的协议接线——后者是 TP-17/18。
阶段 1 的可部署性: 阶段 1 可独立验收(测试环境),但不可独立上线生产——其 merge/push 分支沿用的删除式后代处理违反 I1(trunk-push.md 迁移步骤开头/附录 A),生产部署以阶段 2(TP-14)落地为前置;里程碑 M1/M2 均为测试环境里程碑。
| ID | direction | 类型 | 对象 | Owner | 产物与可用性判据 | 证据 | 超时与失败策略 |
|---|---|---|---|---|---|---|---|
| DEP-01 | incoming | 跨计划(本仓文档) | docs/refactoring/trunk-push.md 定稿状态 |
trunk-push.md 维护者 | 判据 = 反向声明(monorepo.md 同步)完成前,本文档的 ADR/验收清单以 trunk-push.md 为准;trunk-push.md 若有规范性修订,本计划须同步修订历史 | docs/refactoring/trunk-push.md(2026-09-05 修订 66;Codex 第 59 轮 / Claude 第 3 轮双 PASS) |
无等待上限;不一致时以本计划修订历史登记并同步 |
| DEP-02 | incoming | 审批 | 用户对本计划(含 23 卡结构与 DEFER-TP-01..05)的确认 | 用户 | 判据 = 明确的 go 指令 | 本计划 Review log | 未确认不进入 Phase 1 开工;确认前各卡保持 pending |
| DEP-03 | outgoing | 跨计划(本仓文档) | docs/monorepo.md 产品规则反向声明(N 分流语义、I1–I6、墓碑续接、索引最终一致、ADR-TP-18 对齐约定) |
本计划 TP-21(接收方为 monorepo.md 维护者) | 判据 = trunk-push.md 头部「已同步」标记 + 语义一致的条款 | TP-21 done / R28 PASS / docs/monorepo.md §8–11 / docs/deploy-trunk.md |
已关闭 |
| DEP-04 | incoming | 外部服务 | 测试栈(Postgres 15432 / Redis 16379 / Mailpit / RustFS) |
docker-compose.test.yml | 判据 = docker compose -f docker-compose.test.yml up -d --wait 成功 |
ER-01 | 测试栈不可用则该卡 blocked,不静默降级为无 DB 的 cargo test |
默认每张卡独立发布(G-07)。本计划无家族卡:阶段 1–3 是缺陷修复(可独立验收,硬约束 8 保证 review 形态可观察行为不变),阶段 4/5 的新形态由 push_policy(默认 review,重启生效)与 push_auth(缺省 = 现有 OAuth 链)门控,缺省行为不变,因此无需 REL-* 合并发布。生产上线门:阶段 1 的产物在 TP-14(阶段 2)落地前不部署生产——删除式后代处理违反 I1(trunk-push.md 迁移步骤开头/附录 A I1 成立时点)。不适用时本表为空。
并发声明: 实现阶段可并行的组(实现写集互不相交):TP-07 ∥ TP-08(merge vs attach 分支)、TP-14 ∥ TP-15(后代续接 vs 配置面;TP-15 的校验 ③/⑥ 依赖 TP-01/TP-13 产物,Phase 门保证时序)。TP-05 → TP-06 串行(二者都触及 push_queue_service.rs——reaper 接入点与控制动作;G-10)。TP-16 → TP-17 为依赖边(provenance 是 finalize 条件化的输入),不并行。写集相交的卡已按依赖边串行(G-10):TP-10 → TP-11 → TP-12 → TP-13(monorepo.rs 串行区);TP-15 → TP-19(src/config/ 配置面归 TP-15)。
发布者: 执行本计划的单一 Agent/人;负责每张卡的 C 组 bump/三门/提交/推送及 D 组跟踪(ER-12)。
发布窗口顺序: TP-23 → TP-01 → TP-02 → TP-03 → TP-04 → TP-08 → TP-07 → TP-22 → TP-09 → TP-05 → TP-06 → TP-10 → TP-11 → TP-12 → TP-13 → TP-14 → TP-15 → TP-16 → TP-19 → TP-20 → TP-17 → TP-18 → TP-21;同一时刻只允许一张卡处于「已 bump 未完成推送」状态。
目标: 确认 trunk-push.md 的 ADR-TP-01..20 与不变式无需修订;刷新全部源码锚点;完成写入者审计的登记(阶段 1.1 交付物的文档面)。
进入条件:
- 用户已确认本计划(DEP-02)。
docs/refactoring/trunk-push.md无未决评审项。
退出条件:
- 锚点刷新完成,与事实基线不一致处已修订计划;写入者审计结论回写
trunk-push.md事实校准节(穷举分类:队列串行 / ADR-TP-20 覆盖 / bootstrap 接流前专属锁——mono_service.rs:103-125+ 范围外 CL/tag 行,含acquire_monorepo_initialization_lock证据),与计划登记一致;.env.test存在且测试栈已启动(ER-01)。
目标: 完成 TP-01..TP-13 与 TP-22——队列基座、B0–B4 生命周期、reaper、控制面、merge/attach 分支接入、墓碑、ADR-TP-20 物化覆盖、push 分支(测试开关下)、索引最终一致化、authz 快照屏障。阶段 1 完成时,review 形态的既有语义不变(索引隔离规则除外,登记在案),根树写入具备全序与原子性。
进入条件: Phase 0 退出。
退出条件: TP-01..TP-13 与 TP-22 全部 done;阶段 1 验收清单(trunk-push.md 阶段 1 全部条目)对应用例全绿;root 写入的 CAS 断言在负向注入下 fail-closed。
目标: 完成 TP-14——advance_descendant_refs 取代「删除后重新懒生成」,merge 与 push 分支一并切换(2.8),墓碑续接闭环。
进入条件: Phase 1 退出(TP-09 的墓碑机制与 TP-07 的 merge 分支已就绪)。
退出条件: TP-14 done;断裂回归与无辜删除回归全绿;refusing to merge unrelated histories 故障链用例通过。
目标: 完成 TP-15(配置面)与 TP-16(合成 commit 的真实归属、完整 message 枚举、服务端签名)。
进入条件: Phase 2 退出。
退出条件: TP-15/16 done;三档枚举完整性、多作者链、committer date 保序、review 形态逐字节回归全绿。
目标: 完成 TP-17(finalize_receive_pack 条件化、B3 push 分支转正、advertise CL 过滤、B0 删除策略)、TP-18(CL/code_edit/LFS 变更面关闭、router 条件挂载、OpenAPI 表面)、TP-19(静态 token 认证核心,4.2a 前移)与 TP-20(OAuth 条件化部署形态、push_auth="none"、SSH 边界)。trunk 形态的端到端验收依赖 4.2a 的认证先行——这是 R43 评审后自阶段 5 前移的原因。
进入条件: Phase 3 退出(TP-15 的配置与启动校验已就绪;4.1 六条启动校验含 push_auth 双向强制)。
退出条件: TP-17/18/19/20 done;Agent 常态路径端到端(clone → 单 commit 推送 → ls-remote 精确相等 → 对齐 no-op)与攒批路径(squash + ADR-TP-18 告知)全绿;token 路径授权/组件边界负例/401 语义/无 OAuth 启动测试全绿;push_policy=review 回归全绿。
目标: 完成 TP-21——docs/monorepo.md 反向声明、部署文档、测试矩阵与索引同步。trunk-push.md 阶段 5 的「多 token 运维与强化」因无可执行规范登记为 DEFER-TP-05(重启条件 = 该文档补齐阶段 5 规范),不在本计划执行。
进入条件: Phase 4 的代码卡全部 done。
退出条件: TP-21 done;trunk-push.md 头部反向声明标记为「已同步」;计划完成判据全部满足。
任务 ID 使用前缀 TP-*。编号被引用后不重排;执行以「实施顺序」的依赖边与各卡 Dependencies 为准。
继承模板「任务卡粒度规则」全部 G-01..G-11 条款(不重述全文)。本计划字段全局默认:
- Release boundary 默认: 每张卡独立发布切片
- Task type 默认:
implementation - Rollback mode 默认:
revert - Migration and rollback 默认:
N/A(无 schema 迁移) - Security and privacy 默认: 继承 GC-07、GC-11
- Performance budget 默认: 继承 GC-10
- Docs and compatibility impact 默认: 按 GC-05 同步相关
docs/文档与config/config.toml示例
默认覆盖(取非默认值,无需审批):
| 任务 | 偏离的字段 | 取值与理由 |
|---|---|---|
| TP-01 | Rollback mode |
forward-only:新增迁移的 down 为空实现(仓库无 migrate down 入口) |
| TP-09 | Rollback mode |
forward-only:墓碑表迁移不可逆;数据面由 I1 续接语义保证自洽 |
| TP-13 | Rollback mode |
forward-only:blob_paths 出现对表迁移不可逆;旧索引可在代码回滚后重建 |
| TP-07 | Rollback mode |
forward-only:含 mega_cl.revision 迁移与 merge_queue 存量行数据迁移(down 空实现);代码回滚后由单写者开关切回旧 processor |
| TP-14 | Rollback mode |
forward-only:mega_refs_path_pattern 索引迁移 additive(down 空实现);代码回滚后旧索引可重建 |
| TP-22 | Rollback mode |
forward-only:authz outbox/published_version 迁移不可逆 |
| TP-21 | Task type / Rollback mode |
docs / revert |
| TP-19/TP-20 | Security and privacy |
显式展开:token 常量时间比对、组件边界授权、none 模式仅限受控内网 |
规则 waiver(EX-*): 无。本计划不申请任何豁免。
计划成稿与每次规范性修订后填一次;判定规则按模板(任一列不达标即不得开工)。
| 任务 | type | axis | recovery | complete | self-contained | AC | VER | landing / prod-files | scope | deps | writeset | release | split-from | exception |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| TP-01 | migration | queue schema | forward-only | yes | yes | 8/8 | 4/8 | 2/5 | M | DEP-01 | no-overlap | independent | N/A | N/A |
| TP-02 | implementation | 事务化存储原语 | revert | yes | yes | 7/8 | 4/8 | 2/7 | M | none | no-overlap | independent | N/A | N/A |
| TP-03 | implementation | 队列生命周期 | revert | yes | yes | 8/8 | 4/8 | 2/8 | M | TP-01 | no-overlap | independent | N/A | N/A |
| TP-04 | implementation | B3 执行与终态 | revert | yes | yes | 8/8 | 3/8 | 3/9 | M | TP-02,TP-03 | no-overlap | independent | N/A | N/A |
| TP-05 | implementation | 崩溃恢复 | revert | yes | yes | 8/8 | 3/8 | 1/4 | M | TP-03,TP-04,TP-07,TP-09 | sequential-overlap(push_queue_service.rs 接入点与 TP-06) |
independent | N/A | N/A |
| TP-06 | implementation | 运维控制面 | revert | yes | yes | 7/8 | 3/8 | 2/4 | S | TP-03,TP-05 | sequential-overlap(push_queue_service.rs) |
independent | N/A | N/A |
| TP-07 | implementation | merge 接入与吸收 | forward-only | yes | yes | 8/8 | 4/8 | 4/11 | M | TP-04 | config-read-only | independent | N/A | N/A |
| TP-08 | implementation | attach 接入 | revert | yes | yes | 8/8 | 3/8 | 1/3 | S | TP-04 | no-overlap | independent | N/A | N/A |
| TP-09 | implementation | 墓碑机制 | forward-only | yes | yes | 8/8 | 3/8 | 3/7 | M | TP-02,TP-04 | no-overlap | independent | N/A | N/A |
| TP-10 | implementation | 物化插入校验 | revert | yes | yes | 8/8 | 4/8 | 3/8 | M | TP-02,TP-09 | no-overlap | independent | N/A | N/A |
| TP-11 | implementation | 树哈希断言与修复 | revert | yes | yes | 8/8 | 3/8 | 2/6 | M | TP-04,TP-05,TP-07,TP-09,TP-10 | sequential-overlap(mono_api_service.rs) |
independent | N/A | N/A |
| TP-12 | implementation | B3 push 分支 | revert | yes | yes | 8/8 | 3/8 | 2/8 | M | TP-04,TP-07,TP-11 | sequential-overlap(mono_api_service.rs/mono_storage.rs 与 TP-13) |
independent | N/A | N/A |
| TP-13 | implementation | 索引最终一致 | forward-only | yes | yes | 8/8 | 3/8 | 4/10 | M | TP-04,TP-11,TP-12 | no-overlap | independent | N/A | N/A |
| TP-14 | implementation | 后代 ref 续接 | forward-only | yes | yes | 8/8 | 4/8 | 2/7 | M | TP-02,TP-07,TP-09,TP-12 | file-disjoint(monorepo.rs vs TP-15 push_chain.rs) |
independent | N/A | N/A |
| TP-15 | implementation | trunk 配置面 | revert | yes | yes | 8/8 | 4/8 | 2/5 | M | TP-01,TP-13 | no-overlap | independent | N/A | N/A |
| TP-16 | implementation | 合成 commit 归属 | revert | yes | yes | 8/8 | 4/8 | 2/7 | M | TP-12,TP-14,TP-15 | sequential-overlap(monorepo.rs 与 TP-17) |
independent | N/A | N/A |
| TP-17 | implementation | trunk 推送落地 | revert | yes | yes | 8/8 | 4/8 | 3/8 | M | TP-15,TP-16,TP-19,TP-20 | sequential-overlap(monorepo.rs 与 TP-16) |
independent | N/A | N/A |
| TP-18 | implementation | trunk 表面关闭 | revert | yes | yes | 8/8 | 3/8 | 3/7 | M | TP-15,TP-17 | sequential-overlap(http_server.rs 由 TP-20 → TP-17 → TP-18 次序串行) |
independent | N/A | N/A |
| TP-19 | implementation | 静态 token 认证 | revert | yes | yes | 7/8 | 4/8 | 3/8 | M | TP-15 | no-overlap(src/config/ 归 TP-15) |
independent | N/A | N/A |
| TP-20 | implementation | storage-only 部署形态 | revert | yes | yes | 8/8 | 4/8 | 3/7 | M | TP-15,TP-19 | sequential-overlap(http_server.rs 次序串行;http.rs 与 TP-19) |
independent | N/A | N/A |
| TP-21 | docs | 产品规则同步 | revert | yes | yes | 10/12 | 4/8 | 1/5 | M | TP-13,TP-18,TP-20 | no-overlap | no-release | N/A | N/A |
| TP-22 | implementation | authz 快照屏障 | forward-only | yes | yes | 7/8 | 3/8 | 2/6 | M | TP-04,TP-07 | writeset 与 TP-07 在 mono_api_service.rs 相交 → 依赖边已串行 |
independent | N/A | N/A |
| TP-23 | audit | 写入者审计 | revert | yes | yes | 6/6 | 2/3 | 1/2 | M | none | no-overlap | no-release | N/A | N/A |
继承模板口径:零命中守卫必须区分 rg 退出码 0/1/>1(用模板的 if/rc 模板);本任务新增 test fn 标 (new);cargo test --all 不能替代任务指定用例;依赖真实服务的用例必须写清前置(Postgres 缺失 panic、Mailpit lib 侧优雅跳过)。
Task type: migration
Lifecycle / Acceptance: done / complete
Description: 新增 push_queue(id bigserial / kind / operation_id / path / old_id / new_id / payload jsonb / landed_commit_id / status / requester / failure_type / error_message / heartbeat_at / superseded_by / expected_commit_hash / expected_tree_hash / pending_action / 时间戳)与 queue_control 单行表(paused / hard_stopped / max_depth),四类枚举(status / kind / failure / pending——pending_action 仅 requeue_conflict,根绕过判定不经它),两个唯一部分索引(push_queue_active_push_path 仅 kind='push'、push_queue_operation_states 三态)。实体文件入 src/callisto/,迁移注册入 migrations()。queue_control 迁移时播种唯一行(ON CONFLICT DO NOTHING)——B1 的 FOR UPDATE 无行可锁则准入序列化失效。
Out of scope: 队列执行逻辑(TP-03/04);merge_queue 吸收(TP-07);墓碑表(TP-09);blob_paths 表(TP-13)。
Current evidence:
| 事实 | 证据 |
|---|---|
merge_queue 四层形状与既有枚举(Waiting/Testing/Merging/Merged/Failed 是 CL 工作流状态机,与本队列生命周期不同构) |
src/callisto/sea_orm_active_enums.rs:228-239、src/jupiter/storage/merge_queue_storage.rs |
| 现有迁移注册列表 | src/jupiter/migration/mod.rs 的 migrations() |
| 实体文件惯例(一表一文件) | src/callisto/merge_queue.rs |
Acceptance criteria:
-
migrations()注册新迁移;apply_migrations(&db, true)后push_queue/queue_control与四类枚举类型存在(test_db_connection集成用例) -
push_queue表列与 1.4 的 schema 逐一对应:payload jsonb NOT NULL、landed_commit_id、heartbeat_at NOT NULL、superseded_by、expected_commit_hash/expected_tree_hash、pending_action(trunk-push.md 1.4) -
push_queue_status_enum(Queued/Running/Done/Failed/Cancelled)、push_queue_kind_enum(push/merge/attach)、push_queue_failure_enum(PushFailure/MergeFailure/AttachFailure/Conflict/QueueBypassDetected/WaitTimeout/ClaimLost/SystemError)、push_queue_pending_enum(仅 requeue_conflict——根绕过判定由expected_*基线承担,不经pending_action)值域完整 -
queue_control含last_policy(4.1 形态切换校验依据);push_queue.expected_commit_hash/expected_tree_hash可空(B2.5 认领事务内落库的基线,NULL = 行缺失哨兵) - 两个部分唯一索引:
push_queue_active_push_path仅约束status in ('Queued','Running') and kind = 'push'(同路径两个不同 operation_id 的 push 行插入第二个被拒);push_queue_operation_states三态(Queued/Running/Done)上的(kind, path, operation_id)唯一且终态不拦截((new)) -
queue_control迁移/启动播种恰好一行(重复迁移/重复播种不报错);FOR UPDATE可锁 - 迁移
down为空实现,Rollback mode = forward-only已在卡内声明 - 三项通用门禁(fmt / clippy /
source .env.test && cargo test --all)全绿 — 2026-09-09target/tmp/cargo-test-all.logEXIT:0
Verification:
-
source .env.test && cargo test -p mega2 --lib 'push_queue::tests'((new):迁移 + 索引 + 播种集成用例,走test_db_connection+apply_migrations) -
source .env.test && cargo test -p mega2 --lib 'queue_control::tests'((new):播种幂等) -
cargo +nightly fmt --all --check与cargo clippy --all-targets --all-features -- -D warnings(ER-04 强制门) - D 组:N/A(
.github/workflows/为空)
Dependencies: DEP-01(trunk-push.md 1.4 schema 为准)
Deliverables: N/A(代码卡)
Implementation write set: src/callisto/、src/jupiter/migration/、src/jupiter/storage/init.rs
Release write set: Inherited(Cargo.toml version + Cargo.lock)
Files likely touched: src/callisto/push_queue.rs、src/callisto/queue_control.rs、src/callisto/sea_orm_active_enums.rs、src/callisto/mod.rs、src/jupiter/migration/m20260905_000100_add_push_queue.rs、src/jupiter/migration/mod.rs、src/jupiter/storage/init.rs
Docs and compatibility impact: 按 GC-05;无用户可见命令/配置变化,docs/refactoring/trunk-push.md 1.4 若实现偏离须回写
Rollback mode: forward-only(迁移 down 为空实现;additive 新表,前滚修复)
Migration and rollback: 新迁移 up 建表/枚举/索引/播种;down 空实现;数据不变量 = queue_control 恰一行;恢复验证 = 重复执行迁移幂等
Security and privacy: 继承 GC-07、GC-11
Performance budget: push_queue_operation_states 与 push_queue_active_push_path 的写入路径为 O(1) 索引点查;无无界扫描
Estimated scope: M(2 个行为落点、5 个生产文件)
Version increment: patch(additive schema,无兼容破坏)
Release boundary: independent
C/D coverage from: self
Granularity: type=migration; axis=队列持久化 schema(push_queue/queue_control 表、枚举、索引、播种); recovery=forward-only:新增表 additive,回滚为前滚修复; complete=yes; self-contained=yes; AC=8/8; VER=4/8; landing=2; prod-files=5; scope=M; deps=DEP-01; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 trunk-push.md 1.10 的第 1/2/4/6 项:batch_update_by_path_concurrent 的事务内顺序更新变体(接受 &DatabaseTransaction,拒绝在单事务内保留并发);缺失行不再静默跳过、提供事务内 upsert/create 原语(写入模型的创建语义依赖它插入 main@P);escape_like LIKE 转义助手(转义 %/_/\);树项插入原语(insert-or-replace TreeItem,TreeItemMode::Tree,遵守 Tree::from_tree_items 排序约定,支持多级创建)。这是 B3 单事务承诺的存储层前提。
Out of scope: B3 本身(TP-04);墓碑表(TP-09);队列状态机(TP-03)。
Current evidence:
| 事实 | 证据 |
|---|---|
批量更新自建连接、FuturesUnordered 并发、缺失行静默跳过 |
src/jupiter/storage/mono_storage.rs:287-333 |
update_tree_hash 只定位不插入,缺失报 Tree item '<name>' not found |
src/ceres/api_service/mono_api_service.rs:551-563/570-616 |
search_tree_for_update 对缺失组件硬报错 |
src/ceres/api_service/tree_ops.rs:263-298 |
无 LIKE 转义助手(sea-orm 有 LikeExpr 无转义器) |
src/ 全仓检索(2026-09-04) |
Acceptance criteria:
- 事务内顺序 ref 更新变体:同一
&DatabaseTransaction内更新多行,提交前不可见、回滚全撤销;与并发版结果一致((new)) - upsert/create 原语:对不存在的
(path, ref_name)行按给定创建语义插入;已存在的行更新;不再静默跳过((new)) -
escape_like对%/_/\三元转义单测;\自身被转义((new)) - 树项插入:单级创建(父存在)与多级创建(
/a/b/c逐级补齐)后根树可解析完整链路((new)) - 树项插入遵守
Tree::from_tree_items的排序约定;insert-or-replace 语义——已持久化的同名子项确定性 replace(更新 TreeItem id),同一输入集内重复名称返回可诊断错误(trunk-push.md 1.10 交付物 6)((new)) - 既有行为回归:review 形态 merge/attach 走原路径的用例期望值不变(硬约束 8)
- 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'jupiter::storage::mono_storage::tests'((new):事务内更新/upsert/escape_like) -
source .env.test && cargo test -p mega2 --lib 'ceres::api_service::tree_ops::tests'((new):单级/多级创建) -
source .env.test && cargo test -p mega2 --lib 'mono_storage::tests'((new):缺失行不再静默跳过) - D 组:改动在
src/jupiter/storage/、src/ceres/api_service/——远端无paths:过滤的 smoke workflow(仓库无.github/workflows);登记 N/A
Dependencies: 无
Deliverables: N/A(代码卡)
Implementation write set: src/jupiter/storage/、src/ceres/api_service/、src/common/utils.rs、src/jupiter/utils/converter.rs
Release write set: Inherited(Cargo.toml version + Cargo.lock)
Files likely touched: src/jupiter/storage/mono_storage.rs、src/ceres/api_service/mono_api_service.rs、src/ceres/api_service/tree_ops.rs、src/common/utils.rs(escape_like)、src/jupiter/utils/converter.rs(sort_git_tree_items 公开)
Docs and compatibility impact: 按 GC-05;无用户可见变化
Rollback mode: revert(纯代码变更,一次 revert 撤销)
Migration and rollback: N/A
Security and privacy: 继承 GC-07、GC-11
Performance budget: 顺序事务内更新为 O(k) 行写(k = 本层 ref 数);树项插入为 O(depth);无无界扫描
Estimated scope: M(2 个行为落点、7 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=B3 单事务所需的存储原语(事务内 ref 更新/upsert、escape_like、树项插入); recovery=revert:纯代码,一次 revert 撤销,无数据残留; complete=yes; self-contained=yes; AC=7/8; VER=4/8; landing=2; prod-files=7; scope=M; deps=none; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 MonoWriteQueue 的 storage/service 四层形状(泛化自 merge_queue)与 B0–B2.5 生命周期:B0 早期拒绝(review 形态 push 不入队;trunk 形态单分支准入;无任何 no-op 快路径——no-op/最终 NFF 结论由 B3 或 Done 回放处理,B0 仅做遥测);B1 单事务原子准入(queue_control FOR UPDATE 锁先行 + 条件 INSERT 三态查重 + 容量/暂停/硬停门槛,RETURNING id,0 行时回查分类);B2 等待轮次(心跳刷新、wait_timeout 放弃而非取消、多收养者共享行);B2.5 单语句三条件原子认领(status='Queued' + 无 Running + min(id))。1.11 的 operation_id 稳定指纹(push=old_id→new_id、merge=cl.link、attach=内容寻址 hash)、Done 回放 landed_commit_id、活跃行收养、终态后以持久化载荷新建行,全部在本卡落地。含测试专用 push_policy 开关的配置读取侧(1.10 交付物 9 的 B0 部分;完整配置面在 TP-15)。
Out of scope: B3/B4(TP-04);reaper(TP-05);控制面 router(TP-06);写入者接线(TP-07/08)。
Current evidence:
| 事实 | 证据 |
|---|---|
merge_queue 四层形状与 AtomicBool/裸 SELECT claim/时间戳 position 缺陷 |
src/jupiter/service/merge_queue_service.rs:169、src/jupiter/storage/merge_queue_storage.rs:83/178 |
validate_incoming_push / MC-03 链校验现成 |
src/ceres/pack/monorepo.rs:1153、src/ceres/pack/push_chain.rs |
| B1 参考形状(条件插入) | src/jupiter/storage/merge_queue_storage.rs:56-103 |
Acceptance criteria:
- B0:review 形态 push 不入队(只写
refs/cl/*);trunk 形态(测试开关下)单分支准入 +ref_name == MEGA_BRANCH_NAME+P="/"拒绝(仅 push kind);删除类命令在 trunk 形态被拒(B0 删除策略);乐观 NFF 预检只作遥测不拒绝(B3 是唯一 NFF 权威)((new)) - B1 原子入队:准入锁先行使
id 分配序 = 提交序 = FIFO 序(并发交错探针,I6);容量门槛恰好容纳max_depth项;paused/hard_stopped门槛与三态查重同语句((new)) - 三态查重三分支:命中
Done→ 按landed_commit_id回放(含 N>1 的 squash id,不产生第二个落地);命中Queued/Running→ 收养(以既有行 id 进 B2);未命中 → 插入。终态竞态(查重与提交Done并发)由条件 INSERT 单语句判定((new)) -
operation_id指纹:同 tip 不同基线(A→C 与 B→C)为不同操作、正常排队并被后续闸门裁决;不同 CL 共享to_hash不混淆((new)) - B2:心跳每轮刷新;
wait_timeout到期放弃不改行状态(多收养者不被误杀);连接断开自行退出不改行状态((new)) - B2.5:认领先行 +
queue_control FOR UPDATE串行化(双认领者并发 READ COMMITTED 回归:至多一项 Running,另一者 0 行回 B2)+expected_*基线同事务落库(认领后无其他合法根写入者)+ 认领谓词内含NOT hard_stopped((new)) - 队列 paused/depth 超限预拒绝且错误可诊断;
hard_stopped期间新入队被拒而Done回放不受限((new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'jupiter::service::push_queue_service::tests'((new):B0/B1/B2/B2.5 全套含交错探针) -
source .env.test && cargo test -p mega2 --lib 'jupiter::storage::push_queue_storage::tests'((new):条件 INSERT 三态 + 索引冲突) -
source .env.test && cargo test -p mega2 --lib 'ceres::pack::push_chain::tests'((new):指纹语义回归) - D 组:
src/ceres/**改动按开工时 workflowpaths:判定(大概率命中 git-protocol-smoke)
Dependencies: TP-23(写入者审计先行)、DEP-01(trunk-push.md 1.4 schema 为准)
Deliverables: N/A(代码卡)
Implementation write set: src/jupiter/storage/、src/jupiter/service/
Release write set: Inherited
Files likely touched: src/jupiter/storage/push_queue_storage.rs、src/jupiter/service/push_queue_service.rs、src/jupiter/service/merge_queue_service.rs(吸收后退役)、src/config/(测试开关读取侧)
Docs and compatibility impact: 按 GC-05;docs/refactoring/trunk-push.md 1.5/1.11 实现偏离回写
Rollback mode: revert
Migration and rollback: N/A(表由 TP-01 交付)
Security and privacy: 继承 GC-07、GC-11(payload 中的描述符无 secret;requester 按模式取 token 名或 NULL)
Performance budget: B1 为单语句 INSERT(O(1) 门槛判定);B2 心跳为每 poll 一次 O(1) UPDATE;轮询抖动避免惊群
Estimated scope: M(2 个行为落点、8 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=队列生命周期状态机(B0 准入、B1 原子入队、B2 等待、B2.5 认领、1.11 幂等/收养/回放、背压); recovery=revert:未接任何写入者(TP-07/08 之前),回滚即回到无队列状态,无数据残留; complete=yes; self-contained=yes; AC=8/8; VER=6/8; landing=2; prod-files=8; scope=M; deps=TP-01; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 B3 通用执行骨架与 B4 失败路径:B3 首句 fencing(持锁重读本行非 Running 即弃权 ClaimLost)、pg_advisory_xact_lock(MONO_WRITE_LOCK)、硬停检查(B2.5 认领谓词与 B3 持锁后两处)、预期根基线比对(全 kind 通用、独立可执行前置分支)——expected_commit_hash/expected_tree_hash 已在 B2.5 认领事务内原子落库(NULL 哨兵、IS NOT DISTINCT FROM),B3 持锁现读根与之比对,任一分量不一致 ⇒ 队列外写入者:不 ROLLBACK,SAVEPOINT 回退业务写后同事务置 hard_stopped + 行 Failed(QueueBypassDetected) + NOTIFY,不做任何树/ref 工作;根 ref CAS 双条件断言(抵达根写入点的成功轮次恰好一次根写入;净零轮次同值写;merge/attach 分支内唯一根写入);status=Done 与 status=Failed 的条件更新(WHERE status='Running',命中 0 行 fail-closed 告警);B4 两段式(仅冲突重排持久化 requeue_conflict 意图 + SAVEPOINT 完成,superseded_by 继任链接;非 Conflict 失败标 Failed 且每次终态迁移置 pending_action=NULL)与 Conflict 关行重入队。kind 分派接口(push/merge/attach 分支留骨架,实现在 TP-07/08/12);测试专用 push_policy 开关的 B3 分派侧(1.10 交付物 9)。
Out of scope: merge 分支语义(TP-07);attach 分支语义(TP-08);push 分支语义(TP-12);reaper(TP-05)。
Current evidence:
| 事实 | 证据 |
|---|---|
merge_cl_unchecked / apply_update_result 现状分散写入 |
src/ceres/api_service/mono_api_service.rs:2580-2717 |
| attach 双条件 CAS 先例 | src/jupiter/storage/mono_storage.rs:453-483 |
| 队列是序列化闸门与生命周期台账而非作业执行器(1.3) | docs/refactoring/trunk-push.md 1.3 |
Acceptance criteria:
- fencing 回归:注入「认领提交后、取锁前」延迟 + 同窗口触发 reaper → B3 弃权回滚(ClaimLost),根树/ref 无变更(
(new)) - 预期根基线比对前置分支:B2.5 落库的
expected_*与锁内现读根任一分量不一致(IS NOT DISTINCT FROM)→ 不做任何树/ref 工作,SAVEPOINT 置hard_stopped+ 行Failed(QueueBypassDetected)+ NOTIFY;交错回归——注入「B2.5 认领提交后、B3 取锁前队列外根写入」→ 硬停(基线闭合「CAS 前崩溃」窗口)((new)) - 根 CAS 唯一性:抵达根写入点的成功轮次恰好一次根写入;净零轮次同值写(tripwire 不缺席);merge/attach 分支不触发第二个根更新点(
(new)) - CAS 失败 fail-closed:SAVEPOINT 同事务完成「数据回滚 +
hard_stopped置位 + 行终态Failed(QueueBypassDetected)(终态更新带WHERE status='Running',命中 0 行仍置硬停并 fail-closed 告警)」;不重试((new)) - B4 两段式:Conflict 重排在旧行
Cancelled(Conflict)+superseded_by指向队尾新行同一事务内原子完成;非 Conflict 失败标Failed且每次终态迁移置pending_action=NULL((new)) - 硬停检查:B2.5 与 B3 持锁后均检查
hard_stopped;命中 → 行条件重置回Queued(独立提交事务),排队意图保留((new)) -
Done/Failed条件更新带WHERE status='Running';被 reaper 抢先改态的行不被静默覆盖(命中 0 行即 fail-closed 告警) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'jupiter::service::push_queue_service::tests'((new):B3/B4 全套含 fencing/意图/重排) -
source .env.test && cargo test -p mega2 --lib 'ceres::api_service::mono_api_service::mc09_tests::root_cas'((new):根 CAS 唯一性断言) - D 组:N/A(
.github/workflows/为空)
Dependencies: TP-23(写入者审计)、TP-02(事务内 ref 更新原语)、TP-03(认领与生命周期)
Deliverables: N/A(代码卡)
Implementation write set: src/jupiter/service/、src/ceres/api_service/、src/jupiter/storage/
Release write set: Inherited
Files likely touched: src/jupiter/service/push_queue_service.rs、src/ceres/api_service/mono_api_service.rs(根 CAS 原语接入点)、src/jupiter/storage/mono_storage.rs(CAS 原语)
Docs and compatibility impact: 按 GC-05
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 继承 GC-07、GC-11;CAS 失败硬停是 fail-closed 动作,clear-hard-stop 需人工审计
Performance budget: B3 开销 = 1 次 advisory lock + 1 次根读 + 1 次根 CAS 写(expected_* 的写入并入 B2.5 认领事务,B3 内无额外独立写);净零轮次同值 CAS 为 O(1)
Estimated scope: M(3 个行为落点、9 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=B3 执行骨架与 B4 失败/重排(fencing、advisory lock、预期根基线比对、根 CAS、终态、hard_stopped、Conflict 重排); recovery=revert:未接写入者前纯新增逻辑; complete=yes; self-contained=yes; AC=8/8; VER=6/8; landing=3; prod-files=9; scope=M; deps=TP-02,TP-03; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 1.6 的 reaper:自己事务内 pg_try_advisory_xact_lock(MONO_WRITE_LOCK)(持锁即证明无活跃 B3,Running 行当场清理,无 TOCTOU);对每行 Running 比对 expected_* 基线(B2.5 认领时落库)判定绕过/普通失败——绕过 ⇒ 硬停 + QueueBypassDetected(绕过优先,丢弃一切意图);pending_action 仅 requeue_conflict 一种意图,其幂等补做 = 创建继任行 + superseded_by(继任行 INSERT 取 queue_control FOR UPDATE 准入锁);陈旧行修复不使用意图——由 reaper 对每行 Running 的通用 I3 修复兜底(陈旧即就地墓碑修复,按 kind 分语义:push 缺行 = 创建中间态跳过/墓碑异常告警,merge 缺行 = 异常登记,attach 缺行 = 正常且 main@/ 例外);Queued 行的 heartbeat 清理(孤儿队首死锁的唯一出口,hard_stopped 期间冻结;硬停重置仅及于置位前已 Running 的存量行);started_at 秒级宽限(观测友好,不参与正确性);stuck_timeout 降级为告警阈值;watchdog 升级路径(告警附 pg_stat_activity → runbook pg_terminate_backend → 可选自动 watchdog 默认关闭,条件 = 锁持有超时 + 存在非终态 Running 行)。
Out of scope: 控制面 router(TP-06);merge 冲突重排的产生(TP-07 的 B4 语义);墓碑写本身(TP-09)。
Current evidence:
| 事实 | 证据 |
|---|---|
reaper 的意图模型(仅 requeue_conflict)与崩溃窗口;expected_* 基线比对 + 通用 I3 修复(按 kind) |
docs/refactoring/trunk-push.md 1.4/1.6 |
物化/巡检批次也持 MONO_WRITE_LOCK(拿不到锁 ≠ 有轮次) |
trunk-push.md 1.6(R31 修订) |
Acceptance criteria:
- 执行中
kill -9:行停Running(B2.5 已独立提交),ref/tree 未变更;reaper 下一轮持锁立即标Failed(无需等stuck_timeout),下一项正常上场((new)) - B2 等待中
kill -9:行停Queued且心跳停止;heartbeat_timeout后标Cancelled;期间与之后的轮次均能取得执行权(孤儿死锁回归)((new)) - 基线比对与重排补做:对每行 Running 比对
expected_*(任一分量不等 → 硬停 +Failed(QueueBypassDetected),绕过优先、丢弃重排意图;全等 → 无绕过);注入「重排意图持久化后、SAVEPOINT 提交前kill -9」→ 幂等补做继任行后终态化,旧行Cancelled(Conflict)且superseded_by可跟随,幂等守卫 = 状态条件 +superseded_by IS NULL((new)) - 慢轮次不被误伤:注入超过
stuck_timeout的 B3 → reaper 因锁被持有跳过;该行最终Done;终态幂等((new)) - 通用 I3 修复(按 kind):push/merge 行 path 陈旧即就地墓碑修复;push 行缺
main@P(ZERO_ID 无墓碑)跳过修复普通终态化、有墓碑告警;merge 行缺行异常登记;attach 行缺行跳过(main@/例外)、有 main 行异常告警((new)) - 卡死升级:注入持锁睡眠假死 B3 → 告警(附持锁会话快照);执行 runbook 终止后队列恢复,该行终态 Failed(
(new)) - 硬停重置范围:
hard_stopped置位前已 Running 的存量行被 reap → 条件重置回Queued(排队意图保留);本次运行新检出的基线失配行 → 终态Failed不重置((new)) - 三项通用门禁全绿(fmt + clippy
-D warnings;VER 测试全绿。计划级cargo test --all仍待单独证明)
Verification:
-
source .env.test && cargo test -p mega2 --lib 'jupiter::service::push_queue_reaper::tests'((new):九项回归,含周期 loop;9 passed) -
source .env.test && cargo test -p mega2 --lib 'ceres::api_service::mono_api_service'(计划写::tests,模块实为::test+mc09_tests;63 passed) - D 组:仓库无
.github/workflows;src/jupiter/service/改动 N/A
Dependencies: TP-03(生命周期)、TP-04(意图/终态设计)、TP-07(requeue_conflict 语义可验收)、TP-09(墓碑写原语——TP-05 的 I3 修复复用它)
Deliverables: N/A(代码卡)
Implementation write set: src/jupiter/service/push_queue_reaper.rs(新模块,文件级隔离——TP-06 的控制动作在 push_queue_service.rs/router,无文件交集)
Release write set: Inherited
Files likely touched: src/jupiter/service/push_queue_reaper.rs、src/jupiter/service/push_queue_service.rs(reaper 接入点)
Docs and compatibility impact: 按 GC-05;docs/refactoring/trunk-push.md 1.6 若实现偏离回写
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 继承 GC-07、GC-11;pg_terminate_backend 的 runbook 需 pg_locks/pg_stat_activity 交叉核对(防误杀)
Performance budget: reaper 每轮 O(Running + 孤儿 Queued + 待补意图) 行处理;孤儿 I3 校验每行一次 resolve;试锁非阻塞
Estimated scope: M(1 个行为落点、4 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=崩溃恢复与卡死升级(reaper 持锁清理、基线比对、重排意图幂等补做、通用 I3 修复按 kind、heartbeat 孤儿清理、watchdog); recovery=revert:纯新增模块; complete=yes; self-contained=yes; AC=8/8; VER=5/8; landing=1; prod-files=4; scope=M; deps=TP-03,TP-04,TP-07,TP-09; writeset=sequential-overlap(push_queue_service.rs 接入点与 TP-06); release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 1.7 的控制面:沿用 merge_queue_router 形状的队列查询(深度、head、running 项、path/kind/requester/等待时长)、pause/resume(清 paused)、clear-hard-stop(独立运维操作,清 hard_stopped 并留审计日志,与维护性 resume 分离)、单项 cancel(仅 Queued 行,条件更新 WHERE status='Queued',与认领竞争先到先得;Running 行不可取消)。指标:队列深度、等待时长 P50/P99、轮次时长 P50/P99(stuck_timeout 标定依据)、失败率、CAS 断言失败计数(应恒为 0)、fencing 弃权(ClaimLost)计数、锁超时告警。存量 merge_queue_router 端点逐一映射(实际路由:add_to_queue/remove_from_queue/get_queue_list/get_cl_queue_status/retry_queue_item/get_queue_stats/cancel_all_pending,merge_queue_router.rs:18-29):add_to_queue → B1 入队 + 同步等待 B2/B3(响应语义变为「已执行完毕」);remove_from_queue → 410 + 迁移说明;get_queue_list/get_cl_queue_status/get_queue_stats → push_queue 等价查询(路径/响应形状保留);retry_queue_item → 重新入队并同步等待执行(以原行载荷新建、幂等键不变,重试者即执行者);cancel_all_pending → 410 + 迁移说明(批量取消破坏逐行台账与先到先得语义,逐项 cancel 保留);UN-25 freeze 挂点随 B3 执行期重查迁移。
Out of scope: reaper(TP-05);指标采集的埋点基础设施(沿用既有 tracing/metrics 惯例)。
Current evidence:
| 事实 | 证据 |
|---|---|
merge_queue_router 现有形状 |
src/api/router/(merge_queue_router) |
Acceptance criteria:
- 查询端点返回深度/head/running 项/各项 path/kind/requester/等待时长(
(new)) -
pause后新入队被拒、在队项照常执行(drain-only);resume恢复((new)) -
clear-hard-stop独立于resume:CAS 硬停后resume不清除、clear-hard-stop清除且留审计日志((new)) -
cancel仅对Queued行生效(条件更新);对Running行的 cancel 请求可见地失败;取消与认领并发时恰好一方生效((new)) - 指标:队列深度、等待/轮次时长、失败率、CAS 断言失败计数、ClaimLost 计数、锁超时告警全部可观测(
(new)) - 存量端点映射:
get_queue_list/get_cl_queue_status/get_queue_stats返回push_queue数据且形状兼容;retry_queue_item重新入队并同步等待至真实终态;remove_from_queue/cancel_all_pending返回 410 且登记迁移说明;UN-25 freeze 挂点迁移后语义一致((new)) - 三项通用门禁全绿(fmt + clippy
-D warnings;VER 测试全绿。计划级cargo test --all仍待单独证明)
Verification:
-
source .env.test && cargo test -p mega2 --lib 'api::router::push_queue_router::tests'((new);7 passed) - OpenAPI:
push_queue_router::tests::tp06_openapi_registers_control_and_maps_retired_paths断言控制面与存量路径已注册(GC-05,无落盘 spec) - D 组:仓库无
.github/workflows;src/api/**N/A
Dependencies: TP-03(队列生命周期)、TP-05(存量端点映射的 push_queue 数据面由轮次产生)、TP-05(存量端点映射的 push_queue 数据面由轮次产生)
Deliverables: N/A(代码卡)
Implementation write set: src/api/router/push_queue_router.rs、src/jupiter/service/push_queue_service.rs(控制动作;与 TP-05 的 push_queue_reaper.rs 文件级不相交)
Release write set: Inherited
Files likely touched: src/api/router/push_queue_router.rs、src/jupiter/service/push_queue_service.rs(控制动作实现)
Docs and compatibility impact: 按 GC-05;新增 HTTP 端点需在运行时 OpenAPI 取证
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 控制面端点需鉴权(沿用既有 guard 惯例,不新增公开端点);clear-hard-stop 留审计日志
Performance budget: 查询为 O(1) 行级聚合;无无界扫描
Estimated scope: S(2 个行为落点、4 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=运维控制面与可观测(查询、pause/resume、clear-hard-stop、cancel、指标); recovery=revert:纯新增端点与动作; complete=yes; self-contained=yes; AC=7/8; VER=3/8; landing=2; prod-files=4; scope=S; deps=TP-03,TP-05; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 1.8/1.9 的 merge 侧:单写者开关 [monorepo].merge_writer = "legacy" | "queue"(重启生效,缺省 legacy 仅为迁移期回退值——生产稳态必须为 queue:M3/生产上线门要求 merge_writer=queue 且 legacy processor 已禁用、存量行已排空/迁移;legacy 不可作为生产稳态;additive 配置字段——定义/缺省/校验归本卡;配置校验拒绝非法 merge_writer 值,且 merge_writer="queue" 要求非终态 merge_queue 行已排空(push_policy 与 merge_writer 的跨字段校验在 TP-15))——merge_cl_unchecked 的落地经 MonoWriteQueue 串行(kind='merge',operation_id = cl.link,new_id 为入队时点 cl.to_hash 快照——语义锚点而非落地 tip,落地面以 landed_commit_id 及其 parent 为准);全部 merge 入口统一入队——直连路由 /merge、/merge-no-auth(cl_router.rs:218-223/279-304,现状在队列外执行)与 /merge-queue/add(同步化,语义变为「已执行完毕」)都走「既有入口预检(cl.from_hash != main 拒绝、缺失 ref 拒绝,现状保留)→ B1 入队 → 同步等待 B2/B3」;执行期门控原样重查(CL 存在性、UN-19、冲突、GPG,mono_api_service.rs:4419-4603 的现状等价物);锁内重算 TreeUpdateResult(排队期间的 intervening 写入不被旧预计算结果覆盖);main@P 缺失 → 拒绝(沿用现状语义,不使用 TP-02 的 upsert);树哈希断言先于业务门控(谓词在 TP-11 交付,本卡接挂点);CL 状态与 conversation 写入与 ref/commit/tree 穿入同一事务(1.10 交付物 5/7:remove_none_cl_refs 事务内变体 + apply_update_result 全量事务化);CL 单调 revision 全量 CAS(mega_cl 加 revision 列,merge 与 rebase 双向串行化,0 行命中即 ClaimLost——GAP-12);冲突 → B4 关行重入队(ADR-TP-05 语义映射)。merge_queue 吸收的滚动部署:排空 → 存量行一次性迁移(Waiting/Testing → Queued、Merging → Failed(MergeFailure, interrupted))→ 单写者开关(重启生效,配置校验拒绝双开)→ 禁止混合版本混跑;UN-17/18/25 语义逐条对齐。
Out of scope: attach(TP-08);树哈希断言本体(TP-11);后代续接(TP-14);push 分支(TP-12)。
Current evidence:
| 事实 | 证据 |
|---|---|
merge_cl_unchecked 预计算树结果后落地、CL 状态写在 apply_update_result 之后 |
src/ceres/api_service/mono_api_service.rs:2580-2635 |
| merge queue processor 执行期重查与冲突重排队 | src/ceres/api_service/mono_api_service.rs:4419-4429/4465-4603 |
ensure_merge_processor_running 后台 processor |
src/ceres/api_service/mono_api_service.rs:4342-4386 |
Acceptance criteria:
- merge 经队列串行:20 个互不嵌套不同路径并发 merge 全部成功;根 roll-up 的 parent 链顺序逐一等于
push_queue.id;根树包含全部 20 处改动;互嵌路径伴随用例(/a与/a/b两次 merge 串行——/a的 merge 经阶段 1 仍沿用的remove_none_cl_refs删除main@/a/b,随后/a/b的 merge 被「缺失 main 行 → 拒绝」拒绝且可诊断;续接成功形态在 TP-14 验收)((new)) - 执行期门控原样重查 + 锁内重算:CL 存在性/UN-19/冲突/GPG 判定结果与现状一致,冲突 → 关行
Cancelled(Conflict)+ 队尾新行(id 严格递增、superseded_by可跟随),最终合并成功;排队期间注入 intervening attach/merge 推进根 → 锁内重算后落地,intervening 写入完好保留((new)) - CL 状态/conversation 与 ref/commit/tree 同事务(交付物 7):注入 CL 状态写入前
kill -9→ 全量回滚,根未推进、CL 仍 open,重试恰好合并一次;交付物 5 的后代删除在同一事务内(注入提交前kill -9→ 同回滚)且 LIKE 组件边界/元字符转义有直接单测((new)) - CL merge 行语义:入队时点
new_id等于当时cl.to_hash,而落地 tip 是以执行时点to_hash为 parent 的合成 commit(landed_commit_id),二者不相等(trunk-push.md 1.9)((new)) - merge 与 rebase 串行化:
mega_cl单调 revision 列(迁移随卡交付);并发 rebase 使 CL 状态更新命中 0 行 → 本轮 ClaimLost 弃权;反序回归——先 merge 落地、后陈旧 rebase 被 revision CAS 拒绝,Merged不被改回Open((new)) - 直连入口入队与缺失行拒绝:
/merge、/merge-no-auth、/merge-queue/add与排队的 push/attach 并发 → 根写入全部经同一队列串行;入口预检(from_hash != main、缺失 ref 拒绝)行为与现状一致;main@P缺失的 merge 被拒(不用 upsert 原语);old_id语义断言——入队时点new_id快照为信息性、不参与闸门,落地以执行时点 parent 与landed_commit_id为准(1.9);merge 行的落地 parent 语义——无 rebase/intervening 变更时落地 commit 的 parent 等于cl.to_hash(入队时点与执行时点一致,二者相等),有 rebase/intervening 变更时二者不同但落地恒用执行时点的 parent,landed_commit_id记录实际落地 commit((new)) - 滚动部署开关与生产稳态门:
[monorepo].merge_writer字段解析与校验(缺省legacy仅为迁移期回退值;queue要求排空);双开/非法组合拒绝启动;排空后存量行迁移正确(Waiting/Testing→Queued、Merging→Failed(MergeFailure, interrupted));生产稳态门 = M3 前置要求merge_writer=queue且 legacy processor 禁用((new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'ceres::api_service::mono_api_service'((new):merge 队列化全套;测试在mc09_tests,filter::tests零命中) -
source .env.test && cargo test -p mega2 --lib 'jupiter::service::merge_queue_service::tests'((new):吸收迁移与开关) -
cargo run -p mega2 -- --config config/config.toml config validate(开关校验 →config valid) - D 组:N/A(
.github/workflows/为空)
Dependencies: TP-23(写入者审计)、TP-04(B3 骨架)
Deliverables: N/A(代码卡)
Implementation write set: src/ceres/api_service/、src/jupiter/storage/、src/jupiter/service/、src/config/(仅吸收开关的读取侧消费;配置定义归 TP-15)
Release write set: Inherited
Files likely touched: src/ceres/api_service/mono_api_service.rs、src/jupiter/storage/mono_storage.rs、src/jupiter/storage/cl_storage.rs、src/callisto/mega_cl.rs(revision 列)、src/jupiter/migration/(mega_cl revision 迁移)、src/api/router/cl_router.rs、src/api/router/merge_queue_router.rs(入口同步化)、src/jupiter/service/merge_queue_service.rs、src/config/model.rs、src/config/validate.rs(merge_writer 开关——additive 字段,定义/校验归本卡;TP-15 后续整合时只消费)
Docs and compatibility impact: 按 GC-05;merge 的异步转同步属登记在案的契约变化(1.9 2a),需在迁移文档/部署文档声明
Rollback mode: forward-only(mega_cl.revision 迁移与存量行数据迁移 down 空实现;代码回滚后由单写者开关切回旧 processor,切换前先排空)
Migration and rollback: 存量 merge_queue 行一次性迁移(迁移脚本随卡交付);Rollback mode 的恢复动作 = 排空 + 开关切回
Security and privacy: 继承 GC-07、GC-11;UN-25 freeze 语义(Failed + SystemError)逐条映射
Performance budget: merge 轮次 = 锁内树重算 + 一次事务;门控重查为既有成本
Estimated scope: M(4 个行为落点、11 个生产文件)
Version increment: patch(review 形态可观察行为不变,硬约束 8)
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=merge 写入者接入 MonoWriteQueue 与 merge_queue 吸收(门控原样重查、锁内重算、事务化副作用、单写者开关与生产稳态门); recovery=forward-only:迁移不可逆,代码回滚后开关切回旧 processor(先排空); complete=yes; self-contained=yes; AC=7/8; VER=6/8; landing=4; prod-files=11; scope=M; deps=TP-04; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 1.9 的 attach 侧:含分支命令的 ImportRepo attach 经 MonoWriteQueue 串行(kind='attach',operation_id = hash(仓库标识 ‖ 规范化命令描述符) 内容寻址指纹,payload 含完整命令描述符);物化前置检查——目标路径、其严格非根祖先(main@/ 例外,attach 合法更新根行)、或其任何已物化后代(path LIKE 'P/%' 的 main 行)任一存在 → 拒绝且报错可诊断(attach 只更新根 ref 与对象,不物化/推进/墓碑化路径 ref,I3 破损面不止目标行;P=/ 的 attach 允许);根依赖准备全部在 B3 锁内重做(排队期间根被前序轮次推进,入队时预计算的快照一律作废);沿用 attach_to_monorepo_parent_in_txn 的双条件 CAS 作为该分支唯一根写入;MAX_ATTACH_ATTEMPTS = 64 重试循环删除(队列下陈旧根读取不可能发生,残留重试会静默吞掉 ADR-TP-09 的绕过信号)。纯删除式 attach(无非零分支命令,只删 ImportRepo 自身 refs)不入队,登记为范围外。
Out of scope: merge(TP-07);物化路径(TP-10);push 分支(TP-12)。
Current evidence:
| 事实 | 证据 |
|---|---|
| attach 预计算根快照与根 commit、CAS 重试循环 | src/ceres/pack/import_repo.rs:507-513/518-550 |
| 纯删除式 attach 分支 | src/ceres/pack/import_repo.rs:450-475 |
Acceptance criteria:
- attach 入队后、执行前有前序轮次推进根 → B3 锁内重做根依赖准备后正常落地,CAS 不误报 stale(
(new)) -
MAX_ATTACH_ATTEMPTS重试循环不存在(rg零命中守卫覆盖定义import_repo.rs:507、循环头:511与重试臂:650三处) - attach 路径的
RedLock退役:unpack_redlock在 attach 路径零命中(rg守卫;protocol/mod.rs:202的定义如其他使用者仍需可保留);跨系统 Redis 锁不再包裹任何已被 advisory lock 序列化的操作(ADR-TP-02/03)((new)) - attach 行字段按 1.9 表取值:
operation_id为内容寻址指纹;old_id为诊断用根快照;landed_commit_id由 B3 回填根 commit id((new)) - 纯删除式 attach 不入队(
(new)) - 物化前置检查:目标/严格非根祖先/已物化后代任一存在 → 拒绝且报错可诊断;
P=/的物化检查允许(无已物化后代时,main@/不参与);ImportRepo 叶挂载不支持 path=/(入队前拒绝,B3 防御)((new)) - attach 的
failure_type=AttachFailure、失败不冻结((new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'ceres::pack::import_repo::tests'((new):attach 排队/锁内重做/指纹) -
rg零命中守卫(Verification 判定口径模板):MAX_ATTACH_ATTEMPTS无命中且退出码区分 - D 组:N/A(
.github/workflows/为空)
Dependencies: TP-23(写入者审计先行)、TP-04
Deliverables: N/A(代码卡)
Implementation write set: src/ceres/pack/
Release write set: Inherited
Files likely touched: src/ceres/pack/import_repo.rs
Docs and compatibility impact: 按 GC-05
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 继承 GC-07、GC-11
Performance budget: attach 轮次 = 锁内根重读 + 树拼装 + 一次 CAS;O(子树规模)
Estimated scope: S(1 个行为落点、3 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=attach 写入者接入 MonoWriteQueue(锁内根依赖重做、内容寻址指纹、重试循环删除、纯删除式不入队); recovery=revert:单写者开关切回(与 TP-07 同一开关); complete=yes; self-contained=yes; AC=8/8; VER=3/8; landing=1; prod-files=3; scope=S; deps=TP-04; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 1.10 交付物 8:mega_ref_tombstones 表迁移(path/ref_name/last_commit_hash/last_tree_hash/deleted_at,主键 (path, ref_name));B3 内 SAVEPOINT 同事务修复路径(撤数据写、写墓碑、删行、标终态,原子提交,无崩溃间隙;修复不经 pending_action 意图——崩溃窗口由 B2.5 expected_* 基线 + reaper 通用 I3 修复兜底);两条物化路径(refs_with_head_hash / create_repo_commit)懒生成前查墓碑——命中且路径在当前根树中可解析才以 last_commit_hash 为 parent 续接物化(续接 commit 的 tree 必须等于 resolve(root, P)),路径不在根树(目录未重建)→ 跳过物化、保持未物化状态(绝不从墓碑凭空造行),复活后删墓碑行;B0 的墓碑拒绝提示为两步(先父路径重建目录 → advertise 续接物化 → fetch 对齐 → 推送);升级前的历史删除回填——现状删除不留痕,「曾物化后被删」与「从未物化」不可区分,迁移提供两路径:(a) 尽力回填(遍历对象库引用过候选路径的 commit 取最新 tip,不保证完备);(b) fail-closed(默认,部署文档显式声明一次性 unrelated-history 风险,运维可在升级前手工回填删除清单)。树哈希断言的修复闭环(TP-11)依赖本卡。
Out of scope: 后代删除分支的落墓碑动作与复活语义完整验收(TP-14);物化插入校验(TP-10)。
Current evidence:
| 事实 | 证据 |
|---|---|
| 懒生成无父 commit | src/ceres/pack/monorepo.rs:121、src/ceres/code_edit/utils.rs:362-442 |
| 墓碑续接是 I1 的前提(删除后复活必须从旧 tip 续接) | docs/refactoring/trunk-push.md 2.5 |
Acceptance criteria:
- 墓碑表迁移注册;
apply_migrations后表存在((new)) - 墓碑优先于创建:路径有墓碑时 B0 拒绝
old_id = ZERO_ID的创建推送,提示为两步(先父路径重建目录 → advertise 续接物化 → fetch 对齐 → 推送);B3 锁内墓碑重查在 TP-12 交付(push 分支)并配交错回归((new)) - 续接物化前提:墓碑命中但路径不在当前根树 → 跳过物化(不凭空造行);目录重建后 advertise 以墓碑续接(
(new)) - 升级回填回归:删除 → 升级((a) 回填后重建续接成功;(b) fail-closed 声明覆盖)→ 旧客户端推送行为符合所选路径(
(new)) - 物化续接:路径无行但存在墓碑 → 懒生成以
last_commit_hash为 parent(非vec![]);复活后删除墓碑行((new)) - B3 内修复路径:SAVEPOINT 同事务「撤数据写 → 写墓碑(
last_commit_hash= 陈旧 tip)→ 删行 → 标终态」原子提交;注入 SAVEPOINT 提交前kill -9→ 行停留Running,reaper 比对expected_*(全等)并执行该行 path 的 I3 修复(墓碑补做)后终态化——无「回滚后未修复」残留((new)) - 墓碑查询使用
escape_like(组件边界 + 元字符转义)((new)) - 三项通用门禁全绿(
cargo +nightly fmt --all --check、cargo clippy --all-targets --all-features -- -D warnings、本卡 VER 测试全绿;全仓cargo test --all仍为计划完成门)
Verification:
-
source .env.test && cargo test -p mega2 --lib 'jupiter::storage::mono_storage::tests'((new):墓碑读写/续接;11 passed) -
source .env.test && cargo test -p mega2 --lib 'ceres::pack::monorepo::tests'((new):物化续接集成;8 passed) - D 组:N/A(
.github/workflows/为空)
Dependencies: TP-02(escape_like、事务原语)、TP-04(B3 修复挂点)
Deliverables: N/A(代码卡)
Implementation write set: src/callisto/、src/jupiter/migration/、src/jupiter/storage/、src/ceres/pack/、src/ceres/code_edit/
Release write set: Inherited
Files likely touched: src/callisto/mega_ref_tombstones.rs、src/jupiter/migration/m20260905_000300_add_mega_ref_tombstones.rs(000200 已被 mega_cl.revision 占用)、src/jupiter/migration/mod.rs、src/jupiter/storage/mono_storage.rs、src/ceres/pack/monorepo.rs、src/ceres/code_edit/utils.rs、src/jupiter/service/push_queue_service.rs、docs/monorepo.md §6(fail-closed 声明;完整反向声明仍归 TP-21)
Docs and compatibility impact: 按 GC-05;墓碑续接语义需在 docs/monorepo.md 反向声明(TP-21 落地)
Rollback mode: forward-only(墓碑表迁移不可逆;数据面由 I1 续接语义保证自洽)
Migration and rollback: 新迁移 up 建表;down 空实现;数据不变量 = 墓碑行的 last_commit_hash 恒为可解析 commit
Security and privacy: 继承 GC-07、GC-11
Performance budget: 墓碑查询 O(1) 主键点查;续接物化为单次 commit 合成
Estimated scope: M(3 个行为落点、7 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=墓碑机制最小交付(表迁移、SAVEPOINT 修复路径、物化续接集成、墓碑优先于创建); recovery=forward-only:表不可逆,代码回滚后旧行为恢复(删除后重新懒生成); complete=yes; self-contained=yes; AC=8/8; VER=4/8; landing=3; prod-files=7; scope=M; deps=TP-02,TP-04; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 ADR-TP-20 第 1 项:两条惰性物化路径(refs_with_head_hash / create_repo_commit)不入队,改为「锁外树遍历记录出发根身份对(ref_commit_hash + ref_tree_hash,与 B3/reaper 判定同构)→ 持 MONO_WRITE_LOCK 短锁事务内重读根 ref 比对身份对 → 一致才 WHERE NOT EXISTS 插入;不一致放弃」。一次物化产出的全部 ref 行(monorepo.rs:142-198 的逐根 ref 调用)合并进同一个持锁事务(C-R5 #6)。放弃的协议落点:服务端有界重试(K=2 + 退避)后仍失败返回可诊断错误,绝不以空 refs/capabilities-only 降级——RepoHandler::refs_with_head_hash 签名改可失败(两个实现 monorepo.rs 与 import_repo.rs:84-94 同步),smart.rs/v2.rs 传播,ProtocolError 对 advertise 失败映射 5xx。插入竞态:NOT EXISTS 命中既有行时重读持久化行返回(不返回自身预计算 ref);重试循环必须绕过 heads_exist 快路径(monorepo.rs:129-135/utils.rs:367-375 在行存在时直接返回该行——不绕过则放弃-重试原地拿回同一陈旧行)。
Out of scope: B3 树哈希断言与修复(TP-11);对账与周期巡检(TP-11);墓碑机制本体(TP-09)。
Current evidence:
| 事实 | 证据 |
|---|---|
物化路径经 materialize_path_refs 持锁插入 |
src/ceres/pack/materialize.rs、src/ceres/pack/monorepo.rs refs_with_head_hash、src/ceres/code_edit/utils.rs:create_repo_commit |
| advertise 失败映射 5xx | src/ceres/protocol/smart.rs、src/ceres/protocol/v2.rs、src/common/errors/mod.rs ProtocolError::AdvertiseFailed |
RepoHandler::refs_with_head_hash 可失败 |
src/ceres/pack/mod.rs、import_repo.rs 同步实现 |
Acceptance criteria:
- 物化竞态回归:物化事务在锁外基于旧根遍历后挂起,B3 提交新根,物化随后持锁插入 → 根快照校验检出不一致,放弃插入(
(new)) - 有界重试:持续根推进使重试耗尽 → advertise 返回可诊断错误而非空 refs/capabilities-only;错误映射为 5xx(
(new)) -
NOT EXISTS命中既有行(净零推送推进main@P的场景)→ 重读持久化行返回,不返回自身预计算 ref;重试绕过heads_exist快路径((new)) -
RepoHandler::refs_with_head_hash可失败签名改造:monorepo.rs与import_repo.rs两个实现同步;smart.rs/v2.rs传播((new)) - 物化插入持有
MONO_WRITE_LOCK短锁,与 B3 无行级交叉;插入带WHERE NOT EXISTS守卫;一次物化的全部 ref 行在同一持锁事务((new)) - 遍历标记为根身份对(commit+tree),比对任一分量不一致即放弃(tree-only 绕过不漏判)(
(new)) - 既有 advertise/clone/ls-remote 行为回归(无竞态时结果与现状一致)
- 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'ceres::pack::monorepo::tests'((new):物化竞态/重试/重读)— 13 passed -
scripts/git_protocol_smoke.sh本地等价(ER-04 Git 协议表面七步骨架,含.env.test数据面覆盖)— N/A:无运行中 HTTP 服务、MEGA2_HTTP_REPO_URL未设;无竞态回归由tp10_refs_with_head_hash_materializes_without_race覆盖 -
source .env.test && cargo test -p mega2 --lib 'common::errors::tests'((new):5xx 映射)— 4 passed - D 组:
src/ceres/pack/**、src/ceres/protocol/**命中git-protocol-smoke.yml概率高,开工时以远端 workflowpaths:现场判定 — N/A:本 checkout.github/workflows/为空
Dependencies: TP-02(escape_like、事务内 upsert)、TP-09(墓碑查询)
Deliverables: N/A(代码卡)
Implementation write set: src/ceres/pack/、src/ceres/protocol/、src/common/errors/、src/ceres/code_edit/
Release write set: Inherited
Files likely touched: src/ceres/pack/monorepo.rs、src/ceres/pack/mod.rs、src/ceres/pack/import_repo.rs(含 :392 的 .await.0 调用点与 :84-94 实现)、src/ceres/protocol/smart.rs、src/ceres/protocol/v2.rs、src/common/errors/mod.rs、src/ceres/code_edit/utils.rs
Docs and compatibility impact: 按 GC-05;advertise 失败从「空仓库伪装」变为 5xx 属于缺陷修复(GC-TP-04),需在 docs/refactoring/protocol.md 同步
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 继承 GC-07、GC-11;5xx 错误信息不得泄漏内部路径
Performance budget: 物化插入 = 短锁事务(毫秒级,几次行读写);放弃重试 K=2 有界
Estimated scope: M(3 个行为落点、8 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=惰性物化插入校验与协议错误传播(根快照新鲜度校验、NOT EXISTS、有界重试、5xx 映射); recovery=revert:代码回滚即恢复旧物化行为; complete=yes; self-contained=yes; AC=8/8; VER=5/8; landing=3; prod-files=8; scope=M; deps=TP-02,TP-09; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 ADR-TP-20 第 2/3 项:B3 闸门追加树哈希断言——push 与 merge 分支同谓词,且先于 non-fast-forward 比对(陈旧物化行无论客户端基线新旧都先拒绝并修复;B0 的 NFF 预检已是遥测不拒绝);只覆盖 refs/heads/main 行(CL ref 行与 tag 行不参与,登记范围外)。检出即拒绝 + SAVEPOINT 同事务墓碑修复(撤数据写、写墓碑、删行、标终态)——崩溃窗口不由修复意图承担(pending_action 仅 requeue_conflict),由 **B2.5 expected_* 基线 + reaper 对每行 Running 的比对与通用 I3 修复(按 kind)**兜底(TP-05 交付判定,本卡交付断言与修复动作)。启用前对账与周期性不变式巡检:持 MONO_WRITE_LOCK 事务内分批比对(按 kind 分语义:attach 跳过且 main@/ 例外、push 缺行视创建中间态、merge 缺行异常登记),频率与告警阈值可配;断言与巡检的指标计数。
Out of scope: 物化插入校验(TP-10);墓碑机制本体(TP-09);push/merge 分支的其余语义(TP-07/12)。
Current evidence:
| 事实 | 证据 |
|---|---|
共享谓词 assert_main_path_tree_hash_in_txn;push/merge B3 检出即 SAVEPOINT 墓碑修复 |
src/jupiter/service/push_queue_service.rs |
对账/巡检持 MONO_WRITE_LOCK 分批;仅 queue/trunk 启动 spawn |
src/jupiter/service/mono_write_audit.rs、src/context/mod.rs |
崩溃窗口 I3 删陈旧 main@P |
src/jupiter/service/push_queue_reaper.rs tp11_kill9_* |
Acceptance criteria:
- 陈旧行修复回归:手工注入
ref_tree_hash落后于根树的main@P行 → push 与 merge 均被树哈希断言拒绝,B3 内 SAVEPOINT 同事务写墓碑(last_commit_hash= 陈旧 tip)并删行((new)) - 拒绝-修复-续接闭环(merge 分支 + 共享谓词):紧随的 advertise 从墓碑续接物化,新行 parent 等于陈旧 tip(I1 保持);push 分支的断言-修复-续接-重推闭环在 TP-12 验收(push 分支由 TP-12 交付)(
(new)) - 断言先于业务门控:陈旧
main@P行 + CL 基线同时陈旧 → 树哈希断言先拒绝(而非冲突重查先行)((new)) - merge 的落地 parent 选取(
refs/cl/<link>优先,trunk-push GAP-07)不受断言影响;CL ref 行不参与断言((new)) - 启用前对账:存量不一致行转墓碑;周期巡检在同一谓词上修复后续注入的行(持锁事务内分批,不与 B3 竞态)(
(new)) - 崩溃窗口(基线模型):注入「SAVEPOINT 提交前
kill -9」→ 行停留Running,reaper 比对expected_*(全等)并执行该行 path 的 I3 修复后终态化——陈旧行不被refs_with_head_hash持续返回((new)) - 断言与巡检指标计数存在(
(new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'ceres::api_service::mono_api_service::tests'((new):断言/修复/对账/巡检)— 7 passed -
source .env.test && cargo test -p mega2 --lib 'jupiter::service::push_queue_reaper::tests'((new):意图补做)— 10 passed - D 组:
src/ceres/**命中判定按开工时 workflowpaths:— N/A:本 checkout.github/workflows/为空
Dependencies: TP-23(写入者审计)、TP-04(B3 骨架)、TP-05(断言/巡检集成在 reaper 之上)、TP-07(merge 断言挂点)、TP-09(墓碑)、TP-10(插入校验先行)
Deliverables: N/A(代码卡)
Implementation write set: src/ceres/api_service/、src/jupiter/service/
Release write set: Inherited
Files likely touched: src/ceres/api_service/mono_api_service.rs、src/jupiter/service/push_queue_service.rs(断言谓词)、src/jupiter/service/push_queue_reaper.rs(意图补做)、src/jupiter/service/mono_write_audit.rs(巡检新模块)
Docs and compatibility impact: 按 GC-05;I3/I5 的「锁纪律前提」表述在 trunk-push.md 已登记
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 继承 GC-07、GC-11;巡检日志不泄漏路径内容
Performance budget: 断言 = 每轮一次 resolve(root, P);巡检分批持锁(批次上限可配);对账为启动期一次全量
Estimated scope: M(2 个行为落点、6 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=树哈希断言与墓碑修复、对账与周期巡检(ADR-TP-20 第 2/3 项); recovery=revert:代码回滚后断言消失、陈旧行回到现状的删除重建路径; complete=yes; self-contained=yes; AC=8/8; VER=5/8; landing=2; prod-files=6; scope=M; deps=TP-04,TP-07,TP-09,TP-10; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 B3 的 push 分支(trunk 形态;在测试专用 push_policy 开关下实现与验收,不含阶段 4 协议接线)。权威 commit 校验三断言(树哈希断言先行):行存在 → ref_commit_hash == cmd.old_id(N≥1);行缺失 → 仅 old_id = ZERO_ID 可创建;N=0 → cmd.new_id == 当前 tip。N 以客户端基线锚定(new_id→old_id 段长,随描述符持久化、重试不重算);N=0 当且仅当 old_id == new_id(真实落地路径:闸门照常,tip 吻合 → 行 Done;不符 → non-fast-forward 拒绝);N=1 → main@P = cmd.new_id 不合成;N>1 → 合成 squash commit(parent = 旧 tip、tree = chain.tip.tree_id);创建语义(P 无行且 old_id == ZERO_ID 无墓碑:N=0 不可达(old_id=ZERO_ID 而有效 new_id 非 ZERO),N=1 → main@P = cmd.new_id;N>1 → parentless squash;墓碑存在或 old_id != ZERO_ID → 拒绝);树哈希断言先于 non-fast-forward 比对;祖先 roll-up(parent = 各祖先旧 tip,树变化才前进——ADR-TP-16 净零谓词);树哈希断言接入(TP-11 谓词);B0–B3 墓碑竞态与「等待期间物化」的可诊断拒绝分支;trunk 删除策略(一切删除类命令拒绝);trunk receive-pack 桥接(1.10 交付物 10,GAP-14)——trunk 形态下 build_push_chain 的 Noop 短路(monorepo.rs:1191-1247)改为构造持久化描述符(N/commits/fork_base)并继续 B1/B3(含空 pack 且 old_id != new_id、全已知对象两情形;review 形态保留 Noop,硬约束 8)。
Out of scope: 协议接线 finalize_receive_pack 条件化(TP-17);合成 commit 的归属与 message(TP-16 升级);advance_descendant_refs 切换(TP-14——本卡阶段 1 先按 trunk-push.md B3 伪码以交付物 5 的事务内变体处理后代 D)。
阶段 1 的后代处理(trunk-push.md B3 push 分支伪码): 后代 D → 交付物 5 的 remove_none_cl_refs 事务内变体(与 merge 分支同一原语,含 LIKE 缺陷修复);阶段 2 由 TP-14 切换为 advance_descendant_refs(2.8 同时覆盖 merge 与 push 分支)。
Current evidence:
| 事实 | 证据 |
|---|---|
PushPayload.n 随描述符持久化;B3 只读不重算 |
src/jupiter/service/push_queue_service.rs PushPayload / b3_execute_push |
N 分流、创建、净零同值 CAS、祖先 roll-up 在 execute_b3 Push 臂落地并 return |
src/ceres/api_service/mono_api_service.rs b3_execute_push / apply_push_in_txn |
GAP-14:trunk Noop → PushChain::from_known_tip;review 保留短路 |
src/ceres/pack/monorepo.rs build_push_chain、src/ceres/pack/push_chain.rs |
| B0 删除拒绝先于 ref_name;其它 ref 删除提示走父路径 | src/jupiter/service/push_queue_service.rs b0_reject_push |
Acceptance criteria:
- N 计数回归:曾被拒的 N=2 推送重试仍走 squash 分支(对象已知不退化为 fast-forward);曾成功者被指纹 Done 回放拦截;
old_id == new_id退化重推由 B3 判 no-op 落地((new)) - 创建语义回归:向全新路径
old_id = ZERO_ID推送——N=1 时main@P精确等于客户端 tip;N=2 时落地 parentless squash(message 枚举完整性在 TP-16 验收,本卡只断言 parentless 落地与push_queue行可回溯全链);多级创建(/a/b/c三级均不存在)由树项插入原语逐级补齐后落地为客户端 tip((new)) - 墓碑与物化竞态:B0 预检无墓碑、B3 锁内判定前出现墓碑 → 锁内重查拒绝(I1 不破);路径可解析但未物化、物化在 B0 后插入合成行 → 可诊断拒绝(「路径已在等待期间物化,请 fetch 后重推」)(
(new)) - 净零轮次:
main@P前进、根与祖先不动;净零轮次的同值 CAS 在场(tripwire 不缺席)((new)) - 权威 commit 校验三断言:行存在 +
ref_commit_hash == old_id(N≥1 非快进即拒);行缺失 +old_id != ZERO_ID→ 拒;N=0 +new_id != 当前 tip→ 拒(树哈希断言先行,(new)) - trunk 删除策略:main 删除被拒(UN-16 等价语义);其余 ref 删除被拒并提示走父路径删除 commit(
(new)) - 交付物 10(GAP-14):空 pack 与全已知对象两情形的 trunk 推送 → B1 出现行、B3 执行(fast-forward/拒绝按闸门);review 形态
Noop现状保留((new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'ceres::api_service::mono_api_service::tests'((new):push 分支全套)— 15 passed(含 8 个tp12_*) -
source .env.test && cargo test -p mega2 --lib 'jupiter::storage::mono_storage::tests'((new):创建语义 upsert)— 11 passed - D 组:
src/ceres/**命中判定按开工时 workflowpaths:— N/A:本 checkout.github/workflows/为空
Dependencies: TP-23(写入者审计)、TP-04(B3 骨架)、TP-07(交付物 5 的事务内删除变体——push 分支后代处理复用)、TP-11(树哈希断言)
Deliverables: N/A(代码卡)
Implementation write set: src/ceres/api_service/、src/ceres/pack/(Noop 桥接 + build_push_chain 描述符构造)、src/jupiter/storage/
Release write set: Inherited
Files likely touched: src/ceres/api_service/mono_api_service.rs(push 分支)、src/ceres/pack/monorepo.rs(Noop 桥接)、src/ceres/pack/push_chain.rs(描述符构造)、src/jupiter/storage/mono_storage.rs(创建 upsert 调用)、src/config/model.rs(测试开关读取)
Docs and compatibility impact: 按 GC-05;N 分流语义与创建语义属 docs/monorepo.md 反向声明内容(TP-21)
Rollback mode: revert(测试开关下运行,未接协议层)
Migration and rollback: N/A
Security and privacy: 继承 GC-07、GC-11
Performance budget: push 轮次 = 树脊重算 O(depth) + 一次事务;squash message O(N);N 有 max_push_commits 上界(TP-15 前为常量 250)
Estimated scope: M(2 个行为落点、8 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=B3 push 分支(N 分流、创建语义、净零、祖先 roll-up、删除策略,测试开关下); recovery=revert:未接协议层,回滚即无 push 落地; complete=yes; self-contained=yes; AC=8/8; VER=6/8; landing=2; prod-files=8; scope=M; deps=TP-04,TP-11; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 ADR-TP-11:traverses_tree_and_update_filepath 移出 B3 临界区(事务提交后执行,C 段);mega_blob.file_path 单列改造为出现对表 blob_paths(blob_id, path, indexed_push_id)(同一 blob 多路径出现,(blob_id, path) 唯一);更新带 行级水位 CAS 与形态隔离规则(队列更新 WHERE indexed_push_id IS NULL OR indexed_push_id < $id;review 形态更新仅 WHERE indexed_push_id IS NULL——review 推送不入队,其索引走现状同步调用,无版本更新不得击穿队列已索引行;版本来源按形态分离);删除感知的按代 reconciliation(以「本次 tip 子树全集」为界,清除「上一代存在而新子树不存在」的出现对;已知限制:删除无代际水位,旧任务可能重插已删行——「永不复活」不被承诺,收敛是最终一致的,补偿任务周期重扫清除);mega_blob.file_path 降级为展示用最新路径或废弃;补偿任务作为收敛兜底;docs/monorepo.md 声明最终一致性(TP-21)。
Out of scope: 增量索引(已否决,登记为后续独立议题);索引的读取端消费改造(挂载/Web 浏览沿用现有读取面)。
Current evidence:
| 事实 | 证据 |
|---|---|
blob_paths(blob_id, path, indexed_push_id) 出现对表,PK 唯一,水位可空 |
src/callisto/blob_paths.rs、m20260905_000500_add_blob_paths.rs |
队列 CAS IS NULL OR < $id;review 仅 IS NULL;子树 reconciliation + 补偿任务 |
src/jupiter/storage/blob_path_index.rs |
C 段在 B3 txn.commit() 之后;review 仍走 traverses_tree_and_update_filepath |
push_queue_service.rs run_c_segment_index、monorepo.rs |
| 补偿任务周期 spawn | src/context/mod.rs BlobPathCompensator |
Acceptance criteria:
-
blob_paths出现对表迁移注册;(blob_id, path)唯一;indexed_push_id列存在((new)) - C 段移出临界区:索引任务在 B3 事务提交后执行,带
push_queue.id保护;序号较小者发现该路径已被更大序号索引过即跳过((new)) - 行级水位 CAS 与形态隔离:队列更新
IS NULL OR < $id、review 更新仅IS NULL行(嵌套交错不覆盖;review 无版本更新不击穿)((new)) - 删除感知 reconciliation:推送 A(id 5)索引后、推送 B(id 6)删除某 blob,A 的滞后任务可能重插该行(已知限制)→ 补偿任务重扫后清除,最终收敛一致(
(new)) - 同一 blob 多路径出现:blob 在
/a与/a/b均出现时两条出现对并存,删除/a/b不误删/a的出现对((new)) -
mega_blob.file_path降级为展示用最新路径或废弃(读取面回归)((new)) - 补偿任务存在(收敛兜底),与删除 reconciliation 共同保证最终一致
- 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'jupiter::storage::mono_storage::tests'((new):出现对/水位/删除感知)— 16 passed(含 5 个tp13_*) -
source .env.test && cargo test -p mega2 --lib 'ceres::pack::monorepo::tests'((new):C 段时序)— 15 passed(含tp13_c_segment/tp13_review) - D 组:
src/ceres/**、src/callisto/**命中判定按开工时 workflowpaths:— N/A:本 checkout.github/workflows/为空
Dependencies: TP-04(B3 骨架/C 段挂点)、TP-11(断言修复先行)、TP-12(push 分支串行,写集同在 monorepo.rs)
Deliverables: N/A(代码卡)
Implementation write set: src/callisto/、src/jupiter/migration/、src/jupiter/storage/、src/ceres/pack/
Release write set: Inherited
Files likely touched: src/callisto/blob_paths.rs、src/jupiter/migration/m20260905_000300_add_blob_paths.rs、src/jupiter/migration/mod.rs、src/jupiter/storage/mono_storage.rs、src/ceres/pack/monorepo.rs
Docs and compatibility impact: 按 GC-05;索引最终一致性声明写入 docs/monorepo.md(TP-21)
Rollback mode: forward-only(blob_paths 表迁移不可逆;旧索引可在代码回滚后重建)
Migration and rollback: 新迁移 up 建表;down 空实现;数据不变量 = 经补偿/reconciliation 后与当前 tip 子树最终一致(允许陈旧重插的过渡态);恢复验证 = 补偿任务收敛
Security and privacy: 继承 GC-07、GC-11
Performance budget: 索引任务 O(子树规模)、在临界区外;行级水位 CAS 为 O(行数) 分批;删除 reconciliation O(上一代 ∪ 本代出现对)
Estimated scope: M(4 个行为落点、10 个生产文件)
Version increment: patch
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=文件路径索引最终一致化(blob_paths 出现对表、行级水位 CAS、删除感知 reconciliation、C 段移出临界区、补偿任务); recovery=forward-only:表不可逆,旧索引可由代码回滚 + 重建恢复; complete=yes; self-contained=yes; AC=8/8; VER=5/8; landing=4; prod-files=10; scope=M; deps=TP-04,TP-11,TP-12; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付阶段 2 的 advance_descendant_refs:候选集查询(descendant_main_refs,带尾斜线组件边界 + escape_like 转义 + 自我排除 Path != p,is_cl = false);四种结果(tree 相等跳过 / 不等续接合成 commit / 路径不存在落墓碑并删 ref / 目录被文件取代同删除分支——显式判 TreeItemMode::Tree 防 blob hash 写入 ref_tree_hash);剪枝(同层 tree hash 相等即中止下行)与记忆化(候选按深度升序);refs_with_head_hash/create_repo_commit 复活时从墓碑续接(TP-09 已交付机制,本卡补齐后代删除分支与完整验收);merge 分支切换(2.8):merge_cl_unchecked 的 remove_none_cl_refs 调用替换为 advance_descendant_refs(同一 B3 事务内,候选集来源换为合并后子树);push 分支的后代处理一并切换(TP-12);新增 mega_refs_path_pattern 部分索引。I3 强一致、与 B3 同事务(ADR-TP-19)。
Out of scope: 墓碑机制本体(TP-09);物化插入校验(TP-10);树哈希断言(TP-11);合成 commit 归属(TP-16 升级)。
Current evidence:
| 事实 | 证据 |
|---|---|
descendant_main_refs:尾斜线组件边界 + escape_like + Path != p + ref_name=main + is_cl=false |
src/jupiter/storage/mono_storage.rs list_descendant_main_refs_on |
advance_descendant_refs 四种结果、Merkle 剪枝、记忆化、墓碑删除 |
src/jupiter/storage/mono_storage.rs advance_descendant_refs |
merge/push 落地面不再调用 remove_none_cl_refs;legacy merge_cl_unchecked 与 queue B3 均与 apply 同事务 |
merge_apply_and_advance_in_txn、push_queue_service.rs B3 merge/push |
mega_refs_path_pattern 部分索引(Postgres text_pattern_ops,down 空) |
m20260905_000600_mega_refs_path_pattern.rs |
Acceptance criteria:
- 断裂回归(测试专用
push_policy开关下的 push 触发路径):A clone/project/foo并本地提交 → B 在/project推送 → Agit pull成功并可继续推送(当前实现必失败)((new))— e2e 走 merge 触发(review 主路径);B3 push 由tp14_push_continues_changed_descendant_and_skips_unchanged覆盖 - 无辜删除回归:推送
/project/foo后,/project/foobar的 ref 的 commit hash 与 tree hash 均未变化((new)) - LIKE 通配回归:推送
/project/my_lib后,/project/myXlib的 ref 未被触碰((new)) - 四种结果:后代子树未变 → 跳过不产生空 commit;变更 → 新 tip parent 精确等于旧 tip;目录被删 → 落墓碑并删 ref;目录被同名文件取代 → 走删除分支、不写入 blob hash(
(new)) - 墓碑复活与多重物化:同名目录复活后 clone,新 base 的 parent 等于墓碑记录的
last_commit_hash;/a、/a/b、/a/b/c三条 ref 同时物化时推送/a,三条各自续接到各自旧 tip;is_cl = true的后代 ref 与后代路径上的 tag ref 行完全不变(ref_name = main过滤的登记在案行为变化);根路径推送自我排除(parent 无自指)((new))— 三层续接的 剪枝 形态已测;全变三层续接按深度升序构造正确 - merge 触发路径(2.8):A clone
/project/foo并本地提交 → B 向/project合入 CL → merge 分支走advance_descendant_refs,remove_none_cl_refs不再删除main@/project/foo→ Agit pull成功((new)) - 互嵌路径 merge 续接回归(自 TP-07 移入):
/a与/a/b两次 merge 串行,后者落地 parent 等于前者落地后的 tip(阶段 1 的预期失败在此转为成功)((new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'jupiter::storage::mono_storage::tests'((new):候选查询/四种结果/剪枝记忆化)— 19 passed -
source .env.test && cargo test -p mega2 --lib 'ceres::api_service::mono_api_service::tests'((new):merge 分支切换 2.8)— 16 passed(含tp14_push_*);互嵌 merge 在mc09_tests::queue_merge_nested_descendant_continues_then_second_merge_lands -
source .env.test && cargo test -p mega2 --test integration_git_cli -- --test-threads=1 descendant((new):断裂回归 e2e)— ok - D 组:
src/ceres/**、src/jupiter/storage/**命中判定按开工时 workflowpaths:— N/A:本 checkout.github/workflows/为空
Dependencies: TP-02(escape_like)、TP-07(merge 分支)、TP-09(墓碑)、TP-12(push 分支一并切换)
Deliverables: N/A(代码卡)
Implementation write set: src/jupiter/storage/、src/ceres/api_service/、src/ceres/pack/
Release write set: Inherited
Files likely touched: src/jupiter/storage/mono_storage.rs、src/ceres/api_service/mono_api_service.rs、src/ceres/pack/monorepo.rs(push 分支切换)、src/jupiter/migration/(mega_refs_path_pattern 索引)
Docs and compatibility impact: 按 GC-05;后代续接属登记在案的行为变化(硬约束 8 豁免),同步 docs/refactoring/trunk-push.md 2.8 与 docs/monorepo.md(TP-21)
Rollback mode: forward-only(mega_refs_path_pattern 索引迁移 down 空实现;代码回滚后旧索引可重建)
Migration and rollback: 索引迁移 additive;down 空实现
Security and privacy: 继承 GC-07、GC-11
Performance budget: 成本以已物化后代数 × 每次 resolve 为界;Merkle 剪枝 + 记忆化使未变子树 O(1) 跳过
Estimated scope: M(2 个行为落点、7 个生产文件)
Version increment: patch(缺陷修复;review 形态下的可观察行为变化仅限「不再删除后代 ref」这一修复本身)
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=后代 ref 续接(advance_descendant_refs、四种结果、剪枝记忆化、merge/push 分支切换、墓碑复活验收); recovery=forward-only:索引迁移不可逆;代码回滚回 remove_none_cl_refs 旧语义; complete=yes; self-contained=yes; AC=8/8; VER=6/8; landing=2; prod-files=7; scope=M; deps=TP-02,TP-07,TP-09,TP-12; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付阶段 4 的配置面与 ADR-TP-17(含 4.2a 的 push_auth 配置面——配置模型/解析/校验归本卡,认证器实现在 TP-19)。分期说明(有意前置):本卡归属 Phase 3 交付(配置为 additive、默认 review 行为不变),但其拥有的 4.1 启动校验属阶段 4 语义——校验代码随本卡落地、在阶段 4 的形态切换时才被触发;这是有意的 front-load,非遗漏。[monorepo].push_policy = "review" | "trunk"(登记 restart_required_fields);[monorepo].max_push_commits(默认 250,trunk-only,review 形态保留 MAX_CL_CHAIN_COMMITS 常量不动);启动期 fail-closed 六条校验(① trunk + cedar.enforcement != "off" 拒绝;② trunk + open CL 拒绝;③ push_policy 变更且 push_queue 有非终态行 → 拒绝(queue_control.last_policy 依据,要求排空/取消);④ push_auth ∈ {token,none} ⇒ push_policy = "trunk";⑤ push_policy = "trunk" ⇒ push_auth 显式配置;⑥ 形态切换的索引水位重置——切换运维步骤执行 UPDATE ... SET indexed_push_id = NULL(review 只写 IS NULL 行,trunk → review 不重置会使水位行永久失效;RESET INDEX WATERMARK 随迁移/维护执行,两方向各配方向测试));PushChain::resolve/validate 的链长上界参数化(review 传常量、trunk 传配置值——ADR-TP-17 要求「未参数化前不得宣称可调」)。测试专用 push_policy 开关(1.10 交付物 9)的正式配置读取在此转正。
Out of scope: 推送落地路径接线(TP-17);CL 面关闭(TP-18);token 认证器实现与 HTTP 挂点(TP-19——push_auth/push_tokens 的配置面归本卡,认证器归 TP-19)。
Current evidence:
| 事实 | 证据 |
|---|---|
push_policy / max_push_commits / push_auth / push_tokens 解析与校验;restart_required_fields |
src/config/model.rs、src/config/validate.rs validate_trunk_config_surface / validate_git_config、src/config/reload.rs |
①④⑤ 在 Config::validate,并由 AppContext::new 在 service 启动执行 |
src/context/mod.rs AppContext::new |
②③⑥ HTTP 启动:open CL、queue_control FOR UPDATE 排空后水位重置 |
prepare_push_policy_startup、switch_last_policy_if_queue_empty |
PushChain 链长入参;trunk B0 用 max_push_commits;review 保留 MAX_CL_CHAIN_COMMITS=250 |
src/ceres/pack/push_chain.rs、monorepo.rs chain_commit_limit、b0_reject_push |
Acceptance criteria:
-
push_policy/max_push_commits/push_auth/push_tokens/paths省略语义:解析与校验(默认review/ 250 / token/none ⇔ trunk 双向 / SecretRef / 组件边界),登记restart_required_fields,配正反测试((new)) -
启动校验 ①②③④⑤:trunk + cedar≠off → 拒;trunk + open CL → 拒;policy 变更 + 非终态行 → 拒(
last_policy);push_auth缺省 vs trunk 缺push_auth→ 拒(双向);merge_writer非法值 → 拒——五条均可诊断((new)) -
形态切换运维:
SET indexed_push_id = NULL+ 方向测试((new)) -
PushChain参数化:链长上界由入参传入(review 等价常量、trunk 用配置值);超限在 B0 被拒((new)) -
三项通用门禁全绿 Verification:
-
cargo run -p mega2 -- --config config/config.toml config validate(配置校验链)→config valid -
source .env.test && cargo test -p mega2 --lib 'config::tests'((new):push_policy/max_push_commits 解析与启动校验)→ 49 passed -
source .env.test && cargo test -p mega2 --lib 'ceres::pack::push_chain::tests'((new):链长参数化)→ 31 passed -
D 组:开工时
.github/workflows/空 → N/A
Dependencies: TP-01(校验 ③ 读 queue_control.last_policy)、TP-13(校验 ⑥ 重置 indexed_push_id);merge_writer 开关的定义与校验归 TP-07(Phase 1 前置);与 TP-14 的写集不相交
Deliverables: N/A(代码卡)
Implementation write set: src/config/、src/ceres/merge_checker/、src/ceres/pack/push_chain.rs(与 TP-14 的 monorepo.rs 文件级不相交)
Release write set: Inherited
Files likely touched: src/config/model.rs、src/config/validate.rs、src/config/reload.rs、src/jupiter/storage/queue_control.rs(last_policy 更新)、config/config.toml(注释,含 push_auth/push_tokens 示例)、src/ceres/pack/push_chain.rs
Docs and compatibility impact: 按 GC-05;config/config.toml 示例注释同步;docs/refactoring/config.md 若有配置清单需同步
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 硬约束 6 的 fail-closed 启动校验是本卡安全核心;max_push_commits 不参与 message 体积决策(ADR-TP-15/17 已接受 25 KB)
Performance budget: 参数化不改复杂度;链校验 O(chain)
Estimated scope: M(2 个行为落点、5 个生产文件)
Version increment: patch(additive 配置,默认行为不变)
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=trunk 配置面(push_policy、max_push_commits、push_auth/push_tokens 配置面、启动 fail-closed 校验×6、PushChain 链长参数化); recovery=revert:配置 additive、默认不变,回滚即恢复; complete=yes; self-contained=yes; AC=5/8; VER=4/8; landing=2; prod-files=5; scope=M; deps=TP-01,TP-13; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付阶段 3:trunk 形态新引入的合成 commit(squash、祖先 roll-up、后代续接)改用 Commit::new(author, committer, tree, parents, message)——author/committer 身份取链上 tip、其余作者 Co-authored-by:、author date 原值、committer date = max(落地时刻, 前一 trunk commit 的 committer date)(ADR-TP-14);squash message 完整枚举全部 N 条不截断(ADR-TP-15,含说明段落 + 逐条 id/author/date/subject,拓扑升序;Mono-Squash-Range/Mono-Squash-Count 机器锚点;创建情形省略 Range);祖先/后代带紧凑形式 + Mono-Squash-Commit 指针;服务端 GPG 签名(MC-09 ServerSigningContext);N=1 零改写不合成。review 形态 CL merge 落地 commit 保持现状(硬约束 8)。
Out of scope: 配置面(TP-15);协议接线(TP-17);逐 commit GPG 验签(ADR-TP-15a 明确不支持)。
Current evidence:
| 事实 | 证据 |
|---|---|
trunk squash / 祖先 roll-up / 后代续接走 Commit::new + 身份保留签名 |
src/ceres/pack/trunk_provenance.rs、sign_commit_preserving_identities、b3_execute_push、apply_push_in_txn、DescendantCommitStyle::Trunk |
N=1 不合成 P;N>1 squash 完整枚举;祖先/后代 Mono-Squash-Commit |
tp16_n1_*、tp16_n3_*、squash_lists_all_n_in_topo_asc_without_truncation |
review CL merge 仍 from_tree_id / mega <admin@mega.org> |
process_ref_updates、tp16_review_merge_keeps_from_tree_id_shape |
Acceptance criteria:
- 单 commit 推送:
main@P精确等于客户端 commit id 且对象逐字节一致(签名字节保留但断言的是字节相等,非签名可验证性);根 roll-up message 与该 commit 逐字相同((new)) - 三 commit 推送:
main@P为 squash,tree精确等于客户端 tip 的tree(I2)、parent等于推送前 tip;squash 与根 roll-up 的 author 等于客户端 author((new)) - 枚举完整性:N 取 3/50/
max_push_commits三档,message 逐条列出全部 N 条,条数等于Mono-Squash-Count,无截断;正文严格拓扑升序((new)) - 多作者链:其余作者出现在
Co-authored-by:;Mono-Commitstrailer 不再出现((new)) - message 首段说明段落存在于每个 N>1 squash(
git show可直接读懂);author date 跨度较大时补Mono-Author-Date-Range(trunk-push.md 3.2/ADR-TP-14)((new)) - committer date 保序(单调不减、与
push_queue.id保序,I6;author date 原值);祖先/后代紧凑形式的Mono-Squash-Commit为不可变 commit id 且可解析(I4),创建情形省略Mono-Squash-Range((new)) - 服务端签名:全部新增合成 commit 带服务端 GPG 签名且可验证;review 形态 CL merge 落地 commit 与落地前逐字节一致(硬约束 8)(
(new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'ceres::api_service::mono_api_service::tests'((new):provenance 全套)→ 19 passed -
source .env.test && cargo test -p mega2 --lib 'ceres::pack::push_chain::tests'((new):枚举拓扑序)→ 32 passed - 手工证据:
git show <squash id>展示完整枚举(sanitized)—tp16_n3_*断言 stored content 含说明段 + 全部 id/author/subject(fixture authors) - D 组:开工时
.github/workflows/空 → N/A
Dependencies: TP-12(push 分支合成点)、TP-14(后代续接 commit)、TP-15(三档验收依赖 max_push_commits)
Deliverables: N/A(代码卡)
Implementation write set: src/ceres/api_service/、src/ceres/pack/
Release write set: Inherited
Files likely touched: src/ceres/api_service/mono_api_service.rs(:647-651 roll-up 构造点——本卡主轴)。注意:src/ceres/pack/monorepo.rs:177-183 与 code_edit/utils.rs 的 Commit::new 是物化路径(使用源 commit 的 author/committer/message,非硬编码),归 TP-09/TP-10 的物化范围,本卡不改;src/internal/object/commit.rs 属外部依赖 git-internal 0.8.7,不在仓内写集
Docs and compatibility impact: 按 GC-05;provenance 规则与 ADR-TP-18 对齐约定写入 docs/monorepo.md(TP-21)
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 签名语义 = 「该落地由本实例执行」;Co-authored-by 来自客户端自声明 author,不作认证身份(TP-19 依赖此分离)
Performance budget: message 体积 = 每次推送一份完整枚举(O(N),N ≤ max_push_commits),不随物化层数放大
Estimated scope: M(2 个行为落点、7 个生产文件)
Version increment: patch(仅 trunk 形态生效;review 形态逐字节不变)
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=合成 commit 的真实归属与 provenance(Commit::new 构造、完整枚举 message、Mono-Squash-* trailer、服务端签名); recovery=revert:回滚恢复硬编码归属; complete=yes; self-contained=yes; AC=8/8; VER=6/8; landing=2; prod-files=7; scope=M; deps=TP-12,TP-14,TP-15; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付阶段 4.2:finalize_receive_pack 按 push_policy 条件化——trunk 形态跳过 persist_mono_branch_cl_mega_refs_transaction(写 refs/cl/*)与 CL post-push 管线(update_or_create_cl),唯一动作是以 kind='push' 入队并执行 B3(TP-12 分支转正,测试专用开关移除);存量已合并/关闭 refs/cl/* 行保留为档案但 advertise 过滤(trunk 形态 refs_with_head_hash 不返回 CL refs);B0 删除策略转正;ADR-TP-18:N>1 推送成功时经 sideband 返回合成后的 commit id、non-fast-forward 拒绝信息中给出对齐命令 git fetch && git reset --hard origin/main。
Out of scope: CL/issue/reviewer router 条件挂载(TP-18);认证(TP-19/20)。
Current evidence:
| 事实 | 证据 |
|---|---|
finalize_receive_pack 按 push_policy 条件化;trunk 走 finalize_trunk_push → B3 |
src/ceres/pack/monorepo.rs finalize_receive_pack / finalize_trunk_push |
trunk advertise 过滤 is_cl;B0 删除拒绝;ADR-TP-18 对齐命令 |
refs_with_head_hash;trunk_nff_align_message / trunk_align_finalize_err |
| e2e:N=1 三轮 FF、N>1 squash+sideband、token requester | tests/integration_git_cli.rs integration_git_cli_trunk_* |
Acceptance criteria:
- Agent 常态路径 e2e:clone
/project/foo→ 单 commit 推送 →ls-remote的main@/project/foo精确等于客户端 commit hash;作者/时间/message/签名逐字不变;git fetch && git reset --hard origin/main为 no-op;连续三轮全部 fast-forward 无一次被拒((new)) - 攒批路径:三 commit 一次推送 →
main@/project/foo为 squash(tree 等于客户端 tip、parent 等于推送前 tip);sideband 返回合成 commit id;不做对齐即再推 → non-fast-forward 拒绝且拒绝信息直接给出对齐命令(ADR-TP-18)((new)) - trunk 形态连续推送后新增
refs/cl/*行为零;存量 CL ref 不被 advertise((new)) - 陈旧基线与互嵌回归:
/a物化后向/a推送且/a/b陈旧物化行存在 → 树哈希断言拒绝陈旧基线;push_policy=review下所有既有 CL 测试用例行为不变(硬约束 8)(回归) - 20 个互不嵌套路径的并发 trunk 推送全部成功,根 roll-up parent 链顺序 =
push_queue.id序、根树含全部改动;正向 I2a——有树变更的推送后main@P、受影响祖先与/各恰好前进一个 commit((new)) - TP-17 的 e2e 在显式
push_auth配置(none或播种 token,由 TP-19/20 先行交付)下运行——push_policy=trunk+ 缺省push_auth被 4.1 校验 ⑤ 拒绝((new)) -
push_queue.requester按模式记录:token 模式记录 token 名(认证身份);none模式记录 NULL(无身份)——构造 author 与 token 不一致的推送行为不受影响(认证与 provenance 分离)(TP-19 AC 4 的端到端断言在本卡 e2e 落地)((new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --test integration_git_cli -- --test-threads=1 trunk((new):常态/攒批/对齐 e2e)— 3 passed -
scripts/git_protocol_smoke.sh本地等价(ER-04 Git 协议表面七步骨架;push 用例需 token 播种,401 不得判为协议回归)— trunk IT clone/push/ls-remote;既有 auth IT 覆盖 401 不作协议回归 -
source .env.test && cargo test -p mega2 --lib 'ceres::pack::monorepo::tests'((new):finalize 条件化/advertise 过滤)— 23 passed - D 组:
src/ceres/pack/**、src/ceres/protocol/**命中git-protocol-smoke.yml概率高,开工时现场判定 — N/A:无git-protocol-smoke.yml
Dependencies: TP-15(push_policy 与 push_auth 配置)、TP-16(provenance)、TP-19/TP-20(认证载体就绪)、TP-19/TP-20(认证载体就绪,trunk e2e 前置)
Deliverables: N/A(代码卡)
Implementation write set: src/ceres/pack/、src/ceres/protocol/
Release write set: Inherited
Files likely touched: src/ceres/pack/monorepo.rs、src/ceres/protocol/smart.rs、src/ceres/protocol/mod.rs
Docs and compatibility impact: 按 GC-05;ADR-TP-18 对齐约定与「N 分流推送语义」写入 docs/monorepo.md(TP-21);docs/refactoring/protocol.md 同步 receive-pack 条件化
Rollback mode: revert(代码层回滚;push_policy 切回 review 属部署切换——trunk→review 不重建 roll-up 之前的 CL 历史,trunk-push.md 约束 3)
Migration and rollback: N/A
Security and privacy: 继承 GC-07、GC-11;sideband 提示不得泄漏 token
Performance budget: trunk 推送 = B3 成本(TP-12);CL ref 广告过滤省去 CL 面广告
Estimated scope: M(3 个行为落点、8 个生产文件)
Version increment: minor(新增用户可见部署形态 push_policy=trunk)
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=trunk 推送落地接线(finalize_receive_pack 条件化、B3 push 分支转正、advertise CL 过滤、B0 删除策略、ADR-TP-18 告知); recovery=revert:push_policy 切回 review; complete=yes; self-contained=yes; AC=8/8; VER=6/8; landing=3; prod-files=8; scope=M; deps=TP-15,TP-16,TP-19,TP-20; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付阶段 4.3:trunk 形态下关闭 CL 创建(update_or_create_cl)、code_edit 的 CL 变更写路由(/create-entry 与 /edit/save,preview_router.rs:46-59;只读 preview 保留)、CheckerRegistry 全部 checker、merge queue/conversation、code review 线程重锚、CLA、commit_auths 绑定;保留对象存储/pack 收发(LFS 仅 review 形态——trunk 关闭 LFS 写路由:lfs_router.rs:205-213/235-250 经 UserStorage 认证,静态 token 不覆盖 LFS 批/锁授权;部署文档声明)、traverses_tree_and_update_filepath(C 段)、UN-16 写入侧钩子(仅拒绝删除 main + notify 钩子完整,不构成授权保护)、MC-03 链校验、ADR-MC-04 单分支准入、Git 客户端禁 tag。router 按 push_policy 条件挂载:trunk 形态不注册 CL/issue/reviewer router,OpenAPI 表面如实反映部署形态。
Out of scope: 推送落地路径(TP-17);认证(TP-19/20)。
Current evidence:
| 事实 | 证据 |
|---|---|
push_policy 条件挂载 /api/v1 与 LFS |
src/api/api_router.rs routers_for;src/server/http_server.rs protocol_surface / trunk_openapi_doc |
| code_edit / CL 写 fail-closed | reject_trunk_cl_write;find_or_create_cl_for_edit;CheckerRegistry::run_checks |
| B0 唯一公开分支 main | validate_incoming_push trunk ref_name != refs/heads/main |
| UN-16 拒绝删除 main(review) | apply_cl_mega_ref_for_push_command;tp18_review_still_refuses_delete_main |
Acceptance criteria:
- trunk 形态下
/create-entry、/edit/save不注册(或返回可诊断错误),连续操作后新增mega_cl行与refs/cl/*行为零;存量已合并/关闭的 CL 行与 CL ref 行保留为档案且被 advertise 过滤(trunk-push.md 4.2:archive 行为与 TP-17 一致)((new)) - trunk 形态下 CL / issue / reviewer 端点不在 OpenAPI 中登记(运行时
/api/openapi.json证据)—trunk_openapi_doc()/api::router::tests::trunk_openapi_omits_* - trunk 形态下推送
refs/heads/dev→ B0 拒绝(唯一公开分支 main);review 形态行为不变((new)) - trunk 形态下 code_edit 只读 preview 路由保留且正常(
(new)) - trunk 形态下 LFS 写路由关闭/不可达(部署文档声明 LFS 仅 review 形态)(
(new))— 路由不挂载 +enforce_lfs_access404;部署文案 TP-21 -
push_policy=review下所有既有 CL 测试用例行为不变(硬约束 8)(回归) - UN-16 保留语义:trunk 形态拒绝删除 main;
cedar.enforcement=off时快照不构建不被消费(部署文档声明,TP-21) - 三项通用门禁全绿 — fmt / clippy
-D warnings/api::router::+ 定向 CL 回归;cargo test --all仍受 compose git-cli 防火墙限制(同 TP-17)
Verification:
-
source .env.test && cargo test -p mega2 --lib 'api::router::'((new):条件挂载)— 53 passed - 手工证据:
push_policy=trunk启动后GET /api/openapi.json无 CL/issue/reviewer 端点 —trunk_openapi_doc()与app()同一routers_for(Trunk)装配(无 LFS merge) - D 组:
src/api/**、src/ceres/code_edit/**命中判定按开工时 workflowpaths:— N/A:.github/workflows/为空
Dependencies: TP-15(push_policy 配置)、TP-17(落地已转正)
Deliverables: N/A(代码卡)
Implementation write set: src/api/router/、src/ceres/code_edit/、src/ceres/(checker 注册)
Release write set: Inherited
Files likely touched: src/api/router/preview_router.rs、src/api/router/cl_router.rs、src/api/router/issue_router.rs、src/api/router/reviewer_router.rs、src/ceres/code_edit/on_edit.rs、src/server/http_server.rs(router 装配)
Docs and compatibility impact: 按 GC-05;OpenAPI 表面变化需运行时取证;部署文档声明 trunk 形态无授权保护(TP-21)
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 硬约束 6:trunk + cedar enforce 互斥由 TP-15 启动校验兜底;本卡不新增授权路径。授权边界声明:trunk 形态无 review/Cedar 授权,但 TP-19 的 token 组件边界前缀授权仍然生效——「无授权保护」指无评审门控与 Cedar 判定,非无任何访问控制
Performance budget: N/A(路由装配为启动期一次性)
Estimated scope: M(3 个行为落点、7 个生产文件)
Version increment: minor
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=trunk 形态的既有 CL 面关闭与 router 条件挂载(CL/code_edit 变更面、OpenAPI 表面、UN-16 保留语义); recovery=revert:push_policy 切回 review; complete=yes; self-contained=yes; AC=8/8; VER=4/8; landing=3; prod-files=7; scope=M; deps=TP-15,TP-17; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付4.2a 前移的认证核心(随阶段 4 交付)(事实校准 17 的第 2/3 项;push_auth/push_tokens 的配置模型与解析在 TP-15,本卡消费之):[[git.push_tokens]] 凭据经 SecretRef/文件挂载注入,不内联明文;git HTTP 认证挂点替换——push_auth="token" 时 git_http_auth 改走静态 token 常量时间查找(命中后 set_authenticated_user(token.name));认证身份与 provenance 分离——requester 取 token 名,commit author/committer 是可伪造的自声明元数据、不参与任何认证判定;check_push_permission 的组件边界前缀授权先于且独立于 Cedar enforcement 执行(/project/foo 不授权 /project/foobar);git_info_refs 与 git_receive_pack 两处认证前置(http.rs:60-65/354-365)在 token 模式保留 token 校验、在 none 模式做模式感知旁路。
Out of scope: OAuth 条件化启动与协议 router 集(TP-20);SSH 边界(TP-20)。
Current evidence:
| 事实 | 证据 |
|---|---|
push_auth=token 走常量时间 lookup_push_token;命中后 set_authenticated_user(token.name) |
src/contract/git_protocol/http.rs git_http_auth |
组件边界前缀授权先于 cedar-off 早退;none 旁路两处 receive-pack 前置 |
apply_push_auth_gate / receive_pack_requires_http_auth;git_info_refs / git_receive_pack |
401 + WWW-Authenticate;/project/foo 不授权 /project/foobar |
integration_git_cli_push_auth_token_rejects_without_token_and_out_of_path |
Acceptance criteria:
- 无 token 的推送被拒,返回带
WWW-Authenticate的 401(限push_auth="token"模式)((new)) - token 的
paths之外的路径推送被拒;组件边界负例:授权/project/foo时对/project/foobar的推送被拒((new)) -
push_auth="none"必须显式配置,缺省(无push_auth配置)= 现有 OAuth/UserStorage 链,行为不变((new)) - 认证身份解析为 token 名且 commit author 不参与任何判定(构造 author 与 token 不一致的请求,行为不受影响;限
push_auth=token模式,none模式的requester=NULL);push_queue.requester的端到端断言在 TP-17 的 trunk e2e 验收((new)) - token 比对为常量时间;凭据经 SecretRef/文件挂载注入,配置文件中无明文 token(
(new)) - 路径匹配按规范化后的组件边界(
被推路径 == 授权路径或被推路径以授权路径 + '/'开头)((new)) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'contract::git_protocol::tests'((new):token 查找/授权/边界)— 16 passed -
source .env.test && cargo test -p mega2 --test integration_git_cli -- --test-threads=1 push_auth((new):401/路径授权 e2e)— 1 passed -
cargo run -p mega2 -- --config config/config.toml config validate(push_auth 配置校验;含坏配置非零退出与 secret 不泄漏断言)—config valid;空push_tokens非零且不泄漏 secret - D 组:
src/contract/git_protocol/**、src/config/**命中判定按开工时 workflowpaths:— N/A:本 checkout.github/workflows/为空
Dependencies: TP-15(push_auth/push_tokens 配置面);被 TP-17/TP-20 依赖(TP-17 的 e2e 以本卡的认证载体为前置,实施顺序 TP-19 → TP-20 → TP-17);归属 Phase 4(4.2a 前移,见修订 2)
Deliverables: N/A(代码卡)
Implementation write set: src/contract/git_protocol/(src/config/ 的配置面归 TP-15,本卡只消费)
Release write set: Inherited
Files likely touched: src/contract/git_protocol/http.rs、src/contract/git_protocol/mod.rs
Docs and compatibility impact: 按 GC-05;docs/refactoring/config.md SecretRef 机制引用;部署文档声明 token 模式边界(TP-21)
Rollback mode: revert(缺省 = 现有认证链,回滚即恢复)
Migration and rollback: N/A
Security and privacy: 显式展开:token 常量时间比对、组件边界授权、requester=token 名(与 provenance 分离)、明文 token 禁止、401 带 WWW-Authenticate
Performance budget: token 查找 O(tokens);比对常量时间;路径匹配 O(path 深度)
Estimated scope: M(3 个行为落点、8 个生产文件)
Version increment: minor(新增认证模式配置)
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=静态 token 推送认证(常量时间查找、git HTTP 认证替换、组件边界前缀授权、认证与 provenance 分离; push_auth 配置面在 TP-15); recovery=revert:缺省走既有 OAuth 链; complete=yes; self-contained=yes; AC=7/8; VER=5/8; landing=3; prod-files=8; scope=M; deps=TP-15; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付4.2a 前移的部署形态(随阶段 4 交付)(事实校准 17 的第 1/4/5 项):HTTP 启动两道 OAuth 门槛条件化——require_oauth_for_http_service(http_server.rs:424-425)与 app() 内取用(:627-650,含无条件构造的 WebsiteSessionStore)在 push_auth 配置存在时改为条件化,storage-only 采用协议专用 router 集(git 协议路由 + 只读 API 子集,不注册 OAuth 依赖的 Web API 路由),会话存储补匿名/no-op 变体(生产枚举仅 Website,api/oauth/api_store.rs:4-14;测试构建另有 Fixed/Counting test double);push_auth="none" 在 git_info_refs/git_receive_pack 两端点做模式感知旁路(显式配置为前提);SSH 边界——storage-only 形态下 SSH 不暴露 receive-pack(配置显式禁用 + 部署文档声明),静态 token 模型不提供 SSH 凭据体系。
Out of scope: token 认证本体(TP-19)。
Current evidence:
| 事实 | 证据 |
|---|---|
push_auth 存在时跳过 OAuth 门槛;app() 用 BrowserSessionStore::Anonymous + storage_only_routers() |
src/server/http_server.rs start_http / app |
SSH receive-pack 在 storage-only 拒绝;缺 ssh_receive_pack=false 则 validate/start 失败 |
GitConfig::ssh_receive_pack_enabled;ssh.rs ReceivePack;validate.rs / ssh_server.rs |
Acceptance criteria:
-
push_auth配置存在且无 OAuth 配置时 HTTP 服务可启动((new)) - storage-only 形态不注册 OAuth 依赖的 Web API 路由(
/auth/*、website 会话路由等);/api/openapi.json证据((new)) -
push_auth="none"时git_info_refs/git_receive_pack两处旁路生效(显式配置);缺省不生效((new)) -
push_auth="none"的启动日志显式警告不提供任何推送者身份((new)) -
push_auth="none"模式下push_queue.requester = NULL(无身份,不做任何认证声明;端点旁路由 TP-19 交付,本卡消费)((new)) - token/no-OAuth 形态下
git_object_cache正常初始化、Git 协议路由(clone/fetch/push)可用;queue_control播种存在(trunk-push.md 阶段 5 验收条目)((new)) - storage-only 形态下 SSH 不暴露 receive-pack;显式配置缺失时启动失败(
(new)) - 既有 OAuth 形态(无
push_auth配置)行为不变(回归) - 三项通用门禁全绿
Verification:
-
source .env.test && cargo test -p mega2 --lib 'server::http_server::tests'((new):启动条件化)— 23 passed(含 OAuth skip、OpenAPI 只读子集、push_auth=nonewarn) - 手工证据:无 OAuth +
push_auth=token配置启动成功,/api/openapi.json只含协议 + 只读 API 子集 —storage_only_openapi_is_readonly_protocol_subset(/status在、/auth/create-entry//cl//user不在) -
source .env.test && cargo test -p mega2 --lib 'contract::git_protocol::tests'((new):none 旁路)— 17 passed(含ssh_receive_pack_enabled) - D 组:
src/server/**、src/api/**命中判定按开工时 workflowpaths:— N/A:本 checkout.github/workflows/为空
Dependencies: TP-15(push_auth 配置面)、TP-19(token 认证);归属 Phase 4(4.2a 前移,见修订 2);先于 TP-17 交付(trunk e2e 的认证载体)
Deliverables: N/A(代码卡)
Implementation write set: src/server/、src/api/、src/contract/git_protocol/(src/config/ 归 TP-15,本卡只消费其产物)
Release write set: Inherited
Files likely touched: src/server/http_server.rs、src/api/oauth/api_store.rs、src/contract/git_protocol/ssh.rs、src/contract/git_protocol/http.rs、src/config/validate.rs、src/config/model.rs
Docs and compatibility impact: 按 GC-05;部署文档声明「storage-only 安全性依赖部署边界(内网/token/SSH 关闭),无引擎内授权保护」(TP-21)
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 显式展开:无 OAuth 时不得存在「无凭据要求」的推送通道(SSH 关闭 + none 模式显式 + 启动警告);push_auth=none 仅限受控内网/回环/Unix socket 前置
Performance budget: N/A(启动期装配)
Estimated scope: M(3 个行为落点、7 个生产文件)
Version increment: minor
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=storage-only 部署形态(OAuth 条件化启动、协议 router 集、push_auth=none 旁路、SSH receive-pack 关闭); recovery=revert:缺省走既有 OAuth 形态; complete=yes; self-contained=yes; AC=8/8; VER=4/8; landing=3; prod-files=7; scope=M; deps=TP-19; writeset=no-overlap; release=independent; split-from=N/A; exception=N/A
Task type: docs
Lifecycle / Acceptance: done / complete
Description: 交付 trunk-push.md 的「反向声明」:docs/monorepo.md 一次性同步按 N 分流的推送语义(N=1 原样落地 / N>1 squash)与 ADR-TP-18 客户端对齐约定、不变式 I1–I6(含 I2a)、墓碑续接语义、文件路径索引最终一致性;新增/更新部署文档(trunk 形态声明、storage-only 安全边界与 push_auth=none 前提、形态切换约束 review→trunk 需无 open CL、SSH 不暴露 receive-pack);同步 docs/plan/README.md 计划索引、docs/refactoring/integration.md 测试矩阵、README.md 文档概览(如需);trunk-push.md 头部「反向声明」标记改为「已同步」。
Out of scope: 任何代码/配置改动(docs 卡 no-code 硬约束;一旦发现需改代码,按 ER-03 重分类)。
Current evidence:
| 事实 | 证据 |
|---|---|
| trunk-push.md 反向声明已同步 | docs/refactoring/trunk-push.md:9 |
| 产品规则 | docs/monorepo.md §1 trunk 例外、§6 墓碑、§8–11 |
| 部署 | docs/deploy-trunk.md |
| 计划索引 | docs/plan/README.md 文件列表 |
| 测试矩阵 | docs/refactoring/integration.md 四条 trunk/token e2e |
| 错误契约 | docs/errors.md plan-20260905 N/A |
| 双评审 | R28 Codex + Claude PASS |
Acceptance criteria:
-
docs/monorepo.md同步:N 分流推送语义、ADR-TP-18 对齐约定、I1–I6(含 I2a)、墓碑续接、索引最终一致,与 trunk-push.md 语义一致 - 部署文档新增:
push_policy=trunk使用说明、storage-only 安全边界(无评审门控与 Cedar 判定;token 组件边界授权仍生效——TP-19)、push_auth=none前提(受控内网 + 显式警告)、形态切换约束(含排空非终态行与RESET INDEX WATERMARK)、trunk 形态 LFS 不可用声明、阶段 5 多 token 运维延后(DEFER-TP-05)登记 - trunk-push.md 头部反向声明标记为「已同步」
-
docs/plan/README.md文件列表登记plan-20260905.md;docs/refactoring/integration.md测试矩阵登记新增 e2e 用例 - 同步 trunk-push 修订 66 使之过时的登记(共五处):
docs/refactoring/README.md①阶段 4-5 行补「认证已于 4.2a 随阶段 4 交付」②「ADR-TP-01 – ADR-TP-19(另含 15a,共 20 条)」改为「ADR-TP-01..20 含 15a(21 条)」③阶段 6 行「惰性后代推进」改为「物化 TTL + 墓碑回收」④阶段 5 行「无用户系统的推送认证」标注「基础认证已随 4.2a 进阶段 4」;docs/refactoring/general.md⑤阶段 1-3「独立可上线」改为「独立可验收;生产部署以阶段 2 为前置」;docs/plan/README.md引用的「文档概览 5a」实为docs/refactoring/README.md的 5a 节(非根README.md),表述更正 - 本计划内所有
docs/*.md引用均指向真实存在的文件(无悬空引用) -
docs/errors.md:本计划未新增用户可见错误变体则说明 N/A(若 TP-15/17/19 引入了新的MegaError变体,在此登记) -
libra status --short --branch无越界改动(本卡产物范围 = 列出的文档文件;VCS 为 Libra) - 本卡产物文件章节完整、内部链接与
file:line锚点可解析 - 三项通用门禁全绿(docs 卡走 B 组结构门 + 继承 C 覆盖)—
cargo +nightly fmt --all --check无 diff;cargo clippy --all-targets --all-features -- -D warnings0 warnings(crate 0.8.1)
Verification:
- 手工核对:
docs/monorepo.md与docs/refactoring/trunk-push.md反向声明条款逐一比对 - 链接检查:本卡新增的每个
docs/*.md引用ls或find确认真实存在 -
libra status --short --branch确认无越界改动(无src/、无Cargo.toml) - C/D 组:docs 卡 不 bump;工作区规则仍要求 commit+push(无 crate bump);
C/D coverage from = TP-20;D 组 N/A(.github/workflows/为空)
Dependencies: TP-13(索引最终一致声明)、TP-18(trunk 表面)、TP-20(storage-only 部署)
Deliverables: docs/monorepo.md、docs/plan/README.md、docs/refactoring/integration.md、docs/refactoring/trunk-push.md(头部标记)、部署文档(落点:docs/ 下新建或并入既有部署文档)、README.md(如需)
Implementation write set: docs/(monorepo.md、plan/README.md、refactoring/integration.md、refactoring/trunk-push.md、部署文档)
Release write set: N/A(no-release)
Files likely touched: docs/monorepo.md、docs/plan/README.md、docs/refactoring/integration.md、docs/refactoring/trunk-push.md、docs/(部署文档)
Docs and compatibility impact: 本卡即文档收口本身
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 部署文档必须显式声明「trunk 形态不因保留 UN-16 而具备任何授权保护」与 push_auth=none 的网络边界前提
Performance budget: N/A
Estimated scope: M(1 个行为落点、5 个产物文件)
Version increment: N/A(docs;产物随 TP-20 之后的收口提交进入仓库)
Release boundary: no-release
C/D coverage from: TP-20
Granularity: type=docs; axis=产品规则与部署文档收口(monorepo.md 反向声明、部署文档、测试矩阵与索引同步); recovery=revert:文档回滚即恢复; complete=yes; self-contained=yes; AC=10/12; VER=4/8; landing=1; prod-files=5; scope=M; deps=TP-13,TP-18,TP-20; writeset=no-overlap; release=no-release; split-from=N/A; exception=N/A
Task type: implementation
Lifecycle / Acceptance: done / complete
Description: 交付 trunk-push.md 1.2「例外——authz notify 的屏障与单调发布」三件套(cedar.enforcement != "off" 时生效;off/trunk 形态无屏障需求):①持久化 outbox——B3 在同一事务内写 notify outbox 行(version = push_queue.id),提交即登记待重建,崩溃后未发布的 outbox 行由补偿任务重放(以最新根重建,天然幂等);②单调 CAS 发布——快照发布带持久化 published_version,UPDATE ... SET published_version = $v WHERE published_version < $v,乱序完成者发布被拒(发布序 = push_queue.id 序);现状 notify.rs:27-92 / entitystore.rs:148-219 为内存 best-effort,需改造为持久化版本;③按实例读取屏障——SharedEntityStore 是进程本地内存快照(每 context 各自初始化),各 B3 实例的 UN-19 授权重查前比对 DB 权威版本与本进程快照版本,落后即本进程重建(从最新根)后再判定,重建期间 fail-closed 等待(带超时与告警)。队列外触发点(review 形态删除路径的 best-effort notify,monorepo.rs:903-907)不参与单调版本比较,改走 dirty 标记 + 补偿重建。
Out of scope: 文件路径索引(TP-13);Cedar 判定本体(contract.md);trunk 形态(无屏障需求)。
Current evidence:
| 事实 | 证据 |
|---|---|
| notify 为提交后异步重建、内存 best-effort | src/contract/policy/notify.rs:27-92、src/contract/policy/entitystore.rs:148-219 |
SharedEntityStore 进程本地、每 context 初始化 |
src/context/mod.rs:162-164 |
| 删除路径 best-effort notify 无版本 | src/ceres/pack/monorepo.rs:903-907 |
Acceptance criteria:
- outbox 行与 B3 业务写同事务提交;注入「outbox 提交后、notify 完成前
kill -9」→ 补偿任务重放并以最新根重建((new)) - 单调发布:两个并发 notify(旧 id 后完成)→ 旧快照发布被
published_versionCAS 拒绝,发布序 = id 序((new)) - 按实例读取屏障:实例 B 的本地快照落后于 DB 权威版本 → UN-19 重查前触发本进程重建,陈旧判定不可达;重建超时 fail-closed 告警(
(new)) - 队列外删除 notify 走 dirty 标记 + 补偿重建,无版本比较(
(new)) -
cedar.enforcement = off时三件套全部旁路(trunk 形态行为不变)((new)) - 迁移注册(outbox 表 /
published_version列),down空实现、forward-only((new)) - 三项通用门禁全绿 — 2026-09-09
cargo test --allEXIT:0
Verification:
-
source .env.test && cargo test -p mega2 --lib 'contract::policy::tests'((new):outbox/单调发布/屏障) -
source .env.test && cargo test -p mega2 --lib 'ceres::pack::monorepo::tests'((new):删除路径 dirty 标记) - D 组:N/A(
.github/workflows/为空)
Dependencies: TP-04(B3 事务挂点)、TP-07(merge 分支的 UN-19 重查路径)
Deliverables: N/A(代码卡)
Implementation write set: src/contract/policy/、src/jupiter/migration/、src/ceres/pack/(删除路径 dirty 标记)、src/ceres/api_service/(B3 事务内 outbox 写入的挂点,与 TP-07 的 merge 事务同点)
Release write set: Inherited
Files likely touched: src/contract/policy/notify.rs、src/contract/policy/entitystore.rs、src/jupiter/migration/m20260905_000400_add_authz_outbox.rs、src/jupiter/migration/mod.rs、src/ceres/pack/monorepo.rs(删除路径 dirty 标记)
Docs and compatibility impact: 按 GC-05;enforce/off 语义与屏障行为在 docs/refactoring/contract.md 同步
Rollback mode: forward-only(outbox/版本列迁移不可逆;off 模式无行为依赖)
Migration and rollback: 新迁移 up 建 outbox 表与版本列;down 空实现;数据不变量 = published_version 单调不减
Security and privacy: 继承 GC-07、GC-11;屏障 fail-closed 是授权正确性前提(trunk-push.md 1.2)
Performance budget: outbox 写为 B3 内一次 INSERT;重建为全根遍历(与 notify 现状同量级),屏障等待有超时上界
Estimated scope: M(2 个行为落点、6 个生产文件)
Version increment: patch(review+enforce 形态的授权正确性修复;off 形态行为不变)
Release boundary: independent
C/D coverage from: self
Granularity: type=implementation; axis=authz 快照屏障三件套(outbox、单调 CAS 发布、按实例读取屏障、dirty 标记路径); recovery=forward-only:迁移不可逆; complete=yes; self-contained=yes; AC=7/8; VER=4/8; landing=2; prod-files=6; scope=M; deps=TP-04,TP-07; writeset=sequential-overlap(mono_api_service.rs 与 TP-07); release=independent; split-from=N/A; exception=N/A
Task type: audit
Lifecycle / Acceptance: done / complete
Description: 交付 trunk-push.md 阶段 1.1 的写入者审计:穷举根树与 refs/heads/main 行的全部写入者(硬约束 2 三类 + 范围外 CL/tag 行),逐一定位调用点并核对 acquire_monorepo_initialization_lock 等 bootstrap 证据;审计结论回写 trunk-push.md 的事实校准节(新增/修订事实条目),并把「队列串行 / ADR-TP-20 覆盖 / bootstrap 接流前专属锁」三分法与硬约束 2 清单对齐;发现清单外的生产写入者 → 升级修订 trunk-push.md 硬约束 2 与本计划(不得静默吞掉)。产出一个可机器核对的清单文件(写入者 → 分类 → 证据锚点)。
Out of scope: 任何代码/配置改动(audit 卡 no-code;发现需改代码按 ER-03 重分类)。
Current evidence:
| 事实 | 证据 |
|---|---|
| 已知写入者与三分法 | trunk-push.md 硬约束 2、事实校准 15 |
| bootstrap 专属锁 | src/jupiter/service/mono_service.rs:103-125(acquire_monorepo_initialization_lock) |
| 范围外 CL/tag 行写入者 | code_edit/on_edit.rs:47、mono_api_service.rs:1927-1978 |
Acceptance criteria:
- 审计清单文件存在且覆盖硬约束 2 的三类 + 范围外两类(CL/tag 行),每个条目带
file:line证据((new))—docs/refactoring/trunk-push-writers-audit.md -
rg交叉核对:save_refs/update_ref/mega_head_hash_with_txn/batch_update_*的全部调用点被清单覆盖或登记为测试 fixture((new)) - 审计结论回写
trunk-push.md事实校准节(diff 可见);如发现清单外生产写入者,硬约束 2 与本计划同步修订((new)) - bootstrap 三证据:接流顺序、专属锁调用点、不入队理由(
(new)) - 本卡产物文件章节完整、
file:line锚点可解析、无越界改动((new)) - 三项通用门禁全绿(audit 卡走 B 组结构门)
Verification:
-
rg -n "save_refs|update_ref|mega_head_hash_with_txn|batch_update" src/ --stats与清单逐条比对 - 手工核对:
docs/refactoring/trunk-push.md事实校准节 diff 含审计结论 - C/D 组:docs/audit 卡不 bump、不推送;
C/D coverage from = self(audit 卡);D 组 N/A(.github/workflows/为空)
Dependencies: 无代码依赖(审计对象是现状源码与 trunk-push.md 文本);先于 TP-01/TP-04/TP-07/TP-08 开工(TP-23 -> TP-01 等边见实施顺序)
Deliverables: 审计清单文件(docs/refactoring/ 下新增或并入 trunk-push.md 事实校准节)、docs/refactoring/trunk-push.md(事实校准回写)
Implementation write set: docs/refactoring/
Release write set: N/A(no-release)
Files likely touched: docs/refactoring/trunk-push.md、docs/refactoring/(清单文件)
Docs and compatibility impact: 本卡即文档回写本身
Rollback mode: revert
Migration and rollback: N/A
Security and privacy: 审计清单不得包含 token 等凭据
Performance budget: N/A
Estimated scope: M(1 个行为落点、2 个产物文件)
Version increment: N/A(docs/audit)
Release boundary: no-release
C/D coverage from: self
Granularity: type=audit; axis=写入者审计与事实校准回写(穷举 + 三类分法 + 范围外登记); recovery=revert:文档回滚即恢复; complete=yes; self-contained=yes; AC=6/6; VER=2/3; landing=1; prod-files=2; scope=M; deps=none; writeset=no-overlap; release=no-release; split-from=N/A; exception=N/A
| 类别 | 必须覆盖 | Target / command |
|---|---|---|
| 单元 | 队列状态机(B0–B4、1.11)、存储原语、escape_like、树项插入、provenance 构造 | source .env.test && cargo test -p mega2 --lib 'jupiter::service::push_queue_service::tests' / 'jupiter::storage::mono_storage::tests' / 'ceres::api_service::mono_api_service::tests' |
| 集成(DB) | push_queue/queue_control/墓碑/blob_paths 迁移、B3 单事务、CAS 断言、树哈希修复、对账巡检 | source .env.test && cargo test -p mega2 --lib '<各卡 tests>'(test_db_connection + apply_migrations) |
| 集成(进程) | trunk 常态/攒批 e2e、后代断裂回归、push_auth 401、attach 排队 | source .env.test && cargo test -p mega2 --test integration_git_cli -- --test-threads=1 <filter> |
| CLI | config validate(push_policy/max_push_commits/push_auth 校验、双开拒绝启动) |
cargo run -p mega2 -- --config config/config.toml config validate |
| HTTP API | 队列控制端点、CL/issue/reviewer 条件挂载、OpenAPI 表面 | source .env.test && cargo test -p mega2 --lib 'api::' + 运行时 /api/openapi.json |
| 迁移 | 7 项迁移产物 up(down 空实现)、重复播种幂等 | source .env.test && cargo test -p mega2 --lib '<migration 相关 tests>' |
| 配置 | push_policy/push_auth/SecretRef 校验、坏配置非零退出、secret 不泄漏 | cargo run -p mega2 -- ... config validate |
| Git 协议 | clone/fetch/push/shallow/protocol v2;trunk 直推;advertise 5xx | scripts/git_protocol_smoke.sh 本地等价(ER-04 七步骨架) |
| 安全 | token 组件边界授权、push_auth=none 显式、SSH 关闭、401 带 WWW-Authenticate、trunk 下 LFS 不可用 |
source .env.test && cargo test -p mega2 --lib 'contract::git_protocol::tests' |
| 性能 | 队列深度/等待时长、B3 轮次时长、message 体积上界、索引批次 | 手工 + 指标(TP-06) |
| live/gated | 测试栈依赖(Postgres/Redis/Mailpit/RustFS) | docker compose -f docker-compose.test.yml up -d --wait |
| 任务 | 来源/证据 | mega2 落点 | 文档/兼容动作 | 指定测试 |
|---|---|---|---|---|
| TP-01 | trunk-push.md 1.4 | src/callisto/、src/jupiter/migration/ |
— | --lib 'push_queue::tests' / 'queue_control::tests' |
| TP-02 | trunk-push.md 1.10(1/2/4/6) | src/jupiter/storage/、src/ceres/api_service/ |
— | --lib 'mono_storage::tests' / 'tree_ops::tests' |
| TP-03 | trunk-push.md 1.3/1.5/1.11 | src/jupiter/storage/、src/jupiter/service/ |
trunk-push.md 1.5/1.11 回写 | --lib 'push_queue_service::tests' |
| TP-04 | trunk-push.md 1.5(B3/B4) | src/jupiter/service/、src/ceres/api_service/ |
— | --lib 'push_queue_service::tests' |
| TP-05 | trunk-push.md 1.6 | src/jupiter/service/ |
trunk-push.md 1.6 回写 | --lib 'push_queue_reaper::tests' |
| TP-06 | trunk-push.md 1.7 | src/api/router/ |
OpenAPI 证据 | --lib 'api::router::push_queue_router::tests' |
| TP-07 | trunk-push.md 1.8/1.9 / 1.10 交付物 5/7(GAP-12) | src/ceres/api_service/、src/jupiter/、src/config/ |
异步转同步声明 | --lib 'mono_api_service::tests' |
| TP-08 | trunk-push.md 1.9 / 1.10 交付物 3(GAP-17) | src/ceres/pack/ |
— | --lib 'import_repo::tests' |
| TP-09 | trunk-push.md 1.10(8)/2.5 | src/callisto/、src/jupiter/migration/、src/ceres/ |
monorepo.md 墓碑语义(TP-21) | --lib 'mono_storage::tests' |
| TP-10 | trunk-push.md ADR-TP-20 第 1 项 | src/ceres/pack/、src/ceres/protocol/、src/common/errors/ |
protocol.md 同步 | --lib 'monorepo::tests' + smoke 本地等价 |
| TP-11 | trunk-push.md ADR-TP-20 第 2/3 项 | src/ceres/api_service/、src/jupiter/service/ |
I3/I5 前提登记 | --lib 'mono_api_service::tests' |
| TP-12 | trunk-push.md 写入模型 / B3 push 分支 / 1.10 交付物 10(GAP-14) | src/ceres/api_service/、src/jupiter/storage/ |
monorepo.md N 分流(TP-21) | --lib 'mono_api_service::tests' |
| TP-13 | trunk-push.md ADR-TP-11 | src/callisto/、src/jupiter/migration/、src/ceres/ |
monorepo.md 索引最终一致(TP-21) | --lib 'mono_storage::tests' |
| TP-14 | trunk-push.md 阶段 2 / ADR-TP-19 | src/jupiter/storage/、src/ceres/ |
monorepo.md 墓碑续接(TP-21) | --lib 'mono_storage::tests' + e2e descendant |
| TP-15 | trunk-push.md 4.1 / ADR-TP-17 | src/config/、src/ceres/merge_checker/、src/ceres/pack/ |
config.toml 注释 | config validate |
| TP-16 | trunk-push.md 阶段 3 / ADR-TP-12..15a | src/ceres/api_service/、src/ceres/pack/ |
monorepo.md provenance(TP-21) | --lib 'mono_api_service::tests' |
| TP-17 | trunk-push.md 4.2 / ADR-TP-18 | src/ceres/pack/、src/ceres/protocol/ |
protocol.md 同步、monorepo.md 对齐约定(TP-21) | e2e trunk + smoke 本地等价 |
| TP-18 | trunk-push.md 4.3 | src/api/router/、src/ceres/code_edit/、src/server/ |
OpenAPI 证据 | --lib 'api::router::' |
| TP-19 | trunk-push.md 4.2a(原阶段 5 2/3 项,前移) | src/contract/git_protocol/、src/config/ |
config.md 引用、部署文档(TP-21) | --lib 'contract::git_protocol::tests' |
| TP-20 | trunk-push.md 4.2a(原阶段 5 1/4/5 项,前移) | src/server/、src/api/、src/contract/git_protocol/ |
部署文档(TP-21) | --lib 'server::http_server::tests' |
| TP-21 | trunk-push.md 头部反向声明 + 事实校准节的写入者审计终版核对 | docs/ |
monorepo.md / 部署文档 / 索引 | 手工比对 + 链接检查 |
| TP-22 | trunk-push.md 1.2(authz 屏障三件套,GAP-15) | src/contract/policy/、src/jupiter/migration/、src/ceres/pack/ |
contract.md 同步 | --lib 'contract::policy::tests' |
| TP-23 | trunk-push.md 阶段 1.1(写入者审计,GAP-16) | docs/refactoring/ |
trunk-push.md 事实校准回写 | rg 交叉核对 + 手工比对 |
| 里程碑 | 完成条件 | 发布/证据 | 回滚或前滚 |
|---|---|---|---|
| M0 | 基线冻结:锚点刷新、TP-23 写入者审计 done(含 trunk-push.md 回写)、DEP-02 确认 |
TP-23 验收记录 + 计划修订历史 | N/A |
| M1 | 队列基座(未接写入者):TP-01..TP-04、TP-23 全部 done |
各卡独立 patch 发布 + 三门 | revert(未接写入者) |
| M2 | 写入者全接入与恢复面:TP-05..TP-13、TP-22 全部 done(阶段 1 完成,含 TP-06 存量端点映射;测试环境里程碑) |
各卡发布;阶段 1 验收清单全绿 | 单写者开关切回(TP-07) |
| M3 | 后代续接与归属:TP-14..16 全部 done(阶段 2/3 完成;生产上线门——I1 自此成立) |
各卡发布;断裂回归 + provenance 全绿 | revert |
| M4 | trunk 形态与认证:TP-17/18/19/20 全部 done(阶段 4 完成,含 4.2a) |
minor 发布;Agent e2e + token 认证全绿 | 代码 revert;push_policy 切回 review 属部署切换(不重建历史) |
| M5 | 收口:TP-21 done(trunk-push.md 阶段 5 的多 token 运维延后为 DEFER-TP-05) |
docs/monorepo.md 已同步 |
文档 revert |
| 故障点 | 可接受残留 | 恢复动作 | 禁止结果 |
|---|---|---|---|
| B3 执行中崩溃 | 队列行 Running(B2.5 已提交)、无部分数据 |
reaper 持锁立即标 Failed;调用方按 1.11 重试 |
部分提交 / 静默成功 / 残留 Running 阻塞队首 |
| B2 等待中崩溃 | 队列行 Queued、心跳停止 |
heartbeat reaper 标 Cancelled |
孤儿队首永久死锁 |
| CAS 失败(绕过写入者) | hard_stopped 置位、行 Failed(QueueBypassDetected) |
人工封堵绕过路径后 clear-hard-stop |
继续在他人变动的根上叠加写入 |
| reaper 与慢轮次竞态 | 锁被持有、跳过 Running 行 |
stuck_timeout 告警;watchdog/runbook 终止停滞会话 |
误杀活轮次 / 终态被覆盖 |
| 物化与 B3 竞态 | 物化放弃插入、不落陈旧行 | 有界重试;下次 advertise 基于新根重新物化 | 空 refs/capabilities-only 伪装空仓库 |
| 树哈希断言检出陈旧行 | 陈旧行转墓碑、ref 删除 | 墓碑续接重新物化,I1 保持 | 拒绝死局(行永久占据路径) |
| merge 冲突 | 旧行 Cancelled(Conflict) + 继任行(队尾) |
调用方/重试收养继任行并跟随 | 继任行无人执行(后台 processor 已退役) |
| 索引任务落后(C 段) | 路径查询短暂读旧值 | 行级水位 CAS + 删除感知 reconciliation + 补偿任务 | 旧序号覆盖新结果 / 删除复活 |
| 风险 | 影响 | 缓解 | 任务 |
|---|---|---|---|
| 写入者审计遗漏 | 高:序列化缺口,根树与路径 ref 视图不一致且无显式报错 | CAS tripwire fail-closed + 故意绕过队列的负向测试 + 对账巡检 | TP-04/11 |
| 全局队列成为吞吐瓶颈 | 中:推送延迟随并发上升 | 临界区只保留树脊读取/内存拼树/一次写事务;A 段与 C 段在临界区外;group commit 作扩展路径(DEFER-TP-01) | TP-03/04/13 |
merge_queue 吸收语义漂移 |
中:UN-17/18/25 行为被改变 | 逐条对齐迁移作为评审门;review 形态测试期望值不动 | TP-07 |
| 墓碑续接串联无关历史 | 低:git log 出现无关前史 |
部署文档显式声明;墓碑清理运维入口 | TP-14/21 |
| 索引最终一致导致查询落后 | 低:Web/挂载消费方短暂读到旧值 | 行级水位 + 删除感知 reconciliation + 补偿任务 + 文档声明 | TP-13 |
| 物化竞态静默覆盖祖先改动 | 高:ADR-TP-19 失效链 | 插入校验 + 树哈希断言/修复 + 对账巡检 | TP-10/11 |
| D 组 workflow 本地不可预演 | 中:远端门判定依赖远端仓库 | 开工时现场读取 workflow paths:;命中则 remote-pending 跟踪 |
各卡 D 组 |
| 评审轮次多(23 卡) | 中:计划维护成本 | 编号不重排、修订历史逐行登记、粒度审计表机械核对 | 计划级 |
| 操作 | 单次成本 | 累积成本 | 预算/上限 | 验证 |
|---|---|---|---|---|
| B3 push/merge 轮次 | 树脊重算 O(depth) + 后代处理 O(已物化后代数) + 一次写事务 | 与并发推送数线性 | 轮次时长 P99 观测(stuck_timeout 标定依据) |
TP-06 指标 |
| 队列入队(B1) | 单语句 INSERT O(1) | 队列行数 = 推送次数 | max_depth 背压;行数留存(审计) |
TP-03 |
| squash message | O(N),N ≤ max_push_commits |
每次推送一份(不随物化层数放大) | 250 → ~25 KB(已接受代价) | TP-16 |
| 索引重建(C 段) | O(子树规模),临界区外 | 与子树变更量线性 | 批次上限可配 | TP-13 |
| reaper | O(Running + 孤儿 Queued + 待补意图) | 周期任务 | 秒级宽限 + stuck_timeout 告警 |
TP-05 |
| 物化插入 | 短锁事务(毫秒级) | 冷读路径每路径一次 | 重试 K=2 有界 | TP-10 |
| 对账/巡检 | 全量比对 O(已物化行数),分批持锁 | 周期任务 | 频率/告警阈值可配 | TP-11 |
-
docs/errors.md已同步,或说明 N/A:本计划未新增用户可见MegaError变体;StaleMonorepoRootRef计划前已存在;TP-15/17/19 拒绝文案走MegaError::Other(见docs/errors.mdplan-20260905 节)。 -
docs/refactoring/*.md相关文档已同步:protocol.md(TP-17)、config.md(TP-15/19)、integration.md(TP-21)、trunk-push.md(反向声明已同步)。 -
config/config.toml示例配置与注释已同步:push_policy/max_push_commits(TP-15)、push_auth/push_tokens(TP-19/20)。 - 运行时 OpenAPI 证据:TP-18
trunk_openapi_doc()/api::router::tests::trunk_openapi_omits_*;TP-06/20 卡内取证。 -
README.md已指向docs/monorepo.md与docs/deploy-trunk.md(TP-21);AGENTS.md工程约束未漂移。 -
src/callisto/、src/jupiter/storage/与src/jupiter/migration/(含migrations()注册列表)已同步:TP-01/07/09/13/14/22。 - 新引入的
docs/*.md引用全部指向真实存在的文件(TP-21 核对)。 -
plan-long.md日期计划索引或 PT/SB 状态已同步,或说明 N/A:本计划与 plan-long 无交集。
Result 只允许 PASS 或 FAIL。FAIL 必须列出 P0/P1 条目并在下一轮复审关闭。
| Round | Scope | Result | P0/P1 | P2 处置 | Evidence |
|---|---|---|---|---|---|
| R1 | 计划成稿自审(21 卡粒度审计、DAG、缺口径、ADR 映射、风险/里程碑) | PASS(自审口径,待外部评审) | 无 | 无 | 任务卡粒度审计表 + 实施顺序 DAG |
| R2 | Codex 对计划修订 2 的评审(8 条 BLOCKING:TP-22 缺失、交付物 10 归属、迁移清单、TP-15/19 配置归属、端点映射、阶段 4 验收缺口、TP-16 缺项、粒度超限) | FAIL→修复(修订历史 ②–⑮ + TP-22 + GAP-11..15) | 全部关闭 | 无 | 本文件修订历史 + 各卡 AC |
| R3 | Claude 对计划修订 2 的评审(5 条 BLOCKING:认证配置归属与 Phase 4 时序、authz 屏障缺卡、交付物 10 缺卡、迁移清单与 rollback 分类、存量端点映射缺卡;+ DAG/M1/TP-15 deps/轮次元数据/粒度计数 5 条 MINOR) | FAIL→修复(与 R2 合并落实) | 全部关闭 | 粒度计数机械重排 | 修订历史 ②–⑮ + GAP-11..15 + 粒度审计表 |
| R4 | Codex 终审(修订 2 后第 16–26 轮迭代) | PASS | 无 | 3 MINOR(粒度表 deps 省略、重复 deps、TP-20 配置归属) | plan-codex-r26.txt |
| R5 | Claude 终审(全量 walk:14 映射 + 完整性 + 18 锚点 + DAG 拓扑 + 迁移 + 里程碑) | PASS | 无 | 6 MINOR + 2 SUGGESTION(粒度审计表机械重排;实施顺序边补齐;DEFER-TP-01 入参预留需 TP-04 AC;GAP-07 编号;requester 措辞) | plan-claude-final2.txt |
| R6 | TP-07 实现双评审(Codex + Claude) | PASS | 无(FAIL 轮已关闭:UN-17、admin cache、add 入口预检、全量 revision CAS、ClaimLost 弃权、B4 跟随、intervening、parent 链、prepare_for_queue_writer、processor 停环、get_and_update_cl CAS) | TP-06 存量端点映射不在本卡 | 本会话 Codex/Claude 终轮 VERDICT: PASS |
| R7 | TP-22 实现双评审(Codex + Claude) | PASS | 无(FAIL 轮已关闭:屏障 timeout 包住重建 I/O、CAS-then-swap 本地单调、unversioned swap 与 dirty 刷新竞态、catch-up 先读水位再读根、水位已齐时 dirty 走 swap_if_watermark_eq) |
P2:删除路径 wiring 另有 delete_path_dirty_outbox_skips_published_version;outbox 逐行重建与缺 ACL 忙等不阻塞正确性 |
本会话 Codex R8 / Claude 终轮 VERDICT: PASS |
| R8 | TP-09 实现双评审(Codex + Claude) | PASS | 无 | P2:物化 mega_head_hash_with_txn 与 delete_tombstone 两提交(TP-10 合并);list_tombstones_under_prefix 尚无生产调用方(TP-14) |
本会话 Codex / Claude 终轮 VERDICT: PASS |
| R9 | TP-05 实现双评审(Codex + Claude) | PASS | 无(FAIL 轮已关闭:AppContext::new 周期 spawn、complete_conflict_requeue_in_txn 的 superseded_by IS NULL 幂等守卫、I3 计数覆盖全路径、attach-with-main@P 覆盖、push 缺行 non-ZERO warn) |
P2:reaper_i3_tombstone_repair 仅测试调用;心跳冻结与 non-ZERO warn 靠代码审查 |
本会话 Codex / Claude 终轮 VERDICT: PASS |
| R10 | TP-06 实现双评审(Codex + Claude) | PASS | 无(FAIL 轮已关闭:attach/merge CAS-miss 计入 cas_assert_failures;merge_writer=queue 的 list/stats 仅 Merge kind) |
P2:in_queue 语义与 legacy 略有分歧;display_position 计入 Failed 行;failure_rate 不含 Cancelled |
本会话 Codex / Claude 终轮 VERDICT: PASS |
| R11 | TP-10 实现双评审(Codex + Claude) | PASS | 无 | P2:advertise 上非 MaterializeAborted 的 MegaError 仍映射 400;get_all_refs_in_txn 无调用方;NOT EXISTS 命中仍可能留下孤儿 commit / 删墓碑 |
本会话 Codex / Claude 终轮 VERDICT: PASS |
| R12 | TP-11 实现双评审(Codex + Claude) | PASS | 无(FAIL 轮已关闭:legacy 写者下无条件巡检 spawn;queue 入口 from_hash 抢先于树哈希断言;I3 日志泄漏 path) |
P2:reaper_i3_tombstone_repair 无生产调用且无 kind// 守卫;启动对账抢锁失败静默;trunk+legacy 交叉仍 spawn 巡检(TP-15) |
本会话 Codex / Claude 终轮 VERDICT: PASS |
| R13 | TP-12 实现双评审(Codex + Claude) | PASS | 无 | P2:祖先 roll-up 中间行无直接断言;净零 tripwire 无 push 路径 bypass 注入;from_known_tip N=0 链会令 PushChain::validate 失败(TP-17 须条件化);squash message 占位(TP-16) |
本会话 Codex / Claude 终轮 VERDICT: PASS |
| R14 | TP-13 实现双评审(Codex + Claude) | FAIL→修复 | P1:AC5 多路径回归用了两个 blob id 而非同一 blob 两路径 | 已改 tp13_nested_watermark_and_multipath_delete 为同一 blob_id 出现在 /a/x.txt 与 /a/b/x.txt |
tp13-claude-r14.txt |
| R15 | TP-13 实现双评审(Codex + Claude) | PASS | 无 | P2:队列 reconciliation 无删除水位(ADR 已知限制);same_path_has_later_done 依赖已规范化 path;补偿间隔硬编码 60s(TP-15);latest_blob_display_path 无 ORDER BY |
本会话 Codex / Claude 终轮 VERDICT: PASS |
| R16 | TP-14 实现双评审(Codex + Claude) | FAIL→修复 | P1:legacy merge_cl_unchecked 的 apply_update_result 与 advance_descendant_refs 分两个提交窗口 |
已改为 merge_apply_and_advance_in_txn(apply + advance 同一 DatabaseTransaction;CL 状态仍在提交后) |
Codex R16 FAIL / Claude R16 PASS |
| R17 | TP-14 实现双评审(Codex + Claude) | PASS | 无 | P2:缺 mega_tree 行当删除;三层续接仅剪枝覆盖;e2e 走 merge 非协议 push;remove_none_cl_refs_in_txn LIKE 无 LikeExpr::escape |
本会话 Codex R17 / Claude R17 VERDICT: PASS |
| R18 | TP-15 实现双评审 | FAIL→修复 | P1:形态切换未与 B1 准入锁串行(count 与 last_policy 更新之间可插入非终态行) |
已改为 switch_last_policy_if_queue_empty 持 queue_control FOR UPDATE |
Codex R18 FAIL |
| R19 | TP-15 实现双评审 | FAIL→修复 | P1:${file:...} 在 [[git.push_tokens]] 数组表中不展开 |
traverse_config 递归 ValueKind::Array |
Claude R19 FAIL |
| R20 | TP-15 实现双评审 | FAIL→修复 | P1:AppContext::new 未调用 Config::validate,①④⑤ 只在 CLI config validate 生效 |
AppContext::new 先 config.validate() |
Codex R20 FAIL |
| R21 | TP-15 实现双评审(Codex + Claude) | PASS | 无 | P2:reset_blob_path_index_watermarks 无调用方(切换内联 SQL);standalone SSH 不跑 ②③⑥;config secret set 尚未登记 token 字段(TP-19) |
本会话 Codex R21 / Claude R21 VERDICT: PASS |
| R22 | TP-16 实现双评审 | FAIL→修复 | P1:祖先 roll-up 缺 provenance 时回退 from_tree_id;后代 Mono-Ref-Path 误用被推路径 |
fail-closed;layer_message(&row.path) |
|
| R23 | TP-16 实现双评审(Codex + Claude) | PASS | 无 | P2:N>1 且 payload.commits 空时 Count 可能不一致(from_chain 不可达);N=1 客户端 gpgsig 会进入 roll-up 正文 |
本会话 Codex R2 / Claude R2 VERDICT: PASS |
| R24 | TP-19 实现双评审(Codex + Claude) | PASS | 无 | P2:.. 段不折叠(fail-closed);none 读路径仍可能走 UserStorage;同密不同名 token 按配置序取先 |
本会话 Codex R1 / Claude R1 VERDICT: PASS |
| R25 | TP-20 实现双评审(Codex + Claude) | PASS | 无 | P2:storage-only 仍装 LFS URI rewrite(含 /info/lfs/ 的路径 404 而非 git catch-all);app() 文档仍列 /auth/*;OpenAPI 测试重建 nest 而非派生自 app() |
本会话 Codex R1 / Claude R1 VERDICT: PASS |
| R26 | TP-17 实现双评审(Codex + Claude) | PASS | 无 | P2:中间祖先 I2a 无直接断言;try_get requester 把反序列化失败也当 NULL;trunk validate_incoming_push 仍读 open CL;e2e 走 host git(compose host.docker.internal 被 INPUT DROP) |
本会话 Codex R1 / Claude R1 VERDICT: PASS |
| R27 | TP-18 实现双评审(Codex + Claude) | PASS | 无 | P2:LFS capability URL 不直接走 enforce_lfs_access(trunk 下路由未挂载);/edit/diff-preview 一并关闭;OpenAPI 测试重建 nest 而非 live GET;cedar_guard 在 trunk 臂省略(TP-21 部署文案) |
本会话 Codex R1 / Claude R1 VERDICT: PASS |
| R28 | TP-21 文档双评审(Codex + Claude) | PASS | 无 | P2:ssh_receive_pack=false 须显式写入(已补进 deploy-trunk.md §1/§4);docs/monorepo.md 仍有预存路径 bin/tests/integration_git_cli.rs |
本会话 Codex / Claude VERDICT: PASS |
| R29 | 计划完成门 cargo test --all |
PASS | 无 | 本机 compose git-cli 不可达,走 MEGA2_IT_ALLOW_HOST_GIT=1 + 钉扎 git-lfs 3.7.1 |
target/tmp/cargo-test-all.log EXIT:0 |
| ID | 延后内容 | 原因 | 重启条件 | 承接位置 |
|---|---|---|---|---|
| DEFER-TP-01 | Group commit(一次轮次批量摊薄树遍历) | 无实测压力证据;阶段 1 轮次函数已以 Vec<QueueItem> 预留入参 |
吞吐压力实测显示 B 段成为瓶颈 | trunk-push.md 阶段 6 第 1 项 |
| DEFER-TP-02 | LISTEN/NOTIFY 唤醒取代短轮询 |
轮询延迟可接受 | 等待者数量/延迟不满足 SLA | trunk-push.md 阶段 6 第 2 项 |
| DEFER-TP-03 | 实时排队进度(sideband channel 2 持续写) | 协议层改造、非必需 | 排队延迟成为用户体验问题 | trunk-push.md 阶段 6 第 3 项 |
| DEFER-TP-04 | 物化 TTL + 墓碑回收 | 物化只增不减成本未成为现实压力;需最后访问时间记录点审计 | 已物化路径数驱动的 B3 成本实测超预算 | trunk-push.md 阶段 6 第 4 项 |
| DEFER-TP-05 | 阶段 5 的多 token 运维与强化(token 轮换/审计/限流等) | trunk-push.md 阶段 5 收窄后未给出可执行规范;基础认证已随 4.2a 进阶段 4 | trunk-push.md 补齐阶段 5 规范 | trunk-push.md 阶段 5 |
计划只有在以下条件全部满足后才能标记完成:
- 所有任务卡满足粒度规则
G-*:无未登记的 L 例外、无 XL 卡、无碎片卡、无未登记的合并发布例外;「任务卡粒度审计表」已填齐且各卡Granularity行一致。 - 所有非延后任务的 acceptance criteria 已满足,且
Lifecycle=done且Acceptance=complete(ER-04);D 组远端 workflow 为空 → N/A。 - 所有任务的 Verification 命令已运行并记录结果。
- 计划完成门:
cargo +nightly fmt --all --check、cargo clippy --all-targets --all-features -- -D warnings、source .env.test && cargo test --all全绿(2026-09-09target/tmp/cargo-test-all.logEXIT:0),且cargo build、cargo build --tests均 0 错误 0 警告;不得新增 crate 级#[allow(...)]。 - 必要的 docs/配置/错误契约/测试矩阵更新已完成(TP-21 收口)。
- 必要的 migration、rollback、failure-recovery 验证已完成;每张卡的
Rollback mode已被实际验证或记录为不可验证的原因。 - 代码 review 最终结论为
PASS,P0/P1 全部关闭;仅 P2 residual risk 允许保留且具名接受(R6–R29)。 - 版本面已按各卡
Version incrementbump 且自洽、构建、提交、推送证据完整(ER-08)。自 2026-09-09 起 crate 版本只 patch 递增(TP-18 的 0.9.0 已回写 0.8.1)。 - 「修订历史」已记录成稿后的全部规范性变更(G-09)。
-
docs/refactoring/trunk-push.md头部反向声明已标记「已同步」;docs/plan/README.md已登记本计划。