Skip to content

perf(collaboration): avoid rewriting idle request lock holders - #8239

Open
loopx-agent wants to merge 4 commits into
mainfrom
codex/unfinished-delegation-native-read-20261107-025004
Open

loopx-agent wants to merge 4 commits into
mainfrom
codex/unfinished-delegation-native-read-20261107-025004

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

Opening All records reads each original request under the existing mutation marker and kernel lock. The uncontended read preserves the last kernel holder record. When a reader held both fences, a timed-out contender used that retained record to name a writer that had already released its lock.

Timeout diagnostics now consider the fence the waiter was acquiring. When the current holder cannot be identified, the exception and operator guidance report that the lock was busy with an unknown holder. The incident keeps the previous kernel record separately for investigation. A kernel timeout can still surface a live local record for the same lock when no mutation marker is present. The operator guidance calls for confirming that record against the actual holder. Review finding

The history read still takes the mutation marker before the kernel lock. The uncontended path keeps the holder bytes intact, and timed acquisition uses the existing deadline. The target is main, with validation pinned to merge base 8225c89ceaea21f013facae5d824e261c10c36d1. Subsequent target commits touched other files and merged cleanly in a preview.

Author Declaration

  • Written by model_agent (OpenAI Codex).

Implemented against

Criterion Disposition Path Validation
A28 retains original request authority and a coherent snapshot during paging and recovery implemented loopx/control_plane/collaboration/conversation_inventory.py, loopx/control_plane/collaboration/inbox.py Native HTTP and packaged File/SQLite tests cover source access, paging and recovery after both kinds of contention.
Report a holder only from evidence for the contended fence implemented loopx/file_lock.py Independent processes reproduce both waiters naming the same exited PID on the old code. On the revised code the two timeout payloads, incidents and operator actions distinguish busy from historical holder evidence.
Installed performance and adoption deferred Installed stewardship journey Validation uses the source checkout and a verified Chat bundle with isolated synthetic fixtures.

Capable Manager Semantic Handoff, §5.15 and A28

Scope And Continuation

The correction reuses the shared lock diagnostic and the request read adapter. Earlier matched latency measurements remain preliminary. The cause of longer waits and installed performance remain open. The revised head is available for independent review with the required validation hold recorded below.

Validation

  • Tested revision 2cd878adcab6c6030166c199e0d23b17b4bdcb2f.
  • Run state finished for scoped local checks.
  • Input classes synthetic and public_fixture.
Check kind Result Public-safe evidence
regression_parity passed Real request-inventory GET on isolated File and SQLite. A writer exits, a reader holds both fences, and separate waiters reach the default five-second deadline. Both backends reproduce the old PID misattribution before the fix. The updated path reports unknown, preserves the incident history and returns the original snapshot after contention.
integration passed 93 lock, history and request-control tests on macOS. Both writer-first cases recover the same snapshot. Live kernel diagnostics, an independent marker conflict, malformed records, source coverage and audience boundaries are covered.
integration passed 21 native steward, manager round-trip and receiver tests. Includes revoked authority, the agenda projection check, original conversation return and reuse of linked work.
real_entrypoint passed Verified Chat bundle and the 61-request delegation browser smoke on File and SQLite. Cancellation, retry, search, paging, complete original text and source recovery passed. Inventory issued zero mutations.
static passed Repository Ruff scope plus the lock module, control-plane TypeScript check, changed-path public boundary scan and bilingual RFC check. The earlier Ruff finding cleared on the newer base.
static failed Required mypy has the same missing return annotation in decision_capture.py:651 on both immutable revisions. The annotation failure entered the target via #8293.
integration failed An additional SQLite scheduled-report retry test intermittently reaches a non-executable route with no Turn journal. Exact base and candidate reruns preserve the same normalized failure and show zero lock timeout incidents. The required contention and original-conversation tests passed separately.
static blocked Six direct checks and ten selected standard premerge checks passed. Strict exact-scope qualification holds the merge because the required mypy row remains failed.
integration not_run Nine Windows-specific cases skipped on macOS. The repository Windows job covers those cases. The broader local test sweep stopped after reproducing the periodic-report failure and isolating it for paired runs.

Frontend / Visual Evidence

The packaged delegation dialog was used for the browser smoke. The user-visible correction is in the shared lock timeout and operator guidance.

Type of Change

  • Bug fix
  • Test update

LoopX Area

  • Control plane

Technical Direction

Keep A28 original-source recovery and history read behavior grounded in the existing request and lock owners.

Shared-authority RFC fixture impact

The existing source authority and receipt contracts cover this change.

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=max

Request changes conclusion (author-owned PR; GitHub blocks formal self-review)

[P2] 请求锁超时时请区分当前占用者与上一次持有者。 快速读取持有 marker 和 kernel lock 时保留旧记录。先让另一进程获取并释放该锁,再让真实历史列表 GET 持锁超过等待期限,File 与 SQLite 上的旧版 kernel-only 等待方都会在默认 5 秒后收到已退出进程的 PID,并被指引去检查该进程。相同输入下,基线报告实际读取进程。请保留历史记录,同时按等待的 fence 验证当前持有者。无法确认时应如实返回忙碌且持有者未知。 快速获取 · 超时诊断

动机 / Motivation

在协作对话里打开全部记录的人,需要读完原始请求,再按当前快照翻页和搜索。
原来每次读取每条请求都重写持有者记录。空闲锁复用上一条记录后,常见读取省掉两次写入。
配对测试确认翻页结果相同,两道锁也继续阻止重叠。若读取迟迟未释放,旧版等待方会得到已经退出的持有者 PID。
本评审覆盖真实 HTTP 入口和隔离的 File、SQLite。长期延迟、安装版及其他客户端的端到端验收分别保留。

改动思路 / Approach

保留原请求锁的双重约束有必要。无争用时可以省掉历史记录写入,超时时仍需区分当前争用与上一次持有。
本次修复可以保留请求读取的快速路径。等待出错时只对有当前证据的 owner 指名,保留原记录供追溯。
原有 Goal 生命周期、请求身份和两道文件锁继续负责排他。先持有旧 kernel 锁或 mutation marker 的写入方仍能挡住 GET,释放后读取同一快照。反向由快速读取先持锁时,等待仍会正确拒绝重叠,但诊断把历史 PID 当作当前占用者。

具体改动 / Changes

依据改动前的 docs/architecture/rfcs/capable-manager-semantic-handoff-v0.md,版本 79665b97a0a453380da02e15b1b62eee895147df。5.15-backlog-authority 的来源核对和权限范围在配对测试中保留。A28 要求定位真实恢复缺口,当前兼容超时诊断仍需修正。A28-installed-journey 留给现有打包与安装验收。 既有协作契约

关键代码讲解

  • _request_inventory_read 从当前 Session 和 Goal 授权取得读取范围,并校验搜索与窗口参数。前端继续调用该入口。 HTTP 入口
  • _locked_request_batch 按请求排序、去重并锁住当前一批,再交给既有收据读取。此次只在该路径传入 preserve_holder。 批次锁
  • _request_lock 先取 mutation marker,再尝试 kernel lock。空闲时保留旧记录,遇到已持有的 kernel lock 则走原有定时等待。 锁适配器
  • _timeout_error 从最后的 holder 记录生成异常和检查指引。快速读取未写当前 holder,使此处可能指向已经释放锁的进程。 超时输出

完整 diff 为三个文件,新增 57 行、删除 5 行。请求和收据事实沿用原有 owner。

对主干的风险 / Risks

实际回环 HTTP 对同一 49 条请求、七种分页和搜索读取逐项核对。两个后端的 holder 持久化调用分别从 686 降到 0,页大小、匹配数量和覆盖一致,读取没有改动请求收据。独立进程持有任一道锁时,GET 都等待并在释放后恢复。源码组合测试通过 99 项,quick premerge 通过六项直接和两项选中检查。

语义与 CI 对齐

我在真实收据读取点注入延迟,保留两道真实 OS 锁。较早的独立写入进程已退出。在 File、SQLite 上,兼容 kernel 等待均实际等了约 5 秒,head 的异常和落盘事件都指向旧 PID。两道锁的等待适配器也复现。影响范围是到达同一 request fence 的等待方。当前同 Goal 的控制入口还先经过 lifetime guard。请用 test_inventory_legacy_waiter.py 覆盖读取先持锁的方向,再验证释放后原请求仍可恢复。

全量 Ruff 在两版本报同一处 test_goal_create_completion.py:184 F841。另两项 agenda fixture 在基线和 head 都返回 consume_peer_result,断言期待 await_peer_result。该用例直接走 native agenda。这些已有失败单独记录。远端 CI 未核验。

我的整体评价 / Verdict

读取减少了可测的持有者记录写入,分页与排他成立。合入前请让超时指引基于实际争用的锁,或明确当前进程未知。独立验证为源码 HTTP,作者的打包界面结果与安装后表现分别记录。本轮数据只支持配对 fixture 的写入减少。

English verdict: REQUEST_CHANGES

# Inventory needs both fences but can keep the prior holder record when
# the kernel fence is free. A busy legacy writer gets the usual timed wait.
with exclusive_mutation_file_lock(lock):
with try_exclusive_file_lock(lock, preserve_holder=True) as held:

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.

[P2] 请区分历史 holder 与超时的当前争用者。真实历史 GET 持有两个 fence 时,这条快路径保留了已经释放锁的另一个进程的记录。File 和 SQLite 上的兼容 kernel-only 等待均在默认 5 秒后将该旧 PID 作为当前持有者,基线报告实际读取进程。请按等待的 fence 绑定当前证据,无法确认时给出持有者未知,保留历史记录和排他顺序。

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

This branch has not been deployed

No deployments
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.

1 participant