Repository navigation
debugviewer: live-session sidebar + auto-attach + flashing fix; engine live-trace hoist; pipeline e2e fix - #3
Merged
Conversation
…acked The header ● live auto-refresh (and ↻ refresh) redrew the whole graph every 3s unconditionally — svg.innerHTML='' + a full async ELK relayout — even when the compiled graph was unchanged, which flashed the SVG. The same path also ran stopStream(), so an attached live run stopped being tracked each cycle. - Skip the redraw when the graph is unchanged: graphSig() signs nodes/edges/ phases (deterministic for unchanged YAML) and refresh() only redraws on a real change, via the new non-destructive redrawCurrentWorkflow(). - refresh no longer tears down the SSE stream, so a live session stays tracked while auto-refresh is on (workflow switches still reset via selectWorkflow). - Preserve run highlights across a legitimate redraw: RUN_VIS records each state's active/done class and applyRunVis() re-lights nodes after draw().
The live-trace sidecar (what makes a run watchable in the debug viewer) was wired only in baseworkflow.run_live, so websitewf runs — a BaseWorkflow subclass with its own run_live/_run — wrote no sidecar and were invisible to the viewer. Wiring it per engine is engine plumbing leaking into consumer overlays. Attach the observer once in BaseWorkflow.run (inherited by every engine): when tracing is enabled () and the caller supplied no observer, attach a FileObserver labelled by the workflow's YAML stem (WORKFLOW_PATH -> baseworkflow/websitewf, matching the viewer's graph names) and finish only the observer we created. The in-process BusObserver path is untouched (guarded by ctx.observer is None; the viewer finishes its own). - Remove the now-redundant wiring from baseworkflow.run_live. - Revert the copy from websitewf._run — it inherits BaseWorkflow.run. Verified: baseworkflow + websitewf run_mock each emit a correctly-labelled sidecar with a terminal status; the viewer picks up websitewf runs like baseworkflow ones.
… migrate
Three defects surfaced by an end-to-end live run (the action.py stack dump from
the prior commit pinpointed each). With these the full spec→work→build tick
completes live and deploys.
- research.py: LIVE_INFERENCE_WORKERS was keyed "research_investigate" but
ArchitectFactory dispatches by token.split(":")[-1] = "investigate", so the
live FileResearcher/WebResearcher worker was never invoked — raw model prose
hit the JSON adapter and failed the tick. Re-keyed to "investigate" (every
other worker's bind name equals its token's last segment; research was the lone
mismatch). The worker parses loosely and fail-safes to baseline.
- adapter.py: JsonAdapter.decode json.loads'd model output unguarded — empty
output crashed with a bare JSONDecodeError. Now: empty -> {} (failures-as-data),
fenced/prose-wrapped JSON salvaged, genuinely-garbled -> a HANDLED ActionError.
- admin.py: admin:migrate constructed _env.Environment() with no args, but the
ctor requires `sources` — a TypeError that aborted the tick just before publish.
Use Environment.default() (the canonical factory, as at admin.py:292/442).
Verified: live e2e green (ok=True) — engineer codegen builds, publish deploys to
Vercel, consolidate opens one PR, no-issue guard skips the label machine.
… resizable Live runs were buried in a collapsed right-side 'mocked session' fold that only polled while open, and attaching was a manual click — so a live session looked invisible. Make a live session track itself: - Move live sessions to a always-visible panel at the top of the LEFT sidebar, above the workflow list; demote the in-process mock runner to a small fold. - Poll for external live runs unconditionally, and auto-attach the newest actively-running one (⦿ auto toggle to opt out; manual click still works). - Add a draggable width handle to the left sidebar, mirroring the inspector's (double-click resets; width persisted). Robust liveness, not a guess: a live run goes silent for minutes during long inference/publish steps, so a plain mtime cutoff would call it dead. FileObserver now heartbeats its sidecar's mtime every 15s (touch only, no extra lines) and stops on finish(); bus.py exposes mtime; the viewer treats a run as live only if status=running AND mtime is fresh (60s) — which also flags a sidecar whose writer died (stuck at 'running') as dead instead of auto-attaching it. Verified: heartbeat advances mtime while quiet and stops on finish; JS parses; live endpoint carries mtime.
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.
Combined debugviewer + engine work plus the pipeline e2e fix, landing together into beta.
debugviewer (viewer.html)
engine (baseworkflow.py, websitewf.py, trace.py, bus.py)
pipeline
Verified: heartbeat advances mtime while quiet and stops on finish; both engines emit correctly-labelled sidecars; JS parses; flashing eliminated on unchanged-YAML refresh.