Repository navigation
Conversation
This was referenced Oct 27, 2026
11 tasks done
knihit
force-pushed
the
wc/07c-save
branch
5 times, most recently
from
October 27, 2026 21:25
8628432 to
c14dd6f
Compare
knihit
force-pushed
the
wc/07c-save
branch
2 times, most recently
from
October 28, 2026 14:31
0d652a5 to
c1a344b
Compare
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.
… editor state The IO-free part of editing a workflow in the Designer, with no UI yet: - the draft of the stages, where each stage keeps an id while it is renamed - the text a save writes, which replaces only the block of stages - the findings of a check, put on the stage and field they are about - the state of the editor and its reducer, with the selectors on it The wire types gain the hash and read-only flag of a workflow and the path and severity of a finding, and the page reads them.
The server reports a repeated stage name on the later stage only. A person who renames the first stage to a name the second one has saw no mark at the field they were editing. The problems of the draft now hold a copy of such a name problem for the earlier stages with that name. A list of problems leaves the copies out, and a message that several stages repeat is joined once.
… ignore late answers - A save keeps the lines of every stage that is unchanged, with the comments in front of it and the comments after the last stage. Line endings come from the stages line, a lone CR, a BOM and a quoted key are handled, and names that YAML 1.1 reads as booleans are quoted. - The revision of the draft only grows, also across open and reload, and an answer to a save or a reload counts only while that save or reload is on. - Deleting a stage that is not in the draft is not a change, and a name used three times marks the first stage once. - A failed save can say that it may have been written. - A test ties the stage limit of the draft to the contract.
…out with the validator A stage that is new or changed is written with its dashes where the file's own items have them, so a list with four spaces, three, or none stays one list. A list that cannot take items, such as a flow list on the line below stages, is written whole, which the notice already warns about. A kept last stage keeps its own line ending in a file with mixed endings.
…, add, rename, delete The Designer tab gets Properties for the selected stage, with a name field, a list of the agents Konductor ships, and Delete stage. Add stage adds the next agent-N. A stage is chosen by a click, or by Enter or Space on its node, and focus moves to its name. The draft is kept in App, so it survives a switch of tab, and the Execution tab says when it holds changes that are not saved. Nothing is written to the file yet. The graph names a node by the id of its stage, so two stages that share a name for a moment still have two nodes, and the canvas fits the graph again when a stage is added or deleted.
…aved The draft lives in the page only, so a reload or a closed tab threw it away without a word. While the draft differs from the saved file, a beforeunload handler now makes the browser ask whether to leave.
…r when read-only - Enter or Space on the stage that is already selected moves focus to its name, and Escape on a node no longer throws focus away. - The Complete and Needs a fix mark shows only for a draft that a check has answered for; before that it says nothing. - A polite live region says that a stage was added, deleted or selected. - A read-only workflow gets a note that says why, and the card header no longer asks to select a stage to edit it. - An agent that the saved file names stays on offer after another is chosen. - Two stages with one name say their place in the list to a screen reader. - The name box turns off spell check and autocomplete; the strong text is a Cloudscape strong; the agents test skips without the repository.
The note above the graph spans both columns of the Designer grid, so the graph keeps the wide column. An add names the new stage, and each announcement is a new element, so a repeat is read again. Escape is kept from React Flow only on a canvas that can select. Browser tests cover the note's layout and Enter, Space and Escape on the selected stage.
Focus went to the name, but the text stayed unselected, so typing was added to agent-1. The name is now selected.
…d run Pasting another launch address replaced the workflow and dropped the draft without a word. The page now asks first. Cancel keeps the page as it is; the address can be pasted again. The question also names a run being followed, which is let go when another workflow opens.
At this layer a failed load adds advice after the server's message, so the tests that pin the error of a pending or fallback session match its start.
The code element fell back to the generic monospace family, which the host resolves to different fonts, so the problems screenshot differed between machines. Apply the bundled JetBrains Mono and re-shoot it.
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
Layer 3 of 4 of the editing work in the Designer. It adds saving: the page can now write the edited stages to the file, check them while you type, and handle the file changing under it. A stage is still only a
nameand anagent, and the page writes no other key. The API contract and the stub are unchanged, and the page has no stub-only code path.Designer:
No changes,Unsaved changes,Saving,Saved, a polite live region) sit in the header of the graph card. Nothing is written until Save. Save sendsPUT /api/workflowwith thebase_hashof the file you loaded.POST /api/validate. What it finds shows under the field it is about, and in one alert above the graph with the stage name in front. The findings of the last check stay on show while the next one is pending, so the alert does not flicker. Only an error stops a save (Save is off, with the reason in a tooltip); a warning or a note shows as a note and Save stays on. A 422 on save shows its findings the same way.The file changed on disk) with Load the file again, which replaces the draft; focus then moves to the name field.Core (
designer/core/, no IO):ports.ts(EditPort,SaveConflict,SaveRefused,SaveLost),run-check.ts(checkAfterPause),run-save.ts(saveDraft,reloadWorkflow) and the save status line selector. Tests move time by hand with theSchedulerof the run core, so none sleeps.API client:
saveWorkflowandcheckWorkflow;ApiErrorcarries thediagnosticsof an error body;loadWorkflowties the edit calls to the session token and turns a 409conflictand a 422invalid_workflowinto the core's errors.messageOfis shared inapi/message-of.tsby the run and edit code.Tests and docs: unit tests for the loops, the client, the edit port and the Designer's save, check, conflict and failure flows;
stub-api/http/ui-wire.test.tschecks that the text the page writes is accepted by the stub and read back, and that a stale hash is 409;test-support/editing-contract.test.tspins the limits and calls toapi/openapi.yaml. The README section covers saving, checking and the conflict. The capture spec gains the saved, problems and conflict screenshots.How to review
core/run-save.tsandcore/run-check.tswith their tests (the rules), thenuse-editor.ts(how the loops are wired), thenload-workflow.tsandhttp-api.ts, thenEditAlerts.tsxandSaveControls.tsx.cd workflow-canvas && npm ci && npm run dev:stub, change an agent, press Save, and reload to see it kept until the stub stops.What the next layer adds
PR #97: the
editingPlaywright project (the whole flow against the stub, with axe in four states), the README paragraph on it, and the CHANGELOG entry.Fixes from the hands-on QA run
namemust be ..." in the list. A stage with no name is now called by its place in the list ("Stage 1: ..."). Test:DesignerEditor.test.tsx, which failed before the change.messageOfnow adds what to do: for no answer, or a 5xx that is not the API's, "If it stopped, start it again and get a fresh launch address from the server."; for the API's 401, "Get a fresh launch address from the server." The lost-save and refused-read errors use it too. Tests:message-of.test.ts,load-workflow.test.ts, and end-to-ende2e/tests/server-gone.spec.ts(load, run, session lost, save), which failed before the change.npm test(78 files, 1398 tests) andnpm run test:e2e(83 tests) pass; lint and typecheck are clean.Type of Change
workflow-canvas/Testing
npm test(tests/scripts/**/*.test.js): not applicable; this PR changes onlyworkflow-canvas/.cli/changed: not applicable,cli/is untouchedChecked in
workflow-canvas/on this head:npm run lint,npm run typecheck(3 projects),npm test(78 files, 1398 tests),npm run test:stub(20 files, 359 tests),npm run api:lint,npm run buildandnpm run test:e2e(83 tests) all pass.npm run screenshotswas run and its files are committed; a second run gives the same files.Screenshots
Designer tab, full page, 1280x800 (regenerated by
npm run screenshots; the links are pinned to the head commit of this PR):Checklist
Notes for Reviewers
wc/06-execution).PUT /api/workflow,POST /api/validate, thehashand the409and422bodies were already inapi/openapi.yaml, and the stub already served them. The contract has no call that lists agents, so the agent list stays a constant in the page.execution-tab-finished.pngis regenerated without the hover state it had.e2e/support/stub-workflow.ts(reads and rewrites the sample workflow on the stub), and small edits toe2e/support/designer-page.tsande2e/support/editing-fixtures.ts. They carry no product behavior.Fixes from the second adversarial review
current_hashtells a deleted file from a changed one without a read.wc/07b-propertiesby merge (a rebase conflicted in ten files for each of five commits), so its history is kept and no force push was needed.message-ofout of the cores and the single source of truth for "a save is in flight" (refactors with no behaviour change); the wall-clock test noted in the review is a separate fix.Fixes from the third adversarial review
currentWorkflowfails on a refused call. The comments of the purity tests name the message helper.wc/07b-propertiesby merge (the history is append-only, as before); the merge also takes the new layouts of the list from Add the editing core of the Designer: draft, stage text, findings and editor state #98.Fixes from the second hands-on QA run
Round 6
Takes #99 by merge. A 401 on a save, a check or the reload of the editor now clears the kept session (the guard from #83) and shows the shared lost-session sentence, then the note that the draft is lost. The server-gone e2e test for a run start now also checks the message and the empty storage. Unit tests for the three calls failed with the guard removed.
Round 7: the lost-draft sentence now says "when you open a fresh address", because the lost-session message ends with "An address works once." and "when you do" no longer points at one thing.
Round 8: takes #99 by merge, with the old #99 head as the merge base. Three tests of the pending session in
load-workflow.test.tsmatch the start of the error, because this layer adds advice after the server's message.npm test(81 files, 1482 tests), lint and typecheck pass.Round 9: takes #99 by merge, with the old #99 head as the merge base. A test of the pending session matches the start of the error, because this layer adds advice. The
<code>font fix and the re-shotdesigner-problems.pngare kept.npm test(81 files, 1493 tests), lint and typecheck pass.