Files
Bohan Jiang 4581e9ee76 fix(server): surface real reason for failed quick-create (MUL-5268) (#5898)
* fix(server): surface real reason for failed quick-create (MUL-5268, #5885)

When an agent's quick-create run finishes without producing an issue, the
completion path wrote a fixed "agent finished without creating an issue"
inbox, discarding the real reason — most often the active-duplicate guard
rejecting the create. Users saw no actionable detail.

notifyQuickCreateCompleted now:
- distinguishes pgx.ErrNoRows (a confirmed no-issue → real failure) from a
  genuine lookup fault (DB/timeout), so a transient error no longer mislabels
  a run that may actually have created the issue;
- on the real-failure branch, surfaces the agent's final output as the
  failure reason. The quick-create prompt already requires the agent to exit
  with the CLI error as its only output, so this carries the concrete cause
  (e.g. the existing issue's identifier + status), unescaped, bounded, and
  redacted. Empty output falls back to the existing generic message.

No API/CLI contract or migration change.

Co-authored-by: multica-agent <github@multica.ai>

* fix(server): never end quick-create with no notification on lookup fault

Review follow-up. The previous commit returned silently when the completion
lookup failed with a non-ErrNoRows error, to avoid misreporting a failure that
was never observed. But the task is already completed and nothing retries this
reconciliation, so a single transient DB fault permanently stranded the
requester with no inbox result at all.

The indeterminate branch now writes a neutral, terminal notification: it does
not assert failure (the agent may have created the issue), does not reuse the
agent output as if it were the confirmed reason, and points at the one safe
next step — check recent issues before retrying, so a retry cannot silently
produce the duplicate the guard exists to prevent.

notifyQuickCreateFailed / notifyQuickCreateUnconfirmed are now thin wrappers
over a shared writer so both outcomes keep the identical row shape and the
frontend's 'Edit as advanced form' recovery affordance.

Tests:
- TestQuickCreateLookupFault_WritesUnconfirmedInbox: fails against the previous
  commit with 'no rows in result set' (the exact silent-drop), passes now. Uses
  a DBTX wrapper that faults only GetIssueByOrigin so the inbox write still
  reaches the real DB.
- TestQuickCreateFailure_RedactsAgentOutput: locks in that the newly-surfaced
  agent output is scrubbed before storage.

Co-authored-by: multica-agent <github@multica.ai>

* fix(inbox): render unverified quick-create outcome as neutral, not failed

Review round 2. Three fixes.

1. Rebased onto main and updated the three CompleteTask call sites for the
   new sessionRolloutMissing parameter; the branch no longer compiles-fails
   on the merge ref.

2. The unverified outcome reused the quick_create_failed inbox type, so every
   client framed it as a failure regardless of the neutral title/body: web
   list rendered 'Failed: {detail}', web detail showed 'Create with agent
   failed', mobile rendered 'Failed: ...', and getInboxDisplayTitle replaced
   the neutral title with the original prompt. Users saw 'Failed: Couldn't
   confirm...' — asserting a failure never observed. Added a distinct
   quick_create_unconfirmed type end to end: core type union, web list label
   (no failure framing), web detail pane, the original-prompt box and 'Edit as
   advanced form' recovery affordance, mobile label + display title, and en /
   zh-Hans / ja / ko strings. Older clients hit their existing default branch
   and render the already-neutral title.

3. The terminal notification reused the caller's context, so a lookup that
   failed with context.Canceled / DeadlineExceeded failed the write for the
   same reason and still dropped the notification. The write is now detached
   via context.WithoutCancel with a bounded timeout.

Tests (each verified to fail without its fix):
- TestQuickCreateLookupCancelled_StillWritesUnconfirmedInbox: cancels the ctx
  at the lookup; without the detach, 'no rows in result set'.
- inbox-detail-label.test.tsx: resolves accessors against the real en locale;
  pointing the unconfirmed case back at failed_with_detail reproduces
  'Failed: Couldn't confirm...'.
- inbox-display.test.ts: both outcomes stay recoverable rows.

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: J <j@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
2026-07-27 15:35:09 +08:00
..