Skip to content

fix(headless): explain missing workspace dir on switch failure#682

Open
imskull wants to merge 1 commit into
kxn:masterfrom
imskull:fix/headless-explain-missing-workspace-dir
Open

fix(headless): explain missing workspace dir on switch failure#682
imskull wants to merge 1 commit into
kxn:masterfrom
imskull:fix/headless-explain-missing-workspace-dir

Conversation

@imskull

@imskull imskull commented Jun 6, 2026

Copy link
Copy Markdown

Problem

When switching to a workspace whose directory was moved or deleted, the managed
headless launch reaches exec and the OS rejects it with an opaque
"The directory name is invalid." error. This surfaces to the Feishu client as a
generic switch failure with no explanation, leaving the user with no idea what
went wrong or how to recover.

Fix

When the launch fails and the workspace directory no longer exists on disk, map
the failure to an explanatory ErrorInfo (headless_workspace_dir_missing) that
tells the user the directory is gone and to reselect / re-import the workspace.
The raw OS error is preserved in Details. Any other launch failure is returned
untouched, and the success path is unchanged.

Testing

  • go build ./internal/app/daemon/
  • go test ./internal/app/daemon/ -run TestExplainMissingWorkspaceLaunchError -v (2 new unit tests, both pass)
  • go vet ./internal/app/daemon/ clean

(Two pre-existing setup/onboarding test failures on master are unrelated to this change.)

When switching to a workspace whose directory was moved or deleted, the
managed headless launch reaches exec and the OS rejects it with an opaque
"The directory name is invalid." error, which surfaces to the Feishu client
as a generic switch failure with no explanation.

Map that launch failure to an explanatory ErrorInfo
(headless_workspace_dir_missing) when the workspace directory no longer
exists, telling the user the directory is gone and to reselect/re-import it,
while preserving the raw OS error in Details. The success path is untouched.
imskull added a commit to imskull/codex-remote-feishu that referenced this pull request Jun 6, 2026
…p budget

Bring the fork current with upstream/master (16 commits). Conflict
resolutions:

- Resume internals (app_surface_resume_state.go, runtime_state.go,
  surface_resume_state_test.go, service_surface_resume_test.go,
  service_surface_thread_selection.go): take upstream's StickyFailureCode /
  recordSurfaceResumeFailureLocked design. The fork's earlier resume fixes
  (10c42c6/a2af8190/2a5c2bb7) are superseded by upstream's equivalent
  handling and were dropped.

- New feature on top of upstream: a bounded-retry give-up budget that the
  upstream design still lacked. After surfaceResumeMaxFailedAttempts (3)
  consecutive same-code failures a headless/vscode surface stops polling and
  emits one "已停止自动恢复" hand-off notice (use /list or /use), re-armed only
  when the resume target changes or the daemon restarts. The counter is
  deduped per tick (LastAttemptAt guard) so the synchronous recovery loop and
  the async outcome scan sharing one `now` cannot double-count.

- app_headless.go: keep upstream's refactored handleManagedHeadlessLaunchFailure
  and re-apply the missing-workspace-dir explanatory error on the exec-failure
  path (matches PR kxn#682).

- Docs: take upstream's newer state-machine summaries; document the give-up
  budget in remote-surface-state-machine.md.

Tests: new unit tests for the give-up counter dedup and one-time hand-off, plus
the existing missing-workspace-dir tests, all pass. Pre-existing setup/onboarding
and symlink-privilege test failures on Windows are unrelated.
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