Gate agent startup on the effective PTY cwd after default fallback

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinjing
2026-07-04 22:04:44 -07:00
co-authored by Orca
parent 9316771409
commit efaad5bba1
3 changed files with 19 additions and 8 deletions
@@ -82,6 +82,7 @@ vi.mock('../wsl', () => ({
}))
import { LocalPtyProvider } from './local-pty-provider'
import { isRootLikePath } from './pty-path-safety'
import { POWERLEVEL10K_WIZARD_DISABLE_ENV } from '../pty/powerlevel10k-wizard-env'
describe('LocalPtyProvider', () => {
@@ -228,14 +229,15 @@ describe('LocalPtyProvider', () => {
)
})
it('rejects automatic agent startup without an explicit cwd', async () => {
it('falls back to the safe default cwd for automatic agent startup without an explicit cwd', async () => {
spawnMock.mockClear()
await expect(provider.spawn({ cols: 80, rows: 24, command: 'codex' })).rejects.toThrow(
/requires a non-root workspace/
)
// Why: an omitted cwd resolves to a guaranteed-safe default home (the
// guard only rejects root-like paths), so the agent must still launch.
await expect(provider.spawn({ cols: 80, rows: 24, command: 'codex' })).resolves.toBeDefined()
expect(spawnMock).not.toHaveBeenCalled()
const spawnCall = spawnMock.mock.calls.at(-1)!
expect(isRootLikePath(spawnCall[2].cwd)).toBe(false)
})
it('rejects automatic agent startup at POSIX root', async () => {
+6 -3
View File
@@ -343,12 +343,15 @@ export class LocalPtyProvider implements IPtyProvider {
const startupAgentRecognition = args.command
? recognizeAgentProcessFromCommandLine(args.command)
: null
if (args.command && startupAgentRecognition) {
assertSafeAgentStartupCwd(args.cwd, args.command)
}
const defaultCwd = getDefaultCwd()
const cwd = args.cwd || defaultCwd
// Why: gate on the effective cwd (post default-cwd fallback), not the raw
// args.cwd — an omitted cwd resolves to a safe default and must not be
// rejected as if it were a root-like path.
if (args.command && startupAgentRecognition) {
assertSafeAgentStartupCwd(cwd, args.command)
}
const wslInfo = process.platform === 'win32' ? parseWslPath(cwd) : null
const worktreeWslContext =
process.platform === 'win32' ? getWslContextFromWorktreeId(args.worktreeId) : undefined
+6
View File
@@ -22,6 +22,12 @@ export function resolveSafePtyDefaultCwd(env: NodeJS.ProcessEnv = process.env):
// Why: silently falling back to "/" or a drive root is the exact runaway-CPU
// bug this module prevents (see runaway-cpu-hidden-usage-pty-design.md) — fail loud.
if (!selected) {
// Log the rejected candidates so the rare "no safe home at all" environment
// (e.g. HOME=/ or unset in a minimal container) is diagnosable, not opaque.
console.error(
'[pty-default-cwd] No safe default working directory for terminal launch; every home candidate resolved to a root-like path.',
{ platform: process.platform, candidates }
)
throw new Error('No safe default working directory is available for terminal launch.')
}
return selected