feat(coordination): make reviewed Goal promotion recoverable at full-state scale - #4879
Conversation
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
Exact head reviewed: 385aa72dff9e60507c3fa6cce665fcfe631cbb9a
动机
这个 PR 处理的是一次高风险、但边界清楚的运维缺口:既有 whole-Goal coordination authority promotion 可以预览并立即执行,但执行时会重新从当前源状态计算意图;一旦 legacy writer 已被 fence、进程却在 canonical commit/ACK 之间中断,操作者没有办法只凭原审核结果继续完成或读回同一笔事务。另一方面,大 Goal 的 shadow proof 会把完整 head 和每笔历史事务的完整 projection 反复跨 RPC 传输,可能在积累足够 promotion evidence 前就超过 2 MiB 响应预算。
当前切片是有用且完整的:保存的 plan 只绑定意图,不授予执行权限;执行仍必须显式传 --execute,apply 重新验证 fresh source,recover 必须已有完全一致的 durable fence。它没有把 active Goal 迁移、默认 provider、claim policy 转换或 UI 操作入口偷带进来。
改动思路
架构方向正确,并且复用了现有 owner:
coordination-shadow promote的成功 preview 现在携带 canonicalized reviewed-plan envelope;--reviewed-plan执行时重新计算既有 promotion plan digest,source/provider/policy/operation 任一变化都会在 fencing 前拒绝。recover-promotion不读取新的 legacy projection,也不依赖临时 runtime-shadow opt-in;它只接受原 plan,并要求 durable fence、shadow revision/digest、完整 lineage/outbox、资格策略全部仍匹配。- immediate apply 与 recovery 共用同一个 commit/readback helper:业务 commit 只尝试一次;抛错后只读取 receipt 和第一笔事务,不盲目重写。
outbox_read新增显式read_model=proof;TypeScript 内部仍完整验证 lineage,但跨进程只返回 digest、partition marker、event/receipt 和进度。默认未传时仍是 full diagnostic contract。- Python 只解析 CLI 文件和转发请求;计划 identity、fence、qualification、commit/readback 都留在 TypeScript authority boundary。
正向路径上,保存的计划在 source 未变时可 preview/execute;之后即使 canonical head 已继续前进、legacy Markdown 已删除,recover 仍能从 transaction 1 的 exact receipt 得到 replayed,且本次 executed=false。负向路径上,跨 Goal/root、改 policy/source/digest、缺 fence、残留 outbox、receipt/index/transaction 任一不一致都 fail closed。
具体改动
关键代码讲解
-
loopx/control_plane/coordination/reviewed_promotion_plan.ts::decodeReviewedPromotionOperation只接受精确 envelope 或未修改的成功 CLI preview,拒绝未知字段、跨 Goal/runtime carrier、嵌入式 execute authority,以及 recover 携带 fresh legacy source。保存文件因此是 identity carrier,不是权限 token。
-
loopx/control_plane/coordination/local_authority_runtime.ts::executeReviewedCoordinationPromotion重新计算既有
localCoordinationPromotionPlanSha256,同时核对 plan digest 与 writer-fence digest,再把 apply 路由到 fresh-source review path、recover 路由到 durable-fence path;没有在 Python 或新模块复制 provider selection。 -
loopx/control_plane/coordination/local_authority_runtime.ts::promoteLocalCoordinationAuthorityrecovery 在 canonical writer guard 内先验证 exact fence,再检查 canonical 是否已经由原事务初始化;若尚未提交,必须保留同一 shadow revision/projection、
hard_leasepolicy 和完整资格证据。execute=false只返回recovery_ready,不会写 provider。 -
loopx/control_plane/coordination/promotion_receipt.ts::commitPromotionAndReadBack统一两条路径的一次提交与 durable readback。receipt body、operation id、cursor、provider revision、第一笔 projection 全部必须一致;commit 抛错不会触发第二次业务提交。
-
loopx/control_plane/coordination/local_authority_shadow.ts::readLocalAuthorityShadowproof模式仍先执行loadValidatedShadowLineage,再将 transaction projection 降为 digest + partition marker。outbox sequence 分配只读已验证的 last sequence;drain 读取 compact transaction rows;full 模式默认形状保持不变。
精确 diff 为 27 文件、+1765/-261。新增量较大,但约一半是 focused Python/TypeScript tests,另有双语 operator/RFC 文档;生产机制围绕既有 promotion、fence、AuthorityStore 和 shadow owners 展开,没有新建并行迁移框架。
对主干的风险
代码与架构审阅中没有发现 promotion/recovery/proof 逻辑本身的新 blocker。我本地执行了:
- 4 个真实 CLI File/SQLite tests,全部通过;
- 32 个 TypeScript saved-plan、lost-ACK、receipt corruption、provider conformance 与 compact-proof tests,全部通过;
- TypeScript typecheck、Ruff、
git diff --check,全部通过; - 与当前
origin/main的 merge tree 无冲突; shadow_compact_proof在 production-scale retained projection fixture 上把原先大于 2 MiB 的响应压到 128 KiB 以下,同时保留完整内部 lineage validation。
[P1] 当前 exact head 没有通过 capability 要求的最终 required CI
远端 test-shard (4)、pytest 与 merge-gate 失败。直接失败为:
tests/cli_commands/test_project_lifecycle_goal_channel.py::test_refresh_state_dispatches_and_replays_post_writeback_sidecar
fixture 返回的 SimpleNamespace 只有 delivery,而当前 attach_settlement_progress 已要求 readback.progress。我在 PR exact head 与当前 origin/main 上分别执行同一个 focused test,二者都以相同 AttributeError 失败;因此这是 main 基线 fixture 漂移,不是 #4879 改出的 promotion regression。开放的 #4859 正好补齐 typed progress fixture。
但本 packet 明确 wait_for_ci=true,repository_required_checks 是强制 evidence。基线原因不能把红色 exact-head receipt 自动升级成通过。最小修复是先合入 #4859(或等价 fixture 修复),然后把 #4879 rebase 到该 main,并在未改变本次受审逻辑的 head 上重新跑最终 required checks。
语义与 CI 对齐
共享语义本身对齐:reviewed plan 扩展既有 promotion vocabulary;plan 不授予 authority,fence/provider/lineage 仍是现有事实 owner;默认 full read 与普通 promote 行为保持。当前阻塞只是 required CI receipt 尚未闭环,不代表需要扩大本 PR 去修改 project-lifecycle runtime。
剩余风险是:任意进程 kill timing 与 SQLite D2 elapsed soak 仍属于后续 qualification;proof transaction rows 随 bounded history 仍会线性增长,应继续监控,但本 PR 已消除“大 retained projection × history”重复传输的主因。
我的整体评价
这是一次扎实的 authority-boundary 改进:它没有用提高 RPC 上限掩盖重复 payload,也没有把恢复权力塞进保存文件;相反,它把 immutable reviewed intent、durable fence、qualified lineage、single-commit receipt proof 分开,并把重复 readback 逻辑收敛到同一个 TypeScript owner。对 active Goal 原始数据的安全边界也明确:评审与本地验证只使用 synthetic/public/disposable fixtures,不对活跃 Goal 做 promotion。
不过当前 exact head 不能 APPROVE,因为 capability 要求的最终 CI 仍为红色。等 #4859/等价修复进入 main、rebase 后 required checks 全绿,再对新 head 做一次聚焦复审;若受审代码未变,不需要重做无关范围。
English verdict: REQUEST_CHANGES - The saved-plan, exact-fence recovery, single-commit receipt proof, and compact lineage transport are architecturally sound and passed 4 real CLI tests plus 32 focused TypeScript tests. The exact head still lacks the required green final CI receipt because the unchanged project-lifecycle fixture omits readback.progress; land #4859 or an equivalent baseline fix, rebase, and rerun required checks on the new head.
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
385aa72 to
9970bb1
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Exact head reviewed: 9970bb19bdf051f9aca1b117d899967e36533684
动机
这个 PR 处理的是一次高风险、边界清楚的运维缺口:既有 whole-Goal coordination authority promotion 可以预览并立即执行,但执行时会重新从当前源状态计算意图;一旦 legacy writer 被 fence、进程却在 canonical commit/ACK 之间中断,操作者就没有办法只凭原审核结果继续完成或读回同一笔事务。另一方面,大 Goal 的 shadow proof 会把完整 head 和每笔历史事务的完整 projection 反复跨 RPC 传输,可能在积累足够 promotion evidence 前就超过 2 MiB 响应预算。
本次任务是把 CONFLICTING 且落后 main 42 个 commit 的分支修到可合并。rebase 后有三处真实冲突,其中一处的合并需要判断而不是简单取并集(见下)。上一轮评审的唯一阻塞项是 required CI 红,根因是当时 main 基线的 test_project_lifecycle_goal_channel.py fixture 漂移;该修复已经进入 main,我已在本 head 单独复跑并确认通过。
从目标边界看这是完整而非碎片化的切片:保存的 plan 只绑定意图,不授予执行权限;执行仍必须显式传 --execute;apply 重新验证 fresh source,recover 必须已有完全一致的 durable fence。它没有把 active Goal 迁移、默认 provider、claim policy 转换或 UI 操作入口偷带进来。
改动思路
架构方向正确,并且复用了现有 owner:
coordination-shadow promote的成功 preview 现在携带 canonicalized reviewed-plan envelope;--reviewed-plan执行时重新计算既有 promotion plan digest,source/provider/policy/operation 任一变化都会在 fencing 前拒绝;recover-promotion不读取新的 legacy projection,也不依赖临时 runtime-shadow opt-in;它只接受原 plan,并要求 durable fence、shadow revision/digest、完整 lineage 仍匹配;- immediate apply 与 recovery 共用同一个 commit/readback helper:业务 commit 只尝试一次;抛错后只读取 receipt 和第一笔事务,不盲目重写;
outbox_read新增显式read_model=proof;TypeScript 内部仍完整执行loadValidatedShadowLineage,但跨进程只返回 digest、partition marker、sequence 和进度。默认未传时仍是 full diagnostic contract;- Python 只解析 CLI 文件并转发请求;计划 identity、fence、qualification、commit/readback 都留在 TypeScript authority boundary。
正向路径上,保存的计划在 source 未变时可 preview/execute;之后即使 canonical head 已继续前进、legacy Markdown 已删除,recover 仍能从 transaction 1 的 exact receipt 得到 replayed,且本次 executed=false。负向路径上,跨 Goal/root、改 policy/source/digest、缺 fence、recover 携带 fresh source、receipt/index/transaction 任一不一致都 fail closed。
冲突解决(rebase 到当前 main)
loopx/cli_commands/coordination_shadow.py:main给 promote 增加了--handoff-mode-migration/registered-agent 绑定,本分支增加了--reviewed-plan路由与--minimum-operations的None→3归一化。合并后 reviewed-plan 路径照旧只带 plan,fresh-review 路径保留main的 migration/registered-agent digest 与参数。loopx/control_plane/coordination/local_authority_runtime.ts:main增加了 reviewed plan digest 校验与 handoff-mode migration 规划,本分支增加了execute语义、recovery_ready与共享commitPromotionAndReadBack。取并集时保留了promotionTargetProjectionSha256作为 readback 目标,两条路径都经commitPromotionAndReadBack提交migration.target_projection,并移除了本分支原先无条件的handoff_mode !== "hard_lease"分支——因为 migration plan 在默认策略下会用相同的local_authority_promotion_requires_hard_lease冲突拒绝,同时允许显式preserve/hard_lease请求。这正是 #4870 需要的能力,若保留原分支会把它挡掉。tests/control_plane_ts/authority_store_conformance.ts:两侧各注册了一个 conformance suite,都保留。
具体改动
27 个文件、+1807/-302:生产代码 +586/-299、测试 +913、双语文档与 RFC 检查点 +304、构建配置 +3。没有新增持久 schema 版本、provider、capability 或默认行为。
关键代码讲解
-
loopx/control_plane/coordination/reviewed_promotion_plan.ts::decodeReviewedPromotionOperation只接受精确 envelope 或未修改的成功 CLI preview:拒绝未知字段、跨 Goal/runtime carrier、plan 内的
execute,以及 recover 携带 fresh legacy source;apply 则要求同时提供 projection 与 source_snapshot。保存文件因此是 identity carrier,不是权限 token。 -
loopx/control_plane/coordination/local_authority_runtime.ts::executeReviewedCoordinationPromotion重新计算既有
localCoordinationPromotionPlanSha256,同时核对保存 digest 与 writer-fence digest,再把 apply 路由到 fresh-source review path、recover 路由到 durable-fence path;没有在 Python 或新模块复制 provider selection。返回的executed取结果而非请求标志。 -
loopx/control_plane/coordination/promotion_receipt.ts::commitPromotionAndReadBack/readPromotionReceipt统一两条路径的一次提交与 durable readback:receipt body、operation id、cursor、provider revision、第一笔 projection 全部必须一致;commit 抛错只记录
interrupted并读取 durable identity,不会触发第二次业务提交。 -
loopx/control_plane/coordination/local_authority_shadow.ts::readLocalAuthorityShadowproof模式仍先执行完整 lineage 校验,再把 transaction projection 降为scanTransactionView(digest + partition marker),并跳过appendScanPage;full 模式默认形状保持不变,read_model取值非法时直接报错。 -
loopx/cli_commands/coordination_shadow.py与promotion_review.pyrecover-promotion强制要求--reviewed-plan;--reviewed-plan与--minimum-operations/--require-event-kind互斥,避免保存的 qualification policy 被覆盖;Python 侧只做文件读取与 effect 转发。
其余改动是双语文档(operator 流程、RFC 检查点与 provider 选择说明)与测试。
对主干的风险
没有发现新的 blocking finding。
- 108 个 focused TypeScript 测试通过:reviewed plan、lost-ACK、receipt corruption、provider conformance、compact proof(native/legacy)、以及 rebase 需要合并的 handoff-mode migration matrix;
- 16 个 Python CLI/outbox 测试通过(真实 File 与 SQLite 入口);69 个 Python coordination adapter/state/writer 测试通过;
npm run typecheck:control-plane、Ruff、python -m mypy、git diff --check origin/main...HEAD全部通过;loopx canary premerge --from-git-diff:passed selected=19 failures=0;- 上一轮的红色 required 测试
test_refresh_state_dispatches_and_replays_post_writeback_sidecar在本 head 单独复跑通过(基线 fixture 修复已进入main)。
剩余、且本轮未独立复现的风险:作者报告的 isolated PostgreSQL 16 integration、physical-disk SQLite capacity rehearsal、以及与 #4870 组合的只读 captured-state(1,017 Todos / 10 leases)rehearsal 属于 author-reported;任意进程 kill timing 与 elapsed soak 仍是作者明确排除的范围;proof transaction rows 仍随 bounded history 线性增长,属于监控项而非本 PR 的修复目标。
语义与 CI 对齐
本 PR 是对既有 promotion vocabulary 的扩展而非另起一套 actor lifecycle:promotion_plan_sha256、writer fence、recovery_ready、replayed 都沿用现有语义;新增的两个 schema 分别描述 operator carrier 与内部 effect request。plan 不授予 authority,fence/provider/lineage 仍是现有事实 owner,默认 full read 与普通 promote 行为保持。rebase 之后 main 的 handoff-mode migration 语义与该分支的 reviewed/recovery 语义已通过 migration matrix、typecheck 与 coordination 套件验证对齐。
我的整体评价
这是一次扎实的 authority-boundary 改进:它没有用提高 RPC 上限掩盖重复 payload,也没有把恢复权力塞进保存文件;相反,它把 immutable reviewed intent、durable fence、qualified lineage、single-commit receipt proof 分开,并把重复 readback 逻辑收敛到同一个 TypeScript owner。
本次要求的两件事都已完成:冲突按语义合并(而不是机械取一侧),且合并过程中没有牺牲 main 新加入的 handoff-mode migration 能力——我特意检查并移除了会与之冲突的无条件 hard_lease 分支,同时确认默认策略仍以同一 reason code 拒绝非 hard_lease 源。对 active Goal 原始数据的安全边界也保持清晰:评审与验证只使用 synthetic/public/disposable fixtures,不对活跃 Goal 做 promotion。
据此我对本 exact head 给出通过结论,并执行 owner 授权的自合并。
English verdict: APPROVE - head 9970bb1 resolves the conflicts against current main while preserving both the reviewed-plan execution/recovery contract and main's handoff-mode migration feature, keeps the plan an identity carrier rather than an execution grant, shares one commit/readback owner, and adds a bounded proof read model; validation passed (108 TypeScript tests, 85 focused Python tests, typecheck, Ruff, mypy, diff check, canary premerge 19/19, and the previously red baseline fixture test now green), with PostgreSQL/captured-state qualification remaining author-reported.
Goal And Delivered Outcome
Related to #4574 and the shared-authority / TypeScript migration RFCs; base:
main.A reviewed Goal cutover could be recomputed at execution time, and an interrupted cutover had no operator path that could finish without rereading legacy Markdown. Large captured Goals could also exceed the existing RPC response limit before accumulating promotion evidence.
This change lets operators save a promotion preview, execute that exact intent, and recover the same fenced operation. TypeScript owns admission, plan identity, locking and receipt proof. Compact shadow proof reads preserve full internal lineage validation without transporting repeated full-state projections.
Scope And Continuation
coordination-shadow promote --reviewed-plan FILEandrecover-promotion --reviewed-plan FILE, each previewable before--execute. Existing commands and default qualification policy remain unchanged. The plan carries identity, not execution authority.preserve/hard_leaseconversion remains feat(coordination): preserve claims during authority promotion #4870. A disposable combination was resolved and tested, but that integration is not shipped by this main-based branch. The two PRs overlap in promotion orchestration: integration must retain migration strategy, registered-agent binding and target digest.Future-facing refactor applied: collapse duplicate receipt proof and qualification knowledge at the existing coordination owner; keep Python as an IO adapter. No speculative provider framework or new capability is introduced.
Validation
9970bb19bdf051f9aca1b117d899967e36533684unless qualified below. (Earlier runs in this table were taken at385aa72dff9e60507c3fa6cce665fcfe631cbb9a; the rebase changed only the merge reconciliation described below plus the baselinemainfixture that unblocked the required CI.)| regression_parity | passed | Physical-disk SQLite capacity rehearsal: 6 passed after safe cache cleanup, retaining the 5 GiB reserve and original durability settings. This is the bounded rehearsal, not full D2 or elapsed soak. |
Final complete TS run: 2,541 passed, 0 failed, 0 skipped, with qualified Node/SQLite, both isolated PostgreSQL integration databases enabled, physical-disk temporary storage, and
--test-concurrency=4. The final isolated service/store/team recheck separately passed 214/214.Premerge canary: 19 selected checks plus 5 direct checks passed, zero failures and no manual holds. Exact-scope quality receipt
cqr_97bc25cad372bf096d62verifies valid for scope97bc25cad372bf096d6215a5e61881dddfa3a5a36308eab423632ac90c9415cc(27 files; one safe-fix pass; zero blockers, two warnings: #4870 integration and the unchanged caller race below). No merge authority is inferred.Additional broad diagnostic: 2,538 passed / 3 failed / 0 skipped. One service test reused a database whose incarnation the earlier test had intentionally rotated; a fresh isolated database resolves it. One existing Python consumer subprocess timed out and passed its isolated real-PostgreSQL recheck. The third exposed an unchanged baseline team-plan replay race, deterministically reproduced on both base and head: receipt-missing observation → competing commit → fresh head containing the same deterministic Todo IDs → duplicate-ID error. The involved team-plan modules are unchanged here. This remains a separate caller-closure defect; later passing scheduling does not mean it is fixed.
The original broad TS run was 2,535 passed / 3 failed / 1 skipped. Two stale qualification fixtures were corrected and pass in the final focused suite. The skipped service integration was subsequently run against an isolated real database. The capacity failure and its physical-disk recheck are disclosed above; the original run is not represented as green. Fault injection is not arbitrary process-crash or elapsed-soak qualification.
Frontend / Visual Evidence
UI impact: none. This is an explicit administrative CLI workflow. No Dashboard/Lark setting, capability grant, automatic migration button or presentation chrome changes. Existing consumers retain their canonical routing contract. Before/after viewports and source data: not applicable.
Type of Change / LoopX Area
Bug fix, new operator command, supporting refactor, docs and tests. Primary area: control plane; direction: Shared Goal Authority and TypeScript ownership.
Shared-authority RFC fixture impact
Boundary Checklist
Control-plane changes are left for maintainer review and merge. Validation does not grant merge authority.
Branch sync (conflict resolved)
The branch was 42 commits behind
mainandCONFLICTING. It is now rebased ontomainat the time of the sync; both commits keep theirSigned-off-bytrailer and the PR-only range contains no merge commit.Three files needed resolution:
loopx/cli_commands/coordination_shadow.py:mainadded--handoff-mode-migration/registered-agent binding to the promote path; this branch added--reviewed-planrouting plus the normalized--minimum-operationsdefault. The merged block keeps the saved-plan route, and the fresh-review route keepsmain's migration/registered-agent digest and arguments.loopx/control_plane/coordination/local_authority_runtime.ts:mainadded reviewed promotion-plan digest validation and handoff-mode migration planning, while this branch added theexecuteflag,recovery_ready, and the sharedcommitPromotionAndReadBackowner. The union keepspromotionTargetProjectionSha256as the readback target, routes both the review and recover commits throughcommitPromotionAndReadBackwithmigration.target_projection, and drops the branch's unconditionalhandoff_modegate because the migration plan now enforces the identicallocal_authority_promotion_requires_hard_leaseconflict for the default strategy while allowing an explicitpreserve/hard_leaserequest.tests/control_plane_ts/authority_store_conformance.ts: both sides registered a different conformance suite; both registrations are kept.Re-validated on the rebased head: control-plane
tsc --noEmit, 108 focused TypeScript promotion/lost-ACK/receipt/compact-proof/handoff-migration tests, 85 focused Python coordination CLI/adapter/state/writer tests, Ruff, mypy,git diff --check, andloopx canary premerge(19 selected checks, 0 failures).