fix(ui): match a run's step names to the flow graph's nodes, and say why a step wrote nothing - #94
Merged
Merged
Conversation
Workflow.run expands for_each before it emits, so the event stream names the members (base@open) while the flow graph is drawn from the definition, which keeps for_each unexpanded and a composed step as one node. Every comparison in FlowView was between two names that could no longer be equal, so the active step and the finished ones stopped showing. A sub-workflow's inner step mismatched the same way, which also left the Progress list with no active row. runstate.ts reduces both sides to one name - a for_each member to its group, a child's step to the parent_step the engine already puts on its events. A group is finished only when every member is, and only a top-level step_end finishes a composed step. The job page also now says why a step wrote nothing: the Results panel lists the steps that ran and wrote no file, with the reason read off the definition (result.save is false, or no result.content_type), and appears when that list is the only thing there is to say. A workflow that keeps most of its steps in memory read as a run whose outputs had gone missing. Co-Authored-By: Claude <noreply@anthropic.com>
SVG text neither wraps nor takes text-overflow, so a sub-workflow step's path (`templates/minimax/composable-reference-shot.json`) or a long step name ran out of the node's right edge. Each label is now cut to a character budget for its font with an ellipsis where it was cut - a name from the end, a path from the start, since a path is told apart by how it ends - and the node carries a tooltip with whatever did not fit. A clipPath on the node catches what a wider glyph set still pushes past. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Two job-page symptoms, from a diagnosis of the Parhelion run (job
8a58c78c72d1).The flow chart's run state never showed
Workflow.runexpandsfor_eachatdw/workflow.py:734, before it emits theworkflow_start/step_start/step_endevents. The flow graph, though, is drawn from the definition — wherefor_eachis left unexpanded and a composed step is a single node. So the stream namesbase@openwhere the graph saysbase, and a sub-workflow's child reports its own inner step name where the graph says the composed step's.FlowView'sclass:active={node.name === activeStep}and thedoneStepscheck were comparing two names that could no longer be equal, so the active step and the finished ones stopped showing.The same mismatch left the Progress list with no active row and no bar while a composed step ran, since a child's inner step name has no row in the list.
New
ui/src/lib/runstate.tsreduces both sides to one name: a for_each member to its group (splitting at the reserved@), anything a child emitted to theparent_stepthe engine already puts on those events (_parent_progress_fields,dw/workflow.py:328). A group is finished only when every member is — greening it on the first would say the group is behind us while its remaining entries are still queued — and only a top-levelstep_endfinishes a composed step, so one child inner-step no longer marks it done.The page could not say why a step wrote nothing
groupResultFilesdrops steps with no files, so a workflow that deliberately writes nothing was indistinguishable from a run whose outputs had gone missing: the steps were there, their files were not, and nothing said why. (Parhelion declaresresult.save: falseonbase/upscale/refineand noresult.content_typeon its six task steps, so 15 of its 16 steps write nothing by design.)The Results panel now carries a "Steps that wrote nothing" list — one row per definition step, a for_each group collapsed with a
× Nbadge — each with the reason read off the definition. It also appears when that list is the only thing there is to say, rather than the panel vanishing.step_endnamed it, so a job still in flight never accuses a step it has not reached, and a historical job (no events at all) still reads off the manifest.Verification
currentStep/rawfinishedStepsturned both red — so they are genuine regression tests.npm run check,npm run lint,prettier --checkclean;npm run buildrun, so the servedui/distcarries the change. Full Playwright e2e suite passes (92).base ×3/upscale ×3/refine ×3asresult.save is false…, the six task steps asresult.content_type is not declared…, with onlyfilmunderfinal/above, and all ten graph nodes green at the end.Not touched: the separate observation that a sub-workflow step saves its output twice (#92).
🤖 Generated with Claude Code