You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
board → workflow: a task card with a workflow token starts no run (match requires status "open") #1462
What happens
A card written with an explicit workflow:<id> token and put back to not-started starts no run. lanes[wf-a85c4250].queue and active stay empty, routes stays {}.
Read /data/dsh/bot/flybot-workflow/workflows.json 4 s later: wf-a85c4250 lane active: [], queue: [], top-level routes: {} — no run, no route entry.
Why it cannot match @flybot/workflow/match.js returns null on task.status !== "open"; the DSH board carries column (not-started / in-progress / done), so the two vocabularies never meet. The wiring itself is optional and guarded: index.js:151 if (typeof fb.tasks?.onWrite === "function") — when the host has no tasks.onWrite, the hook is silently skipped and nothing reports it.
Acceptance
(a) a card put back to not-started with a workflow:<id or name> token starts a run (or queues one when the lane is at maxConcurrent) within a few seconds; (b) when the hook is unavailable the Workflow panel shows it, instead of looking like manual-only by design; (c) either matchTask accepts the board column vocabulary, or the hook translates column → status before matching.
Why it matters: an operator who fills the board expects the pipeline to pick work up; today only an explicit run_workflow does that, and the UI gives no hint.
Triage: agent-ready. The defect is real, but not where the report puts it — and that changes the fix. Verified on main176d33d0 (2026-10-28T06:2xZ).
What the code says
flybot.tasks.onWrite exists (core/src/host/hooks.js:1306) and this plugin already registers it (plugins/workflow/index.js:160). "No onWrite, silently skipped" is not the cause on this build.
The listener receives view(task), which carries status (open / claimed / working / …), not column — so matchTask's status === 'open' gate is not a vocabulary clash either.
Only two write paths ask the listener: task-create (core/src/host/tasks.js:951) and task-update (:965). The track_tasks path (rt.trackBotTasks, tasks.js:635-780) saves the card and never calls routeOpenTask.
The repro card proves it.task-da7da173a16106d5 carries an actor at 2026-10-27T14:41:27Z with status: open, by: conversation and no memberId — that is the record() at tasks.js:766, i.e. a track_tasks write that set note workflow:wf-a85c4250 · … and a no-op column: not-started. The card was open, the workflow wf-a85c4250 existed, and workflows.json still shows routes: {} — ingest was never called.
So the class is: a board write that does not come through task-create/task-update never asks the plugin — exactly the path a Bot uses to record its own cards.
core/src/host/tasks.js: after save() in trackBotTasks, route each saved card through routeOpenTask(task, 'create' | 'update'), and return the views after routing so a routed ownerBotId is visible. No recursion: routeOpenTask → ingest writes the workflow store, not the board.
plugins/workflow/index.js: in the else of the tasks.onWrite registration, warn once instead of skipping silently, and expose the wiring flag in service.state(); plugins/workflow/client.js shows one line on the stage/panel when the flag is false (acceptance b).
Acceptance
A track_tasks card with workflow:<id or name> starts a run, or queues one at maxConcurrent, within a few seconds, and workflows.json gains routes[<taskId>] with key workflow:<id>.
A second identical write is a no-op (ingest.already), no second run.
A host without tasks.onWrite warns and the Workflow panel shows the wiring is unavailable.
npm run verify green; arch-docs satisfied (update docs/subsystems/workflow.md — the wiring line at :43 and the "open card only" note at :54 — and the core-host page that owns core/src/host/**, or a valid Docs-not-needed: trailer in both the branch commit and the PR body).
Tests, red first
core/test/task-route.test.js: register a listener via rt.flybot.scope('flybot-workflow').tasks.onWrite, write through rt.trackBotTasks(botId, { tasks: [{ title: 'please workflow:delivery' }] }), assert the listener saw the card once and its { ownerBotId } was applied — red on main.
plugins/workflow/test/assign.test.js: apply with an fb that has no tasks → one warn and a false flag in state; with tasks.onWrite → true.
plugins/workflow/test/host.test.js: end-to-end through the real host — a track_tasks write starts a run.
Tier: T2 — core/src/host/** and plugins/** are both T2 in .github/agent/risk-rules.json; the PR needs a PASS at the tip plus green tests-ok. Nothing here touches the security surface.
Claimed #1462 — first step: route track_tasks cards through routeOpenTask.
Branch dev/1462-track-tasks-route, base main @ 176d33d. Following the triage scope: core/src/host/tasks.js routes each card saved by rt.trackBotTasks and returns the routed views, plugins/workflow/index.js warns once and exposes the wiring flag instead of skipping silently, the client shows it, plus tests (red first) and the subsystem docs.
Reconcile at 2026-10-28T10:35:25Z: PR #1568 already exists (branch dev/1462-track-tasks-route, head 1b320caa9915255f89f37bd5b4638dbfe1228464, body Fixes #1462, labelled agent-pr), so agent-ready is removed and no new implementation starts here.
Next action is on the pull request: CI at the tip, then a Reviewer PASS at that tip, then the queue. Its mergeable was still unknown at this read (GitHub had not finished computing it).
Label repair at 2026-10-28T10:50:22Z: agent-pr added — this issue's open pull request is #1568 (this repository), head 1b320caa9915255f89f37bd5b4638dbfe1228464. Implementation stays on the pull request line; nothing new starts from this issue.
Activity
Birfy commentedon Oct 28, 2026
Written-by: Triage
Triage:
agent-ready. The defect is real, but not where the report puts it — and that changes the fix. Verified onmain176d33d0(2026-10-28T06:2xZ).What the code says
flybot.tasks.onWriteexists (core/src/host/hooks.js:1306) and this plugin already registers it (plugins/workflow/index.js:160). "NoonWrite, silently skipped" is not the cause on this build.view(task), which carriesstatus(open/claimed/working/ …), notcolumn— somatchTask'sstatus === 'open'gate is not a vocabulary clash either.task-create(core/src/host/tasks.js:951) andtask-update(:965). Thetrack_taskspath (rt.trackBotTasks,tasks.js:635-780) saves the card and never callsrouteOpenTask.The repro card proves it.
task-da7da173a16106d5carries an actor at2026-10-27T14:41:27Zwithstatus: open, by: conversationand nomemberId— that is therecord()attasks.js:766, i.e. atrack_taskswrite that set noteworkflow:wf-a85c4250 · …and a no-opcolumn: not-started. The card wasopen, the workflowwf-a85c4250existed, andworkflows.jsonstill showsroutes: {}—ingestwas never called.So the class is: a board write that does not come through
task-create/task-updatenever asks the plugin — exactly the path a Bot uses to record its own cards.Scope (keep #1318's rule:
opencards only, claimed/working/finished untouched, reverse column moves stay refused)core/src/host/tasks.js: aftersave()intrackBotTasks, route each saved card throughrouteOpenTask(task, 'create' | 'update'), and return the views after routing so a routedownerBotIdis visible. No recursion:routeOpenTask→ingestwrites the workflow store, not the board.plugins/workflow/index.js: in theelseof thetasks.onWriteregistration, warn once instead of skipping silently, and expose the wiring flag inservice.state();plugins/workflow/client.jsshows one line on the stage/panel when the flag is false (acceptance b).Acceptance
track_taskscard withworkflow:<id or name>starts a run, or queues one atmaxConcurrent, within a few seconds, andworkflows.jsongainsroutes[<taskId>]with keyworkflow:<id>.ingest.already), no second run.tasks.onWritewarns and the Workflow panel shows the wiring is unavailable.npm run verifygreen; arch-docs satisfied (updatedocs/subsystems/workflow.md— the wiring line at :43 and the "open card only" note at :54 — and the core-host page that ownscore/src/host/**, or a validDocs-not-needed:trailer in both the branch commit and the PR body).Tests, red first
core/test/task-route.test.js: register a listener viart.flybot.scope('flybot-workflow').tasks.onWrite, write throughrt.trackBotTasks(botId, { tasks: [{ title: 'please workflow:delivery' }] }), assert the listener saw the card once and its{ ownerBotId }was applied — red onmain.plugins/workflow/test/assign.test.js:applywith anfbthat has notasks→ one warn and afalseflag in state; withtasks.onWrite→true.plugins/workflow/test/host.test.js: end-to-end through the real host — atrack_taskswrite starts a run.Tier: T2 —
core/src/host/**andplugins/**are both T2 in.github/agent/risk-rules.json; the PR needs a PASS at the tip plus greentests-ok. Nothing here touches the security surface.Birfy commentedon Oct 28, 2026
Written-by: Dev
Claimed #1462 — first step: route
track_taskscards throughrouteOpenTask.Branch
dev/1462-track-tasks-route, basemain@ 176d33d. Following the triage scope:core/src/host/tasks.jsroutes each card saved byrt.trackBotTasksand returns the routed views,plugins/workflow/index.jswarns once and exposes the wiring flag instead of skipping silently, the client shows it, plus tests (red first) and the subsystem docs.Route a card written through track_tasks to the board listeners (#1462)
Birfy commentedon Oct 28, 2026
Written-by: Triage
Reconcile at 2026-10-28T10:35:25Z: PR #1568 already exists (branch
dev/1462-track-tasks-route, head1b320caa9915255f89f37bd5b4638dbfe1228464, bodyFixes #1462, labelledagent-pr), soagent-readyis removed and no new implementation starts here.mergeablewas stillunknownat this read (GitHub had not finished computing it).Birfy commentedon Oct 28, 2026
Written-by: Triage
Label repair at 2026-10-28T10:50:22Z:
agent-pradded — this issue's open pull request is #1568 (this repository), head1b320caa9915255f89f37bd5b4638dbfe1228464. Implementation stays on the pull request line; nothing new starts from this issue.Route a card written through track_tasks to the board listeners (#1462)
Route a card written through track_tasks to the board listeners (#1462)
Route a card written through track_tasks to the board listeners (#1462)
Route a card written through track_tasks to the board listeners (#1462)
fix(core): route a card written through track_tasks to the board list…