Files
orca/src/shared/absolute-dir-override.test.ts
T
manuaudioandClaude Opus 5 170dbdb874 fix(ai-vault): ignore non-absolute env overrides for agent scan roots (#13118)
Six scan roots took a directory from an environment variable and used it
verbatim. A relative value is resolved by whichever Orca process reads it —
main sits at `/` when Finder-launched, the terminal daemon chdirs itself to
the user data dir, the AI Vault service inherits main's cwd — so one value
names a different directory in each, and walkSessionFiles walks it with no
depth cap, no entry cap and no time budget, about once a minute per the
session-list cache TTL.

The agent CLIs do accept a relative home (verified against real Grok 1.0.30:
`GROK_HOME=myhome grok du` creates `<grok-cwd>/myhome`), but they resolve it
against their own per-terminal cwd, which no Orca reader shares. Falling back
to the default home is therefore not a lost configuration — it replaces an
unbounded walk of an arbitrary tree with a bounded read of a known one, and
matches what readGrokHomeEnvelope, skill-provider normalizedRoot and
absoluteConfiguredDir already do with the same values.

Add resolveAbsoluteDirOverride and apply it to CODEX_HOME, COPILOT_HOME,
OPENCLAW_STATE_DIR, DEVIN_HOME, KIMI_CODE_HOME and GROK_HOME. It takes an
explicit platform so the Windows shapes are provable from a POSIX CI box:
`C:\...`, `C:/...` and UNC roots are kept, while the drive-relative `C:foo`
and bare `C:` fall back. Tilde expansion stays out of it — Grok creates a
literal `~` directory rather than expanding one — so absoluteConfiguredDir
keeps its own Pi/Prime-specific expansion and delegates the absolute check.

isAbsolute is syntactic only, so `/..` still collapses to `/`. That is fine
for read-only discovery; these roots never gate renderer-supplied paths.

Tests assert at the call sites, not just on the helper: the four
session-scanner-agent-sources roots are module-level consts evaluated at
import time, so they are exercised through AI_VAULT_AGENT_SOURCES with
vi.stubEnv plus vi.resetModules. Reverting any one of the six call sites
fails them (11-33 cases each).

Closes #13082

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 01:44:53 -07:00

63 lines
2.7 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { resolveAbsoluteDirOverride } from './absolute-dir-override'
const FALLBACK = '/home/user/.agent'
describe('resolveAbsoluteDirOverride', () => {
it('keeps an absolute override, trimming first', () => {
expect(resolveAbsoluteDirOverride('/srv/sessions', FALLBACK, 'linux')).toBe('/srv/sessions')
expect(resolveAbsoluteDirOverride(' /srv/sessions ', FALLBACK, 'linux')).toBe('/srv/sessions')
})
it.each([
['undefined', undefined],
['null', null],
['empty', ''],
['whitespace only', ' ']
])('falls back for %s', (_label, value) => {
expect(resolveAbsoluteDirOverride(value, FALLBACK, 'linux')).toBe(FALLBACK)
expect(resolveAbsoluteDirOverride(value, FALLBACK, 'win32')).toBe(FALLBACK)
})
it.each([
['a bare dot', '.'],
['a parent reference', '..'],
['a relative path', 'rel/path'],
// Grok 1.0.30 does not expand `~` — `GROK_HOME=~/x` makes it create a literal `~` dir under
// its own cwd — so expanding one here would point Orca at a directory no agent writes to.
['an unexpanded tilde', '~/sessions'],
// Drive-*relative*: both resolve against that drive's current directory, not its root.
['a drive-relative path', 'C:foo'],
['a bare drive letter', 'C:']
])('falls back for %s on every platform', (_label, value) => {
expect(resolveAbsoluteDirOverride(value, FALLBACK, 'linux')).toBe(FALLBACK)
expect(resolveAbsoluteDirOverride(value, FALLBACK, 'darwin')).toBe(FALLBACK)
expect(resolveAbsoluteDirOverride(value, FALLBACK, 'win32')).toBe(FALLBACK)
})
// Why: the check is platform-bound, so a POSIX CI box would silently "reject" every real
// Windows root if it ran the POSIX predicate. These pin the Windows shapes users actually set.
it.each([
['a drive-rooted path', 'C:\\Users\\ada\\.grok'],
['a forward-slash drive root', 'C:/Users/ada/.grok'],
['a UNC share', '\\\\server\\share\\grok'],
// Rooted but drive-relative; `path.resolve` still bounds it to the current drive.
['a drive-current-root path', '\\grok']
])('keeps %s on Windows', (_label, value) => {
expect(resolveAbsoluteDirOverride(value, FALLBACK, 'win32')).toBe(value)
})
it.each([['C:\\Users\\ada\\.grok'], ['\\\\server\\share\\grok'], ['\\grok']])(
'falls back for the Windows path %j on POSIX',
(value) => {
expect(resolveAbsoluteDirOverride(value, FALLBACK, 'linux')).toBe(FALLBACK)
}
)
it('defaults to the host platform', () => {
const rooted = process.platform === 'win32' ? 'C:\\srv\\sessions' : '/srv/sessions'
expect(resolveAbsoluteDirOverride(rooted, FALLBACK)).toBe(rooted)
expect(resolveAbsoluteDirOverride('rel/path', FALLBACK)).toBe(FALLBACK)
})
})