Repository navigation
fix(runtime): stop long-lived helpers pinning the caller's directory on Windows #6652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
loopx-agent
merged 3 commits into
loopx-project:main
from
JasonBuildAI:codex/agent-n2v7-topic
Oct 17, 2026
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P2] 移开 cwd 前保留观察器的相对路径语境。在 observe_quota_cycle 派发之前按调用者 cwd 固定 registry_path 和 runtime_root(同时审查 request 中其余路径),继续让两个后台进程使用稳定临时目录;补相对 registry/runtime 的真实 detached 绑定和周期读回测试。 独立观察:真实存活进程的 cwd 已从调用者目录改到临时目录;同时,实际 detached Python→TypeScript 链中,base 的相对和绝对路径均记录 quota_cycle 与 codex_turn,当前源码、普通 wheel 和 sdist 的相对路径只记录 unknown 的 quota_cycle,绝对路径对照正常。 验证要求:用真实 detached Python→TypeScript、合成合法绑定及只读 SQLite/session 文件,比较相对/绝对 registry 和 runtime 的实际 quota_cycle/codex_turn 聚合;关闭统计仍应零子进程,后台 cwd 继续为稳定目录。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed on
add1d0603(pushed after your review).I reproduced the finding on this head before changing anything.
tests/test_usage_goal.py::test_caller_relative_registry_and_runtime_reach_the_detached_observerdrives the realobserve_quota_cycle→ detachedpython -m loopx.usage_goal→ detached TypeScript chain over a read-only SQLite/session fixture, withmonkeypatch.chdirto the caller directory andPath("registry.json")/Path("runtime")as the caller's arguments. Without the pinning change it fails with exactly the signature you described (no bound turn, only the unbound cycle):With the change:
1 passed in 6.01s, bothquota_cycleandcodex_turn, hostcodex_app.The scope is wider than the explicit relative flag: the default CLI registry is
.loopx/registry.json(loopx/paths.py::default_registry_path), andresolve_runtime_rootkeeps a--runtime-root/common_runtime_rootvalue relative to the project registry root, so ordinary project-local quota cycles already carried a relative registry and runtime root. Your reading of the failure mode (binding exception swallowed by the existing best-effort branch, cycle still recorded as unknown) matches the aggregator records.What changed, and why at this layer:
_detachis the boundary that moves the child out of the caller's directory, so it now freezes every caller-owned path in the request (path,registry,runtime) withPath(value).expanduser().resolve()before dispatch (_pin_caller_paths). The two helpers keep the stable OS temp cwd; the quota observer keeps its binding for relative and absolute arguments; and the other_detachcallers (begin/finish,observe_verified_return, the Goal observer) get the same guarantee, so no caller can hand a child a path that only resolved while it inherited the caller's cwd. Thepath(state file) field already comes fromPath.home(), but it is pinned too so the rule is uniform rather than caller-specific. Pinning insideobserve_quota_cyclealone would have left thepathfield and the other three callers on the old implicit contract.Evidence on this head (native Windows):
tests/test_usage_goal.py: 10 passed in 21.00s — absolute and caller-relative registry/runtime variants both retain the bound turn, numeric-timing and long-header variants unchanged.tests/test_usage_ping.py+tests/control_plane/test_effect_runtime_listener_startup.py: 36 passed, 10 failed. The ten are the pre-existing host-locale failures; reverting only the pinning change on this machine reproduces the same ten names (tests/test_usage_ping.py: 31 passed / 10 failed), so the follow-up adds no host failure.ruff checkclean on the changed files; canary premerge direct checks (diff hygiene, changed-filepy_compile, module-ceiling colocation) passed; the semantic-vocabulary drift canary passes once this checkout's npm dev dependencies are installed (the first failure was the missingtypescriptpackage, not the diff). The two remaining risk-profile smokes (catalog-planner,pytest-smoke-suite-facade) fail for the unchanged Windows fixture-cleanup class: the planner smoke itself exits 0 withcatalog-canary-planner-smoke ok.Unchanged, per your scope note: the seven other spawn candidates, the TypeScript entries (
process.cwdappears nowhere underloopx/), and the pre-existingWinError 5cleanup class. I do not claim native Windows deletion, wheel/sdist installs, or hosted CI beyond what is listed above.One CI note for the record: shard 6 on the previous head failed
test_real_detached_cycle_and_bound_codex_event_reach_shared_ts_aggregatorat its 8s deadline, which is the unbound-cursor wait. On that same headtest_bound_session_with_a_long_metadata_header_still_reaches_ts, which drives the identical detached Python → TypeScript chain, passed in 1.5s, andmain's own shards are red for unrelated tests, so I read it as a scheduling flake rather than a break in the chain; this head is re-running and I will report what it shows.English verdict: the P2 is confirmed and fixed on
add1d0603— caller-owned paths are pinned before dispatch, the stable helper cwd is unchanged, and a real caller-relative registry/runtime regression covers it.结论:P2 已复现并修复(
add1d0603)。在离开调用者目录之前按调用者 cwd 固定registry/runtime(以及状态文件path),后台进程仍使用稳定临时目录;新增真实相对路径的分离 Python → TypeScript 回归,修复前同一测试失败、修复后保留codex_turn。合并权限与最终评审仍在维护者。