Repository navigation
Conversation
This was referenced Oct 27, 2026
knihit
force-pushed
the
wc/06a-run-core
branch
2 times, most recently
from
October 28, 2026 14:31
1b8d610 to
47fe83a
Compare
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 28, 2026 14:54
47fe83a to
955e1f4
Compare
knihit
marked this pull request as ready for review
October 28, 2026 15:37
knihit
requested review from
georgebearden,
ihmaws,
shsenior and
simonkrol
as code owners
October 28, 2026 15:37
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 28, 2026 15:38
955e1f4 to
c57d1ae
Compare
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 28, 2026 16:28
c57d1ae to
fc9ba5c
Compare
knihit
force-pushed
the
wc/06a-run-core
branch
2 times, most recently
from
October 28, 2026 18:31
c5274b7 to
3e0ed33
Compare
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 28, 2026 19:27
3e0ed33 to
b45f8a7
Compare
7 of 11 tasks
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 28, 2026 21:38
b45f8a7 to
b4e0f06
Compare
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 28, 2026 22:46
b4e0f06 to
0fe9409
Compare
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 28, 2026 23:50
0fe9409 to
639c654
Compare
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 29, 2026 00:41
639c654 to
b2b5e9a
Compare
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 29, 2026 01:49
b2b5e9a to
5fd9259
Compare
The API client gains startRun and getRun, parsed against the contract. The run core has no IO: the state of a run, the loop that starts and follows it through a clock port, the state of each node and the status sentences. A test holds the core to the same no-IO rule as the graph core.
ApiError carries the run_id of the error body, so a caller can find the run that is already active. A run reply with an exit_code that is not an integer or null, or with a stage name twice in order, is a bad reply instead of being read as null or as two stages of one name.
A reading of another run ends the loop with a failed event instead of leaving the tab in the following state. The abort listener of the fake scheduler is removed once it fires, the abort test builds its own loop so it asserts the whole event list, and the README describes the four calls of the port and the purity test of the run core.
- A failure names the run it belongs to, so a loop that lost cannot end the state of the one that won. - A start refused with 409 already_running and a run id follows that run. - A read that fails with no answer or a 5xx is tried again, up to three in a row. Any other 4xx, or a reply the page cannot read, ends at once. - Every call takes an AbortSignal and gives up after 15 seconds. A body that stops arriving counts as no answer. - A run reply must hold together: id pattern, exit code and stage states for its status, and the stages in order. A 2xx start with an unreadable reply says the run may have started. The fix of an error body is shown.
… run core docs A start with no answer or an unreadable accepted reply now ends as an error that says the run may have started. A run_id in an error body must look like a run id. FollowRequest says one loop runs at a time, and startAndFollow says it rejects only when emit throws.
… session A run start or read that the server answers with 401 now clears the kept token through the same guard as the load, and fails with the same message. The test fakes of the new session tests carry the run calls.
… has every method
The api of a test now carries the run calls, so the two tests that resume a pasted session and keep a quiet notice build it with apiWith like their neighbours.
knihit
force-pushed
the
wc/06a-run-core
branch
from
October 29, 2026 02:51
5fd9259 to
3659250
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
Part 1 of 3 of the Execution tab (#116 is part 2, #93 part 3). This part adds the code that reads and models a run. It has no UI: nothing here changes what the page shows.
API client (
src/api/):WorkflowApigainsstartRunandgetRun.createHttpApisends the goal as{ "params": { "goal": ... } }, readsrun_id, and reads a run into an ordered list of stages. A reply that breaks the contract is a bad reply: a run id outside theRunIdpattern, a status it does not name, anexit_codethat is not an integer or null, a stage name twice inorder, a stage instagesthatorderlacks, or a status that does not fit the exit code and the stage states (running with an exit code, passed with a stage not passed, halted without exactly one stage blocked). Thefixof an error body is added to its sentence. A start with no answer, or a 2xx start whose reply cannot be read, is told to the core asRunStartUnsure: the run may have started. The run id is encoded in the path.ApiErrorcarries therun_idof an error body when it has the shape of a run id; the contract uses it in the 409already_running. Each run call takes anAbortSignal, and every call gives up after 15 seconds; a body that stops arriving counts as no answer (status 0).loadWorkflowties the run calls to the session token, so only those calls hold it. It turns a 409already_runningwith a run id intoRunAlreadyActive, and a 4xx or unreadable reply on a read intoRunReadRefused.Run core (
src/execution/core/, no IO):startAndFollow(starts a run, or follows the one that is already active, then reads it every 1000 ms until it is no longer running; a read that fails with no answer, a 5xx, 408 or 429 is tried again, up to 3 in a row, while a refused read or a reading of another run ends the run with an error), the state of each node, the status sentences, and the goal check (1 to 2048 characters).failedevent names the run it belongs to, and the reducer ignores one that names another run or none once a run is being followed, so a second loop that was refused cannot end the state of the first.RunPort(start and read a run, each with a signal) andScheduler(wait for some milliseconds). Tests use a fake scheduler 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.Docs: the README names the four calls of the port, the retry and timeout rules and the purity test of the run core.
Graph (
src/graph/):withStatusesadds a status to the nodes it names.buildGraphis unchanged.Type of Change
workflow-canvas/Testing
npm test(tests/scripts/**/*.test.js): not run; this PR changes onlyworkflow-canvas/.cli/changed: not applicableChecked in
workflow-canvas/atb4e0f06:npm run lint,npm run typecheckandnpm test(52 files, 886 tests) pass. The e2e suite is run on the top of the stack, as no page changes here.Tests added:
getRunandstartRun(request shape, token, encoded id, parsing, bad replies including a wrongexit_codeand a repeated stage name, error sentences, therun_idof a 409); the reducer (every state, an event that does not fit is ignored, a reading or a failure of another run is ignored);startAndFollowwith the fake scheduler (polls every 1000 ms, no wait before the first read, stops on passed and on halted, retries and gives up, a refused read, joining an active run, two overlapping loops, a read that never answers and is aborted, nothing emitted after an abort); the HTTP adapter with a signal, a timeout, a dropped body and a hung body; node states for a running, passed and halted run; status sentences; the goal check;withStatuses; the no-IO rule of the core.Checklist
Notes for Reviewers
wc/05b-theme); this PR is six commits (the first is the original change; the others answer reviews). Part 2 is Draw the run on the Execution tab with a Run button and live node states #116 (wc/06b-run-panel), and Run the workflow from the Execution tab with live node states #93 (wc/06-execution) is part 3.src/api/parse.ts(strictness about unknown statuses), the reducer andstartAndFollowtransitions, and that the core imports nothing from React or the UI.Fixes from the second adversarial review
wc/05b-theme; the test fakes of the source tests now include the run calls.emit(the port says it must not throw).Fixes from the third adversarial review
RunStartUnsure,maybeStarted), instead of "did not start".run_idin an error body must look like a run id.FollowRequestsays the caller runs one loop at a time, andstartAndFollowsays it rejects only whenemitthrows. The README says "each run call" takes a signal.wc/05b-theme.queuedname for a node that did not run, trimming the goal): no behaviour.Restack
Round 6
Rebased on #85. A 401 on a run start or a run read now clears the kept session through the guard added in #83 and fails with the "server no longer knows this session" message (before, only the load did). New tests: start and read forget the session, a failure that is not a 401 keeps it, a newer session is not forgotten. The earlier test that expected the raw 401 sentence on a read is replaced.
Round 7: no change to the product code. One test of the refused-address notice builds its API with the helper that has every method.
Round 8: rebased on #85. The tests added in #83 for a pasted session build their API with the helper that has every method.
npm test(55 files, 969 tests), lint and typecheck pass.Round 9: rebased on #85. One test of the pending session builds its API with the helper that has every method.
npm test(55 files, 980 tests), lint and typecheck pass.