Repository navigation
Conversation
knihit
marked this pull request as ready for review
October 26, 2026 21:03
knihit
requested review from
georgebearden,
ihmaws,
shsenior and
simonkrol
as code owners
October 26, 2026 21:03
11 tasks done
knihit
force-pushed
the
wc/06-execution
branch
from
October 27, 2026 01:20
aad1848 to
8e2211b
Compare
This was referenced Oct 27, 2026
knihit
force-pushed
the
wc/06-execution
branch
from
October 27, 2026 15:14
8e2211b to
7358195
Compare
knihit
force-pushed
the
wc/06-execution
branch
5 times, most recently
from
October 27, 2026 21:25
23ab802 to
9b7eaee
Compare
knihit
force-pushed
the
wc/06-execution
branch
2 times, most recently
from
October 27, 2026 22:23
f1e444e to
e3ad08c
Compare
This was referenced Oct 27, 2026
knihit
force-pushed
the
wc/06-execution
branch
from
October 28, 2026 18:31
fa76347 to
27e862d
Compare
knihit
force-pushed
the
wc/06-execution
branch
from
October 28, 2026 19:38
27e862d to
70a80ec
Compare
7 of 11 tasks
knihit
force-pushed
the
wc/06-execution
branch
from
October 28, 2026 21:38
70a80ec to
85a8371
Compare
knihit
force-pushed
the
wc/06-execution
branch
from
October 28, 2026 22:46
85a8371 to
71135c4
Compare
knihit
force-pushed
the
wc/06-execution
branch
from
October 28, 2026 23:50
71135c4 to
19c44a5
Compare
knihit
force-pushed
the
wc/06-execution
branch
from
October 29, 2026 00:43
19c44a5 to
dacddb5
Compare
knihit
force-pushed
the
wc/06-execution
branch
from
October 29, 2026 01:49
dacddb5 to
ebb01f1
Compare
…calls A 409 already_running names the active run, so the Execution tab follows it instead of ending in a dead end, for example after a page reload. A failed read is tried again before the tab gives up, a reading for another run ends the follow with an error, and a call that gets no answer ends after a timeout. The error sentence is announced through an alert region, and Enter in the goal box runs.
canRetryStatus in api/api.ts holds the rule next to the "0 = no answer" convention: no answer or a 5xx can be tried again, any 4xx cannot. The README now says any 4xx, as the code does.
…reload After a reload the Execution tab said Ready although a run was going. The tab now keeps the id of the latest run in sessionStorage and, when the page opens again, reads that run once. A run that is still running is followed as a joined run. A run that has ended, cannot be read, or a blocked storage leaves the tab ready.
- Run pressed while the page is still looking for a run to join stops the look and starts the run, instead of doing nothing. - The first reading of the remembered run is tried again like any other. - The launch code call has no timeout: the code works once, so giving up on a slow answer would leave no way back in.
…o answer from one refused - The look for the remembered run reports a run that may be going when the readings fail, and stays quiet only when the server will not give the run. - A start that got no answer, or was accepted in a reply that could not be read, says the run may not have started and that Run joins it.
- While the tab follows a run that was already going, the Goal box says the goal is not known instead of showing another goal; the status line still says the run was already in progress once it ends. - The README says resume after a reload works only where the launch code can be traded again, and a test shows what a reload does on a server that follows the contract.
…in the code timeout The remembered run id is dropped once the run ends or turns out to be gone, so a failed look at page open does not name a run that finished long ago. A run that a reload joined is no longer cut off when the page gets new runs. The test for the launch code call without a timeout now ends the call on abort, so it fails when the timeout comes back. The README says what a reload does.
The run id kept for a reload belongs to the session that was left. It is dropped with the run, so a later reload does not look for it on another server. A run that a reload joined is still not cut off by a repeated render, only by another workflow.
The page keeps its session in the tab, so a reload no longer ends in no launch code. The end-to-end test reloads during a run on a stub that takes the code once and checks that the run is followed again.
Drives the page: the start is answered 401, the run error says the server lost the session and where to get a new address, and the tab storage is empty.
knihit
force-pushed
the
wc/06-execution
branch
from
October 29, 2026 02:51
ebb01f1 to
358e293
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The Execution tab of the workflow canvas now runs the workflow. It draws the same graph as the Designer, read-only, with a goal box and a Run button. Run starts a run on the API, then reads it once a second, and each node shows its live state until the run ends. The contract and the stub are unchanged, and the page has no stub-only code path: it calls the relative
/api, so it works the same against the stub (npm run dev:stub) or a server named byWC_API_TARGET.Execution tab (
workflow-canvas/src/execution/):Execution.tsx: the graph, a Goal box and Run. The goal starts as the outcome of the intent, becausePOST /api/runneeds a goal of 1 to 2048 characters. Run and the goal box are off from the click until the run ends.role="status",aria-live="polite"), and the name of each node for a screen reader ends with its state.role="alert"region that is always on the page, so a screen reader reads the sentence. A failed stage is a result, not an error.POST /api/runanswers 409already_running(for example after a page reload in the middle of a run), the tab follows the run named in the answer, as the contract says a client should, and the line under the button says so. A read that fails is tried again after a second; the tab gives up after three in a row. Enter in the goal box runs.App, so a run goes on while the Designer tab is open.Run core (
src/execution/core/, no IO):startAndFollow(starts a run or joins the active one, then reads it every 1000 ms until it is no longer running; a failed read is tried again up to three times in a row; a reading of another run ends it with an error), the state of each node, and the status sentences.RunPort(start and read a run) andScheduler(wait for some milliseconds).timerScheduleris the browser adapter; tests use a fake that they move by hand, so no test sleeps.test-support/execution-purity.test.tsholds the core to the same rule as the graph core: it imports only its own modules, the graph core and the wire types, and reads no clock, randomness, environment or network.API client (
src/api/):WorkflowApigainsstartRunandgetRun.createHttpApisends the goal as{ "params": { "goal": ... } }and readsrun_id, and reads the run into an ordered list of stages. A status the contract does not name is a bad reply. The run id is encoded in the path.ApiErrorcarries therun_idof an error body.createHttpApiends a call after a timeout (15 s) with the "server did not answer" sentence.loadWorkflowties the run calls to the session token, so only those calls hold it, and turns the 409already_runninginto the core'sRunAlreadyActive.Shared pieces:
WorkflowGraphCard(the card with the graph) andWorkflowGate(loading, error and empty states) are used by both tabs;designer/states.tsxmoved toworkflow/states.tsx.buildGraphis unchanged;withStatusesin the graph core adds a status to the nodes it names.canvas.css, and a test checks that they match the theme module and reach WCAG 2 AA in both modes.Docs:
workflow-canvas/README.mdhas an Execution tab section, and CHANGELOG has an entry under Unreleased.VERSIONis untouched.How to run
cd workflow-canvas npm ci npm run dev:stubOpen the address it prints, open the Execution tab and press Run. The stub fakes a run: the
draftstage runs for 3 seconds, thenreview, then the end shows Passed.Fixes from the hands-on QA run
sessionStorage(the id is no secret; the session has its own memory since Draw the workflow on the Designer tab with React Flow #83). When the page opens again it reads that run once, and a run that is still going is followed as a joined run, without a click on Run. A run that has ended, one that cannot be read (for instance after the server started again), or a browser that blocks storage leaves the tab ready for a new run.resumeRunin the run core,RunMemoryport withsessionRunMemoryas its adapter, anduseExecutiontakes the memory;Apptakes an optionalrunMemoryandmain.tsxpasses the real one.resumeRun(still running, ended, unreadable, another run, aborted, a failure while following), of the hook and of the memory (including blocked storage); end-to-end test "shows the run that is still going when the page is opened again", which failed before the change, and one that a finished run leaves the tab ready.npm test(58 files, 995 tests),npm run test:e2e(68 tests) andnpm run screenshotspass; lint and typecheck are clean.Type of Change
workflow-canvas/Testing
npm test(tests/scripts/**/*.test.js): not run; this PR changes onlyworkflow-canvas/and the rootCHANGELOG.md.cli/changed: not applicableChecked in
workflow-canvas/:npm run lint,npm run typecheck(3 projects),npm test(58 files, 995 tests),npm run buildandnpm run test:e2e(68 tests, against the stub) all pass.npm run screenshotsgives byte-identical files on a second run. The build prints only the existing chunk-size warning.Tests added:
startAndFollowwith a fake scheduler (polls every 1000 ms, no wait before the first read, stops on passed and on halted, retries a failed read and counts only failures in a row, joins the active run, onefailedevent for a refused start, repeated failed reads or a reading of another run, nothing is emitted after an abort); the node states for a running, passed and halted run; the status sentences; the goal check (empty, 2048 and 2049 characters, characters outside the basic plane); the no-IO rule of the core.getRunandstartRun(request shape, token, encoded id, parsing, bad replies, error sentences); the timer adapter with fake timers;withStatuses; the tab throughAppwith a fake server and scheduler (idle, Run disabled while in flight and from the click, each node going queued -> running -> done, a failed run, one alert for a refused start and for a failed read, the alert cleared by a new run and announced through its region, a joined run, a read that fails once, Enter in the goal box, the run continuing on the Designer tab, reading stops when the page closes, loading and failed-load states); the state colours (contrast and match with the theme module).e2e/tests/execution.spec.ts): the tab before a run; a real run on the stub that clicks Run and sees draft go Running -> Done, then review Running -> Done, then the end Passed, in that order, with Run off in between; the live region and node names; a failed stage, a refused run, a joined run (409 with the run id) and a dropped read (the stub never fails a stage and runs one run at a time, so these answer the run calls in the test); the run kept across tabs.e2e/tests/accessibility.spec.ts): axe on the Execution tab with a stage running, a failed stage and a passed run, and with a failed stage in the dark mode.Screenshots
Execution tab, full page, 1280x800 (regenerated by
npm run screenshots):Checklist
Notes for Reviewers
wc/06b-run-panel), which is stacked on Read runs through the typed client and add the run core #115 (wc/06a-run-core), which is stacked on Give the workflow canvas the docs theme, with light and dark modes #85 (wc/05b-theme). The diff of this PR is the 10 commits of part 3.execution-tab.pngis replaced byexecution-tab-idle.png,-running,-finishedand-dark.Fixes from the second adversarial review
POST /api/session. It fails when the session memory is switched off. A restarted server makes a reload ask for a fresh launch address.wc/06b-run-panel.Fixes from the third adversarial review
RunMemory.forget).wc/06b-run-panel; the retry and "may not have started" parts moved down to Read runs through the typed client and add the run core #115 and Draw the run on the Execution tab with a Run button and live node states #116 and are no longer in this diff.Fixes from the second hands-on QA run
Round 6
Rebased on #116. New e2e test: a 401 on the run start shows the lost-session message and leaves the tab storage empty (it failed with the guard removed).
Round 9: rebased on #116. No change of its own.
npm test(1089 tests), lint and typecheck pass.