Skip to content

fix(process): allow whitespace in workspace cwd segments (#410 parity)#674

Open
BlackKeyZ wants to merge 2 commits into
mainfrom
fix/spawn-cwd-whitespace-regression
Open

fix(process): allow whitespace in workspace cwd segments (#410 parity)#674
BlackKeyZ wants to merge 2 commits into
mainfrom
fix/spawn-cwd-whitespace-regression

Conversation

@BlackKeyZ

@BlackKeyZ BlackKeyZ commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes Sentry ELECTRON-3PP (AionUi 2.1.40): teams with a claude/codex leader fail with "Agent runtime failed to start" while aionrs leaders work — plus two sibling parity gaps found by auditing every upstream fix on the replaced spawn path against the session rewrite.

Commit 1 — whitespace cwd regression (the P0)

  • aionui-process::prepare_command_cwd rejected any cwd containing a whitespace path segment. Every claude/codex direct-CLI spawn goes through it (RealSpawner → ManagedProcess::spawn), so workspaces under iCloud Drive (~/Library/Mobile Documents/…) — or any folder with a space — failed instantly (µs-level, before posix_spawn). Non-team claude/codex conversations in such workspaces are equally affected; teams just mask the error hardest.
  • Upstream already removed the same check from the legacy spawn path in fix(conversation): align workspace path availability handling #410 (with pinned regression tests); the rewritten crate kept the pre-fix(conversation): align workspace path availability handling #410 semantics and feat(session-port): route claude/codex through the direct-CLI SessionAgentTask #609 carried it into production. The cwd is passed to the OS as a single argument (never through a shell), so no quoting hazard exists.
  • Drop the check + its error variant; pin regression tests (whitespace in any segment / trailing whitespace must pass; empty, missing, non-directory still rejected).
  • attach_member_runtime (aionui-team): log the raw TeamError at warn before sanitize_member_runtime_failure genericizes it — production logs previously carried no trace of the real cause.

Commit 2 — two parity follow-ups from the same audit

  • fix(conversation): align workspace path availability handling #410 error-class parity: a missing / non-directory workspace now keeps its dedicated class end-to-end instead of collapsing into an opaque 502: ProcessError::WorkspaceUnavailableBackendError::from_spawn (all six conn spawn sites) → AgentError::WorkspacePathRuntimeUnavailable → the existing WORKSPACE_PATH_RUNTIME_UNAVAILABLE API error the frontend already renders.
  • fix(ai-agent): make find_native_claude cross-platform (ELECTRON-1CG) #299 Windows CLI-resolution parity: when resolve_bundled_cli finds no bundled binary, resolve the bare claude/codex through resolve_command_path (PATHEXT + npm .cmd/.ps1/.bat shim lookup) instead of handing a bare name to CreateProcess, which cannot resolve npm shims. Nothing-on-PATH still falls back to the bare name so the spawn error stays diagnosable.

Root-cause evidence (commit 1)

  • 07-22 (v2.1.39 legacy ACP): the same leader conversation spawned fine with cwd=/Users/…/Library/Mobile Documents/com~apple~CloudDocs/… (user logs, pid 2407).
  • 07-23 (v2.1.40): same conversation fails 320µs after the approval policy resolved log — exactly the pre-spawn cwd guard; bundled CLI resolution succeeded (binaries verified present, +x, runnable in the 2.1.40 artifact).
  • An aionrs-leader team on the SAME workspace works (in-process, no spawn) — matching the user report.

Testing

  • New tests: prepare_command_cwd classification + whitespace pins (aionui-process), from_spawn unit (types.rs), open_session wiring with a workspace-gone spawner (codex_conn)
  • cargo clippy -p aionui-process -p aionui-session -p aionui-ai-agent -p aionui-team -- -D warnings
  • just push full gate ×2 — workspace nextest 7429 passed / 18 skipped

The session-port spawn path (aionui-process::prepare_command_cwd)
rejected any cwd with a whitespace path segment, so every claude/codex
direct-CLI spawn failed instantly for workspaces like iCloud Drive
(~/Library/Mobile Documents/...). Upstream removed the same check from
the legacy spawn path in #410; the rewritten crate silently reintroduced
it and #609 carried it into production (Sentry ELECTRON-3PP: team
leaders on claude/codex fail with "Agent runtime failed to start" while
aionrs, which spawns no subprocess, works).

- drop the whitespace-segment rejection + its ProcessError variant;
  the guard now checks availability only (non-empty, exists, is-dir),
  matching #410 semantics and the legacy cli_process guard
- pin regression tests (whitespace in any segment / trailing whitespace
  on an existing dir must pass; empty, missing, non-dir still rejected)
- team attach: log the raw TeamError at warn before it is sanitized to
  the generic public reason - production logs previously carried no
  trace of the actual cause
…TH-resolve CLI fallback

Two follow-ups from the regression-by-rewrite audit round 2 (fix-history x
session spawn path), same family as the whitespace-cwd regression:

- #410 parity (error class): a missing / non-directory workspace now keeps
  its dedicated class end-to-end instead of collapsing into an opaque 502:
  ProcessError::WorkspaceUnavailable (path payload) -> BackendError::
  WorkspaceUnavailable via the shared from_spawn mapping at all six conn
  spawn sites -> AgentError::WorkspacePathRuntimeUnavailable in
  build_session_instance -> the existing WORKSPACE_PATH_RUNTIME_UNAVAILABLE
  API error the frontend already renders. Legacy cli_process surfaced this
  class; the session path degraded it to bad_gateway.

- #299 parity (Windows CLI resolution): when resolve_bundled_cli finds no
  bundled binary, resolve the bare "claude"/"codex" through
  resolve_command_path (which handles .exe via PATHEXT and npm .cmd/.ps1/.bat
  shims) instead of handing the bare name to CreateProcess, which cannot
  resolve npm shims. Nothing-on-PATH still falls back to the bare name so
  the spawn error stays diagnosable.

Tests: prepare_command_cwd classification (aionui-process), from_spawn unit
(types.rs), open_session wiring with a workspace-gone spawner (codex_conn).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant