* fix: resolve Windows junction identities without breaking upgrade locks Problem: Windows users whose existing data directory is a junction cannot start sessions after configuration locks begin requiring physical identity. Recovery also labels runtime-start failures as failed draft saves. Root cause: EvalSymlinks can leave a junction leaf unchanged and reject its children, splitting aliases or failing before the OS lock is acquired. Fix: resolve existing Windows paths through native metadata handles, retain legacy workspace lock spellings, isolate/rebuild derived catalog identities, and separate historical draft submission errors from persistence errors. Add a read-only probe and native regressions to the Windows PR selectors. Preserve current eager session creation and authoritative user data formats. Verification: owning Go suites, host/Windows golangci-lint, repolint, frontend production/test typechecks, draft ownership and recovery regressions, real Chromium recovery interactions, and Windows selector coverage passed. Native Windows execution and complete upgrade qualification remain CI/manual gates; cross-compilation does not establish those results. * fix: preserve native Windows error kinds and verify historical lock spelling Problem: native Windows CI rejected dangling-link and loop error kinds, and the legacy-lock fixture expected the unexpanded runner temporary path. The recovery UI also exceeded an almost exact startup-byte budget. Root cause: os.IsNotExist does not traverse arbitrary wrapping, native reparse exhaustion uses ERROR_CANT_RESOLVE_FILENAME, and EvalSymlinks expands 8.3 ancestors even when it preserves a junction leaf. Fix: use wrapped-error matching and the native reparse-loop code; derive the fixture's legacy key with the historical filesystem algorithm. Keep all rejection and lock assertions. Remove a duplicated browser invocation. Adjust only the raw startup ceiling to the measured producer size: same source/dependencies/commit stamping adds 506 B raw (0.024%) and 120 B gzip; Linux Electron measures 2103802 B, rounded to 2054.5 KiB. Verification: pathidentity, workspacelease and probe tests; host/Windows lint; repolint; bundle budget; same-toolchain base/candidate production builds. All compressed, chunk, CSS, locale and residency budgets remain unchanged. * test: exercise native junction identity across Windows volumes Problem: the reported regression crosses system and data volumes, while the initial regression fixtures only created same-volume junctions. Root cause: filesystem alias tests did not exercise drive-prefix changes. Fix: create a temporary junction from the system temp drive to RUNNER_TEMP and compare entry and missing-tail identities with the physical target. Require the two-volume fixture on GitHub Windows runners. Single-volume local machines still run the unconditional same-volume regression suite. Verification: Windows-target lint and cross-compilation; the native Windows PR lane is required to execute the cross-volume fixture. * Preserve credential ACL recovery and bind artifact consumers to producer Node Problem: native identity resolution blocked credential ACL repair before edit locking, and prepared frontend consumers selected different Node patch versions. Root cause: FILE_READ_ATTRIBUTES requires permissions that legacy read-deny ACLs remove; floating Node majors resolve independently on hosted runners. Fix: use zero-access metadata handles, keep read denials intact until credential recovery, cover linked and unrecorded ACL cases, and propagate the producer Node version to every artifact consumer without weakening verification. Verification: pathidentity/config tests, Windows cross-compilation and golangci-lint, 40 workflow/artifact/selector tests, repolint and diff checks passed. Native Windows execution remains a CI gate. * Bind memory screening consumers to their build Node version Problem: a memory shard rejected the prepared build before running because its floating Node major selected a different patch version. Root cause: the independent app-memory workflow owns a second producer-consumer identity contract. Fix: propagate its producer runtime to shards and aggregation, preserving exact identity validation. Add a workflow regression for both consumers. Verification: 51 workflow and memory protocol tests, repolint, and diff checks passed. * Open Windows identity handles with exact native access rights Problem: CreateFile with zero desired access still fails against legacy credential DENY RX ACLs. Root cause: Win32 adds SYNCHRONIZE and FILE_READ_ATTRIBUTES, as already documented by the credential ACL recovery owner. Fix: open a zero-access NtCreateFile handle that follows reparse points, use the native namespace for long/UNC paths, and translate NTSTATUS failures back to Win32 codes for existing error classification. Verification: Windows compilation and golangci-lint, repolint, and diff checks passed. Existing save/load/revision tests require identity to resolve while content reads remain denied; native CI verifies this contract. * Request valid metadata access for native Windows identity queries Problem: NtCreateFile rejects a zero access mask, breaking ordinary Windows identity queries. Fix: request FILE_READ_ATTRIBUTES without implicit synchronization; when an ACL denies that right, try READ_CONTROL, which file owners retain for security metadata. Neither handle grants content access or mutates the ACL. Preserve NTSTATUS classification and all denial assertions. Verification: Windows compilation and golangci-lint, repolint and diff checks passed; Windows execution is required before qualification.
Reasonix Windows 路径诊断 / Windows path probe
用于核对 Go 路径解析、构建时的 Reasonix 路径解析和 Windows 原生句柄解析是否在 Junction 上产生不同结果。报告中的 identity_version 标识 Reasonix 解析器版本;修复版为 3。它是诊断工具,不会修改已安装应用。
Compares Go, the build's Reasonix resolver, and native Windows handle resolution through junctions. The identity_version field identifies the Reasonix resolver (3 for the fixed implementation). This diagnostic does not change the installed application.
使用 / Usage
- 将整个 ZIP 解压到普通、可写的本地文件夹,不要直接在压缩包内运行。
- 使用受影响用户的普通 Windows 账户,双击
run-probe.cmd。无需安装 Go,也无需管理员权限。 - 等待完成,通常数秒,采集上限默认 60 秒。把同目录生成的
reasonix-path-probe-*.json返回给排障人员。 - 若程序被系统阻止或报错,记录原文并返回;不需要关闭系统防护。
Extract the ZIP to a writable local folder. Run run-probe.cmd as the affected Windows user without elevation. Return the generated JSON beside the executable. Go installation is not required. If execution is blocked, return the exact error without disabling protections.
可选命令 / Optional command:
.\reasonix-path-probe.exe -out .\new-report.json -timeout 60s 'E:\ReasonixData\.reasonix'
指定的输出文件必须尚不存在。额外路径只增加采集目标,默认锁目录仍会检查。
The output must not already exist. Positional paths add targets; default lock paths remain included.
采集范围 / Collection scope
- 检查当前 OS 用户的
.reasonix\locks\config-edits-<用户身份摘要>、最多 99 个已有.lock文件及祖先目录,并比较原生解析得到的物理路径;最多 300 个路径。 - 逐项记录
Lstat、Readlink、filepath.EvalSymlinks、Reasonixpathidentity.Resolve和 WindowsCreateFileW/GetFinalPathNameByHandleW的结果、错误链、系统错误码、文件身份。 - 不读取配置、凭据、锁文件或会话内容;不申请锁、不联网、不修改现有应用数据。唯一写入是新建 JSON 报告。
- 报告替换当前主目录用户名和 SID;其他目录名、盘符、文件名和时间仍保留,便于判断路径问题。转发前可检查报告。
- 普通文件上的
Readlink失败、刻意不存在的reasonix-probe-uncreated-child\absent.lock上的直接查询失败均属预期;不能把每条ok: false都当作根因。 - 超时会保存已完成部分,并在
timed_out/incomplete_path标明。原生路径成功但文件身份读取失败时,errors仍会记录后者。
Collects path metadata, structured error chains and file identity only. It does not load configuration, read file contents, acquire locks, access the network, or modify existing application data. Its only write is a newly created report. The current home-directory username and SID are redacted; other path components remain. Readlink failures on ordinary entries and direct lookup failures on the deliberately absent child are expected. Timed-out collections preserve completed observations. Inspect errors even when native path resolution succeeds.
判读 / Interpretation
若逻辑路径的 Go/Reasonix 解析失败,而同一路径的原生解析成功,且原生解析得到的物理路径能被 Go/Reasonix 正常解析,则支持 Junction 解析分歧这一判断。必须以报告中的具体失败路径和错误链为准;工具不会自动认定 Studio 为原因。
A failure on the alias in Go/Reasonix, native success on that same alias, and Go/Reasonix success on the resulting physical path support a junction-resolution discrepancy. Use the actual failing paths and error chains; the probe does not attribute causation to Studio.
构建 / Build
From the repository root, using the affected release's Go version:
GOTOOLCHAIN=go1.26.6 go test ./tools/pathidentityprobe ./internal/pathidentity
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 GOTOOLCHAIN=go1.26.6 go build -trimpath -o reasonix-path-probe.exe ./tools/pathidentityprobe
随包构建信息记录完整源码提交、工具链、源码校验值及验证范围。Windows 交叉编译通过不等于 Windows 实机执行通过。
The package build record identifies the source commit, toolchain, source hashes and validation scope. Windows cross-compilation does not establish native Windows runtime success.