Migrate governed capability lifecycle validation to TypeScript - #3706
Conversation
huangruiteng
left a comment
There was a problem hiding this comment.
评审 exact head:c149372181ae39b1e2c7524c25b3cf3ac41f9b06
动机
这个 PR 想把 governed external capability 的生命周期判断从 Python 搬到既有 TypeScript control-plane owner:不仅校验单次 provider result,还一次解释 admission、journal identity、request digest、provider 状态、settlement callback、terminal state,并由 TypeScript 投影 public receipt。Python 继续负责文件锁、原子 journal I/O、provider 执行、transition proposal 落盘、writeback 和 quota spend。这个方向符合仓库“typed TypeScript boundary owns state/effect authority”的约束,也试图减少 reconcile/replay 的 managed-runtime 往返次数。
改动思路
loopx/control_plane/governed_capability.ts 新增 versioned lifecycle packet/reduction、稳定 JSON digest、journal status 枚举、whole-journal reducer 和 receipt projection;旧的 standalone validateGovernedCapabilityResult 入口仍兼容原 provider-result adapter。loopx/extensions/governed_capability_execution.py 将原来的 Python _validate_journal/_public_receipt 改成一次 governed_capability.validate_result lifecycle 调用,并只在本地 overlay Python 实际完成的 I/O effects。测试同时覆盖 TS reducer、Python 端到端运行、runtime-call 数量和 legacy adapter。
正向路径完整:selected Todo admission → prepare request/journal → TS inspect → provider start → TS observe_result → transition settlement → reconcile provider → durable writeback → quota spend → committed receipt。负向路径也覆盖了 request lifecycle/digest 篡改、callback identity/digest 篡改、provider result/receipt 矛盾和非法 transition proposal,均在 typed boundary fail closed。
具体改动
governed_capability.ts的reduceGovernedCapabilityLifecycle绑定 transaction settlement identity、request authority、start idempotency key、operation profile 和 journal/provider 状态;validateStoredSettlementCallback再验证 writeback/quota receipts;lifecyclePublicReceipt统一生成公开 receipt。governed_capability_execution.py的_reduce_governed_capability_journal负责跨运行时适配,_receipt_with_local_effects反映 Python-owned durable effects;start/reconcile/replay 都复用 lifecycle reduction,仍保留文件锁、0600 journal、atomic replace、transition proposal settlement 和 writeback-before-spend。- TypeScript 14 个 focused tests 与完整 203 个 control-plane tests 通过;Python governed-capability 14 个 tests 通过;control-plane typecheck、Python compileall、ruff、
git diff --check均通过;loopx check --scan-root .公私边界扫描无 error(3 个 warning 为仓库/registry 既有状态,与本 diff 无关)。SonarCloud 远端检查为 success。
[P1] Existing-journal replay 绕过了 operation 的 selected-Todo action/target 授权
在 start_governed_external_capability 的 existing-path 分支中,_require_admission 已不再接收 todo_contract,随后 _reduce_governed_capability_journal(... phase="inspect") 也没有传 admission。因此这个分支只校验 heartbeat settlement identity,不再校验 selected_todo.action_kind / target_key 是否属于 operation profile。新增的 test_material_start_recovers_an_existing_journal_without_new_run_authority 还把 should_run 设为 false、删除 selected_todo 并要求 replay 成功,说明这是可观察的默认行为变化,但 PR 同时声明 “no functional changes”。
这不只是只读 readback:当 journal 已有 provider result 时,该 replay 分支会调用 _settle_journal_transition_proposals,可创建、更新或完成 LoopX monitor Todo。于是一个仅携带旧 exact settlement identity、但当前没有被选择且没有 action/target authorization 的 admission,可以重新触发 control-plane writes。此前每次 start/replay 都通过 validate_admission 校验 operation todo contract。
请保留 typed migration,但恢复 side-effecting replay 的 selected-Todo operation authorization;或者把纯 receipt readback 与需要恢复 transition writes 的路径拆开,只有后者要求新的 runnable/authorized admission。同时把这个恢复语义作为行为变化明确写入 PR,并增加 negative test:缺失或不匹配的 selected Todo 不得触发 transition settlement。
对主干的风险
主要风险在授权边界,不在 reducer 的基本状态机:TypeScript whole-journal validation、writeback-before-spend、terminal receipt binding 本身是清晰的,Python/TypeScript 数字 canonicalization 差异也通过本地 provider-result digest overlay 被显式处理。但当前 replay 放宽会让“相同 effect identity”被误当成“当前仍有 operation authority”,把幂等恢复与新一轮 control-plane write 授权混为一谈。这个变化涉及 Todo/transition authority,不能以 refactor-only 合并。除此之外,public receipt 仍需 Python overlay 实际 I/O 结果,是合理的 provider boundary,而不是第二套生命周期规则。
我的整体评价
整体架构方向正确:它把重复的 journal/result/settlement 判断收敛到 typed TypeScript owner,Python 保留 effect adapters,测试覆盖和运行时调用经济性也扎实;bounded future-facing pass 在正确边界上实施,无需再扩展新抽象。但 exact head 目前存在一个可执行 side effect 的 replay 授权回归,并且 PR 元数据未披露该默认行为变化。结论:CHANGES_REQUESTED。修复 replay authorization、补 negative coverage 并更新行为披露后,可以重新评审;当前不要合并。
English verdict: CHANGES_REQUESTED for exact head c149372181ae39b1e2c7524c25b3cf3ac41f9b06. The TypeScript lifecycle-owner migration is well structured and the focused TS/Python, full control-plane, typecheck, compile, lint, diff, and boundary checks pass, but existing-journal replay now accepts a non-runnable admission with no selected Todo and can still settle transition proposals. Restore action/target authorization for side-effecting replay (or split read-only replay from authorized recovery), add a negative regression test, and disclose this default behavior change before merge.
huangruiteng
left a comment
There was a problem hiding this comment.
结论:REQUEST_CHANGES。评审 exact head:c149372181ae39b1e2c7524c25b3cf3ac41f9b06。
阻塞项(P1):existing-journal replay 丢失了 operation 的 selected-Todo action/target 授权。start_governed_external_capability 的已有 journal 分支只用 _require_admission 校验 settlement identity,随后调用 _reduce_governed_capability_journal(..., phase="inspect") 时没有传入 admission;当 journal 已有 provider result 时,该分支仍会调用 _settle_journal_transition_proposals。因此,携带旧 settlement identity、但当前 should_run=false 且没有 selected_todo 的调用,仍可恢复并写入 monitor Todo transition。最低修复是恢复 side-effecting replay 的 operation todo-contract 校验,或把纯 receipt readback 与会落 transition 的 recovery 分成两个路径并只授权后者;同时补一条缺失/不匹配 selected Todo 不得写 transition 的负向测试,并把这个默认行为变化从“no functional changes”中明确披露出来。
动机
这个 PR 试图把 governed external capability 的整段生命周期判定从 Python 收敛到既有 TypeScript control-plane owner。旧实现由 Python 同时解释 admission、journal identity、provider result、settlement callback、terminal state 和 public receipt;新实现希望让 TypeScript 一次读取 whole-journal lifecycle packet,负责 typed state 与合法迁移,Python 只保留文件锁、原子 journal I/O、provider 调用、transition materialization、writeback 和 quota spend 等 effect adapter。这个方向能减少 Python 与 managed runtime 的重复权威,也把 committed replay 的 runtime 调用从 3 次降到 1 次。非目标是改变现有 operation 授权、provider request 合同或 writeback-before-spend 语义;正因为 PR 自称 refactor-only,replay 权限放宽不能被当作迁移细节带入主干。
改动思路
入口仍是 governed_capability.validate_result,但 validateGovernedCapabilityResult 会按 schema 分派:legacy provider-result 继续走 validateProviderResult,新的 lifecycle packet 走 reduceGovernedCapabilityLifecycle。reducer 以 settlement identity、canonical request digest、operation profile、journal status、provider result、writeback/quota receipts 为权威输入,返回 canonical journal status、validated provider result 与 public receipt。Python 的 _reduce_governed_capability_journal 负责组包并调用 typed runtime,_receipt_with_local_effects 再覆盖只有 Python 才能证明的本地 I/O effects。
正向路径是:selected Todo admission → prepare request/journal → TypeScript inspect → provider start → TypeScript observe_result → transition settlement → reconcile provider → durable writeback → quota spend → committed receipt。负向路径对 request lifecycle/digest 篡改、provider result/receipt 矛盾、callback identity/digest 篡改、quota-before-writeback 和非法 journal status 都会 fail closed。架构边界整体合理:状态机与 receipt 判定在 TypeScript,副作用执行和持久化在 Python;不需要再新增 capability 或抽象层。
具体改动
loopx/control_plane/governed_capability.ts(+418/-1)新增 lifecycle packet/reduction/run/receipt schema、stable JSON digest、JOURNAL_STATUSES、whole-journal reducer 与 receipt projection;legacy standalone result adapter 保持可用。loopx/extensions/governed_capability_execution.py(+195/-235)删除重复的 Python_validate_journal/_public_receipt权威,统一经 TypeScript reduction 解释 start、reconcile 和 replay;文件锁、0600 journal、atomic replace、transition proposal settlement、writeback-before-spend 仍由 Python 执行。tests/control_plane_ts/governed_capability.test.ts(+152)增加 observed-result、committed replay、request/callback tamper 等 reducer 覆盖。tests/extensions/test_governed_capability_execution.py(+88/-3)覆盖 runtime 调用次数、legacy adapter、Python digest overlay、replay 与 settlement;其中test_material_start_recovers_an_existing_journal_without_new_run_authority明确把should_run设为 false、删除selected_todo后仍期待 replay 成功,证明授权变化是当前实现的可观察合同,而不是推测。
关键代码讲解
reduceGovernedCapabilityLifecycle(TypeScript 第 605 行)是新的状态权威:它校验 exact packet fields、settlement identity、request authority/lifecycle/digest、operation profile、provider result、writeback/quota callback 和 terminal receipts。未执行 provider 时只有在 packet 携带 admission 的情况下才会调用validateGovernedCapabilityAdmission;provider result 存在后则强制 admission 为 null。lifecyclePublicReceipt(TypeScript 第 542 行)从 typed journal 投影 provider/transition/writeback/quota 状态;_receipt_with_local_effects(Python 第 294 行)仅覆盖 Python 实际落盘和 effect adapter 能证明的字段。这是合理的 provider boundary,不构成第二套生命周期规则。_reduce_governed_capability_journal(Python 第 207 行)构造 lifecycle packet、调用 managed runtime、检查 reduction schema/status,并在 inspect 时验证返回的 provider result 与 journal 一致;EffectRuntimeRejected只在无 admission 的 inspect 路径转成ValueError,其他路径保持 fail closed。start_governed_external_capability(Python 第 359 行)在新 journal 路径会把 admission 传给 reducer,因此 action/target 合同仍生效;但 existing-journal 路径不传 admission,却在 provider result 存在时继续执行_settle_journal_transition_proposals,这里把幂等 identity 与当前 operation authority 混为一谈,是本次阻塞项的具体位置。reconcile_governed_external_capability(Python 第 537 行)先 inspect journal,再按 provider running/terminal 状态执行 observe_result、transition、writeback、spend 与 committed checkpoint;失败时保留 typed settlement failure,重试不会重复已提交 writeback。
对主干的风险
最高风险不是 reducer 的 typed state 设计,而是授权边界:同一个 effect identity 只能证明“这是同一笔恢复”,不能证明“当前仍允许此 operation 对 LoopX Todo 产生新副作用”。在 provider result 已经写入、transition receipt 尚未 checkpoint 的 crash 窗口里,无 selected Todo 的 replay 会进入 _settle_journal_transition_proposals,可能创建、更新或完成 continuous monitor。影响面覆盖所有采用该 governed material capability adapter 的 operation;错误可在 Todo 历史中观察并可依靠 journal/receipt 恢复,但在写入发生后才可见,不能靠幂等性替代前置授权。
Typed-state lens 方面,journal status、phase 和 transition kinds 都使用闭集/typed helper,没有 substring denylist;domain-neutrality 方面新增错误文本保持 goal/provider-neutral;guidance-vs-obligation 方面没有把强制 flag 描述成建议。不过 behavior-change disclosure 不满足:PR 勾选“Refactoring (no functional changes)”,而测试和代码实际允许无 runnable selected Todo 的 replay。除这个 P1 外,我没有发现新的 blocker。最小回归测试应模拟 provider result 已写入但 transition receipt 未落盘的 crash,然后用缺失或 action/target 不匹配的 admission replay,断言 transition setter 未被调用且 monitor 未写入。
独立验证:focused TypeScript 14/14 通过;focused Python 14/14 通过;完整 control-plane 203/203 通过;Python compileall、ruff changed-file scan、git diff --check 均通过;public/private boundary scan 0 error(3 个 warning 为现有 registry/history 状态,不来自本 diff);远端 SonarCloud 为 success。绿测证明迁移主体稳定,但当前测试把授权放宽编码成成功路径,因此不能消除上述风险。
我的整体评价
整体架构方向正确,代码量与迁移范围基本匹配:TypeScript 成为 whole-journal typed owner,Python 收缩成 effect adapter,legacy adapter、positive/negative state paths 和运行时调用经济性都有覆盖;bounded future-facing pass 已落在相邻且正确的 ownership boundary,无需再扩展框架。当前 exact head 仍有一个 side-effecting replay 的 P1 authorization regression,并且默认行为变化没有披露,所以正式结论是 REQUEST_CHANGES,当前不要合并。修复 replay authorization(或拆分只读/有副作用恢复)、补负向 crash-window coverage 并更新 PR 描述后再复审。
English verdict: REQUEST_CHANGES for exact head c149372181ae39b1e2c7524c25b3cf3ac41f9b06. The TypeScript lifecycle-owner migration is coherent and focused TS/Python, full control-plane, compile, lint, diff, boundary, and remote checks pass, but existing-journal replay accepts a non-runnable admission with no selected Todo and can still settle transition proposals. Restore action/target authorization for side-effecting replay (or split read-only replay from authorized recovery), add a negative crash-window regression test, and disclose this behavior change before merge.
c149372 to
ee90211
Compare
Signed-off-by: hyk <4408344+hhyykk@users.noreply.github.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
ee90211 to
18bcf9b
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
评审 exact head:18bcf9b7f01658eb2d6742efac5fc4bae0360041。未发现新的 blocker。 上一轮 P1 已修复:已有 journal 只有在仍存在未结算的 continuous_monitor_upsert 时才重新要求 should_run=true 和当前 selected Todo 的 action/target 授权;纯 committed/readback 路径仍保持幂等,不会因为没有新 run authority 而失败。缺失 selected Todo、should_run=false、action 不匹配都会在任何 transition 写入前 fail closed,并且不会重复调用 provider。
动机与架构判断
这个 PR 把 governed external capability 的 whole-journal 生命周期判断收敛到既有 TypeScript control-plane owner,Python 继续只负责文件锁、原子 journal I/O、provider 调用、transition materialization、writeback 和 quota spend。这个 ownership 划分解决了 Python/TypeScript 双重解释状态的问题,也保留了 provider/effect boundary;没有新增不必要的 capability 或 speculative abstraction。对用户和 operator 的主要收益是 crash/replay/reconcile 在同一个 typed contract 下 fail closed,同时减少 managed-runtime 往返。主要风险仍是 recovery authority 与幂等 readback 被混淆,而当前修复已把两者按“是否尚有可写 transition”明确分开。
Refine 结果
本轮在贡献者 fork 分支上完成 rebase 和 bounded refine。TypeScript reducer 现在允许 inspect 阶段携带 admission 并复用 operation profile 的 todo_contract 验证;Python 只在检测到未结算 monitor transition 时传入 admission,已经结算的 journal 不增加无意义授权要求。新增 TS contract test 与 Python crash-window tests 同时证明:合法 authority 可补写 receipt,三种无效 authority 都保持 journal 字节不变且 provider 调用次数不增加。这个 companion change 位于相邻 ownership boundary,后续无需再扩展框架。
验证
本地 Python governed-capability focused tests 18/18、TypeScript focused tests 15/15、完整 TypeScript control-plane tests 320/320(1 个 environment skip)、TypeScript typecheck、ruff、repository mypy、git diff --check 均通过。LoopX exact-scope change-quality 覆盖 4 个文件,fingerprint 464a56993657c4c500625d61990dd5dbb69e0c701b766312efd15ccbb687510b,receipt cqr_464a56993657c4c50062 验证有效;premerge 9/9 通过,无 manual hold。GitHub DCO、dependency review、build、Python/PowerShell tests 与 Sonar checks 全部通过。
合并决定
先前 changes-requested 的唯一授权 blocker 已在 exact head 上关闭,改动保持单一目的、DCO 完整、公私边界干净,验证覆盖正常路径、负向授权与恢复窗口。结论:APPROVE,并按 owner 授权自合并。
English verdict: APPROVED for exact head 18bcf9b7f01658eb2d6742efac5fc4bae0360041. The prior P1 is fixed by requiring fresh runnable selected-Todo action/target authority only when replay can still settle a monitor transition, while pure committed readback remains idempotent. Negative crash-window tests prove invalid authority performs no journal write and no provider retry; focused/full TS and Python validation, type/lint/mypy/diff checks, exact-scope quality receipt, premerge, and all required GitHub checks pass. Self-merge is authorized.
Summary
governed_capability.validate_resultTypeScript operation.Migration economics:
The Python authority file changes by
+195/-235(net-40). The overall product delta is net+377, primarily the new typed lifecycle owner in TypeScript.Issue Or Task
Validation
python3 -m py_compile loopx/*.py(covered by compile-all verification for the changed Python module)loopx check --scan-root .(exact changed-file public/private scan: 0 errors, 0 warnings)npm run test:control-plane— 203 passedKnown baseline findings outside this diff:
TestContexterrors in unrelated tests.TRY004findings on untouched lines in the Python module.Type of Change
LoopX Area
Technical Direction
Core control-plane hardening
Long-horizon benchmark evidence
Operator surface and IM integration
Shared Goal Authority and cross-host coordination
Architecture and research incubator
Target base branch:
mainDirection tracker or promotion unit: TypeScript control-plane migration RFC
Boundary Checklist
.loopx/,.codex/goals/, liveACTIVE_GOAL_STATE.md, credentials, private benchmark traces, verifier output, raw agent sessions, internal document links, or local machine paths.Signed-off-bytrailer (git commit -s).