Skip to content

fix(leases): accept scoped native Windows worktree paths - #7817

Merged
huangruiteng merged 2 commits into
loopx-project:mainfrom
LIHUA919:codex/issue7805-windows-scope-20261101
Nov 1, 2026
Merged

huangruiteng merged 2 commits into
loopx-project:mainfrom
LIHUA919:codex/issue7805-windows-scope-20261101

Conversation

@LIHUA919

@LIHUA919 LIHUA919 commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

Native Windows --write-worktree observation rejected existing in-scope entries because realpath() returns native separators while the containment test appended a literal slash. Use the existing Node path owner to compare the physical child's relative location, preserving rejection of the root, parent escapes and absolute cross-root relations.

Closes #7805. Target: loopx-project/loopx:main, based on 789694fa42972db17acd47aa2604b1907060028d.

Author Declaration

Criterion Disposition Evidence
Accept normal existing in-scope paths on supported platforms implemented Existing cross-platform producer fixture now creates and observes a real scoped directory/file
Reject redirected/outside checkout paths implemented Existing file-link, directory-link, unresolved, chained, administration and out-of-scope negatives retained
Preserve lease identity and canonical authority implemented Existing real File/SQLite CLI admission, replay, renewal and independent-worktree cases
Run the scoped observation on native Windows CI implemented Existing Windows job and its exact qualification manifest both include the workspace suite

Scope And Continuation

The TypeScript filesystem observation owner keeps its policy and path-free result. The local relative string was renamed to scopePath so the existing imported path operation can be used. No stored scopes, repository identities, lease comparison rules or authority-store semantics change.

Compared the maintained MIT-licensed is-path-inside design and Node path documentation. The fix reuses the relative-path boundary convention already present in this owner.

Bounded refactoring: remove the local name shadow and reuse native path relations within the existing observation loop. The Windows workflow retains its jobs, required gates and timeout budgets; it gains this suite.

Validation

Current head: 94253740d1fe82c4d04d9fe291674f3921bd0184.

Runtime/CLI validation below remains pinned to 54f4f258f8530abc2d0d516d0495fdda8c8fbd91; the follow-up changes only the existing CI qualification manifest.

  • Local Node Win32 path probe reproduces the original false rejection for a normal child. This is a path-API probe on macOS, not a native Windows run.
  • Five focused TypeScript suites: 48 passed, one existing PostgreSQL integration case skipped because no isolated server was configured. Full control-plane typecheck passed.
  • Real public CLI / canonical-provider journeys: 14 passed, covering File and SQLite admission/replay, independent worktrees, invalid redirections, repository mismatch and retained lease authority.
  • CI classifier's code/docs and required-gate tests: 14 passed. Focused Windows/workflow checks: four passed.
  • Standard premerge: four direct checks and all 16 selected checks passed (seven catalog canaries, eight risk smokes, one public-boundary scan), including real lease runtime and CLI output budget smokes.
  • Diff-scoped semantic advisory found no supported new vocabulary carriers; its published dynamic/unnamed-form limitations remain.
  • Public-boundary scan is clean. No graphical UI change.
  • Native Windows CI at the current head has now passed; the expanded scoped-worktree fixture is included in the successful host-qualified step. Installed Windows behavior, PostgreSQL qualification and full CI success remain separate.

Every commit is DCO signed. No private state, raw logs, credentials or generated artifacts are included.

CI manifest follow-up

The first hosted changes job failed its exact Windows-suite contract because the workflow addition was not yet included in scripts/ci/test_windows_lane_coverage.py. The same failure was reproduced locally (one failure in the two-case module). Commit 94253740d1fe82c4d04d9fe291674f3921bd0184 extends that existing manifest; its exact-list and fail-closed assertions remain intact.

All 21 CI preflight unit tests pass after the fix. Current-head standard premerge passes four direct checks, changed-Python compilation and all 19 selected checks (ten catalog canaries, eight risk smokes and the public-boundary scan). Ruff, bilingual diff and the focused public scan pass. Native Windows CI has since passed at this new head; full hosted CI remains held by a separate Dashboard check. The earlier manifest failure is retained as historical evidence.

Remote Windows qualification

At unchanged head 94253740d1fe82c4d04d9fe291674f3921bd0184, the native Windows job completed successfully, including the unconditionally executed host-qualified control-plane step containing task_lease_workspace.test.ts. This resolves the native Windows qualification hold for the scoped observation path.

The separate Dashboard shard failed the frozen loaded-lens switch budget: one measured switch was approximately 1,258 ms against the unchanged 1,000 ms ceiling. That failure and the failed aggregate remain open; this update does not establish its cause or pristine-base parity, and it does not claim full CI readiness or installed App acceptance.

Signed-off-by: Lihua <1017343802@qq.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

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

动机 / Motivation

受影响的是在 Windows 独立 Git 工作树内申请代码编辑租约的用户或 Agent。例如申请 docs/** 时,目录和普通文件都在已验证的工作树内,旧版仍因反斜杠与硬编码斜杠不匹配而拒绝;修复后同一任务可以取得租约并继续编辑。本次验证看到范围内申请成功、持久化回读和重放保留同一租约,同时越界链接与已知同目录冲突继续被拒绝。本 PR 不改变机器身份来源、租约权限、共享状态隔离、scope 语法或合并授权,也不交付已安装 Windows 产品的完整资格证明。

我先读取了 PR 的完整说明、现有讨论和关联 issue,再对照不可变基线 789694fa42972db17acd47aa2604b1907060028d 与当前 head 94253740d1fe82c4d04d9fe291674f3921bd0184。依据是 issue #7805,spec_revision 为 sha256:99a47b946bd3cb78c9073436ec466f4ba661e567257b021876dde70469ac8eac,读取时的 updated_at 为 2026-11-01T09:43:46Z。下面的 W7805-1、W7805-2、W7805-3 是便于逐项核对而给出的评审局部标签,原 issue 没有这些编号。

W7805-1 要求真实范围内的普通目录、文件可以通过观察;W7805-2 要求越界路径及不支持的重定向仍被拒绝;W7805-3 要求路径修复继续使用同一个无本地路径的工作树身份和租约规则。三项均有下述对应执行证据。本次交付解决的是这一个已复现的阻断,不以测试数量代替结果,也不把更上层长期协作验收写成已经完成。

改动思路 / Approach

保留在现有 TypeScript 文件系统观察 owner 中:这是所有已启用工作树租约都必须满足的正确性不变量,无需增加配置、状态或第二个判定服务。当前边界是修复独立工作树的路径归属判断,并把实际扫描普通文件和目录的既有测试纳入原生 Windows lane。

旧路径在 realpath(full) 后拼接 ${root}/ 做字符串前缀判断。Windows 的 realpath 返回反斜杠,所以即使正常子项也会被拒绝。新路径使用 Node 的 path.relative(root, physicalPath),再拒绝空关系、父目录、以父目录开头的关系和绝对关系。空关系不能作为普通子项通行,跨盘关系也不能借此变成合法子目录;名称本身以两个点开头的合法文件仍应允许。

该做法复用了同文件 requireInternalFileLink 已使用的相对路径边界表达。两处分别处理普通物理子项和直接文件链接,后者还有逐段检查、目标 scope、禁止目录链接等额外义务;把它们强行合成通用策略会扩大本次修改。局部变量从 relative 改为 scopePath,也消除了对导入函数的遮蔽。这个有界整理已经随修复完成,未发现值得增加框架或新配置的剩余重构。

触发 基线 当前 head
Windows 范围内目录与普通文件 错报 redirected path 申请成功并持久化
已知越界链接、同一物理 checkout 的冲突 拒绝 继续拒绝
未提供 write_worktree 的旧租约路径 既有规则 完整响应、回读和历史保持一致

这是源代码与下述执行结果的比较表,没有把模拟运行当成原生 Windows 截图或安装证据。

具体改动 / Changes

生产逻辑仅修改 observeLeaseWorktree 所属的 task_lease_workspace.ts:先按原有 scope matcher 选择实际目录项,再用相对路径确认其物理归属。目录仍递归扫描,ignored 文件仍检查;只有原有 ENOENT 并发删除分支被忽略,其他错误继续上抛。Git 管理目录、独立 worktree 根目录、origin codec 和 MachineGuid/inode 摘要的逻辑没有变化。

调用链已追到 executeTaskLeaseAcquire:仅当请求显式携带 write_worktree 时,它要求 canonical authority 和非空 scopes,调用观察器,将既有 LeaseWorkspace 交给 canonical acquire owner。失败走现有 typed envelope,申请被拒绝时实际 authority 与 journal 均保持不变;通过观察也不会绕过 Todo 所有权、仓库身份或同物理 checkout 的冲突检查。sameLeaseCheckout 和 leaseWorkspace 继续消费原先四个字段,没有新权限或新持久化格式。

既有 observed Git origins use the Todo repository identity contract 测试现在创建 docs/guide.md 并通过实际 docs/** scope matcher 扫描目录和文件,替换了原来永远返回 false 的 callback。原 Windows 分支此前没有经过出错位置,这是本次最有价值的回归覆盖。.github/workflows/python-tests.yml 把此套件加入原生 Windows 的现有命令,test_windows_lane_coverage.py 同步精确清单;未修改 runner、激活条件、非阻断选项或 Node 版本。四条路径全部读取,最终 diff 为 +16/-8,生产代码 +9/-6。

我独立执行的验证如下,均以当前 head 为准,作者提供的计数没有混入:

  • PASS:npm run typecheck:control-plane;6 个相关 TypeScript 套件共 520 tests,通过一次性的真实 PostgreSQL 服务运行,零 skip。包含工作树观察、native CLI、租约生命周期及 PostgreSQL authority-store integration;服务随后关闭,未访问活动 Goal 数据。
  • PASS:uv run --extra test python -m pytest -q tests/test_task_lease_worktree.py tests/control_plane/test_task_lease_cli.py tests/control_plane/test_task_lease_argument_recovery.py tests/test_cli_entrypoint.py,163 passed。
  • PASS:scripts/ci/test_windows_lane_coverage.py、scripts/ci/test_impact_plan.py、tests/test_python_ci_workflow.py,556 passed、33 subtests passed;检查了真实 YAML 中单一命令和精确清单的绑定。
  • PASS:同一实际 Git/worktree fixture、固定时钟,在基线和 head 经 native JSON CLI 运行 File、SQLite。macOS 每后端每版本各 9 次调用,比较完整 response、authority 和 history;仅归一化独立 runtime 路径及 provider revision 的随机部分,保留 generation、状态、诊断、ownership、scope、工作树摘要和完整 receipt。两后端全部一致,归一化摘要分别为 ac3a53a7e0b732e3c813e4cd2c61b0dc4f4c4411072a83572e6d98dcd3613cea 和 ff1a3e663cbfb71251b0d52b9b5861d56b6fa0dab2886413c49fca19aa2e7c9e。
  • PASS:同一 native JSON CLI、真实 File/SQLite store 以及真实 Git/文件系统,通过未改动的生产观察器源码投影到 Windows 命名空间;使用真实 path.win32,仅替换观察器的路径/平台 IO 适配与合成 MachineGuid。每后端基线 5 次、head 9 次,旧版正常 scoped acquire 确实返回 redirected path,head 则 applied;拒绝外部链接后修复,可以继续申请,重放不新增事务,同 checkout 的新申请被拒绝,独立 checkout 保留 integration advisory。对未覆盖邻项允许的窄 scope,在 scope 内新增文件后,head 重放仍保留原 receipt,基线暴露同一误拒绝。关闭 worktree 模式的完整响应及状态历史也在 Windows 投影中一致。
  • PASS:另外 17 个 Windows 路径关系用例分别在基线和 head 执行真实生产观察器,含大小写别名、空格与 Unicode、UNC、父目录、跨盘、跨共享、同名前缀目录和未来文件的重定向祖先。6 个预期误拒绝得到修复,其余 11 个保持预期结果。独立的“应允许范围内申请”oracle 又通过 native CLI 在旧版实际失败(exit 1),修复后的相同调用通过;并非只比较新 helper 的返回值。
  • PASS:loopx canary premerge --from-git-diff --git-diff-base 789694fa42972db17acd47aa2604b1907060028d,5 个 direct checks、19 个 selected checks;包括 RFC bilingual、changed Python compile、现有 canary 和 public boundary。另跑 Ruff、diff-scoped semantic advisory、DCO 与 4 路径公共边界扫描。两个提交均有 sign-off,advisory 没发现受支持的新词汇载体;这不等于动态语义不存在。

不可变 fixture 摘要为 3c5d8ff1f3c45c8701bf4efbde2d04af97d8dc2a2e1aeffe0f949d46be96782d。Mac CLI 和 Windows 命名空间 CLI 共 64 次调用另加一次预期失败的敏感性运行;上面的 17 例是独立的观察器边界探针。初次本地验证中存在错误测试路径、测试 harness 缺少 VM flag/source receipt 及模拟绑定错误;这些运行没有覆盖对应义务,保留为失败记录,修正的是评审脚本。最终执行使用正确入口和同一 fixture/oracle,没有改变产品代码或放宽断言。

对主干的风险 / Risks

最需要防止的是修复 Windows 误拒绝时把真正的越界误判为内部目录。新判断同时拒绝父路径、根自身及跨盘绝对结果;基线/head 的路径探针覆盖这些相反方向。真实文件系统测试另覆盖 ignored 外链、未创建叶项的祖先重定向、链接目标的 scope 和回退后重试。现有链接检查独立保留,因此通过正常子项不会降低链接约束。同一 checkout 的冲突、不同 checkout 的 advisory、repository mismatch 与 retained receipt 也由真实 provider 测试覆盖。

这不是新增的 default-off 功能。worktree 模式依旧由显式参数启用,纯 legacy acquire 没有调用观察器;测试证明该入口在两个 provider 上的完整可观察语义相同。对于已启用模式,路径归属检查是强制安全条件,不是“建议”。PR 说明已披露旧、新默认行为的差异,错误文本继续是通用工作树诊断,没有按 PR 标题或 prose 子串推导权限。已有 CLI 足以完成原任务,用户无需增加配置、复制已知信息或额外确认;非法链接修复后可直接重试。

这里没有原生 Windows OS 实跑,因此没有证明 Windows ACL、junction/设备路径、原生注册表访问或平台安装的全部组合。Windows 命名空间执行和 macOS 真文件系统分别给出有用但不同的证据,不能互换。PR 已补进现有原生 Windows lane;平台发布资格仍由该 lane 及维护者处理。我遵守当前 wait_for_ci=false,没有获取、轮询或等待 CI。作者提供的较早 CI 清单失败和后续待确认信息保留为 diagnostic、required=false、原因 unresolved;上述独立本地验证只证明当前代码与清单,不追认早先远端失败的原因。公共扫描的唯一提示来自空的临时 runtime 尚未创建,不是源码泄漏。

我的整体评价 / Verdict

APPROVE,未发现需要阻断此 head 的具体缺陷。修复将 Windows 的正常代码编辑任务从误拒绝带到可取得、回读、重放的租约,并保留 scoped refusal 与所有权边界;这比仅添加一个序列化字段或静态测试有实际使用价值。代价限制在现有 owner 的路径判断与相应测试,没有新服务、新状态或迁移负担。复用现有 scope/identity/lease owner 的判断符合仓库边界,本次有界重构已完成,扩大为通用路径抽象没有证据收益。

未改变渲染界面;检查的是 task-lease acquire 的 CLI、TypeScript 观察器和已有 File/SQLite 后端,结果通过现有命令直接回读。原生 Windows 操作系统实跑及已安装 App 未验证;Windows 命名空间执行保留了模拟边界。长期执行方面,本次仅证明合法工作能继续、拒绝后可修复重试、重放不重复写入;未测长程 soak、安装采用或长期成本收益,也不据此宣布上层目标完成。关联经验中“使用既有 owner、让真实消费路径完成有用工作”的指导已用到上述 acquire/持久化/重放对照,经验本身不作为运行通过的证据。

本结论只覆盖 94253740d1fe82c4d04d9fe291674f3921bd0184。APPROVE 与后续 merge readiness、原生平台资格和维护者合并授权分别判断;没有执行合并或 bypass。

English verdict: APPROVE — head 9425374; the Windows scoped-path false rejection is fixed while containment, lease identity, refusal and replay behavior remain covered. Local checks and real-provider tests passed; native Windows OS execution and installed-product qualification remain unverified. No merge performed.

@huangruiteng
huangruiteng merged commit 2ee0d48 into loopx-project:main Nov 1, 2026
31 of 39 checks passed
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.

[Bug]: native Windows --write-worktree scoped observation rejects every in-scope path

3 participants