Skip to content

board → workflow: a task card with a workflow token starts no run (match requires status "open") #1462

Closed

Description

@Birfy

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 {}.

Repro (2026-10-27)

  1. Board card task-da7da173a16106d5 (#1460) updated to column not-started, note workflow:wf-a85c4250 · 无 PR,分诊后由 issue 流水线开发.
  2. 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.

Activity

  1. Birfy commented on Oct 28, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Triage

    Triage: agent-ready. The defect is real, but not where the report puts it — and that changes the fix. Verified on main 176d33d0 (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.

    Scope (keep #1318's rule: open cards only, claimed/working/finished untouched, reverse column moves stay refused)

    1. 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.
    2. 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.

  2. added
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 28, 2026
  3. self-assigned this
    on Oct 28, 2026
  4. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 28, 2026
  5. Birfy commented on Oct 28, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Dev

    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.

  6. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 28, 2026
  7. Birfy commented on Oct 28, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Triage

    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.

  8. Birfy commented on Oct 28, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Triage

    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.

  9. added a commit that references this issue on Oct 28, 2026
    034aba2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

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