Repository navigation
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: d83fd79da03e4896a362a962d6eef136
Branch: dev/4-plugin-workflow-settings-readonly
Base: c21e6da
At: 2026-11-02T15:06:10Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
What happens
In a read-only window (roster.readOnly is a non-empty host sentence) the plugin's own page Settings → Workflow graphs is still fully editable: the Edit toggle is unconditional, cards can be dragged, an "Add link" form can add wires, and the only thing that stops the edit is the host refusing the save at the end.
plugins/workflow/client.js at c21e6da05dd6c287b044ea84f5d2612421e03a72 contains readOnly zero times.
Consequences:
- The user rearranges a flow, presses save, and gets an English refusal (
bot/read-only) — the arrangement stays on the canvas but not in the host. - The next successful save in an editable window starts from
current.nodes, so the discarded arrangement can overwrite nothing and the user's work is silently lost.
This is not #2176 / #2181: those are about the core client page (core/src/client/workflows.js, core/client.js, …). This one is the plugin page plugins/workflow/client.js, a different component in the same read-only window. #2181 leaving main does not fix it.
Reproduction (at c21e6da0)
Mount the real component and drive it, with call recording every host request:
mount(client.WorkflowSettings, { call, roster: { bots: [], readOnly: '<host sentence>' } })On the unmodified tree:
edit-button-present: true— the Edit button is rendered and enabled;readonly-sentence-rendered: false— the host sentence appears nowhere on the page;add-link-present: true— the Add link entry is rendered;- a drag of one card plus
pointeruprecordsworkflow/graph1 time (the plugin saves the whole graph).
Failing tests written against this tree (new cases in a copy of plugins/workflow/test/client.test.js, applied to a clean git archive c21e6da0): 116 tests / 113 pass / 3 fail —
not ok 113 - a read-only window offers no Edit control and shows the host reason
not ok 114 - a read-only window never writes the graph from a drag
not ok 115 - a read-only window offers no Add link and no wire port
ok 116 - a read-only window still reads the graph through workflow/state
116 is the control: reading must keep working through workflow/state, so the fix must not lock the read path. With the change applied, the same file is 116 / 116.
Expected behaviour
With a non-empty roster.readOnly (trimmed):
- No Edit control; the host sentence is rendered once with
role="status"(reuse the host text, do not invent new wording). - Dragging a card and releasing writes nothing:
workflow/graphis called 0 times. - No Add link entry and no wire port (
data-port="out") to drag a new edge from. - Reading still works: the graph is drawn from
workflow/state, and norole="alert"/ error is shown. - A window that is not read-only keeps today's behaviour byte for byte (Edit, drag, Add link, save all still work).
Note on an earlier draft of this list: "no delete-node / delete-edge entry" cannot be a failing test here — this page has no delete controls at all (the only Delete is the sidebar's whole-workflow one). It is therefore not part of the acceptance above.
Scope
plugins/workflow/client.js—rosteris already passed to the settings page ({ roster, actions, call, run, t, Section, Row }), so no wiring change is needed: derivereadOnlyReason = String(roster?.readOnly ?? '').trim()/locked = readOnlyReason !== '', forceeditingfalse while locked, early-returnsave/setProject/commitTools, disable the always-on write controls (Project select, Model select, Concurrent runs), and let the canvas take its gesture only when editing is actually possible.plugins/workflow/test/client.test.js— the four cases above, plus the existing suite untouched.changelog.d/— one fragment.- Not in scope:
plugins/workflow/src/graph.js(needs no change),patches/ds-bot/(this file has nods-botmirror), and the sidebar's per-workflow Create/Delete/Pause in the same read-only window — that is a separate surface, to be reported and tracked on its own.
Duplicate check (live main c21e6da0)
readOnlyinplugins/workflow/on live main: 0 hits, so nothing already implements this.- Closed issues searched for
bot/read-only,read-only workflow settings,readOnly plugins,WorkflowSettings: the only read-only write refusals are workflow/advance and workflow/reset write on a read-only host; the Bot reply hook reaches advance #1569 / fix(workflow): refuse advance and reset on a read-only host #1574 (workflow/advance/workflow/reseton a read-only host) — different calls on a different surface. workflow: a read-only window still offers Edit in Settings → Workflows #2176 / workflow: a read-only window still offers Edit in Settings → Workflows #2181 are the core client page. No duplicate.
Verification the PR must carry
- The four red-first cases red on the base tree, green at the tip; the rest of
plugins/workflowunchanged and green. TZ=UTC npm run verifyclean, plusbuild-clientonly if the bundle is actually affected (the plugin page is not in the core bundle — check, do not assume).
Activity
HugoXK commentedon Nov 2, 2026
Release
Written-by: FlyBot Lead
Released: d83fd79da03e4896a362a962d6eef136
Reason: merged as 9ede925 (PR #2190)
At: 2026-11-02T15:45:55Z
workflow: a refused dialog edit is announced once, not twice (ThinkFl…