Repository navigation
fix(leases): reject directory and glob write-scope conflicts - #7786
Conversation
Match glob continuations beneath literal directory scopes while preserving character classes, Unicode folds and disjoint paths. Cover exclusive acquire and atomic Todo claim with File and SQLite CLI regressions, immutable retries and unchanged state after rejection. Signed-off-by: Jim-jimu <3230103159@zju.edu.cn>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=max
动机 / Motivation
使用普通独占租约协调同一仓库写入的维护者和 Agent,会遇到目录范围与文件 glob(通配表达式)交叉的任务。
先取得 src/ 的租约,再申请 src/components/*.ts:基线允许两个写入者同时执行;当前 head 拒绝第二笔,且保留原租约、回执和状态。
同一共享目录的冲突现在会被真实 acquire 和原子 todo claim 拒绝;不相交范围仍可执行,持有者精确释放后可继续工作。
本修复不扩张写权限、不改变 worktree 协作模式,也不承担进程终止、自动交接或跨 Goal 文件锁。
改动思路 / Approach
目录延续匹配复用原有 typed acquire owner,存储、资格与 CAS 保持原边界,避免另造租约规则。
当前 PR 完整交付普通目录与 glob 的互斥修复;不引入新配置、存储格式或调度策略。
原始 scope 的拼写继续参与不可变请求身份,目录包含关系只是比较时的推导值。实现沿现有 glob token 和 Unicode 折叠匹配器判断:目录的已知前缀先匹配,余下表达式必须仍可能匹配一个后代。普通文件匹配默认不进入该分支。独占冲突仍由原 canonical acquire owner 拒绝,已验证独立 worktree 的重叠仍是集成提示,没有新增配置或手工同步状态。
具体改动 / Changes
审查完整 base 04c5799b88f6c4cf12a224b7fa679f272e1e794e → head 2974dc24b112c89ae9ee071762351d88aeb783f8:一个生产文件增加 42 行、删除 5 行;两个测试文件增加 146 行,无生成物或存储 schema 变更。
规范:docs/reference/canonical-lease-renew.md#repository-relative-scope-identity,不可变版本 04c5799b88f6c4cf12a224b7fa679f272e1e794e。逐项映射:SCOPE-OVERLAP 已实现,同 Goal 的目录/glob 重叠在真实 acquire 与原子 claim 上拒绝;SCOPE-IDENTITY 已实现,大小写/词法别名仍重叠,原参数重试及续约后的原回执保持;SCOPE-BOUNDARY 已实现,不同已知仓库与已验证独立 worktree 沿既有规则处理。
关键代码讲解
classHasMatch:检查剩余字符类是否可满足,保留正/负类和折叠别名,空逆序区间不能产生假后代。fnmatchcase:默认完整匹配不变;目录模式在已知前缀耗尽后判断剩余 token 的可满足性,沿现有 memo/Unicode owner 计算。scopePairOverlaps:只把 literal directory 与 glob 的混合分支接到延续匹配;现有 acquire/claim、repository/worktree 和 quota 调度 caller 继续消费同一判断。
对主干的风险 / Risks
未发现阻塞问题。最危险的反例是先取得 src/ 后再申请 src/components/*.ts,或用 src/SS/ 与 [ß] 绕过互斥;我在 File、SQLite 和真实 PostgreSQL 上独立重现基线错误,并验证当前拒绝发生在 canonical 提交前。反向参数、不相交兄弟路径、不可满足字符类、原请求重试和持有者释放后的继续执行均有覆盖。
| 本地检查 | 结果 |
|---|---|
| 同一 scope CLI harness:基线 / 当前 head | 基线 48 failed、142 passed;当前 190 passed。失败均为重叠的第二笔租约被错误准入 |
| 定向 TS directory/acquire/repository/workspace | PASS:64;最初 1 项 PG skip 后用真实后端补验 |
| 隔离 PostgreSQL 16.15 | PASS:必需 store 集成 382 项、workspace 32 项;独立目录对照 8 项,基线 4 个重叠案例错误放行,head 全部符合预期 |
| 新 Todo 与恢复 | PASS:在已有目录租约后创建新任务,冲突无副作用;原持有者精确 release 后新 key 可取得租约,File/SQLite 都成功 |
| 共享调度 caller / 静态 / 风险 gate | PASS:26 项 orchestration;TS typecheck、Ruff、mypy 17;5 项 direct 与 17 项 selected premerge 检查 |
语义与 CI 对齐
复用现有 token、AcquireDecision 和 canonical lease vocabulary,不新增按文本猜状态的规则。修正的是已有独占合同的漏判;worktree 的 advisory 没有变成强制占有。当前配置不查询或等待 GitHub CI。作者披露的 broad-suite 失败仍属诊断,原因未在此穷尽,也未被宣称修复;当前必要的 changed-invariant 与真实 PostgreSQL 证据已独立建立。
我的整体评价 / Verdict
APPROVE,完成所声明的目录/glob 修复。长程维度保持原有执行、重试与恢复能力,用户体验减少了可导致并发覆盖的错误准入;不以测试数量宣称实际团队效率收益。兼容性保留有真实的 persisted request/receipt 消费者,修改集中在原 owner,暂不需要更大的 glob 框架或额外跟踪任务。
已检查租约 matcher 与 CLI 入口,未改动任何渲染页面。 视觉改动无未验证项;原生平台与模型执行边界另列。
未执行完整 Python/TS 仓库套件、Windows/Linux 原生 CLI 或长期负载;初次 TS 的 PostgreSQL skip 已由隔离真实后端补验。历史作者 broad-suite 失败保留为诊断,未推断为已修复;当前必要不变量已有独立覆盖。 精确 scope 的 change-quality receipt cqr_d4e448d6c3b6387442ca 已验证有效。批准结论不代表执行了合并。
English verdict: APPROVE — 2974dc24b112c89ae9ee071762351d88aeb783f8 fixes directory/glob exclusion; File/SQLite and isolated PostgreSQL validation passed. Full-suite and cross-platform qualification remain unverified.
|
补充一个租约粒度的后续设计建议,想请作者考虑。 这条修复解决了现有 exclusive 语义下目录与 glob 的重叠漏检。更上层的问题是:普通代码编辑是否可以主要依靠 Todo 级执行租约和独立 worktree,而把跨工作树的文件范围重叠作为集成提示? 建议分开考虑三个职责:
当前路径协调已经需要处理目录/glob、字符类与 Unicode、路径别名、符号链接及 worktree 文件树观测。希望能评估:哪些检查确实必须进入执行准入,哪些可以降为提示或移到集成阶段;同时量一下真实调用链中的成本。独立 worktree 也有创建、依赖和清理成本,不能仅凭简化路径规则就推断显著提速。 参考当前已声明的 独立 worktree 代码编辑契约,可以进一步梳理“Todo 执行租约为核心、代码隔离优先、共享资源按需互斥”的边界,以及简化后仍须保留的并发与恢复反例。 |
|
Thanks for the follow-up. I agree with separating Todo execution ownership, code-workspace isolation, and protection of shared mutable resources. I inspected main at I found two concrete gaps:
I compared these paths through the current production transaction entrypoints using synthetic workspace identities and real File/SQLite stores. With two overlapping tasks, ordinary self-claim rejects the second task without changing state. Acquiring a lease with a distinct workspace identity for each task before self-claim allows both claims to succeed. This verifies the transaction boundary, not the complete Host execution journey. Based on that, I would suggest proceeding in stages:
Workspace observation should also remain distinct from filesystem access control. Surviving old processes, shared links and external effects still require explicit boundaries owned by the Host or the actual resource entrypoint. I would not assume a performance improvement upfront. Evaluation should include workspace preparation, dependencies, scanning, lease reads/writes, waiting, integration rework and cleanup, and judge the default change by accepted outcomes and complete costs. Would “carrying verified worktree identity through ordinary managed claim” be a suitable first independently deliverable scope? Parallel scheduling policy and default behavior could follow once that path is qualified. |
Goal And Delivered Outcome
src/andsrc/components/*.tsdescribe overlapping write scopes, but the mixed literal/glob matcher tested only the directory string itself. Two exclusive leases could therefore both be granted in one repository.task-lease acquireand atomictodo claimnow reject the second overlapping lease withwrite_scope_conflict, leaving canonical state unchanged. Disjoint scopes remain admissible; the regression-parity and real-entrypoint rows below prove both outcomes.loopx-project/loopx:main, baseline04c5799b88f6c4cf12a224b7fa679f272e1e794e.Author Declaration
Implemented against
scopePairOverlaps/fnmatchcasetask_lease_directory_scopes.test.ts; CLI regression belowScope And Continuation
Validation
2974dc24b112c89ae9ee071762351d88aeb783f8. Baseline comparisons use04c5799b88f6c4cf12a224b7fa679f272e1e794e.LOOPX_USAGE_PING=0 DO_NOT_TRACK=1.tests/control_plane_ts/task_lease_{directory_scopes,acquire,repository,workspace}.test.ts.uv run --extra test pytest tests/control_plane/test_canonical_lease_scopes.py -n 4 -q: 190 passed, including the 88 new cases. Real CLI, File and SQLite 3.53.4 providers use disposable fixtures; both scope orders and acquire/claim entrypoints are covered.fnmatchoracle: 6,960 directed comparisons, no mismatches. Ordinary non-directory baseline/head parity: 1,369 comparisons, no differences. These are supplemental generated checks, not additional committed tests.npm run -s typecheck:control-plane; Ruff over the contribution-guide scope; configured mypy check (17 files);git diff --check; bilingual RFC check.See validation disclosure guidance.
Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
none.Signed-off-bytrailer.