6.6 KiB
created, status, requirements, system_design, legacy_specs
| created | status | requirements | system_design | legacy_specs | ||||
|---|---|---|---|---|---|---|---|---|
| 2026-09-05 | completed |
|
|
Implementation Plan: Task Launch Error Consolidation
Overview
The change first isolates pull-request refs from reused local branch names. Then it makes recovery actions category-specific. The final work order gives one error card ownership of the desktop and phone presentation.
Confirmed root cause
PR #3408 uses feature/unit-7-reject-leg-wa-waj at
a76c5d8de780b0b857af8195eab4772bb1a5839b. The shared clone still has the same
local branch from PR #3294 at f825122f586978ed5e33fe48d61e401a610318e2.
Neither commit contains the other. The required fetch tried to update the local branch directly. Git rejected the update as non-fast-forward, and preparation stopped before the agent started.
The backend stored one typed launch error. The frontend also derived a previous agent error, a failed preparation row, an empty-turn warning, a generic failed status, and a stopped-session recovery banner from the same failed start.
Scope
In scope
- Preserve a reused local branch and prepare the exact pull-request head.
- Classify checkout preparation separately from base-branch errors.
- Offer only category-valid recovery actions.
- Render one matching launch-error card on desktop and phone.
- Keep bounded technical details in one disclosure.
- Prove the error and recovery flows with unit and Playwright tests.
Out of scope
- Reconcile provider and local history after an agent starts.
- Change generic runtime-error recovery after successful agent startup.
- Add new provider-specific branch pickers.
- Change pull, push, merge, rebase, or force-push policy.
Technical approach
Pull-request ref isolation
Update apps/backend/internal/worktree/manager_lifecycle.go to fetch a
pull-request head into the Kandev-owned refs/kandev/pull/<N>/head ref. Verify
that full ref before worktree creation. If a same-named local branch has
unrelated history, create a unique task branch from the verified ref using a
task-owned suffix and bounded collision retries. Set a source-branch upstream
only when its commit matches the verified PR start point.
Keep the named local branch unchanged. Continue to use the existing Git admission, timeout, and non-interactive environment.
Failure category and recovery
Add workspace_checkout_failed and retry_launch to
apps/backend/internal/task/models/launch_errors.go. Preserve unknown-value
filtering in the task-status projection.
Update apps/backend/internal/orchestrator/executor/launch_failure.go so the
failure category selects the action list. A repository row must not add branch
actions to a generic error.
Extend task.launch.recover in
apps/backend/internal/orchestrator/task_launch_recovery.go and its WebSocket
handler. retry_launch must validate the current stamp and relaunch without a
base-branch write.
Single frontend owner
Derive one ownership flag in apps/web/components/task/task-chat-panel.tsx from
the active error, session identity, and stamp. Pass this flag to the transcript
and composer boundaries.
Update TaskLaunchErrorEntry with category-specific titles, cause text, a
no-change statement, and a technical-details disclosure. Keep action state and
WebSocket requests in the existing component.
When the flag is active, suppress the matching last-agent-error notice, preparation row, empty-turn notice, failed-agent status, stopped-session banner, and focused-task toast. Do not suppress unrelated historical or runtime errors.
Mobile contract
Desktop and phone use the task Chat surface. The phone card stacks full-width actions. All touch actions have at least a 44-pixel hit area.
The task transcript owns scrolling. The details disclosure wraps its bounded
content without an inner scroll region. Base-branch selection keeps the existing
MobilePickerSheet behavior.
Tests
apps/backend/internal/worktree/manager_pr_head_collision_test.gocovers two pull requests that reuse one branch name with divergent histories.apps/backend/internal/orchestrator/executor/executor_launch_failure_classification_test.gocovers category-specific actions.apps/backend/internal/orchestrator/task_launch_recovery_test.gocovers authorized, stale, and failedretry_launchrequests.- Frontend tests cover one-owner arbitration, the details disclosure, action payloads, launch-error ownership in the composer, recovery-state reset, and preservation of unrelated runtime errors.
E2E tests
apps/web/e2e/tests/task/launch-failure-recovery.spec.tsproves one desktop error card, one retry action, and no matching duplicate surfaces.apps/web/e2e/tests/task/mobile-launch-failure-recovery.spec.tsproves the same result onmobile-chrome, 44-pixel actions, and no horizontal overflow.
These tests map to
AC-TASKS-TASK-LAUNCH-FAILURE-RECOVERY-001.2,
AC-TASKS-TASK-LAUNCH-FAILURE-RECOVERY-001.7, and
AC-TASKS-TASK-LAUNCH-FAILURE-RECOVERY-001.8.
Work orders
- Task 01: Isolate reused pull-request refs
- Task 02: Classify launch recovery actions
- Task 03: Consolidate launch-error presentation
Verification results
- Backend focused race coverage passed: 1,212 tests across worktree, task models, status summary, and executor packages, plus 11 targeted task-launch recovery tests.
- Frontend focused coverage passed: 10 Vitest files and 152 tests.
- Review-remediation frontend coverage passed: 7 Vitest files and 75 tests, including task-wide launch-error visibility, composer ownership, and recovery-state reset.
pnpm run typecheck,pnpm run lint,pnpm run i18n:check, andpnpm run i18n:ratchetpassed.- Managed Playwright coverage passed: desktop launch-failure recovery 3/3 and mobile launch-failure recovery 2/2.
- The broader orchestrator package run was attempted but exceeded its timeout in an existing SQLite/concurrency test; the focused race and recovery suites passed independently.
Risks
- A ref-selection error can discard local-only commits. Tests must prove that the existing branch remains unchanged.
- Error events can arrive in a different order from task-status updates. The owner logic must converge after either event order.
- Old persisted generic errors can contain branch actions. Projection and UI normalization must not show actions that conflict with the current category.