10 KiB
Workflow Console Selected-Step Dataflow Design
Date: 2026-08-09
Status: Approved design for Workflow Console Slice 3.
Related:
- Workflow Console draft authoring workbench
- Atomic step input bindings
- Atomic step output bindings
- Capability step update
- Current roadmap
Goal
Make capability-step dataflow fully editable from the console. An operator can inspect and atomically replace ordered step inputs, bind capability outputs into workflow state, and edit optional execution metadata without using raw JSON.
This slice deepens the existing selected-step inspector. It does not introduce a second editable graph model or broaden into workflow-level contract editing.
Roadmap Context
The remaining graph-authoring work is split into independently useful slices:
- selected-step input and output dataflow;
- workflow Input, State, and Outcomes contract projections;
- explicit End authoring and a typed Add step palette;
- typed interrupt, control, subgraph, and foreach forms; and
- direct graph gestures lowered through the same canonical mutations.
This document specifies only the first item.
Scope
Slice 3 includes:
- separate selected-step Setup, Inputs, and Outputs inspector views;
- ordered canonical path and literal input bindings;
- ordered capability-output-to-state bindings;
- schema-informed source and target choices;
- automatic projection of missing state fields from capability output schemas;
- presence-aware retry and timeout editing;
- revision conflict preservation and reapply;
- operation evidence for every mutation; and
- the two focused binding operations in the authored TypeScript and browser boundary.
Slice 3 excludes:
- manual workflow input, state, or output schema replacement;
- final workflow output projection;
- non-capability step creation or editing;
- direct drag-to-bind;
- state-field deletion; and
- dataflow edges that require the future State contract graph node.
Inspector Composition
Selecting a capability step shows three compact tabs:
Setup
Setup edits description, retry count, and timeout. Step id and capability reference remain visible but read-only. Changing the capability itself remains an explicit remove/add operation.
Metadata is presence-aware:
- adding a step with blank retry or timeout omits that field;
- editing an absent value without touching it sends no update for that field;
- clearing an existing value sends explicit
null; - retry accepts integers greater than or equal to zero; and
- timeout accepts values greater than zero or remains absent.
The UI must never require operators to enter 0 in blank optional controls to
make a mutation submit.
Inputs
Inputs replace the complete ordered canonical input-binding list. Each row has:
- a capability-local target derived from the capability input schema;
- a source mode of Path or Value;
- an
input.*,state.*, orcontext.*graph path in Path mode; - a schema-driven literal editor in Value mode; and
- remove and reorder controls.
Explicit null, nested local targets, whole-payload projection, repeated source
fan-out, and mixed path/literal bindings preserve their canonical forms. The UI
does not lower these records into the lossy compatibility input map.
Outputs
Outputs replace the complete ordered canonical step-output binding list. Each row has:
- a source derived from the capability output schema;
- a
state.*target path; - a schema summary for the source; and
- remove and reorder controls.
Existing state paths are suggested. A new target previews the state field schema that the backend will project from the selected capability output. Repeated sources remain valid for fan-out. Submitting an empty list deliberately clears the step output bindings but does not silently delete state declarations that already exist.
Canonical Dataflow
The returned draft remains the only graph document. Components edit local form models, then submit complete canonical binding lists. On success, the returned draft, diagnostics, status, and revision replace the workbench state.
canonical draft + capability schemas
-> selected-step form projection
-> local ordered binding rows
-> focused revision-checked mutation
-> returned canonical draft
-> inspector and graph reprojection
Slice 3 may show compact input/output binding summaries on a graph node. It does not invent temporary state nodes or browser-only dataflow edges. Binding edges arrive with the real State contract projection in Slice 4.
Module Boundaries
The workspace domain exposes focused selected-step mutations through the existing draft-authoring client. React components do not own operation names or call the transport directly.
The selected-step form projection is a pure module that:
- parses canonical bindings from keyed or compiled draft shapes;
- preserves binding order and repeated sources;
- returns explicit unsupported reasons rather than guessing malformed shapes;
- derives schema-informed field choices from capability detail and workflow contracts; and
- serializes form rows back to canonical transport records.
It also projects structured binding diagnostics by selected step, field, and
row index. Diagnostics without a structural row location remain in the shared
draft diagnostics panel; the browser does not assign rows by parsing prose.
Recognized row locations are compiled nodes[N].input[M] / output[M], keyed
JSON Pointer /steps/<id>/input/M / output/M, and focused
bindings[M] diagnostics carrying the exact selected step_id.
Malformed persisted binding rows remain visible as bounded raw previews at their original positions. Saving is blocked until each malformed row is either repaired into a canonical row or explicitly removed; unsupported data never silently disappears during replacement.
The draft-authoring controller remains the single mutation module. Setup, Inputs, and Outputs are separate form surfaces but share revision checking, pending state, evidence, conflict retention, reload, and reapply behavior.
TypeScript And Browser Boundary
The checked contract manifest already contains:
workflow.draft_workspaces.set_step_input_bindings; andworkflow.draft_workspaces.set_step_output_bindings.
Slice 3 makes those operations callable through the authored Effect RPC group, method registry, console operation union, service dispatch, and Hono browser allowlist. Runtime payload and success schemas come from the checked generated contract through the existing supported schema translator. The implementation must not hand-write duplicate transport schemas.
The browser allowlist remains explicit. Adding these two focused draft operations must not expose generic patching, replacement/import, deletion, artifact, deployment, run, source-admin, or secret operations.
Validation And Errors
Client validation covers errors that are local and unambiguous:
- blank or malformed paths;
- unsupported source roots;
- duplicate local targets where canonical semantics forbid them;
- invalid retry or timeout values;
- malformed literal values; and
- incomplete binding rows.
The workflow API remains authoritative for schema projection, compatibility, overlap, semantic validation, draft validity, and revision conflicts.
Server diagnostics attach to the owning binding row when their path identifies one. Unmatched diagnostics remain visible in the draft diagnostics panel. A semantically invalid but persisted draft still replaces the displayed canonical draft and shows its invalid status. Transport failures preserve the last confirmed draft and all local edits.
Revision conflicts retain the exact active tab and ordered local rows. Reload discards local edits in favor of the server draft. Reapply reruns the same focused mutation against the refreshed revision.
The selected-step inspector owns active-tab and unsaved-row state, keyed by the selected step. The authoring controller owns only confirmed canonical state and the last submitted payload needed for conflict reapply. Closing the mounted mobile sheet therefore does not erase unsaved work.
Evidence And Truthfulness
Every mutation records the operation name, bounded request and response, duration, target, equivalent CLI guidance, and failure details through the shared write executor. The UI must distinguish:
- unsaved local rows;
- a pending mutation;
- a confirmed canonical draft;
- a persisted invalid draft with diagnostics; and
- a failed or conflicted mutation that did not replace confirmed state.
Responsive And Accessible Behavior
Desktop keeps the graph visible while the inspector tab changes. Each tab owns its vertical scrolling and keeps its primary save action reachable.
Mobile continues to use the existing context-inspector sheet. Closing and reopening the sheet preserves selection, active tab, binding order, and unsaved rows. Reorder controls have button alternatives and do not require drag.
Binding rows use fieldsets or labelled groups. Source mode, source, target, schema summary, row errors, and remove/reorder actions have stable accessible names. Status and conflict changes use the existing live regions.
Verification
The implementation must include:
- generated-schema parity tests for both newly authored RPC operations;
- service dispatch and browser allowlist positive tests;
- browser allowlist negative tests for representative unrelated mutations;
- exact client payload tests for ordered bindings and metadata omitted/null/value semantics;
- pure projection tests for nested paths, literals, explicit null, fan-out, whole-payload bindings, malformed stored data, and empty lists;
- controller tests for success, invalid persisted drafts, failures, stale responses, conflicts, reload, and reapply;
- inspector tests for all tabs, row editing, reorder alternatives, inferred state previews, clearing, diagnostics, and optional metadata;
- responsive sheet regression coverage; and
- a real-server browser smoke that selects a
wf.*capability step, replaces inputs and outputs, and confirms the returned revision and projected state contract.
Focused tests, the full console test suite, TypeScript typecheck, production
build, React Doctor changed-scope scan, and git diff --check are completion
gates.