Repository navigation
fix(file-lock): name the Windows holder sidecar without a .json suffix - #6165
Closed
JasonBuildAI wants to merge 2 commits into
Closed
JasonBuildAI wants to merge 2 commits into
JasonBuildAI wants to merge 2 commits into
Conversation
JasonBuildAI
requested review from
huangruiteng and
loopx-agent
as code owners
October 10, 2026 19:10
The Windows lock-holder sidecar was named `<lock>.json.lock.holder.json`, so
any `*.json` state store over the locked directory matched it. External chat
admission locks `<request>.json` and then enumerates sibling requests with
`ChatExternalConversations.pending()` (`glob("*.json")`), which read the holder
metadata as a request and crashed at `_admit_prepared` with `KeyError:
'binding_id'` (issue loopx-project#6128). The same name also fed the lark delivery store,
which raised `KeyError: 'status'` while walking the same directory.
The sidecar is advisory lock metadata, not state, so drop the trailing `.json`
and keep `.holder` (`<lock>.json.lock.holder`). Every reader already resolves
the path through `lock_holder_path`, so only name-based `*.json` filters need
updating; the POSIX single-file holder record is unchanged.
Closes loopx-project#6128
Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
…walkers The Windows holder sidecar lost its .json suffix, but a runtime root upgraded from a release that wrote `<lock>.holder.json` still carries that file, and a `*.json` state store reads it as a record: external chat admission then raised KeyError `binding_id`, and the lark delivery store raised KeyError `status` (issue loopx-project#6128). Acquisition now best-effort deletes the legacy sibling while the lock is held, and the three record walkers accept only the 24-hex request reference that admission already enforces, matching the existing collaboration-inbox guard. Verified: pending()/health()/pending_delivery_paths() raise KeyError on the legacy sibling without these changes, and their new regression tests pass with them. Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
JasonBuildAI
force-pushed
the
codex/agent-k3f9-topic
branch
from
October 10, 2026 20:16
2752251 to
96955af
Compare
Contributor
Author
|
Closing this PR: it duplicates the earlier, equivalent PR #6164 (opened 2026-10-10T18:59Z, 11 minutes before this one), which fixes the same root cause in the same files ( Under the coordination rules for this contribution batch (an earlier equivalent PR takes the topic; a later agent must not keep a second PR for the same fix), this PR yields and is closed rather than pushed forward. No maintainer action is needed on it. The branch |
JasonBuildAI
added a commit
to JasonBuildAI/loopx
that referenced
this pull request
Oct 10, 2026
9 of 17 tasks
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Goal And Delivered Outcome
*.jsonglobs, causing Windows-only test flakes #6128 (reproduced on a native Windows host, commit5c62c5c03).<lock>.json.lock.holder.json, so a*.jsonstate walker over the locked directory harvests ephemeral lock metadata. External chat admission locks<request>.jsonand then enumerates sibling requests withChatExternalConversations.pending()(glob("*.json")); it read the holder sidecar as a request and crashed at_admit_preparedwithKeyError: 'binding_id'. The same name also races directory snapshots (a walker lists the holder, a concurrent lock deletes it, and the read fails).test_exclusive_lock_persists_public_safe_holder_metadata,sorted(tmp_path.glob("*.json"))is['state.json', 'state.json.lock.holder.json']before the change and['state.json']after (regression_parityrow). End to end, theexternal-requestsdirectory holds...json.lock.holderafteradmit,pending()returns only the real request, and the reportedKeyErrorno longer fires (real_entrypointrow).*.jsonglobs, causing Windows-only test flakes #6128; basemain.Author Declaration
Implemented against
*.jsonglobs, causing Windows-only test flakes #6128 plus the accepteddocs/reference/protocols/file-lock-acquisition-v0.mdcontract at5c62c5c03.loopx/file_lock.pylock_holder_pathtests/test_file_lock.py::test_exclusive_lock_persists_public_safe_holder_metadata*.jsonwalkers must stop matching the holder sidecar (issue #6128 repro 1)<lock>.json.lock.holderglob("*.json")assertionloopx/capabilities/native_chat/external_conversations.pypending()(unchanged; now receives no sidecar)real_entrypointrow belowdocs/reference/protocols/file-lock-acquisition-v0.mdloopx checkscan / reviewlock_holder_pathos.name == "nt"branchtests/test_file_lock.py,tests/test_file_lock_cross_process.pylock_holder_path, every reader (loopx/paths.py, incident/timeout code) and every literal.lock.holder.jsonreference; all readers go throughlock_holder_path, so only the name-based*.jsonfilters needed updating. Ran the focused and neighboring suites, the fail-before/mutation check,ruff,git diff --check, the public-boundary scan and the semantic-vocabulary advisory. Deliberately left out: repairing the unrelated downstreamdelegateauthorization failure described in the gaps below, and theuv.lockartifact this host generated.Scope And Continuation
.json, so no*.jsonwalker can harvest it; the reported admission crash and the walker-race class are both removed at the one place that names the sidecar.FileNotFoundError) is not needed for this defect: the sidecar is no longer a candidate for any*.jsonwalk.Validation
275225121regression_paritypassedassert sorted(tmp_path.glob("*.json")) == ["state.json"]fails (Left contains one more item: 'state.json.lock.holder.json'); with the change it passes. Mutation verified by re-adding the.jsonsuffix to the sidecar name.unitpassedtests/test_file_lock.py tests/test_file_lock_cross_process.py: 18 passed, 2 skipped.unitpassedtests/test_loopx_turn_executor.py::test_reserved_managed_start_recovers_after_death_before_the_first_journal_write,::test_run_once_rejects_corrupted_failed_turn_recovery_before_host_retry,tests/test_loopx_turn_driver.py::test_turn_run_once_cli_commits_distinct_host_guidance_without_task_step_edit: 6 passed.real_entrypointpassedtests/extensions/test_lark_private_manager_returns.py::test_production_pump_returns_to_original_private_source_after_restart, host-native Windows with the Node runtime: on the base revision the fixture errorsKeyError: 'binding_id'atexternal_conversations.py:87; on the head that error is gone and the directory contains...json.lock.holder, withpending()returning only the real request. The test still fails later on this host for an unrelated reason (see gaps).real_entrypointpassedtests/test_collaboration_sidecar_scan.py tests/control_plane/test_legacy_coordination_writer_fence.py: 14 passed - the harness-simulated sidecar is still ignored by the collaboration inbox, and the writer-fence holder assertions (vialock_holder_path) still hold.staticpassedruff checkon the changed files: all checks passed;git diff --checkclean.manualpassedloopx checkon the changed paths:public boundary scan clean: 6 files;scripts/generate_semantic_inventory.py --changed-from HEAD: no supported new vocabulary carriers.*.jsonglob, the external-request enumeration, the collaboration sidecar scan and the writer fence. One reported, unrelated failure remains and is disclosed rather than hidden: the end-to-end Lark fixture now reaches a downstreamIndexError(transport.core.actions.store.list()[0]) on this host because the/delegatecommand settles ascommand_completedwithfailure_kind=ValueError("original commission authorization is not currently valid") instead of producing a proposal - a host/environment authorization state in that harness, independent of the sidecar name.tests/control_plane/test_agent_lifecycle_state.pyandtests/test_turn_lane_fence.pywere reviewed (they read the holder only throughlock_holder_path, so the rename is transparent) but could not finish inside this host's time budget; they belong in CI.Frontend / 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).