Repository navigation
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
Description
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) setsrun.status='failed',run.updatedAtandrun.failure={code, at, nodeName?, text?}; a step failure also setsnext.failure(:500-506).- One line lands in that graph's
messages:kind:'system', tone:'bad'(push() :273-280), serialized bywrite() :245-251. - No notification:
notify/deliver(hits insideplugins/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 byhistoryRow :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
- 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, elseupdatedAt), and the task it came from whenrun.task.idexists. publicRungains two additive fields:finishedAt(null while running) andcurrentStep({ id, name }or null) — nothing existing is renamed or removed.- 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
runningmust not appear; - a failed run whose card is gone (
run.task.idabsent) 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-graphruns/history/messages,service.js:296-330); reuse the existing statuses and card renderer; the answer path staysinboxAnswer.core/src/client/index.js: one actionworkflowState: () => call('workflow/state')(precedent:core/src/client/workflows.js:47readWorkflows(call), 8s timeout).plugins/workflow/src/service.js: add the two fields topublicRunonly (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 carrydata-run, neverdata-task).
Acceptance
- Red-first exactly as above on live main; the seeded running run stays out.
- Inbox row names graph + node + reason + time; clicking it opens that graph read-only (no new answer controls).
publicRundiff is additive only; every existing consumer ofpresent()still sees the same keys plus the two new ones.TZ=UTC ARCH_DOCS_BASE=<live main> npm run verifyexit 0 (report the measured counts);node scripts/ds-bot-patches.mjs checkgreen ifcore/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
HugoXK commentedon Oct 29, 2026
Handoff record (claim
b686bbd3a15447f7afce80aef62d5eafunchanged): this issue goes to FlyBot Dev-1 as bench work while#1701slice 1 is active on Dev-2, and the branch is renameddev/1-workflow-failure-inbox(the line above still saysdev/2-…, written at claim time). Base is live main742e06cce128b6a16fb37406881a53bd29ea5d64.Sequencing agreed with Dev-1: red first on that base — seed one
status:'failed'run carryingfailureand showinboxModel(...)surfaces 0 cards for it, with a still-runningrun as a negative control and a failed run withoutrun.task.idas a must-appear control — then a short row-shape andpublicRunfield-shape proposal before any implementation.#1701slice 1 is client-only kanban, so the two do not share files.HugoXK commentedon Oct 29, 2026
Release
Written-by: FlyBot Lead
Released: b686bbd3a15447f7afce80aef62d5eaf
Reason: shipped: #1716 merged 16:13:09Z
At: 2026-10-29T18:32:07Z