From b10080c7dd4505e6d8e43cc1186ce1b6355f37c5 Mon Sep 17 00:00:00 2001 From: Affaan Mustafa Date: Thu, 2 Apr 2026 18:22:07 -0700 Subject: [PATCH] fix: respect home overrides in hook utilities --- WORKING-CONTEXT.md | 1 + scripts/lib/utils.js | 4 ++++ tests/lib/utils.test.js | 44 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/WORKING-CONTEXT.md b/WORKING-CONTEXT.md index 4fc29316..1ef8d562 100644 --- a/WORKING-CONTEXT.md +++ b/WORKING-CONTEXT.md @@ -127,3 +127,4 @@ Keep this file detailed for only the current sprint, blockers, and next actions. - 2026-04-02: Direct-ported the safe web/frontend rules lane from `#1122` into `rules/web/`, but adapted `rules/web/hooks.md` to prefer project-local tooling and avoid remote one-off package execution examples. - 2026-04-02: Adapted the design-quality reminder from `#1127` into the current ECC hook architecture with a local `scripts/hooks/design-quality-check.js`, Claude `hooks/hooks.json` wiring, Cursor `after-file-edit.js` wiring, and dedicated hook coverage in `tests/hooks/design-quality-check.test.js`. - 2026-04-02: Fixed `#1141` on `main` in `16e9b17`. The observer lifecycle is now session-aware instead of purely detached: `SessionStart` writes a project-scoped lease, `SessionEnd` removes that lease and stops the observer when the final lease disappears, `observe.sh` records project activity, and `observer-loop.sh` now exits on idle when no leases remain. Targeted validation passed with `bash -n`, `node tests/hooks/observer-memory.test.js`, `node tests/integration/hooks.test.js`, `node scripts/ci/validate-hooks.js hooks/hooks.json`, and `node scripts/ci/check-unicode-safety.js`. +- 2026-04-02: Fixed the remaining Windows-only hook regression behind `#1070` by making `scripts/lib/utils.js#getHomeDir()` honor explicit `HOME` / `USERPROFILE` overrides before falling back to `os.homedir()`. This restores test-isolated observer state paths for hook integration runs on Windows. Added regression coverage in `tests/lib/utils.test.js`. Targeted validation passed with `node tests/lib/utils.test.js`, `node tests/integration/hooks.test.js`, `node tests/hooks/observer-memory.test.js`, and `node scripts/ci/check-unicode-safety.js`. diff --git a/scripts/lib/utils.js b/scripts/lib/utils.js index 7a5796a3..f1717e5d 100644 --- a/scripts/lib/utils.js +++ b/scripts/lib/utils.js @@ -25,6 +25,10 @@ const WINDOWS_RESERVED_SESSION_IDS = new Set([ * Get the user's home directory (cross-platform) */ function getHomeDir() { + const explicitHome = process.env.HOME || process.env.USERPROFILE; + if (explicitHome && explicitHome.trim().length > 0) { + return path.resolve(explicitHome); + } return os.homedir(); } diff --git a/tests/lib/utils.test.js b/tests/lib/utils.test.js index 2f7a0300..a85758e4 100644 --- a/tests/lib/utils.test.js +++ b/tests/lib/utils.test.js @@ -60,6 +60,50 @@ function runTests() { assert.ok(fs.existsSync(home), 'Home dir should exist'); })) passed++; else failed++; + if (test('getHomeDir prefers HOME override when set', () => { + const originalHome = process.env.HOME; + const originalUserProfile = process.env.USERPROFILE; + const fakeHome = path.join(process.cwd(), 'tmp-home-override'); + try { + process.env.HOME = fakeHome; + process.env.USERPROFILE = ''; + assert.strictEqual(utils.getHomeDir(), fakeHome); + } finally { + if (originalHome === undefined) { + delete process.env.HOME; + } else { + process.env.HOME = originalHome; + } + if (originalUserProfile === undefined) { + delete process.env.USERPROFILE; + } else { + process.env.USERPROFILE = originalUserProfile; + } + } + })) passed++; else failed++; + + if (test('getHomeDir falls back to USERPROFILE when HOME is empty', () => { + const originalHome = process.env.HOME; + const originalUserProfile = process.env.USERPROFILE; + const fakeHome = path.join(process.cwd(), 'tmp-userprofile-override'); + try { + process.env.HOME = ''; + process.env.USERPROFILE = fakeHome; + assert.strictEqual(utils.getHomeDir(), fakeHome); + } finally { + if (originalHome === undefined) { + delete process.env.HOME; + } else { + process.env.HOME = originalHome; + } + if (originalUserProfile === undefined) { + delete process.env.USERPROFILE; + } else { + process.env.USERPROFILE = originalUserProfile; + } + } + })) passed++; else failed++; + if (test('getClaudeDir returns path under home', () => { const claudeDir = utils.getClaudeDir(); const homeDir = utils.getHomeDir();