Skip to content

chore(workflow): remove the dead workflow/say surface and its fake receipt #1475

Closed

Description

@HugoXK

Written-by: FlyBot Product

Cleanup, not a user-facing defect. The stage composer that used to call this endpoint was removed by #1461 on the owner's decision in #1459 ("Workflow does not need messaging"), so nothing in the product can send a workflow/say message today. What is left is dead surface that still lies when called: say() always records the text and, while a node runs, invents a reply ("收到。我继续处理「…」") that no Bot ever said. Owner has opened this line to us (2026-10-27): we implement it and will open a PR once the grep list below is confirmed.

Why now

  • #1455 is closed as not planned: the entry point is gone (#1459 / #1461).
  • plugins/workflow/index.js:105 still registers the endpoint, so any script or Bot that knows the name can call it and get a fabricated receipt.
  • The rest is dead weight for the next reader: one command in a docs sentence, one handler, one service method, one test half.

Grep inventory (clean tree at 8f1ac121)

grep -rn "workflow/say" .

./docs/subsystems/workflow.md:41:- `workflow/create`, `workflow/rename`, `workflow/delete`, `workflow/assign`, `workflow/concurrency`, `workflow/graph`, `workflow/advance`, `workflow/reset`, `workflow/say`, `workflow/ingest` write. ...
./plugins/workflow/index.js:105:    fb.api.handle('workflow/say', body => service.say(body)),

grep -rn "say(" plugins/workflow --include=*.js

plugins/workflow/src/service.js:879:    say(body = {}) {
plugins/workflow/index.js:105:    fb.api.handle('workflow/say', body => service.say(body)),
plugins/workflow/test/assign.test.js:125:test('a read-only host refuses assign, and a say lands in the workflow chat', () => {
plugins/workflow/test/assign.test.js:132:  const said = live.say({ workflowId: DELIVERY_ID, text: '请把 notice 再短一点' })
plugins/workflow/test/assign.test.js:135:  live.assign({ workflowId: DELIVERY_ID, taskId: '#say', title: 'Notice tweak' })
plugins/workflow/test/assign.test.js:136:  const withRun = live.say({ workflowId: DELIVERY_ID, text: '继续' })

grep -rn "收到。我继续处理" .

plugins/workflow/src/service.js:889:          lines.push({ kind: 'bot', botId: running, step: '进行中', text: `${node?.name ?? running}:收到。我继续处理「${run.task?.title ?? ''}」。` })

No caller anywhere else: grep -rn "workflow/say" plugins/workflow/client.js core/ returns nothing, and no test asserts the registered-name list contains it.

Additional hit on live main 5b9d0d7 (Dev-2's grep):

grep -n say plugins/workflow/README.md

49:A reply that says the model could not answer (`could not answer your message` or `model call failed`) fails that node in the chat. It is not retried in a loop, and its successor does not start. A 429 or a rate-limit mention in an otherwise successful reply does not fail the node.
74:Endpoints, all under `flybot/workflow/`: `state`, `templates` (read), `create`, `assign`, `concurrency`, `advance`, `reset`, `say`, `graph`, `ingest`.

:49 is prose ("says") and stays; the endpoint list at :74 is the hit to remove.

Scope — delete exactly these

  1. plugins/workflow/index.js:105 — the fb.api.handle('workflow/say', …) registration.
  2. plugins/workflow/src/service.js:879-893 — the say() method, including the fabricated { kind: 'bot', … } line at :889 ("收到。我继续处理…").
  3. docs/subsystems/workflow.md:41 — only the workflow/say token; that sentence lists ten write commands and the other nine stay.
  4. plugins/workflow/README.md:74 — the bare say in the endpoint list (line 74 on live main 5b9d0d7; it is the ninth of ten names). Remove the name and its comma; the other nine stay. The first inventory missed it because that list spells the endpoint without the workflow/ prefix, so grep "workflow/say" does not see it.
  5. plugins/workflow/test/assign.test.js:125-140 — the half that calls live.say() (and the /Planner|收到/ assertion at :139); keep the read-only assign refusal that shares this test, split into its own test.

Out of scope — do not touch (hard boundaries)

  • stageMessages() (plugins/workflow/client.js:137-145) and its two callers: filter and read-only stage chat stay exactly as they are.
  • Stored data: state.logs, saved messages and run history stay as they are; no migration, no deletion, no rewrite of workflows.json. Old fabricated lines remain as historical records and are not edited.
  • Every other endpoint keeps its behaviour: workflow/state, assign, advance, reset, pause, resume, graph, ingest, create, rename, concurrency, delete, templates.
  • The leftover .wf-composer CSS in plugins/workflow/client.js:1270-1272 is not part of this cleanup.
  • No new feature, no retry, no queue: deletion only.

Acceptance

  • Both greps (workflow/say, 收到。我继续处理) return no hits in the tree, and the endpoint list at plugins/workflow/README.md:74 no longer names say. A changelog entry that names the removal is the only allowed hit; none exists today, so today the result is zero.
  • node --test $(ls plugins/workflow/test/*.test.js) is green.
  • Reverse cases, one test each and still green: workflow/state reads, workflow/assign assigns, a run advances, workflow/delete deletes and releases.
  • The endpoint is gone, not emptied: the plugin's registered-endpoint list no longer contains workflow/say, and asking the host for that name answers Unknown FlyBot endpoint workflow/say with code bot/not-found (core/src/host/hooks.js:1044) — not { ok: true }, not {}, not undefined.
  • If any generated artifact carries the name, regenerate it with the repo's build script; never hand-edit a generated file.

Effort

0.5 person-day.

Sequence

Dev-2 posts the full grep list first (including the generated-artifact check); code changes only after that list is confirmed. Stop at local READY — no PR until then.

Activity

  1. added a commit that references this issue on Oct 28, 2026
    510ccfb
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