Files
open-design/e2e
cd07d359df feat(chat): surface daemon failure_detail to sharpen run-error guidance (#5321)
* feat(chat): surface daemon failure_detail to sharpen run-error guidance

The daemon already classifies each run failure into failure_category /
failure_detail (run-failure-classification.ts) for retry policy and
telemetry, but kept it daemon-internal — so the chat could only key error
guidance off the coarse errorCode. That collapses distinct causes that
share one code: a hard quota and a transient 429 both arrive as
RATE_LIMITED, and a text-detected missing CLI leaks in as the opaque
AGENT_EXECUTION_FAILED.

Propagate the classification to the client (contract DTO + SSE end frame,
mirroring the proven `resumable` path) and let resolveRunFailureUi take
`detail` as a first-class input that can override a too-coarse code:

- hard_quota / workspace_credits_exhausted -> a distinct "Quota exhausted"
  card that drops the futile Retry (primaryAction 'none') and steers to the
  hosted-AMR switch card instead.
- cli_not_installed (text-detected) -> the same install-the-CLI card the
  AGENT_UNAVAILABLE code path already renders.

A transient 429 without a hard-quota detail still offers Retry, and the
Antigravity terminal switch-model flow still wins over the generic detail
override.

Stacks on #5308 (the code->guidance mapping this detail layer refines).

* chore(i18n): rebrand user-facing "AMR" to "Open Design Cloud"

The hosted model service is now Open Design Cloud, but the run-error
cards this PR sharpens (switch / auth / balance), plus settings account +
wallet labels, avatar console, onboarding gate, and the handoff website
link, still showed the old "AMR" (or bare "Open Design") name. Normalize
every user-visible brand mention to "Open Design Cloud" across all 19
locales. Value-only: no keys, agent ids, URLs, or raw daemon error
strings touched.

* fix(chat): persist daemon failure classification onto assistant message

The daemon emits the terminal `error` SSE frame from the child-close
handler before a run is finalized, so `failureCategory` / `failureDetail`
(computed at finalize) weren't known when that frame was first persisted
to the assistant message — the stored `status:error` event kept only
`{ detail, code }`. A failure persisted without the live web error
handler saving the message, or a conversation reloaded before that save
landed, therefore fell back to the coarse errorCode UI and lost the
specific fix guidance this PR adds.

Stamp the finalize-time classification onto the persisted assistant
message: enrich the last `status:error` event in place (append one only
if a failed run somehow never persisted an error frame). Covered by a
daemon regression that reads the stored assistant message via the
conversation-messages API after a failed hard-quota run.

* fix(chat): keep daemon failure classification on the live web reload/recovery paths

Two live-propagation gaps let the sharpened run-error card degrade back to
the coarse/raw UI even though the daemon now sends the classification:

- appendErrorStatusEvent() no-op'd whenever the message already had a
  trailing status:error with the same detail. In the reload/reattach race
  (reload reads the daemon-persisted error frame first, then the run
  finishes and onError arrives with the finalize-time classification) that
  dropped the new code / failureCategory / failureDetail. Merge those into
  the existing event in place instead; no-op only when nothing is added.

- The error-frame-then-status recovery probe in providers/daemon.ts broke
  out on a terminal failed status without copying failureCategory /
  failureDetail (unlike the post-loop status fallback), so markErrorRunFailure
  stamped null and the failureDetail mapping fell back to the generic card on
  the reconnect path. Mirror the two assignments before the break.

Covered by chat-events (in-place merge) and daemon-sse-reconnect (error
frame + terminal status fetch, no end frame) regressions.

* fix(web): update AMR tier-upgrade test for 3-arg resolveRunFailureUi

The main merge kept a two-argument call site that passed agentId as
detail after the signature gained an explicit detail parameter.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci: re-trigger validate workspace on approved head

Co-authored-by: Cursor <cursoragent@cursor.com>

* test: align AMR rebrand assertions with Open Design Cloud copy

Update unit and e2e selectors that still expected pre-rebrand strings
for account status, handoff website link, and switch-and-retry CTA.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-10 03:46:01 +00:00
..