fix(cli): normalize empty Windows profile before imports (#2482)
Follow-up to #2345; thanks to @gefrezim for the import-time home lookup diagnosis. Normalize only an empty Windows USERPROFILE before runtime dependency imports, preserving all nonempty caller selections. Reuse the existing public setup dry-run regression in the Windows curated CI lane. No additional filesystem query, engine call, cache or retry. Verified real Windows Node 24.18.0 CLI unset/empty/selected-profile controls, setup dry-run home selection and unchanged configuration, and baseline/candidate SDK stdio MCP catalogue parity. Nine related tests and static/docs checks passed. No IDA or Ghidra engine was used. Scoped resource observations and measurement limits are recorded in experiments/analysis-efficiency/windows-empty-profile.md. Fixed the review finding and original CI package-scope ownership failure. Current-head CI is green; the unrelated MCP identity timeout passed on a failed-job rerun without changing its code or timeout. Current-head review completed with no further findings.
This commit is contained in:
parent
45984a4319
commit
fa4b828865
|
|
@ -509,6 +509,7 @@ jobs:
|
||||||
tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts
|
tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts
|
||||||
tests/boundary/filesystem/setupUnavailableProvider.test.ts
|
tests/boundary/filesystem/setupUnavailableProvider.test.ts
|
||||||
tests/boundary/filesystem/windowsNpxRegistration.test.ts
|
tests/boundary/filesystem/windowsNpxRegistration.test.ts
|
||||||
|
tests/acceptance/setup/homeDirectoryFallback.test.ts
|
||||||
tests/boundary/filesystem/webScriptManifestPaths.test.ts
|
tests/boundary/filesystem/webScriptManifestPaths.test.ts
|
||||||
tests/boundary/process/ProcessEvidence.host.test.ts
|
tests/boundary/process/ProcessEvidence.host.test.ts
|
||||||
tests/acceptance/webModuleCli.test.ts
|
tests/acceptance/webModuleCli.test.ts
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
# Windows empty-profile startup verification
|
||||||
|
|
||||||
|
Follow-up to [#2345](https://github.com/morluto/rea/pull/2345), including
|
||||||
|
@gefrezim's diagnosis of the import-time Windows home lookup.
|
||||||
|
|
||||||
|
## Source and boundary
|
||||||
|
|
||||||
|
Baseline: main `172407787f1842dedbcd27b5385177595f786ce4`. Verification used
|
||||||
|
the real Windows 11 10.0.22631.0 host, official Windows x64 Node 24.18.0,
|
||||||
|
locked production dependencies and REA's compiled public CLI / SDK 2.3.1 MCP
|
||||||
|
server. No IDA or Ghidra engine was used. Runtime copies and compact receipts
|
||||||
|
live outside the checkout; no account profile path or ambient environment is
|
||||||
|
recorded here.
|
||||||
|
|
||||||
|
The tested dispatcher SHA-256 is
|
||||||
|
`526105418604cc6e5a202a6275b700814e27450bfaffd45e7510530ba669de8d`.
|
||||||
|
Only the dispatcher changed in the deployed runtime. It treats an empty Windows
|
||||||
|
`USERPROFILE` as unset before dependency imports. Nonempty selections continue
|
||||||
|
to reach the existing home resolver; no additional lookup or fallback owner is
|
||||||
|
introduced.
|
||||||
|
|
||||||
|
## Real Windows observations
|
||||||
|
|
||||||
|
With `HOME` empty in each case, the baseline produced:
|
||||||
|
|
||||||
|
| USERPROFILE selection | `--version` | `--help` | MCP discovery |
|
||||||
|
| --------------------------- | ----------------------- | ----------------------- | ------------- |
|
||||||
|
| Unset | Exit 0 | Exit 0 | Healthy |
|
||||||
|
| Empty | Exit 1, `uv_os_homedir` | Exit 1, `uv_os_homedir` | Healthy |
|
||||||
|
| Nonempty test-owned profile | Exit 0 | Exit 0 | Healthy |
|
||||||
|
|
||||||
|
The corrected CLI passed all six invocations with no stderr. Version output
|
||||||
|
remained 6 bytes and help output 15,497 bytes. Real setup dry runs with empty
|
||||||
|
and nonempty profile selections both exited 0, planned their configuration
|
||||||
|
under the expected home, preserved existing configuration bytes and created no
|
||||||
|
configuration under the working directory. No installation was performed.
|
||||||
|
|
||||||
|
MCP was already healthy in the baseline; this change does not claim to repair
|
||||||
|
an MCP startup failure. Complete baseline discovery was 187 tools and 2,545,790
|
||||||
|
serialized bytes, SHA-256
|
||||||
|
`1e6bbca7f62852134eb703ea098f5a302d1fe333b8433475429f6fc1b1aba18f`.
|
||||||
|
All three corrected MCP controls also passed with no stderr and the same
|
||||||
|
catalogue bytes and digest.
|
||||||
|
|
||||||
|
The existing `homeDirectoryFallback` acceptance test exercises the import-time
|
||||||
|
failure through the public setup dry run. Adding it to the Windows curated lane
|
||||||
|
makes that regression execute on the affected platform. No duplicate startup
|
||||||
|
test was retained. Nine related tests passed, including the existing MCP doctor
|
||||||
|
and curated-lane path checks; Linux passing alone does not prove Windows behavior.
|
||||||
|
Review caught a missing package-scope registration for the newly listed test;
|
||||||
|
the original CI shard failed that ownership invariant. The path is now also
|
||||||
|
registered in `scripts/ci/scopes.mjs`, and all 84 scope checks plus the two
|
||||||
|
curated-path checks pass. Runtime source and its tested digest are unchanged.
|
||||||
|
|
||||||
|
## Efficiency and resource limits
|
||||||
|
|
||||||
|
Heavy host probes ran serially at BelowNormal priority, with one CPU and a
|
||||||
|
512 MiB CLI/server heap setting (256 MiB for the probe parent). Heap settings do
|
||||||
|
not bound total process memory. An exit-time `process.resourceUsage()` observer
|
||||||
|
recorded individual corrected CLI invocations: CPU time ranged from 7.968 to
|
||||||
|
9.874 seconds and peak working set from 299,956 to 301,852 KiB. These figures
|
||||||
|
exclude the probe parent and any observer overhead outside the CLI process.
|
||||||
|
The six observed wall times ranged from 8.656 to 10.961 seconds.
|
||||||
|
|
||||||
|
The baseline did not use that resource observer, and cold/warm caches were not
|
||||||
|
normalized. These observations establish functional behavior and bounded probe
|
||||||
|
scope; no CPU, memory or latency improvement is claimed. The fix adds one
|
||||||
|
constant-time environment check, no filesystem lookup, engine call, retry or
|
||||||
|
cache. Output bytes are not model tokens; actual model usage was not measured.
|
||||||
|
|
@ -55,6 +55,7 @@ export const SCOPES = {
|
||||||
"tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts",
|
"tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts",
|
||||||
"tests/boundary/filesystem/setupUnavailableProvider.test.ts",
|
"tests/boundary/filesystem/setupUnavailableProvider.test.ts",
|
||||||
"tests/boundary/filesystem/windowsNpxRegistration.test.ts",
|
"tests/boundary/filesystem/windowsNpxRegistration.test.ts",
|
||||||
|
"tests/acceptance/setup/homeDirectoryFallback.test.ts",
|
||||||
"tests/boundary/filesystem/webScriptManifestPaths.test.ts",
|
"tests/boundary/filesystem/webScriptManifestPaths.test.ts",
|
||||||
"tests/boundary/process/ProcessEvidence.host.test.ts",
|
"tests/boundary/process/ProcessEvidence.host.test.ts",
|
||||||
"tests/acceptance/webModuleCli.test.ts",
|
"tests/acceptance/webModuleCli.test.ts",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,12 @@ const isMcpMode =
|
||||||
const isMcpDoctorMode = args[0] === "mcp" && args[1] === "doctor";
|
const isMcpDoctorMode = args[0] === "mcp" && args[1] === "doctor";
|
||||||
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||||
|
|
||||||
|
// Windows home lookup throws for an empty USERPROFILE. Dependencies resolve
|
||||||
|
// home during import, before REA's own resolver can apply its account fallback.
|
||||||
|
if (process.platform === "win32" && process.env.USERPROFILE === "") {
|
||||||
|
delete process.env.USERPROFILE;
|
||||||
|
}
|
||||||
|
|
||||||
// Playwright's registry assumes one of its three desktop host platforms when
|
// Playwright's registry assumes one of its three desktop host platforms when
|
||||||
// it chooses the browser cache directory. Termux reports `android`, although
|
// it chooses the browser cache directory. Termux reports `android`, although
|
||||||
// its Node runtime and filesystem are POSIX-compatible. Keep the cache path
|
// its Node runtime and filesystem are POSIX-compatible. Keep the cache path
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue