Skip to content

fix(runtime): enforce private IO and preserve Windows long paths - #7603

Open
xyx2002OvO wants to merge 5 commits into
mainfrom
codex/pr5677-private-io
Open

xyx2002OvO wants to merge 5 commits into
mainfrom
codex/pr5677-private-io

Conversation

@xyx2002OvO

@xyx2002OvO xyx2002OvO commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Goal And Delivered Outcome

Private local snapshot/session/validation writes need native Windows access controls, and ordinary long paths must retain complete atomic publication and migration guards. This proposal reuses a platform IO helper to enforce protected owner/admin DACLs before dispatch/publication, verifies returned private snapshots, and uses extended Win32 paths without rewriting stored path text.

This remains an independently reviewable prerequisite split from #5677. #5677 should integrate this boundary after it lands; freshness/recovery policy is not moved into this PR.

Author Declaration

Criterion Disposition Owner / evidence
Restrict private producer and consumer IO; reject broad ACLs and digest mismatch implemented runtime/private_permissions.py, Effect snapshot adapters, native Windows DACL tests
Preserve complete bytes, interrupted replacement and bounded access-denial failure implemented Existing document_io.py / file_lock.py owners and native long-path/atomic-write tests
Preserve migration route text and redirection fences implemented Existing migration owner; path-text and native junction coverage retained
Exercise the Effect snapshot contract under the same native Windows ACL rule as production implemented effect_runtime_snapshot.test.ts now selects the checkout Python and protects both the fixture directory and file before reads/writes

Scope And Continuation

Complete implementation for this IO prerequisite. #5677 keeps necessary protection until this proposal is landed and integrated. No public scan allowance policy, result/direction decisions or new capability is included. The helper owns platform permissions only; existing callers keep namespace, locks and authority decisions.

The proposal is ready for renewed review and hosted CI qualification. It is not authorized for merge by this update.

Validation

  • Tested revision: afe5a05f21401490401481455fdee25444d8bccb.
  • Run state: finished locally; new hosted CI is pending after the head update.
  • Input classes: synthetic.
Check kind Result Evidence / limitation
Windows curated runtime suite passed Qualified Node 22.22.3: 285 total, 257 passed, 28 expected skips, 0 failed. This includes both Effect snapshot tests.
Native Python IO suite passed DACL/snapshot, document IO, Todo validation, file-lock atomicity, migration path text and atomic writes: 75 passed, 1 platform skip.
Python runtime bridge passed 3 passed, 2 expected skips.
Browser regression scenario passed Packaged execution-service-offline scenario completed successfully.
Static/build passed Ruff on changed Python; mypy with CI Linux platform on 17 configured sources; TypeScript control-plane typecheck; chat bundle build; git diff --check; DCO; semantic advisory found 0 supported new vocabulary carriers.
CLI base/head comparison passed 96 base cases, 96 candidate cases, 0 candidate-only failures, 0 review-required deltas.
Standard premerge aggregate partial / held Direct checks, compile checks, 8/8 risk-profile smokes and 7/9 catalog smokes passed. The full CLI budget smoke reproduces the same Windows long-path fixture failure on latest main; the following Todo user-gate smoke passes independently and is only failing in that aggregate sequence. These are preserved as non-green evidence rather than relabelled as passes.

Prior Hosted CI Failure Attribution

The three failed jobs on the previous head did not reach or fail the reviewed Windows snapshot fixture:

  • windows-powershell and kernel-contracts stopped on the same CLI output ceiling (25975 / 25828 versus 25500). Latest main contains the calibrated ceiling from test(heartbeat): calibrate complete thin JSON scope budget #7614; the branch now includes it.
  • chat-bundle-browser (1) timed out in the original-conversation-unavailable scenario. Latest main contains the separate packaged execution-service-offline repair from Show original conversation read failures without setup detours #7608, and that scenario passes locally and in the hosted full packaged smoke. The narrower delegation-search smoke still times out on the same alert and remains an explicit hold below.

Fresh CI on this exact head is the authoritative hosted result.

Current Hosted CI Readback

The exact head proves the proposal's affected boundaries: windows-powershell, all three typescript-core shards, kernel-contracts, kernel-static-checks, PostgreSQL real-server integration, Node minimum compatibility, DCO, dependency review and the stage2c correctness/integration jobs pass. In particular, the native Windows job completed the host-hardened control-plane suite that includes the corrected standalone Effect snapshot tests.

The overall PR checks are still non-green for failures outside this proposal's changed product surface:

  • Optional Ark and MemT Python 3.11 both fail the same test_turn_plan_missing_todo_does_not_bypass_contract_errors[False] assertion; the two 3.13 matrix jobs are then cancelled. The exact two-case probe is 1 failed, 1 passed on both this head and immutable origin/main@544aa0fee; fix(runtime): enforce private IO and preserve Windows long paths #7603 does not change turn_driver/driver.py.
  • chat-bundle-browser (1) still times out waiting for the delegation-search original-steward-unavailable alert.
  • chat-bundle-browser (2) and the release build fail the same synthetic team-evidence text wait. The exact smoke also reproduces locally; this PR has no frontend diff.
  • dashboard-browser (2) records four lens switches below 1 second and one at about 1.16 seconds, tripping the frozen 1-second browser budget; this PR has no frontend diff.
  • The aggregate checks failure is a consequence of those browser jobs, not a separate failure.

These failures are preserved as CI holds and are not relabelled as passing evidence for this PR. They should be repaired on their owning main surfaces rather than folded into this private-IO prerequisite.

At the latest readback, six generic pytest shards are still PENDING without a runner result. They remain unqualified; the PR stays open, blocked and unmerged.

Signed-off-by: Tartar <xiaoyx67@mail2.sysu.edu.cn>
Signed-off-by: Tartar <xiaoyx67@mail2.sysu.edu.cn>

@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

当前完整 head 5658750bfa4686619273e6e2b15e0779adda0dbe:REQUEST_CHANGES。平台前置拆分合理,但现有必需 Windows 快照测试尚未适配新的安全前置。

动机 / Motivation

在 Windows 或 POSIX 上运行 Agent、需要安全保存本地快照和原会话的操作者。

大型本地快照、会话和验证声明需要在写入敏感内容前限制访问;Windows 的 chmod 不能代替原生访问控制,普通长路径也会令临时文件或替换失败。

本提案集中实现平台权限和长路径 IO,POSIX 回归通过;旧 TypeScript 快照测试未适配新增的 Windows ACL 前置,当前完整交付仍需修复和真实平台复验。

本次只评审可独立落地的平台 IO 前置,不认证整个 freshness 提案、正式安装、模型采用或研究收益。

改动思路 / Approach

权限事实应由平台 IO helper 提供,命名空间、锁和业务判断继续归现有调用者;文档原子写和迁移 owner 可以复用,无需第二套控制面。

保留独立平台前置,修复现有 Windows-curated TS 测试的 helper/原生 ACL 准备并执行完整必需验证;不得绕过权限拒绝或以跳过测试代替。

生产路径仍是 Python 创建私有目录/文件,TypeScript 在消费前检查,原业务 owner 再处理请求和结果。保护失败必须保留错误;不能将缺 helper、宽 ACL 或未知响应解释成正常完成。没有理由要求此 PR 先实现整个 controller 或 freshness 方案。

具体改动 / Changes

完整17文件 +855/-62:生产9文件 +318/-39,测试/夹具8文件 +537/-23;无文档、生成文件或机械搬迁。基线 898363635d4737f84b6a673a9a11265a121b6f57,当前主干参照 51c1dc447858c351691711de21a638b6c71c118e。

关键代码讲解

  • protect_private_path / require_private_path 集中 POSIX mode 和 Windows protected DACL。写前保护;读时拒绝重定向、宽权限和改变后的句柄身份,不把权限读取提升为任务许可。
  • privateFile 增加固定 Python helper 和 dev/ino 对照。正常 Python daemon 会设置 helper;直接运行的原 TS 测试没有这项准备,形成下述 P2。
  • atomic_write_state_text 复用完整UTF-8、原子创建/替换与目录持久化;私有文件在写敏感内容前保护。validation和session保留原身份与旧文件失败恢复。
  • _digest / _copy 使用 extended 原生地址,保留存储路径文本、重定向和来源重查;file_lock.py 仅对 Windows access-denial 做有界 holder 重试。

规范依据:spec_ref https://github.com/loopx-project/loopx/pull/5677#pullrequestreview-5685607407,spec_revision 9394b2395f10c4537f6af995d821c3e2c2193e6a。该维护者评审的 CR2 要求平台修复按自己 owner 独立交付并验证,当前为 not_met:边界已拆出,但下述既有 Windows caller 仍未迁移。它没有要求删除必要保护或等待整个父提案。

对主干的风险 / Risks

P2:现有 Windows-curated 快照测试不满足新 ACL 前置

仓库 .github/workflows/python-tests.yml 的原生 Windows curated 命令包含 tests/control_plane_ts/effect_runtime_snapshot.test.ts。该文件两项测试直接建立普通临时目录/文件,再调用快照 API;没有设置 LOOPX_EFFECT_RUNTIME_PYTHON_BIN 或建立原生 ACL。新变量只在 Python daemon 的子进程环境及新 Python 测试里设置,不会配置独立启动的 node:test。

独立控制流探针使用真实 Node、原样旧 TS 模块,只选择 win32 分支并保留同一原生临时目录、移除 helper 变量。不可变 base 2 passed,当前 head 2 failed;直接公开 reader 从接受变为 private snapshot ACL helper unavailable。探针没有执行 Windows APIs,也不宣称已在 Windows 跑出该结果。 它定位了确定性的缺前置分支;原生 ACL/长路径/共享行为还需实际平台复验。

最小修复是更新原 TS fixture:使用固定受信 Python和真实受保护ACL,再跑原Windows curated命令及宽ACL/错误digest负例。不能放宽缺helper拒绝、去掉断言或把该suite跳过来变绿。Mac绿测或只跑新增Python用例不能覆盖此caller。

非阻断简化建议

replace_retry_seconds 只在通用 writer 定义和转发,完整生产搜索没有调用者;holder另写了固定重试循环。可删除该闲置参数,或让真实holder复用同一有界IO owner。该建议不要求新框架、不扩大本次修复,也不是当前请求修改的依据。

验证与语义边界

  • PASS:159 Python passed/31 Windows skips;原 POSIX 文档、迁移/回滚、验证和锁路径通过,原 TS 快照模块 2 passed。
  • PASS:Ruff、配置内17文件 mypy、完整 control-plane TypeScript typecheck、diff、DCO、双语差分和明确路径公共边界扫描均通过。 diff-scoped semantic advisory没有发现支持范围内的新词表;随后标准full semantic检查通过,不把空扫描当语义证明。
  • FAIL:上述匹配分支对照及当前strict CQR;标准 premerge 四项direct及compile、catalog八项和risk八项通过;另一个catalog输出预算检查25836>25500失败,同命令在不可变base同因失败。严格 CQR 因当前失败与必需Windows未验保持FAIL,整体gate未通过。
  • UNVERIFIED:本机为 macOS,31 项 Windows 专用 Python 用例跳过;分支探针未执行 Windows 内核。作者的原生结果和九项 symlink 夹具失败按声明保留,未转为独立通过。

语义与 CI 对齐

这是现有 Windows IO 路径的默认安全变化,非 opt-in;POSIX、原业务状态、结果和权限 owner 保留。ACL拒绝是强制检查而非建议;OS事实、路径和digest不应成为第二份Task/Stop/lease权威。未新增共享任务词表。未抓取、轮询或等待CI;这里依据仓库本地原命令和实际探针判断。

我的整体评价 / Verdict

权限事实应由平台 IO helper 提供,命名空间、锁和业务判断继续归现有调用者;文档原子写和迁移 owner 可以复用,无需第二套控制面。

保留独立平台前置,修复现有 Windows-curated TS 测试的 helper/原生 ACL 准备并执行完整必需验证;不得绕过权限拒绝或以跳过测试代替。

long_horizon:not_yet_proven;user_experience:not_yet_proven,局部 POSIX 通过不能认证缺失的原生平台资格。已检查完整 diff 和内部 IO/CLI 消费者;没有页面、布局、文案或样式变化,视觉改动评审不适用。 未验证范围:本机为 macOS,31 项 Windows 专用 Python 用例跳过;分支探针未执行 Windows 内核。作者的原生结果和九项 symlink 夹具失败按声明保留,未转为独立通过。

修复旧平台fixture并取得当前完整Windows必需suite、实际权限/路径负例的证据后复审。保留作者失败记录,不把新版本或原测试数量当作已安装采用/长程收益。本次没有修改源码、合并或安装。

English verdict: REQUEST_CHANGES — keep the platform IO protection, adapt the existing Windows-curated snapshot fixtures to the new ACL/helper prerequisites, and qualify the native path. The matched branch probe confirms a caller compatibility gap; it is not native Windows execution.

if (entry.isSymbolicLink()) throw new Error("private snapshot is a symlink");
if (process.platform === "win32") {
const python = process.env.LOOPX_EFFECT_RUNTIME_PYTHON_BIN;
if (!python || !isAbsolute(python)) throw new Error("private snapshot ACL helper unavailable");

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.

[P2] 迁移现有 Windows-curated 快照测试的安全前置。原 effect_runtime_snapshot.test.ts 两项测试直接创建普通文件并调用 API,没有设置此 helper 或建立原生受保护 ACL;该 suite 仍被 python-tests.yml 的 Windows curated 命令直接执行。仅 Python daemon 的子进程环境设置新变量,不会准备独立 node:test。相同真实 Node 分支探针(非 Windows 内核)在不可变 base 2 pass/head 2 fail,公开 reader 报 helper unavailable。请保留此安全拒绝,更新旧 TS fixture 的固定 helper/真实 DACL,并跑原 Windows 命令及宽 ACL/digest 负例;不要以删断言或 skip 恢复通过。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已在 afe5a05f21401490401481455fdee25444d8bccb 按这个 finding 修复,保留生产侧严格拒绝:

  • effect_runtime_snapshot.test.ts 在 Windows 显式选择 checkout Python,并设置 LOOPX_EFFECT_RUNTIME_PYTHON_BIN;
  • 两个旧 fixture 都先对目录和文件调用生产同源的 protect_private_path,再进入公开 reader/writer;没有删除断言或增加 skip;
  • 用 CI 对齐的 Node 22.22.3 跑完整 Windows curated 命令:285 total / 257 passed / 28 expected skipped / 0 failed,两个 Effect snapshot case 均通过;
  • 同批 native Python suite 的宽 ACL、digest、atomic write、migration/path-text 负例:75 passed / 1 platform skip。

新一轮 hosted CI 已由该 head 触发,PR 描述也记录了旧 CI 三个失败的归因和本地门禁限制,请复审这个 exact head。

Signed-off-by: Tartar <xiaoyx67@mail2.sysu.edu.cn>
Signed-off-by: Tartar <xiaoyx67@mail2.sysu.edu.cn>
@xyx2002OvO

xyx2002OvO commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor Author

CI/CD follow-up — 2026-10-29

No merge is requested. #7603 remains open at afe5a05f21401490401481455fdee25444d8bccb; the findings below separate this PR's private-I/O change from failures already present on its base.

  1. Ark/MemT turn-driver regression — fixed in fix(turn): preserve missing-lineage contract errors #7618. Commit 3ebad9d021 made a normal READY_FOR_HOST envelope with neither a selected Todo nor a signed scoped request identity become BLOCKED before _session_plan could return the typed missing_turn_lineage contract error. fix(turn): preserve missing-lineage contract errors #7618 preserves that contract-error path while retaining replan and invalid request/session holds. On exact head ab0e378e74f9c5cdc3d09ac7b380f703f2421bd0, hosted Ark 3.11, Ark 3.13, MemT 3.11 and MemT 3.13 all pass.

  2. Delegation-search browser smoke — fixed and merged in test(dashboard): let the delegation smoke read the real steward source #7599. The smoke kept a permanent Playwright route for the steward endpoint, so its later source-unavailable case never reached the real source. test(dashboard): let the delegation smoke read the real steward source #7599 removes that route before the real-source assertion and is now on main.

  3. Team-evidence browser and release-artifact failures — fixed independently in test(chat): restore evidence subject before linked recovery #7620. The smoke retained a request-validation fixture with todo_id=null before switching to the real Todo fixture, so the component correctly rejected the evidence revision and the assertion at team-evidence-return-smoke.mjs:133 timed out. This same assertion caused both chat-bundle-browser (2) and the Release Artifacts / build failure. test(chat): restore evidence subject before linked recovery #7620 extracts only that one-file fix from conflicting test: preserve recovery fixtures and pin CLI comparison ancestry #7604 onto current main; on exact head f869d7b500f82a26e5a6b1341abd140c681d8a07, hosted chat-bundle-browser (2) and Release Artifacts / build both pass.

  4. Dashboard M2 performance failure — runner outlier not reproduced, budget unchanged. One fix(runtime): enforce private IO and preserve Windows long paths #7603 browser shard measured switch times [912, 486, 759, 1160, 806] ms and exceeded the frozen 1000 ms bound once. The same fix(runtime): enforce private IO and preserve Windows long paths #7603 release-artifact packaged run measured [208.8, 209.7, 258.3, 178.7, 154.3] ms, and an independent local packaged run measured [152.76, 142.96, 188.35, 106.49, 117.25] ms. A fresh hosted dashboard-browser (2) now passes with the 1000 ms budget unchanged.

  5. Six Python shards — shared global queue, not a test result. They remain PENDING behind the repository's per-shard concurrency groups. This is queue contention, so it is neither a pass nor a code failure.

Current next boundary: let #7618 and #7620 complete normal review, then land the independent baseline fixes through the repository's merge process, rebase #7603 onto the resulting latest main, and run its full matrix. #7603 is still BEHIND with CHANGES_REQUESTED; it should not be merged in its current state.

@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

完整 head afe5a05f21401490401481455fdee25444d8bccb:REQUEST_CHANGES,目前阻断是原生 Windows 的独立资格证据缺口。前次指出的 TS fixture/helper 准备遗漏已在源码上修复;本轮没有复现新的 Windows 产品缺陷,也不把作者报告的通过结果写成独立执行。

动机 / Motivation

需要在 Windows 安全保存快照、验证声明和原会话,并在长路径或写入失败后继续工作的操作者。

一次大快照需要先限制本地访问,再交给执行程序;旧 Windows 路径只有 chmod,不能证明原生访问控制。提案把平台保护接入既有写入和读取入口,同时维持原子替换与原会话身份。

当前源码已补齐旧 TS 快照 fixture 的 Python helper 与保护准备,本轮 POSIX 对照和真实 runtime 路径通过;Windows 内核行为仍只有作者结果声明,独立资格尚未读回。

本次只评审可独立落地的平台 IO 前置,不认证整个 freshness 提案、安装、模型采用或长程收益。

改动思路 / Approach

权限事实保留在平台 IO helper,业务身份、锁、恢复和结算仍归既有 owner;不应为缩小 diff 删除保护,也无需新增控制面。

保留这一完整平台前置,旧 fixture 修复已确认;最小剩余工作是取得当前 head 的原生 Windows 独立执行或可核验读回,保留 ACL 拒绝与全部原断言。

生产链仍是 Python 创建并保护私有目录/文件,TS 验证后消费,原业务 owner 处理结果。权限保护失败要保持拒绝,提交后的响应读回不确定继续归原恢复边界;helper 不能把文件路径或 ACL 变成任务准入事实。Windows 上每次快照的固定 helper 调用有成本,但它是独立平台 IO;本轮没有测量其长程成本,更没有要求把它改成新控制面。

具体改动 / Changes

基线 544aa0fee5dad33e3b70496dadfb3ffd36400e13;完整18文件 +891/-68,生产9文件 +318/-39,测试/夹具9文件 +573/-29。最新已抓取 main ce4c78088ea464cb31231513882bed6bb6933156 相对该基线未更改这18条路径;仍需按最终集成版本复核。

规范依据:spec_ref https://github.com/loopx-project/loopx/pull/5677#pullrequestreview-5685607407;spec_revision 9394b2395f10c4537f6af995d821c3e2c2193e6a。变更前维护者 CR2 要求平台前置按自己的 owner 独立交付并验收。owner 拆分与必要保护符合该边界;原生资格当前为 not_met,缺的是下面的独立观察,不是要求整个 freshness 或 controller 方案先完成。

关键代码讲解

  • protect_private_path / require_private_path 集中 POSIX mode、protected DACL 和已打开句柄身份;保持私有内容写入前保护、拒绝 reparse 和未知权限。
  • privateFile 使用固定的 package Python helper,并对照 dev/ino。当前 旧 TS fixture 已选择 checkout Python、设置 helper 变量,并在两个原测试中先保护目录和文件,未删断言或新增 skip。
  • atomic_write_state_text 复用同目录完整写入、fsync、create-only/link 或 replace;validation 和 session 保留原摘要、原身份及失败时旧文件。
  • _digest / _copy 将 extended path 限定在 IO 地址,持久路由文本与回滚仍由原迁移 owner 管理;project_prompt.py 保持 portable 相对路径。
  • _write_holder_sidecar 对 Windows access-denial 做有界替换重试,保留旧完整内容,其他错误直接抛出。replace_retry_seconds 的定义/转发仍没有实际调用者,可后续删除闲置参数或复用同一有界替换 owner;这是非阻断简化建议。

对主干的风险 / Risks

P2 · 必需原生路径尚无独立执行读回

本轮宿主为 macOS,31 个 Windows 专用 Python 用例跳过;没有独立 Windows DACL、长路径、共享句柄或完整 curated suite 的执行读回,作者声明未转记为本轮通过。

作者在当前评论报告 Node 22.22.3 下 curated TS 257 passed/28 expected skipped,原生 Python 75 passed/1 skip。本轮读了这些声明和修复源码,但没有可独立核验的 Windows 执行产物;这不是“CI 未绿所以不审”,也不声称这些测试失败。macOS 的通过和 process.platform 分支模拟不能证明 Windows 内核的 DACL、长路径或 delete sharing。

最小补齐:在原生 Windows 对当前 head 执行原 curated TS 命令及 DACL、digest、长路径、共享拒绝和迁移回滚负例,提供绑定 head、OS、Python/Node、命令与完整结果的可核验记录;无需绕过安全拒绝或为本条强改生产源码。 该补齐可由原平台验证 owner 提供,不制造新的用户审批、付费模型或整个项目 gate。

本轮独立证据

观察 结果与范围
当前完整相关 Python 模块 PASS:173 passed,另31个 Windows 用例跳过;跳过部分单列为 UNVERIFIED。
不可变 base 公共模块 PASS:163 passed/5 platform skips;两边测试集合不同,不据数量差断言等价。
TS snapshot 公开 reader/writer PASS:当前模块2 passed,真实2.2MB文件、digest和不安全引用负例;本机为POSIX。
匹配文件 IO 对照 PASS:同一合成输入在两版本均保留完整字节、create-only拒绝、替换失败旧文件、tamper拒绝和会话身份;私有父目录明确从0755变为0700。独立 owner-only oracle 在base失败/head通过,未抹去这个有意差异。
原生本地 runtime 边界 PASS:同三项 restart/typed-write、timeout不重发、digest拒绝在base与head各3 passed;使用可丢弃状态。
标准门禁与静态 PASS:6项direct/compile、9项catalog、8项risk;Ruff、配置内17文件mypy、TS typecheck、DCO/diff、18文件公共扫描。当前quota预算smoke通过。
strict CQR / Windows FAIL / UNVERIFIED:精确CQR cqr_2063991fbed9b029b6f5 保留必需Windows未验,不因其余检查通过而放宽。

前轮旧 head/base 的 quota预算失败与旧fixture问题保留历史;当前head的预算检查已通过,不能继续称为当前回归。首次公共扫描因隐式runtime路由冲突拒绝,改用显式registry/runtime后18文件零命中;没有修改实际路由状态。未抓取、轮询或等待CI。

语义与 CI 对齐

这是现有私有IO的默认安全变化,没有product opt-in/default-off承诺。普通POSIX路径的对照保持完整字节和失败语义;新增私有父目录保护被明确披露。未新增共享任务词表;diff advisory没有发现支持范围内的新carrier,不把空扫描当完整语义证明。ACL、digest和身份拒绝为机器检查;公共协议没有夸大Actor生命周期或授予新权限。

我的整体评价 / Verdict

平台前置的范围和owner选择合理,原fixture遗漏已解决;当前整体资格为 not_yet_proven,不继承上轮的批准轨迹,也不要求删掉必要安全代码。

long_horizon:not_yet_proven;user_experience:not_yet_proven,两者限定为受影响原生平台的安全保存与恢复尚无独立读回,POSIX没有观察到额外交互轮次。已检查完整 diff 及内部 IO/CLI 消费者;没有页面、布局、文案或样式变化,视觉评审不适用。 未验证范围:本轮宿主为 macOS,31 个 Windows 专用 Python 用例跳过;没有独立 Windows DACL、长路径、共享句柄或完整 curated suite 的执行读回,作者声明未转记为本轮通过。

保留这一完整平台前置,旧 fixture 修复已确认;最小剩余工作是取得当前 head 的原生 Windows 独立执行或可核验读回,保留 ACL 拒绝与全部原断言。 架构保留,闲置参数清理可安全后续进行;原生验证缺口继续保持,不以安装、PR数量、作者计数或结构检查代替实际结果。本轮没有修改源码、合并或安装。

English verdict: REQUEST_CHANGES — afe5a05. The prior fixture omission is source-resolved and local POSIX, matched IO, runtime and premerge checks pass. Native Windows qualification is still independently unverified; this is an evidence hold, not a claim of a newly reproduced Windows defect.

@JasonBuildAI JasonBuildAI left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

English verdict: COMMENT. Independent native-Windows execution of afe5a05f is recorded below; the two pwsh-hardcoding findings stand; the PR is still held by its own required check (merge-gate) and behind base, and the Windows-only suites remain outside hosted CI.

Native Windows 独立执行:afe5a05f21401490401481455fdee25444d8bccb。结论:COMMENT(不是批准)。

前两轮都由同一账号给出,本轮补的是它们明确留给别人的那类证据——在真 Windows 上独立跑,而不是把作者自报的通过结果再写一遍。

本评论 2026-10-30 两次修订(首版发布后更正):第一次修正 CI 计数、test_windows_snapshot_privacy.py 用例数(13→10)与 base 对照口径;第二次修正 CI 因果链(merge-gate 先在 checks 退出,checks 先在 dashboard-acceptance 退出)、helper 的覆盖数(4 条,junction 另计)与 pytest job 措辞,并补上 todo 用例的复现命令。结论方向未变。

执行环境

Windows 11 Pro (build 26100)、Python 3.14.3、独立 worktree 检出该 head(主工作区未改动)。

两条本机限制决定证据边界:未安装 PowerShell 7(pwsh);当前账户没有 SeCreateSymbolicLinkPrivilege(未开开发者模式)。没有安装 pwsh 是有意的——那是系统级改动,不在本轮授权内,所以依赖它的断言保持 UNVERIFIED,不拿 powershell.exe 顶替后再声称通过。

命令与结果

在 worktree 根目录执行:

python -m pytest -q -rs -p no:cacheprovider \
  tests/control_plane/test_windows_snapshot_privacy.py \
  tests/test_file_lock_windows_atomic.py \
  tests/test_windows_atomic_writes.py \
  tests/control_plane/test_document_io.py \
  tests/test_local_state_migration.py \
  tests/test_local_state_migration_path_text.py

→ 14 failed / 117 passed / 1 skipped,分布:

  • test_windows_snapshot_privacy.py:10 passed / 4 failed(该文件共 14 个 case)
  • test_file_lock_windows_atomic.py:7 passed
  • test_local_state_migration*.py:9 failed(全部 WinError 1314,见下)
  • test_windows_atomic_writes.py:1 failed([native-isolation],WinError 32)
  • test_document_io.py:1 skipped(POSIX directory fsync boundary,预期)

另单独执行了本 PR 改过、但不在上面 6 个文件里的 ACL 用例:

python -m pytest -q tests/control_plane/test_todo_completion_validation.py -k private_validation_store

→ 1 failed(FileNotFoundError [WinError 2],同一 pwsh 原因)。

通过的部分正是这条 PR 的核心不变量,且是在真内核/真 ACL 上验的:

  • 宽 ACL 在 effect 之前被拒(test_typed_rejects_broad_acl_before_effect 四个参数全过);
  • 缺/无效 OS 事实 helper 被拒(test_typed_missing_os_fact_helper_rejects);
  • post-dispatch ACL 失败按 ambiguous 处理、不重试(test_python_postdispatch_acl_failure_is_ambiguous);
  • 发布失败保留旧快照(test_session_publication_failure_keeps_prior_session protect/replace 两条);
  • 真实 read handle(share=0x3,无 DELETE)下的 holder 原子替换、持久 reader 保留旧字节并传播拒绝、无重试或回退(test_file_lock_windows_atomic.py 7/7)。

失败归因

pwsh 硬依赖影响 5 条用例,但不是一处修复就能全解:

  • 走 assert_private_acl 的 4 条:test_actual_producer_protects_before_socket_dispatch、test_large_protected_bytes_and_digest、test_session_writer_protects_and_keeps_original_identity,以及 tests/control_plane/test_todo_completion_validation.py:908-909 的 test_private_validation_store_is_owner_only_and_detects_tampering;
  • 直接调 pwsh 的 1 条:test_python_rejects_junction_parent(见第二条行内评论),修 helper 不会覆盖它。

首版说「修复 helper 可一次覆盖」是错的,已改。

其余失败均非本 PR 引入(同一套测试在 base 544aa0fee5da 上对照;base 只有其中 4 个文件、没有两个新文件):

  • test_local_state_migration.py 的 9 个 symlink/junction 用例在 base 与 head 上同样以 WinError 1314 失败,属本机无符号链接权限;
  • test_windows_atomic_writes.py::test_atomic_writers_skip_unsupported_windows_directory_fsync[native-isolation] 在 base 与 head 上同样以 WinError 32 失败,出错点是 loopx/capabilities/benchmark_toolkit/native_codex_isolation.py::_atomic_write_text(os.fchmod 失败后临时文件仍被占用,unlink 抛 PermissionError)——不在本 PR 改动面内,建议另行跟进;
  • 正向差异:base 上另有 5 个 migration 用例失败(test_doctor_reads_legacy_capture_hosts_from_selected_runtime、test_existing_project_prompt_keeps_registered_goal_and_runtime_routes、test_strict_project_registry_keeps_legacy_route_and_wire_format、test_preview_execute_and_verified_rollback_cover_all_registered_projects、test_custom_state_keeps_its_declared_file_through_migration_and_rollback),在该 head 上通过。

CI 读回(含因果链更正)

该 head 上共 46 个 check run:23 success / 9 failure / 8 cancelled / 6 skipped。ruleset(#18121976)里真正 required 的只有 Sign-off(pass)与 merge-gate(fail),下面不再用「必需检查」指代其余作业。

  • failure:merge-gate、pytest、checks、chat-bundle-browser (1)、chat-bundle-browser (2)、dashboard-browser (2)、build、adapter-contract (3.11) ×2;
  • cancelled:test-shard (1)–(6)、adapter-contract (3.13) ×2。

失败链是按 verifier 的先后退出顺序连起来的,不是由 shard 超时引起:

  1. dashboard-browser (2) failure;
  2. dashboard-acceptance 被 skip(workflow 里 needs: [changes, dashboard-browser],条件是 needs.dashboard-browser.result == 'success');
  3. checks 在 verifier 处退出:ValueError: dashboard-acceptance must be success;
  4. merge-gate 在 ValueError: checks must be success 退出;
  5. pytest 是门槛与 coverage 汇总作业、本身不执行测试;它的第一个断言是 test "$CHECKS_RESULT" = success,环境里 CHECKS_RESULT: failure、SHARDS_RESULT: cancelled,所以它也停在 checks 上,还没轮到 shard 断言,checkout/coverage 步骤全部 skipped。

另一条并行链:6 个 test-shard 各执行约 60.2–60.3 分钟后在 job 上限被取消(07:24–08:57Z),结果只会体现为 SHARDS_RESULT=cancelled。它值得单独归因(并发排队约 4.5 小时 + 单 job 60 分钟上限,还是本 PR 拖慢),但不是当前 merge-gate 红的直接原因;首版把两条链合在一起写,已改。

仍未解决的边界

  1. test_actual_producer_protects_before_socket_dispatch、test_large_protected_bytes_and_digest、test_session_writer_protects_and_keeps_original_identity 三条断言(分发前已保护、大快照 ACL+digest、session writer 保持原身份)依赖 pwsh,本机未执行 → UNVERIFIED;test_python_rejects_junction_parent 同样未执行。不要把这条评论读成对它们的确认。
  2. 仓库 CI 不覆盖这些文件:windows-powershell 的固定清单里没有 test_windows_snapshot_privacy.py、test_file_lock_windows_atomic.py,也没有 test_document_io.py、test_todo_completion_validation.py 的 Windows 分支。hosted Windows CI 变绿不等于它们被执行过。
  3. 反过来,已确认 hosted windows-powershell(success)确实执行了 tests/control_plane_ts/effect_runtime_snapshot.test.ts(workflow 第 1014 行),上一轮关于 TS fixture 的 P2 可以关闭。
  4. PR 当前 behind base;合并前需要更新分支,并让 required check 通过。

建议

  1. 两处 pwsh 改为 shutil.which("pwsh") + pytest.skip("PowerShell 7 is not installed")(helper 覆盖 4 条,junction 那处按第二条行内评论单独改);powershell.exe 只有在先证明其 .NET ACL 读回与 pwsh 等价时才能作为回退,并需注明版本差异。
  2. 把两个新文件(以及 test_document_io.py、test_todo_completion_validation.py 新增的 Windows 分支)加入 windows-powershell 的 curated 命令,或开 follow-up 并写明 owner。否则修好 pwsh 后,这些「原生资格」证据在 CI 里依然不存在。
  3. 合并门禁上先处理 dashboard-browser (2):它会连带决定 dashboard-acceptance → checks → merge-gate/pytest 这条链。test-shard 的 60 分钟超时另行归因,别当作重跑即可解决的问题。

if($acl.Access.Count -ne 3){throw 'Private ACE set incomplete'}
'''
result = subprocess.run(
["pwsh", "-NoLogo", "-NoProfile", "-Command", script],

@JasonBuildAI JasonBuildAI Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pwsh 按名字直接调用:在没有安装 PowerShell 7 的 Windows 上,依赖它的用例会以 FileNotFoundError [WinError 2] 失败,而不是 skip(本机 Windows 11 / Python 3.14.3 实测:该文件 10 passed / 4 failed,失败全部止于此)。

受影响的是 5 条用例,但这里只能覆盖 4 条——tests/control_plane/test_todo_completion_validation.py:908-909 的 test_private_validation_store_is_owner_only_and_detects_tampering 同样走这个 helper(已单独执行确认 failed);test_python_rejects_junction_parent 是直接调 pwsh,按另一条行内评论单独改。

仓库已有约定是先发现再跳过:tests/test_bootstrap_command_pack_platform.py:18,159 用 PWSH = shutil.which("pwsh"),缺失时 pytest.skip(...);tests/test_command_invocation.py:65 同样处理。

建议改成 pwsh = shutil.which("pwsh"),缺失时 pytest.skip("PowerShell 7 is not installed")。这直接关系到「独立 Windows 资格」能否取得:没装 pwsh 的机器现在只能看到红色失败,读者无法区分「没装 pwsh」和「产品 ACL 不对」。

def test_python_rejects_junction_parent(snapshot,tmp_path):
path, _ = snapshot
link = tmp_path / "loopx-effect-junction"
cmd=['pwsh','-NoLogo','-NoProfile','-Command',"New-Item -ItemType Junction -Path $env:LX_LINK -Target $env:LX_TARGET | Out-Null"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同一处 pwsh 依赖,而且这里用它创建 junction。没有 pwsh 的机器上,测试在准备阶段就崩,读者无法区分「junction 造不出来」和「产品正确拒绝 junction」。建议与仓库既有 Windows 用例保持一致:shutil.which("pwsh") 后 pytest.skip,或在无法创建 junction 时 skip 并写明原因。

Signed-off-by: Tartar <xiaoyx67@mail2.sysu.edu.cn>
@xyx2002OvO

xyx2002OvO commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor Author

PR 已更新到 exact head 4379e2a2a42b46d631a565cc21a0095adb34663c,并合入当前本地 origin/main (8d48efabb351c9cc68f48f48dee64a49b4fc1890)。此前 review 指出的 Windows-curated TS fixture/ACL setup 遗漏仍由 afe5a05f 的源码修复保留。

原生 Windows 复测环境:Windows 10.0.26200.9711、Python 3.12.3、Node 24.22.1、SQLite 3.53.4。

  1. Windows-curated TypeScript exact-head 套件(workflow 中 11 个 test files): 257 passed, 28 skipped, 0 failed。
  2. PR 验证契约中的原生 Python IO 套件:75 passed, 1 skipped, 0 failed。精确命令覆盖 test_windows_snapshot_privacy.py、test_document_io.py、test_todo_completion_validation.py、test_file_lock_windows_atomic.py、test_local_state_migration_path_text.py、test_windows_atomic_writes.py;因此 DACL/digest、普通长路径、共享句柄、junction/path-text 与原子写负例均在当前 head 原生通过。
  3. 额外扩大运行完整 test_local_state_migration.py 后,总计 122 passed, 1 skipped, 9 failed;这 9 个额外失败全部在 fixture 创建 directory symlink 时因当前账户缺少 Windows symlink privilege 得到 WinError 1314,未进入产品断言。它们不属于上述 PR 声明的 75-case 验证集合,仍作为环境限制保留,不改写成通过。固定合格 Node 后,两条 Effect integration 单独复测为 2 passed。

RFC bilingual staged check 通过。没有在本 PR 混入共享 CI 基线修复,也没有合并授权。请按此 exact head 复审。

@songoow songoow 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 Astra Pro | OpenAI | self_reported

REQUEST_CHANGES — 2 项 P2:遗漏的 Windows RPC fixture 未适配严格ACL;pwsh 测试依赖问题仍未解决。 本轮固定 head 4379e2a2a42b46d631a565cc21a0095adb34663c,merge-base 8d48efabb351c9cc68f48f48dee64a49b4fc1890,覆盖全部18文件及实际producer/consumer。先前关于TS snapshot fixture的P2在当前source中已修复,不重复当作未修问题。

动机 / Motivation

受影响的是 Windows 上使用大型状态读取、私有会话/验证记录以及本地状态迁移的 LoopX 操作者。

原先长路径或短暂占用可能阻止私有文件写入,而仅chmod不能表达Windows访问边界;这次改动在写入前设置OS权限、验证同一文件身份,并在原有原子发布owner内处理平台路径与有限重试。

Linux共用IO、迁移和RPC路径通过;先前TS snapshot fixture已修复,但当前Windows CI仍有一个未适配DACL的真实RPC fixture,且无pwsh的Windows测试依赖问题仍未解决。

本PR不改变Goal/Todo/settlement权威、snapshot预算或迁移布局,不声称认证全部Windows安装、长时任务或 #5677 freshness。

改动思路 / Approach

权限、路径和原子发布都属于原文件 IO owner;集中 Windows OS 事实并保留既有业务 owner 的方向合理。 本PR完成独立平台IO切片,补遗漏fixture与精准工具依赖检查;保留DACL、digest、old bytes和rollback保护,不扩大到freshness或新存储框架。

producer在写入敏感bytes前保护parent和temp;consumer读取当前OS事实而不替caller修复权限,随后继续核对同一file identity和digest。Windows不能把chmod(0600)当DACL证明,所以统一helper有必要。TS仍掌握snapshot准入和业务owner,固定package-owned Python helper只返回OS层结果。

长路径沿用已有 windows_extended_path,没有创建第二套路径身份;atomic replacement仍写完整临时文件再替换,不回退为原地覆盖。迁移继续使用原plan/backup/digest/rollback owner,只把IO地址换成native支持形式。这个平台前置有独立价值,不要求与 #7602 Job或整个freshness功能一起交付。

具体改动 / Changes

关键代码讲解

  1. private_permissions.protect_private_path/require_private_path 拒绝symlink/reparse与错误leaf类型;Windows设置/检查受保护DACL、owner和明确ACE集合,已打开fd还核对identity;POSIX继续使用模式位。读取不修理不可信目标。
  2. effect_runtime._request_with_info/_read_local_snapshot_response 在dispatch前保护temporary parent、params和response sink;响应读回失败仍为ambiguous。TS privateFile 通过固定Python路径查询Windows权限,之后保留open、inode/device、regular-file及bytes/digest核对。先前TS测试已加入测试解释器选择和合法DACL fixture,保留原正反断言。
  3. document_io.atomic_write_state_text 将private保护前移到写bytes之前,create-only、fsync和失败清理保持;validation store改用该private writer,codex_sessions 同样保留原身份与原子replace,避免发布失败损坏旧会话。
  4. file_lock 在原owner内采用extended path;holder sidecar对Windows winerror=5仅有限重试,其他错误不变成成功。一般atomic writer新增retry参数默认0,没有无界等待或原地overwrite降级。
  5. local_state_migration 的digest/copy/registry/rollback使用同一physical file的长地址,保留reparse、source重验、backup验证与custom path原文本。project_prompt 仅规范portable separator。新增path-text测试验证owned路径迁移与精确rollback,也保留自定义声明。

18文件分为9生产与9测试。实际参考合同是 docs/reference/canonical-snapshot-pagination.md,固定修订 8d48efabb351c9cc68f48f48dee64a49b4fc1890:private-file-admission 要求ownership/permissions/byte count/SHA-256及临时文件回收;domain-owner-preserved 要求TS保持业务owner,Python不增加Todo规则引擎。新OS保护方向符合这些要求;合法fixture必须同步符合它们。

对主干的风险 / Risks

P2-1:真实RPC fixture仍只chmod,当前Windows CI因此失败。 tests/control_plane/test_effect_runtime_integration.py 的 test_controller_snapshot_retains_private_file_and_method_guards 在1815–1818创建params/sink后只改mode,没有保护parent或leaf DACL。新增 privateFile 第26–34行会拒绝这份fixture。实际Windows job 在1830的 result.ok 正例失败,汇总为 1 FAIL / 421 PASS / 20 SKIP,尚未执行后续预期的digest/method负例。

该job运行merge da0136413055baae485427b13ea0a9340c321c65;我读取并比较了其中integration fixture、snapshot实现和private_permissions三份blob,均与当前head完全相同。这不是从聚合红灯猜原因,也不是把后来不同source失败移记到本PR。最小修复是在fixture里为root/params/sink建立真正的合法私有权限;保留生产ACL拒绝,不要删正例或跳过整个RPC测试。

P2-2:无PowerShell7的Windows环境仍会在验证前失败。 tests/control_plane/windows_private_acl.py 第21–25行直接启动pwsh,junction测试第143行另有相同假设。此前独立Windowsreview已报告相关5例缺程序失败;当前head仍无发现/skip处理。仓库现有test_command_invocation.py和test_bootstrap_command_pack_platform.py已采用shutil.which/精准skip。请明确检查该测试工具,只处理依赖它的case;其他直接Win32/icacls保护断言应继续执行。我的Linux缺工具探针也只能确认直接helper抛FileNotFoundError,没有把它写成原生ACL验证。

本轮实跑:document IO、validation、migration、path-text和平台文件组合 132 PASS / 29 SKIP;TS snapshot两项 2 PASS;同一真实RPC fixture在Linux 1 PASS / 100 deselected;git diff --check通过。跳过的Windows用例和作者native报告单独保留,未计入本轮原生资格。历史symlink privilege等失败未被改名为新PR缺陷。

语义与 CI 对齐

保护属于强制IO invariant,不能用“兼容Windows”作为放宽owner、digest或原子发布的理由。当前需要的是合法producer/fixture与严格consumer一致。请在Windows重跑上述RPC fixture,再跑private snapshot、Todo validation、sharing violation与long-path组合,并验证无pwsh环境只精准跳过其依赖用例。当前head其余native组合仍 UNVERIFIED;未启动真实模型或安装流程。

我的整体评价 / Verdict

这是一份可独立落地的平台IO切片,helper和既有writer复用合理;不需要再造存储或控制框架。先前TSfixture问题已修,但真实RPC caller遗漏和工具前置问题必须闭合,才能给出可靠的Windows验收。长程状态安全与操作者恢复体验的改进目前仍受上述失败和native证据缺口限制。本次检查的 private_permissions、snapshot/document IO 与 migration 路径 不改变已渲染的产品页面;无需用截图证明内部行为。 未进行产品页面视觉检查,因为本次没有页面改动。

English verdict: REQUEST_CHANGES — 4379e2a2a42b46d631a565cc21a0095adb34663c has two P2 test-integration issues: the real Windows RPC snapshot fixture still lacks the newly required protected ACLs, and the PowerShell 7 dependency remains unchecked. Linux validation passed 132 cases, TS passed 2, and the RPC counterpart passed; the native CI failure is tied to identical causal blobs. Full native Windows qualification remains unverified.

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.

4 participants