Repository navigation
fix(runtime): serialize archive with artifact writers - #5862
huangruiteng merged 3 commits into
Conversation
Signed-off-by: Duang777 <duangjl007@gmail.com>
|
@loopx-agent please review exact head |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · xhigh
动机
归档运行历史时仍有 quota 写入在途的用户会遇到这个问题。
旧版会越过已准入写入;新版本在全局路由存在时增加 source 和 maintenance 互斥,但全局路由缺失时仍能先归档,随后已准入写入因文件 IO 失败而无法完成结算。
常规路由上的等待测试通过;真实归档入口的无全局路由反例仍失败,尚未证明已准入结算与归档一致完成。
本 PR 不新增权限、租约、持久化格式或外部发布能力,未验收完整 provider 迁移及长期运行。
改动思路
沿用已有 TypeScript maintenance 与跨语言锁路径,Python 负责现有文件管理 IO;不新增平行状态规则或权限。 本次边界是 runtime 归档与已准入 artifact 写入的互斥;无全局路由也必须保护结算,不能依赖路由投影完整。 真实入口沿现有 CLI 调用文件管理函数,以注册表和 source/maintenance 锁为权威输入,完成后另外读回文件与路由。无变化会继续保留写入竞争;较小且完整的修复是在既有 owner 内调整副作用与锁的先后,而无需新建事务框架。锁超时属于执行拒绝,不能当成普通建议;正常恢复必须依赖持锁者释放后实际完成。
具体改动
本次精确归档竞争没有已接受的书面规范;已读 CLI 归档说明及 canonical/source writer ownership,采用当前 PR 的已准入写入须完成后才归档这一可复现实务契约,不把未来 RFC 指标升级成当前门槛。
关键代码讲解
archive_runtime_goal(loopx/runtime.py:55):Acquires projected source guard(s), maintenance and registry; rechecks membership before move。既有输入、返回结构和作用域保持;独立读回实际状态,未用 mock 提供待验证的结果。record_quota_slot_spend_from_preview(loopx/control_plane/quota/spend_commit.py:198):Exact writer admits index/source before added maintenance; absent projection allows archive to overtake this interval。既有输入、返回结构和作用域保持;独立读回实际状态,未用 mock 提供待验证的结果。write_turn_journal_checkpoint(loopx/control_plane/turn_driver/journal_store.py:71):Runtime-shaped paths add maintenance guard; non-runtime paths keep direct TS journal write。既有输入、返回结构和作用域保持;独立读回实际状态,未用 mock 提供待验证的结果。
完整 PR 为 5 文件,532 增、33 删,主要生产变更是共享锁接入,测试负责竞争与失败回归。新 Turn 用例在 journal write 处替换 IO,因此只证明 Python 路径的等待;真实 quota 结算漏例另由生产 effect runtime 和 source CLI 验证,未把 mocked journal 当成完整 durable Turn 证明。
对主干的风险
[P1] 不要用全局路由是否存在决定是否保护已准入 artifact writer。 同一隔离 fixture 中,exact quota 已取得 index/source admission,在新增 maintenance 取得前暂停;全局 registry 无该 route,真实 archive-runtime --execute 仍 exit 0、archived=true。归档完成后放行 writer,其生产 TS commit 抛 EffectRuntimePermanentIOError,归档中没有本次完成的 quota event。source 生命周期仍有效,路由投影缺失不能说明没有在途写入。Join every runtime artifact writer and archive to a stable common guard before admission can be overtaken, independent of global route presence; preserve consistent source/index/maintenance ordering. Cover absent global route plus already-admitted exact writer, completion/readback and timeout with no split or lost settlement.
20 archive/quota/Turn tests; independent real CLI with absent global route and admitted exact quota writer。没有查询、轮询或等待 CI。这是既有竞争尚未覆盖的漏例,并非声称本 PR 新引入该竞争。路由完整时的正例确实有改进,但本 PR 声称完成的已准入结算保护还未闭合。
语义与 CI 对齐
当前义务是归档不能越过已准入的 durable 写入。被删除的全局 route 只是共享投影,不能作为 source lock 不需要的事实;上述生产入口反例违反这个义务。增加无 route 的 exact quota 竞争,并重跑 archive concurrency/quota runtime tests;不要扩大协议或降低验证要求。
我的整体评价
精确 head:f3e90cd72d97e214891b7f95e31875707c1fd106。结论 REQUEST_CHANGES。long_horizon 和 user_experience 均为 not_yet_proven:Head archives successfully while exact quota writer holds index/source admission but is paused before maintenance; resumed writer fails with EffectRuntimePermanentIOError. No completed quota event reaches archive. 机制与范围合理,默认预览、协议名称与权限没有扩张。未来改造检查选择在既有 guard/admission owner 修复漏例,不引入另一套生命周期。未测 Windows、长期压力及完整 provider 迁移;隔离本地文件与生产 TS 锁/effect 路径证据不等同安装态 App/Lark 全部采用,也不代表整个 Goal 完成。修复后须重新对新 head 审查完整范围,不能继承当前局部通过结果。
English verdict: REQUEST_CHANGES. Head archives successfully while exact quota writer holds index/source admission but is paused before maintenance; resumed writer fails with EffectRuntimePermanentIOError. No completed quota event reaches archive. Join every runtime artifact writer and archive to a stable common guard before admission can be overtaken, independent of global route presence; preserve consistent source/index/maintenance ordering. Cover absent global route plus already-admitted exact writer, completion/readback and timeout with no split or lost settlement.
The earlier archive lock relied on global source routes, so an exact writer could hold index/source admission while an unrouted archive moved its goal directory. Acquire a stable runtime artifact guard before writer admission and archive source discovery, while preserving the existing inner lock order. Signed-off-by: Duang777 <duangjl007@gmail.com>
|
@loopx-agent please re-review exact head The P1 is fixed with a route-independent runtime artifact guard stored outside Red evidence on the prior head: absent-global-route exact quota let archive finish first and the resumed production TS writer raised Validation on this head:
The prior head's |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: loopx-agent / model_agent; gpt-6.1-sol / OpenAI; runtime_reported; reasoning_effort=xhigh
Exact head: ef7b418c19ad512b686cdf69c7d06ab3846fed78. Verdict: APPROVE. 未发现当前阻塞项;旧版缺路由并发反例已独立验证修复。
动机
同时使用原生 quota 或 Turn 写入、并执行 Goal runtime 归档的操作者。
之前写入已经获准但尚未完成时,归档可能先搬走目录,导致记账失败或后续日志重新写到活目录;现在归档等待已经进入的写入完成,再整体搬走。
独立真实 CLI 在全局路由缺失时,确认 quota 与 Turn 两条路径都等待写入,并把完成产物保留在归档内。
本次不扩展归档授权、不新增状态迁移,也不证明跨平台硬崩溃恢复、锁等待延迟或模型长期收益。
改动思路
稳定外层生命周期锁覆盖路由尚未发现或已消失的已获准写入,内层仍复用原有 source、index 与 maintenance 锁;这是文件归档完整性约束。
本 PR 只闭合归档与现有 quota、Turn 写入之间的生命周期互斥,不创建第二套决策或权限来源。
业务准入、结算和日志语义仍由现有 TypeScript owner 决定;Python 负责真实文件 IO 生命周期。外层锁位于不会随 Goal 目录被搬走的稳定路径,先于路由发现和内部 source/index/maintenance 锁。因此缺少全局路由不再让已准入写入逃出归档互斥。它是默认必须满足的完整性规则,不是可选策略;阻塞与重试继续沿用现有 owner,锁也不授予归档或写入权限。
具体改动
完整审查十个文件、+901/-62,包括原生 source prepare/release、quota 两种写入分支、Turn checkpoint 与调用者,以及 source IO 清单和并发测试。不是只检查最后新增的锁。此处没有针对该归档并发缺陷的已接受书面规范,验收依据是现有调用者的持久完成约束及可重复反例;未将未来 RFC 属性升格为当前义务。
关键代码讲解
loopx/runtime.py:55/archive_runtime_goal:outer stable artifact lock before discovering source paths;source/index/M ordering and recheck under lock。loopx/control_plane/quota/spend_commit.py:201/record_quota_slot_spend_from_preview:artifact guard wraps both existing writer branches;outer lock held until durable TS commit completes。loopx/control_plane/turn_driver/journal_store.py:74/write_turn_journal_checkpoint:legacy artifact+M; admitted caller owns artifact/source then M;avoid nested artifact reacquisition。loopx/control_plane/goals/first_party_host_admission.py:73/_runtime_artifact_lifetime:prepare/release wrap real runtime artifact lifetime;canonical path validation preserved。
语义与 CI 对齐
复用现有 typed admission/journal 和锁身份,不增加第二套状态决策或持久协议。registry IO manifest 反映实际调用位置;完整语义测试 126 通过。本次没有读取或等待远端 CI。业务语义、日志回放和路径验证仍由已有边界负责。
对主干的风险
独立隔离文件系统上运行实际 archive-runtime CLI,同时让真实 quota/Turn writer 已获准、停在最终 IO 前;全局路由故意为空。不可变基线 746b868e9eb2cee5aefc255022be20e88f14c73b 的 quota 出现永久 IO 错误,Turn 在搬走后重建活目录;前一头 f3e90cd72d97e214891b7f95e31875707c1fd106 同样暴露。当前头两条路径均等待写入,最终产物在归档内、活目录未重建。基线尚无 maintenance 钩子,barrier 放在真实 pre-IO seam;旧头和当前头使用同一 3 秒暂停窗口。
109 个相关 Python 测试、126 个语义测试通过;原生 diff-selected premerge 的 16 项及 5 项直接检查通过,无失败、warning、advisory 或 manual hold。先前 0.6 秒 quota 探针因 CLI 启动时长未可靠暴露旧竞态,保留为不充分证据,随后同条件 3 秒测试才作结论;错误路径的初次测试调用和错误 canary 参数也未计作通过。没有修改现行 Goal 或 provider。
我的整体评价
长程效果预期正向:结算与日志不再被一次成功归档拆散,后续恢复可沿同一完整历史继续。体验也正向:操作入口与授权步骤不变,归档等待已经开始的写入,减少事后找回记录的干预。代价是同 Goal 的锁竞争和额外 IO;未测吞吐、等待分布或模型成本,不能宣称速度更快。
未来改动的归属已检查:共用稳定 artifact 锁、保留既有 TypeScript 决策 owner,当前边界无需新框架;625 行并发夹具的价值在真实竞争分支而非字段计数。跨平台硬崩溃、异常宿主退出与长期压力仍是未测边界。该控制面 PR 的合并由 maintainer 处理;本结论不结清上层 Goal。
English verdict: APPROVE - ef7b418c19ad512b686cdf69c7d06ab3846fed78. The whole exact-head archive and production writer paths preserve durable completion in real unrouted concurrency counterexamples. Focused suites and native premerge passed; lock contention and cross-platform crash recovery remain unmeasured. Maintainer merge required.
Signed-off-by: Duang777 <duangjl007@gmail.com>
|
@loopx-agent please re-review exact head The PR-specific archive/artifact-writer diff is unchanged. Post-merge validation:
|
|
CI attribution for exact head I reran that exact test on both this head and its immutable base |
|
Follow-up on the baseline failure: upstream PR #5863 ( |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=xhigh
Independent exact-head review: f04b071fbaa94a9a8eb3bdd5946008445eace2b1, immutable base e47e4507a4d22ed9d52e9644a5d1f25f8f7f77e1. No unresolved blocking finding at this head; the prior archive/writer finding is independently resolved. This approval replaces the older body/head-mismatched conclusion, without borrowing its validation.
动机
归档旧 Goal 运行目录、同时有已准入记账或 Turn journal 写入的 CLI 操作者。
旧版本在没有全局路由的已准入写入期间先完成归档:quota 写入随后报错,Turn 完成产物回到归档外的 live 目录。当前版本让归档等待同一 Goal 的写入,完成的 index/journal 留在归档内。
本轮真实 CLI + TypeScript effect runtime 对照确认:基础版本两条路径丢失归档内完成产物,当前 head 两条路径都等待写入、归档内产物完整且不重新生成 live 目录。
不授予归档活跃 Goal 的新权限,不替代 source retirement,不阻止归档完成后的新写入,也不修复另行审计的相对 runtime 路径定位。
本轮未验证 Windows、本机安装升级、全平台或进程崩溃持久性;相对 runtime 路径缺陷由现有 #5859 承接,archive 后的新写入生命周期不在此 slice。
改动思路
复用外置 runtime artifact guard 保全正在执行的文件效果,Python 只持有 host IO 锁;现有 TypeScript 准入、账务、journal 决策及权限仍各归原 owner。 本 PR 完成 archive 与既有 quota/Turn artifact writer 的串行化,并重验等待后的目录/注册资格;不把互斥锁扩展为生命周期退休授权。 Existing maintenance lock alone permits the exact source-admission gap; a runtime-artifacts target outside the moved directory covers it without relying on optional global routes. Preserve routed/unrouted and legacy branches; source effects reuse their locked handoff. Artifact guard precedes source/index/maintenance admission; archive reloads membership and containment under locks, then moves once. Writer artifact and archive destination are read back on the real filesystem. Doing nothing retains demonstrated data loss. Only source-route locking misses unrouted writers; copying TS source-lifetime decisions into Python adds duplicate authority. Reuse the host IO guard and typed owner.
具体改动
10 files +901/-62: six Python production boundaries, exact IO-census coordinates, two internal call-site tests and a 625-line durable concurrency regression suite. PR body, current exact review and durable concurrency tests disclose waiting/serialization; #5859 path repair remains separate.
Contract: PR #5862 prior exact-head blocking review and existing GoalRef/source-lifetime + archive permission contracts, immutable revision e47e4507a4d22ed9d52e9644a5d1f25f8f7f77e1. 既有 archive 仅在显式执行且注册资格通过后移动;已准入 index 与 journal 完成必须保留在同一归档目录。旧 P1 要求路由缺失也不能超越已准入 writer。 admitted-artifact-integrity — implemented: Archive waits for already admitted quota and Turn writes even without a global route. mutation-time-gate — implemented: Membership, containment and bounded timeout remain enforced before moving.
关键代码讲解
-
archive_runtime_goal: Stable outer guard precedes source/maintenance/registry locks, then reloads mutation-time membership and containment before one move. -
record_quota_slot_spend_from_preview: Guard precedes both legacy and exact accounting admission; preserves existing typed quota owner and admitted artifact. -
source_journal_admission: Holds the route-independent artifact guard before the source guard; prepared/released source effects use the same stable lifetime. -
write_turn_journal_checkpoint: Source-admitted paths use existing outer caller guard; standalone runtime journals acquire it before maintenance and real TS write.
对主干的风险
Deadlock from inconsistent lock ordering or archive overtaking a source-admitted writer before maintenance; a stable outer guard must cover every changed production writer path. 生产 quota/Turn writer 与实际 archive CLI、真实文件锁和 TS effect runtime;只在可丢弃合成 registry/runtime 中暂停 admission seam,未用假后端替换 durable effects。非活动 Goal,不认证崩溃/全平台。
Independent current head: 126 Python passed, 102 TypeScript passed, TS typecheck passed; 5 direct + 16 selected standard premerge checks passed, zero warnings/holds. The real CLI uses absolute isolated runtime fixtures with unrouted exact source registries; base quota errors and base Turn recreates live, while head retains both completed artifacts. Initial test invocation named a test only present in related #5859 (collection exit 4, no tests); corrected selected suite passes. Initial base probe emitted no parseable JSON, so it was not qualification; diagnostic-preserving rerun at the same immutable source reproduced the two defects.
语义与 CI 对齐
No new state vocabulary; whole-tree semantic premerge passes after bounded advisory. Existing authority ordering and effect identity are exercised at the real backend. The waiting/error delta is intentional and independently validated; membership refusal and original stop boundary persist, with no guidance renamed as permission. Existing preview/permission refusals retain their boundary; real default writer integrity improves. Locks and admission witnesses are machine-enforced; archive permission prose remains explicit required caller confirmation, not a guidance-only grant. 本轮未查询、轮询或等待 CI。静态 advisory 空结果不认证语义等价;实际原始记录、生产入口和同输入基础版本对照才是判据。
我的整体评价
APPROVE; delivery judgment justified_increment. 完成产物在 archive 内保持,避免结算失败或 split history;同一请求的等待/超时/retry owner 可读回。 CLI 操作者不需重填已知信息或新增确认;原权限边界保留,错误不会静默伪报已完整归档。 复用外置 runtime artifact guard 保全正在执行的文件效果,Python 只持有 host IO 锁;现有 TypeScript 准入、账务、journal 决策及权限仍各归原 owner。 本 PR 完成 archive 与既有 quota/Turn artifact writer 的串行化,并重验等待后的目录/注册资格;不把互斥锁扩展为生命周期退休授权。 Future-facing pass: the shared stable-target helper is applied; broader runtime artifact lifecycle abstraction is deferred because it would change the independently owned retirement boundary. The test fixture can be thinned later when another consumer needs it, not replaced by speculative framework.
残余边界:本轮未验证 Windows、本机安装升级、全平台或进程崩溃持久性;相对 runtime 路径缺陷由现有 #5859 承接,archive 后的新写入生命周期不在此 slice。 这不关闭父 Goal,也不授予 control-plane 合并权限;该 PR 继续交维护者处理。
English verdict: APPROVE - f04b071; 126 Python, 102 TS, typecheck and 5 direct/16 selected premerge checks passed. Independent immutable-base/current-head real CLI races resolve the prior unrouted writer blocker. No CI consulted; relative-path, later-write lifecycle, crash/platform and installed-host qualifications remain separate.
Independently resolved at exact head f04b071. A stable runtime artifact guard precedes source/index/maintenance admission independently of global routes. Actual archive-runtime CLI plus production TS quota and Turn effects reproduce both failures on immutable base e47e450, and retain both completed artifacts inside the archive on this head. Timeout and mutation-time membership checks pass. Current exact-head approval and full evidence: #5862 (review). Discussion is retained; no CI consulted or merge performed.
Goal And Delivered Outcome
archive-runtimecould moveruntime/goals/<goal_id>while a quota or Turn writer was admitted but had not completed its durable write. The writer could then recreate the live goal directory after archive returned, splitting one goal's history between live and archived paths.main.Author Declaration
Implemented against
record_quota_slot_spend_from_preview,archive_runtime_goaltests/test_runtime_archive_concurrency.pywrite_turn_journal_checkpointtests/test_runtime_archive_concurrency.pyarchive_runtime_goaltests/test_runtime_archive_concurrency.pyproject_registry_io_manifest_v1.jsonScope And Continuation
Validation
f3e90cd72unitpassedunitpassedregression_paritypassedstaticpassedstaticpassedintegrationpassedreal_entrypointpassedFrontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).