Synthetic API errors were carrying only English display text, so desktop chat could not distinguish our compatibility guidance from raw upstream failures and recovery logic depended on those English strings.
Add stable business error codes for media, PDF, request-size, prompt-length, and auto-mode errors. Desktop chat now resolves those codes through locale keys and suppresses the stale English fallback for known business errors, while normalizeMessagesForAPI still supports legacy text matching for old transcripts.
Constraint: Raw upstream provider details must remain available for diagnostics but should not drive localized business UX.
Rejected: Localize src/services/api/errors.ts strings directly | that would make persisted transcript text and media recovery depend on the active UI language.
Confidence: high
Scope-risk: moderate
Directive: Add new user-facing synthetic API errors with businessErrorCode values before localizing their display text.
Tested: bun test src/services/api/errors.test.ts tests/mediaRecoveryAndEstimation.test.ts src/server/__tests__/ws-memory-events.test.ts
Tested: cd desktop && bun run test -- run src/stores/chatStore.test.ts src/components/chat/MessageList.test.tsx
Tested: bun run check:server
Tested: bun run check:desktop
Not-tested: Manual desktop screenshot smoke for the rendered Chinese error card
The goal command now uses a session Stop hook as the durable completion mechanism and removes the separate evaluator path. Completion output is persisted as local command output so CLI streams, transcripts, and desktop history all see the same completed state.
Desktop keeps active goals in a compact header strip and lets completed goals render in the conversation flow, which avoids the old duplicate pinned card behavior while preserving visibility for running goals.
Constraint: /goal state has to survive transcript replay and desktop session restore.
Rejected: Keep the legacy evaluator alongside Stop hooks | duplicate completion paths made desktop state drift and hid the final card.
Confidence: high
Scope-risk: moderate
Directive: Keep goal completion events on the local_command transcript path unless desktop history restore is changed at the same time.
Tested: bun test src/goals/goalState.test.ts src/query/stopHooks.test.ts src/commands/goal/goal.test.tsx src/commands/headless.test.ts src/server/__tests__/ws-memory-events.test.ts src/server/__tests__/sessions.test.ts
Tested: bun run check:server
Tested: bun run check:desktop
Tested: real /tmp /goal CLI run 98fb4bb2-52da-4850-bc8e-e5e1cc0e4c51 with deepseek-v4-pro and WebUI screenshot verification
Not-tested: Remote release workflow
The goal flow needs to drive the agent loop and remain visible after desktop reconnects, so this change treats /goal output as a structured lifecycle signal across CLI, server, and desktop history restoration.
Constraint: The current TypeScript CLI does not share Codex's Rust app-server thread-goal database, so persistence is reconstructed from the existing session transcript.
Rejected: UI-only goal badges | would leave the CLI self-loop unable to recover active or completed goals after process restart.
Rejected: Add a new persisted store | larger migration surface than needed for the existing transcript-backed session model.
Confidence: high
Scope-risk: moderate
Directive: Keep future goal state changes mirrored in transcript-visible local command output or introduce a real migration-backed store.
Tested: bun test src/goals/goalEvaluator.test.ts src/goals/goalState.test.ts
Tested: cd desktop && bun run test -- --run src/stores/chatStore.test.ts src/pages/ActiveSession.test.tsx src/components/chat/MessageList.test.tsx
Tested: bun run verify
Not-tested: Live provider baseline with a real model-driven goal loop.
Coding sessions need a native way to keep working until a stated completion condition is actually met. This adds a CLI /goal command, goal state and evaluator logic, and a headless-safe command filter so interactive and print-mode runs can both start a goal and continue when the evaluator says more work remains.
Constraint: The evaluator must work with saved third-party provider runtimes that may reject structured output schemas.
Constraint: Completion evidence must come from visible transcript text, not hidden goal prompts or assistant thinking blocks.
Rejected: Implement /goal as a bundled skill only | it would not own the query loop or support native continuation semantics.
Rejected: Expose all local-jsx commands to headless mode | interactive UI commands would become available in print mode.
Confidence: high
Scope-risk: moderate
Directive: Keep /goal evaluator evidence scoped to visible transcript text before adding richer completion signals.
Tested: bun test src/commands/headless.test.ts src/goals/goalState.test.ts src/goals/goalEvaluator.test.ts
Tested: bun run check:server
Tested: bun run verify
Tested: Real provider /goal smoke with MiniMax-M2.7-highspeed, including a two-turn continuation that logged Goal continuation #1 and completed with GOAL_SMOKE_LOOP_DONE.
Not-tested: Durable cross-process goal persistence for resumed sessions.
Bypass all three gating layers (compile-time feature flag, subscription
check, GrowthBook remote config) and replace Anthropic's private native
modules (@ant/computer-use-swift, @ant/computer-use-input) with a Python
bridge using pyautogui + mss + pyobjc. Works on any macOS with any
Anthropic-protocol compatible model.