Skip to content

fix(runtime): supervise optional cache flush after effect drain - #6468

Merged
huangruiteng merged 1 commit into
mainfrom
codex/runtime-retirement-cache-20261015
Oct 15, 2026
Merged

huangruiteng merged 1 commit into
mainfrom
codex/runtime-retirement-cache-20261015

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

A settled Effect runtime can remain alive indefinitely when Node's synchronous compilation-cache flush blocks. A disposable real-server test reproduces this after the accepted journal write completes. This proposal supervises optional cache persistence after all admitted handlers drain, then retires only the locator owned by that runtime. Base: main at 3c681f1132fe719e01f75e5a41bfd854dfa9e346.

Author Declaration

  • Written by: model_agent — OpenAI GPT-6 (Codex).
  • Specification and revision: no separate written specification; the reproduced defect and behavior described here are the basis. Relevant existing boundary: docs/development/testing-and-quality.md at the stated base, managed Effect-process isolation.
Criterion Disposition Implementation / evidence
Finish admitted effects before retirement, including disconnected clients implemented Existing server drain precedes retireRuntime; real journal/result and negative IO cases
Optional cache persistence cannot keep a settled runtime alive indefinitely implemented Same-process worker supervises native flush; blocked/throwing flush and unavailable-worker tests
Preserve fencing and replacement locator ownership implemented One shared cleanup retains mutation lock and exact token/PID/fingerprint; late-flush contention and replacement tests
Preserve healthy cache and disabled-cache behavior implemented Real cache population, edits/corruption/private paths; disabled path creates no worker or cache
Qualify native Windows lifecycle and establish original intermittent cause partial Natural Windows lifecycle batch passes, including the new faults; original intermittent cause and full job remain unqualified

Scope And Continuation

effect_runtime_compile_cache.ts owns supervision and shared locator cleanup; the server calls it only after drain. Python transport and authority providers are unchanged. The worker shares the runtime PID and has its own cache disabled. An atomic ownership transition prevents the main thread from terminating a worker that has started fenced cleanup when a slow flush finally returns.

Default behavior changes for cache-enabled retirement: allow one second for cache persistence, with a separate one-second worker-startup allowance. Successful flush retains the normal exit path. Failed/stalled persistence or unavailable supervision cleans the owned locator and forcefully exits the already settled process, bypassing Node's automatic exit flush. Optional cache entries may be lost. Locator lock/storage waits and OS scheduling are outside this allowance. Cache-disabled retirement uses ordinary cleanup without supervision. See Node v24.21 cache semantics.

Cost disclosure: matched, sequential macOS/Node 24 samples after local builds/tests completed observed warm shutdown at 11–21 ms on the immutable base and 73–79 ms on this head (four samples per arm). Cold samples were 23 ms and 81 ms. This adds retirement startup cost for liveness; these descriptive samples qualify neither Windows nor tail latency.

The bounded related refactor extracts the existing locator cleanup once, within its existing owner, for both paths. Local atomic states and the worker mode tag are internal synchronization vocabulary, not a new persisted/caller protocol or capability.

This is a completed source proposal. Natural Windows lifecycle and minimum Node execution now pass within the scopes below. Exact-head independent source review is now recorded as APPROVE below; complete hosted CI and release qualification remain open. Existing full-CI work in #6458 and #6463 is not closed by this proposal. No manual hosted workflow, runner-capacity change, merge or installed-product upgrade was performed.

Validation

  • Tested product revision: ee05c5e98b15ce7b90445150fb46bfc35d338835.
  • Run state: finished.
  • Input classes: synthetic, public_fixture.
Check kind Result Evidence / limitation
regression_parity passed New blocked-cache case fails on the original six-second retirement assertion before the fix; journal already complete, owner still alive. Same admitted-write invariant passes after the fix.
integration passed tests/control_plane/test_effect_runtime_integration.py: all 90 cases; drain, disconnect/shutdown, replacement/fence, restart, receipt and permission/error cases.
unit passed tests/control_plane_ts/effect_runtime_compile_cache.test.ts: 16 cases, including real cache bytes and late-flush/locator-lock race.
real_entrypoint passed Normal noneditable wheel in an isolated environment: all 90 integration cases. Source and installed wheel both serve real ping and doctor --restart-runtime --installation-only, read back stopped, and remove their own locator. Module provenance verified.
static passed npm run typecheck:control-plane, configured mypy, repository Ruff, diff advisory before full semantic smoke, six-path public scan and DCO.
integration failed npm run test:control-plane: 4685 passed, 39 skipped, one content_digest_single_owner consumer-pin failure for direction_authority.ts. Identical targeted command fails on immutable base and head with identical fixture bytes. Existing #6431 owns that repair; this failure is retained.
regression_parity passed Risk-based premerge checks: four direct checks, two catalog checks, eight risk-profile smokes and one public-boundary check. No manual holds or execution failures.
integration passed Natural Windows lifecycle batch, Node 24.21.0/Python 3.11.9: 208 passed, 19 skipped across the combined batch, including this runtime integration file and its new drain/fault cases. These aggregate counts do not mean every runtime case ran on Windows.
integration failed The same Windows job subsequently fails legacy migration: 26 passed, one test_extension_cli_keeps_legacy_machine_state_without_a_global_registry failure (extension revision history is invalid), matching existing #6463. Subsequent steps are skipped; the whole job remains failed.
unit passed Natural Linux TS shard 1/3, Node 22.22.3: all 16 cache tests explicitly pass; shard total 1622 passed, 31 skipped. Shard 3/3 also passes (1419 passed, two skipped).
integration failed Natural TS shard 2/3: 1644 passed, six skipped, one identical direction_authority.ts consumer-pin failure; #6431 remains its existing repair. No baseline exemption.
real_entrypoint passed Additional isolated macOS Node 22.22.3 validation: cache tests 16/16; source runtime 90/90; normal installed-wheel runtime 90/90. Both source and wheel serve real ping, then CLI doctor restart reads back stopped, Node 22.22.3 and SQLite authority qualification. Module provenance verified. The separate minimum-Node CI also passes typecheck and its 18 admission/lease cases; those 18 are not the cache suite.
integration failed Original-run browser shards 2/3 and 3/3 fail: explicit Host/Origin 403 in revision-preview on shard 2; proposal-readback timeout on shard 3 has no explicit 403 in its log. Related forwarding-fixture #6460 is now merged at 873e8fee87c04561ce58e0bbbd565da220a49f4d; it is absent from this original CI checkout. The timeout's cause is not independently established here.
manual blocked Managed change-quality qualification retains full-TypeScript and whole Windows-job failures. Complete hosted CI and exact-head independent review remain open; six Python shards were pending at the observation. Passing subsets does not override those gates.

Natural CI provenance: actual merge checkout b426f6d0ee3be9a55be4142f2da3054450f0f1a2 has the stated author head and base as its two parents; every changed runtime/test source blob equals the author head. Latest main now contains the browser-fixture repair above, with no intervening runtime-owner source changes. No new source commit, manual rerun or merge was made merely to reproduce known upstream failures. One passing Windows lifecycle batch does not establish the original intermittent cause or sustained qualification.

Earlier local failures were corrected and retained in local validation records: new fixture parameter omitted at a direct call, test-environment typing, and stale frontend bundle during wheel construction. The ordinary frontend build and wheel were rebuilt and verified; no UI source change is included.

Frontend / Visual Evidence

  • UI impact: none. Existing runtime/client/restart operations retain their entrypoints; no UI/configuration operation or first viewport changes.
  • Source data: synthetic.
  • Shared-authority fixture impact: N/A; no authority-store, provider-routing or compatibility-projection refactor. The real Node/file-lock path is exercised; no PostgreSQL qualification claim.
  • Technical direction: existing S2/S10/S12 runtime hardening and integration acceptance; native platform/full-CI acceptance remains separate.

Boundary Checklist

  • Public-safe diff and body; no private state, raw traces, credentials, internal links or local machine paths.
  • Scoped runtime repair; no duplicated benchmark work.
  • UI impact marked none.
  • Signed-off commit.

Independent source review and remaining platform gap

The published exact-head independent review concludes APPROVE for ee05c5e98b15ce7b90445150fb46bfc35d338835. It uses a COMMENTED review because the agents share the author account. The reviewer independently exercises immutable-base/current real processes with an admitted journal write, client disconnect, shutdown, a blocked or throwing optional flush, and replacement-locator fencing; current source, ordinary wheel and cache tests pass within the reported scope. The review explicitly does not qualify native Windows, minimum Node, complete hosted CI, sustained latency or the original intermittent cause. The earlier author-side Node 22 and natural Windows subset evidence above remains separate.

A later natural Windows job for #6474 again reports 199 passed, 19 skipped, 1 failed at the original decode-change retirement case. Its five runtime/diagnostic/test source files match its unmodified main base; it does not include this proposal's retirement implementation. The replacement locator remains after the two-second wait, with flush_enter and no observed replacement flush_done in the bounded diagnostic. This keeps the original platform/root-cause gap concrete; it is neither a failing test of this proposal nor proof of the complete cause. No additional hosted run was started to obtain it.

独立评审已对本精确提交给出 APPROVE,并用真实进程正反例验证业务排空、缓存故障退出与替代实例保护。此结论限定于源码修复;原生 Windows、原间歇故障根因、完整 CI 和持续资格仍未关闭。后续主干代码的 Windows 再现不包含本修复,不能据此认定本提案回归或已解决该平台问题。未新增源码提交、CI rerun、安装或合并。

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=xhigh

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

Reviewed head: ee05c5e98b15ce7b90445150fb46bfc35d338835。当前共用作者账号以 COMMENTED 发布独立评审。

动机

执行连续 CLI 工作的维护者,需要已完成业务的后台运行进程正常退出,让后来命令可以恢复或启动下一实例。 旧版在业务 journal 已经写入后,最终缓存写盘阻塞仍会让进程和定位文件一直留下;当前版先排空已接纳业务,再有界监督可选缓存并只清理原进程的定位文件。 相同隔离真实进程反例中,旧版阻塞缓存六秒后仍存活,当前版保留完整业务写入并退出;缓存关闭和正常缓存的业务结果保持。 本轮验收缓存退休故障的有界修复,不认证原生 Windows、最小 Node、完整 hosted CI、原间歇故障根因或持续运行尾延迟。

改动思路

同步缓存调用可阻塞主线程的计时器,因此同进程 worker 承担独立监督;排空与定位文件锁仍复用原 owner,不另建业务或授权状态。 本 PR 交付业务已结算之后的缓存失败退出,保留 handler、receipt、替代定位文件与缓存关闭路径;平台及持续资格仍由现有运行验证工作承接。

最强反对理由是强制退出可能先于业务落盘,或者同步写盘晚返回时把正在清理的 worker 杀掉。把 timeout 放主线程不能解决阻塞本身;一律关闭缓存则丢失健康缓存收益。当前选择仅在已结算进程内增加短命监督线程,并在同一现有模块提取一次定位文件清理。业务 drain、并发锁和精确身份判断仍为不变量;缓存只是可丢弃的 provider IO。未增加 Python 决策、通用框架、用户确认或新配置入口。

具体改动

完整6路径 +273/-32:缓存 owner 新增监督和共享清理,server 删除旧内联清理并在排空后调用;三项测试/故障诊断覆盖实际缓存、写入和退出,指南新增20行中英说明。未改 frontend/Lark/CLI 操作入口、权限、数据 provider 或业务 receipt。预加载的原私有目录、禁用和 coverage 判断保持;新 worker 自身禁用缓存。

关键代码讲解

locatorRetirement:26 在 flush 前加载原 IO owner,两条路径共用原 mutation lock;读取 token、PID、fingerprint 全部匹配才删除,替代实例的定位文件保留。superviseCache:57 先读好清理依赖并报告 ready,收到 flush 信号后才启动一秒计时;只有 CAS 从 FLUSHING 成功改成 RETIRING 的线程取得清理权。retireRuntime:71 在缓存关闭时直接普通清理;正常 flush 完成则终止监督并原样清理。启动不可用、抛错或超时才进入已结算进程的强制退出。若同步调用晚返回且 worker 已取得清理权,主线程等待它,不会把持锁线程终止。

依据变更前 docs/development/testing-and-quality.md,固定版本 3c681f1132fe719e01f75e5a41bfd854dfa9e346:Isolate the managed Effect process as well as the data 的隔离/先 settle 后 stop、Local Validation Environment 的源码解释器来源、Risk-Based Review 的真实边界与失败限定均 implemented。新增指南不是独立验收依据。原 server close 的 pendingRequests 等待位于 retireRuntime 之前,断开客户端不减少已接纳 handler 的寿命。

对主干的风险

我以同一私有脚本分别运行固定 base/current 的真实 Node 服务:业务写入被真实文件锁挡住,客户端超时,随后请求 shutdown;0.6秒后两端仍活着、journal尚不存在。释放锁后四组 journal 都逐字段精确匹配。正常及缓存关闭两端均退出;blocked-cache 的 base 在六秒后仍活着且 locator 保留,当前全部消失;throwing-cache 的 base 虽退出但留旧 locator,当前完成清理。只向可选 flush 调用注入故障,业务 IO、结果运输和锁保持真实,结束时仅清理自有隔离 PID。

当前 source 集成90pass/0skip;缓存 TS16pass/0skip,固定base原9pass。实际缓存字节、同路径编辑/腐败、禁用/coverage、worker不可用、阻塞/抛错及晚返回/替代 locator 均覆盖。晚返回反例持锁超过监督期限后发布替代定位文件,原进程等锁释放才退出,替代内容保持。普通 noneditable wheel 的相同90用例也通过;包内两个 TS owner、IO和Python运输四个blob与head完全一致。第一次构建因本地旧frontend bundle过期失败,按正常build重建并验证后重试成功,失败记录保留;没有把重建当作 UI 改动或正式安装升级。

TypeScript全源码compiler通过;advisory先于full语义检查,原生canary4direct+11selected/executed全过,0失败/skip/timeout/manualhold,六条公开路径扫描干净。单独的content_digest消费者检查在base/head均17tests、16pass/1fail,缺同一个direction_authority pin;完整归一化断言签名相同,oracle、consumer和digest owner三个blob相同,属既有不相关失败,#6431仍负责。没有声称full TS suite全绿,也未查询/轮询/等待/启动 hosted CI。

强制退出可能丢失可选缓存;一秒是flush额度,另有一秒startup额度,不涵盖定位锁、存储及OS调度。作者公布的73–79ms对11–21ms退出开销只是其描述样本,本轮未独立计时,也不据此认定native Windows、Node22最小版、长期尾延迟或原间歇故障根因。这些资格不由故障注入或一个通过批次替代。

我的整体评价

APPROVE,当前限定路径无阻塞finding。long_horizon/user_experience在已完成业务后退出与后续实例恢复上改善,原业务结果和替代定位文件所有权有真实正反例;未新增用户操作步骤。future-facing pass已在既有typed owner删除两条路径的重复清理,局部原子状态/worker tag属于local_only,无新共享协议。保持这个有界边界即可,不需扩大框架或关闭整个运行资格计划。本COMMENTED结论不授merge或bypass权限;closeout/readiness分别回读,原生平台、完整hosted与持续资格仍明确未验证。

English verdict: APPROVE - ee05c5e; immutable-base/head real servers preserve the disconnected admitted journal while blocked-cache retirement changes from a live process/stale locator to clean owned retirement. Current source90, ordinary installed-wheel90 and cache16 pass, including late-fence replacement and disabled parity. The identical baseline digest-consumer failure is retained; native Windows/minimum Node/full hosted CI and sustained latency are not independently qualified. No merge authority is granted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants