Skip to content

A failed workflow run never reaches the Inbox: it is visible only inside its own graph (and publicRun has no finishedAt or current step) #1706

Closed

Description

@HugoXK

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.

Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: b686bbd3a15447f7afce80aef62d5eaf
Branch: dev/2-workflow-failure-inbox
Base: 742e06c
At: 2026-10-29T14:44:04Z

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.

What happens today

A workflow run that fails writes its failure only into the workflow plugin's own state, and nothing surfaces it where the Owner looks:

  • plugins/workflow/src/service.js:642-657 (endRun) sets run.status='failed', run.updatedAt and run.failure={code, at, nodeName?, text?}; a step failure also sets next.failure (:500-506).
  • One line lands in that graph's messages: kind:'system', tone:'bad' (push() :273-280), serialized by write() :245-251.
  • No notification: notify / deliver( hits inside plugins/workflow/src/ = 0.
  • core/src/client/inbox.js: grep -c -i workflow = 0 — the Inbox never mentions a run.
  • No cross-graph run list anywhere (grep = 0). The sidebar live dot (plugins/workflow/client.js:2034), sidebarPreview (:357-363) and the Settings row preview (service.js:386-389) only describe runs that are running; they never show a failure.
  • The only place a failure is readable is Settings → Workflow → that graph → Runs tab (plugins/workflow/client.js:612-618, :1290, failureText :250-257, fed by historyRow :690-700).

So the Owner asking "did last night's card fail, and where" must already know which graph it ran in: 4 steps plus prior knowledge.

Also missing in the payload

publicRun (service.js:89-107) returns status, startedAt, updatedAt, failure? …, but no finishedAt and no explicit current step: steps is an integer count (blankRun :122-123), and the current step has to be derived from running + nodeStatus. A read-only consumer (Inbox) therefore cannot say "failed at 03:12 on node X" without guessing.

Expected

  1. A failed run appears in the Inbox as a notification row: graph name, failing node name, reason (failure.nodeName / failure.text / failure.code), when (finishedAt, else updatedAt), and the task it came from when run.task.id exists.
  2. publicRun gains two additive fields: finishedAt (null while running) and currentStep ({ id, name } or null) — nothing existing is renamed or removed.
  3. No second answer entry: the row reuses STATUSES / InboxCard / inboxAnswer; a failed-run row does not grow its own button set.

Red-first (must be shown on live main, before any fix)

Seed a state with one status:'failed' run carrying a failure, then on live main:

  • inboxModel(...) (or the equivalent Inbox card list) contains 0 cards mentioning that run — this is the red;
  • after the fix: exactly 1 card, naming graph + node + reason;
  • a run that is still running must not appear;
  • a failed run whose card is gone (run.task.id absent) must still appear (it is the run that failed, not a task row).

Scope

  • core/src/client/inbox.js: add the workflow source from the existing payload (workflow/state → present(): per-graph runs/history/messages, service.js:296-330); reuse the existing statuses and card renderer; the answer path stays inboxAnswer.
  • core/src/client/index.js: one action workflowState: () => call('workflow/state') (precedent: core/src/client/workflows.js:47 readWorkflows(call), 8s timeout).
  • plugins/workflow/src/service.js: add the two fields to publicRun only (read-only additive).
  • Not in scope: any change to the run's write path, any new endpoint, any new store, core/src/shared/workflow-run.js / workflow-store.js, and merging a run into the core task identity (rows carry data-run, never data-task).

Acceptance

  1. Red-first exactly as above on live main; the seeded running run stays out.
  2. Inbox row names graph + node + reason + time; clicking it opens that graph read-only (no new answer controls).
  3. publicRun diff is additive only; every existing consumer of present() still sees the same keys plus the two new ones.
  4. TZ=UTC ARCH_DOCS_BASE=<live main> npm run verify exit 0 (report the measured counts); node scripts/ds-bot-patches.mjs check green if core/ mirrors change.

Evidence re-read at live main d5347032 by FlyBot Product (scheduled audit) and re-checked by FlyBot Lead on the same commit.

Activity

  1. HugoXK commented on Oct 29, 2026

    @HugoXK
    ContributorAuthor

    Handoff record (claim b686bbd3a15447f7afce80aef62d5eaf unchanged): this issue goes to FlyBot Dev-1 as bench work while #1701 slice 1 is active on Dev-2, and the branch is renamed dev/1-workflow-failure-inbox (the line above still says dev/2-…, written at claim time). Base is live main 742e06cce128b6a16fb37406881a53bd29ea5d64.

    Sequencing agreed with Dev-1: red first on that base — seed one status:'failed' run carrying failure and show inboxModel(...) surfaces 0 cards for it, with a still-running run as a negative control and a failed run without run.task.id as a must-appear control — then a short row-shape and publicRun field-shape proposal before any implementation. #1701 slice 1 is client-only kanban, so the two do not share files.

  2. HugoXK commented on Oct 29, 2026

    @HugoXK
    ContributorAuthor

    Release

    Written-by: FlyBot Lead
    Released: b686bbd3a15447f7afce80aef62d5eaf
    Reason: shipped: #1716 merged 16:13:09Z
    At: 2026-10-29T18:32:07Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions