Sprint U-0: web dashboard recon (WIP) - #186
Draft
konjoinfinity wants to merge 37 commits into
Draft
Conversation
Fixture-server (detached Cargo workspace, mirrors fuzz/'s own rationale) drives the real embedded SvelteKit dashboard through its real composer UI plus a recon-only /recon/pump control route, since panes/cards are pure client-side session state never rehydrated from the server. Playwright capture protocol (fixed viewports, DPR 2, frozen clock, blocked webfonts, motion off/on stills + frame strips) is running across all reachable states; this checkpoint has S1 complete and S2 in progress. Census/report drafts included, to be finished once capture completes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
konjo-gates flagged net-new em-dashes in recon/LEDGER.md, recon/REPORT.md, and recon/census_streaming.md (prose gate, WARN) - replaced with plain hyphens throughout. Also picks up regenerated S1/S2 screenshots from the latest capture.mjs run (button-relabeling index-drift fix for 4-pane states) and whatever later states have landed so far. The same gate run also flagged tools/recon/fixture-server's std::fs::remove_file calls as a one-way door (diff:data-delete). Those calls only ever delete this throwaway binary's own /tmp scratch SQLite file (and its -wal/-shm sidecars) at a fixed recon-only path it creates itself - never anything under the repo, never real user data - so acknowledging it here per the gate's own instructions. Konjo-Acknowledged-Oneway: 7d63f05cd889 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Continuing capture batch progress checkpoint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Continuing capture batch progress checkpoint. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Found that the previous capture run silently no-op'd /recon/pump for S5/S9/S10/S11/S12: a fixed 300ms sleep stood in for "wait until the real POST /api/tasks response lands," which is a race, not a guarantee — those five states settled with 0 tokens and no live-output panel because the pump call carried an undefined task_id and Json<PumpRequest> deserialization failed before the handler ever ran. Replaced with an explicit wait for the real created id(s), and pump() now throws loudly on a missing id or a non-2xx response instead of failing silently. Re-running the full batch now — this commit is a transient checkpoint mid-run (some states show as deleted here because the old, wrong screenshots were cleared before the fresh run started; the next commit restores them with corrected content). Not marking this ready for anything. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Root cause of the S5/S9/S10/S11/S12 failures (0 tokens, no live-output panel) wasn't the missing-id race fixed earlier, and wasn't cross-state event accumulation either (confirmed by giving each state its own fresh fixture-server, which still failed identically). It was plain timing: a fixed sleep long enough to observe a one-shot pump settle in isolation was not long enough once the same script had already run S1-S4 first and the system was under more load. Diagnosed by reproducing the exact S5 builder logic standalone (worked every time) vs. inside the real 9-state batch (failed every time) — same code, different system load. Replaced every fixed "wait N ms then assume it landed" after a pump() call with actual polling for a real signal: the live-output panel existing, a scenario's specific terminal log line, or every RUNNONG badge clearing. This is correct regardless of how slow the system gets, instead of encoding an assumption about it. Transient checkpoint mid fresh re-run — later states still show as deleted here pending regeneration. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Contributor
Author
|
Generated by Claude Code |
The polling fix (previous commit) genuinely helps but didn't fully eliminate the flake — a run deep into the batch still occasionally timed out waiting for a one-shot pump's signal even at 15s. Root cause not conclusively pinned (most likely some form of resource contention this sandbox exhibits under sustained Chromium+tokio load; a from-scratch isolated repro of the exact same builder code never reproduced it). pumpUntil() now re-fires the scenario up to 3 times, 8s each, if the expected signal doesn't show — safe since re-firing only appends more of the same fixed-content log lines, and makes the harness recover from whatever the underlying cause turns out to be rather than require pinning it down exactly. Transient checkpoint mid this run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Checkpoint mid-run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Checkpoint mid-run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Checkpoint mid-run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Checkpoint mid-run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Checkpoint mid-run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Even with a fresh fixture-server per state and 3x retry, S5 failed all three attempts (24s total) every single time it ran as part of the full 9-state batch — yet the exact same builder code, run standalone with its own freshly-launched browser, worked every time it was tried. The one condition every failing run shared and every working repro didn't: one Chromium instance reused across all ~90 contexts in the batch. Launching chromium.launch() fresh per state (closed alongside the fixture-server at the end of each state) removes that variable entirely. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Checkpoint mid-run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTT6n6W3J4aveFKzThbEp3
Same-port reuse across states was the remaining S5 flake: a not-yet-torn-down previous server can still answer /api/health on the old port, giving waitForHealth() a false positive that points the new browser at a zombie server whose broadcast channel is still saturated with the prior scenario's events.
Unique-port-per-state fixed the S5 zombie-server flake, but a second, different flake (a task-id race at S3, never seen in ~5 prior full-batch runs) surfaced once, pointing at cumulative load inside one long-running node/V8 process rather than anything port- or server-specific. Adds a --state flag to capture.mjs and a run-states.sh wrapper that invokes one node process per state, giving each a fresh process/heap/event loop and a real process-exit boundary between states.
S5's card submission reproducibly triggers a second, real POST /api/tasks 700-900ms after the first (server response carries duplicate_of: <first-id> — confirmed by direct inspection). Which of the two ids ends up bound to the visible card isn't something this read-only harness can control, so pump the gate-failure scenario to every id captured after a settle window instead of assuming the first one is the one actually rendered. Pumping a stale/orphaned id is inert. Removed temporary RECON_DEBUG instrumentation added during diagnosis.
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.
Summary
Read-only reconnaissance pass on the axum/SvelteKit web dashboard, per the Sprint U-0
brief. No dashboard code touched — everything lives under
tools/recon/andrecon/.Status: in progress. This draft is open early per repo convention (push → draft PR).
Screenshot capture across all reachable states/viewports is still running; the four
censuses and final report will be updated in follow-up commits before this is marked
ready for review.
tools/recon/fixture-server/— a detached Cargo workspace (mirrorsfuzz/'s ownrationale) serving the real, unmodified
lopi-uiaxum app plus one recon-only/recon/pumpcontrol route, used to replay deterministicAgentEventsequences forstates that only exist transiently on a live dashboard. Never spawns the agent pool's
dispatch loop — no
claudesubprocess, no git call reachable from this binary.tools/recon/scripts/— Playwright capture driver + census aggregation, ownpackage.json, not part of the lopi workspace.recon/—REPORT.md,LEDGER.md,census_streaming.md(drafted), pluscensus_color.json/census_layout.json/census_animation.jsonandshots/(inprogress).
One early architectural finding, already written up in
recon/REPORT.md§1: thedashboard's
panes/cardsclient state is never rehydrated from the server — reopeningthe tab always starts from two empty composers, regardless of what the store holds. That
shaped the whole fixture design (see
recon/LEDGER.md).Test plan
off/on + one S4 video)
tools/recon/scripts/build_censuses.mjsproducescensus_color.json,census_layout.json,census_animation.jsonrecon/census_streaming.mdmeasured-numbers placeholders filled in from S4 datarecon/REPORT.mdsections 3–6 written from real census data; draft PR → ready forreview
git diff --statagainstmainshows changes only undertools/recon/,recon/,and
LEDGER.mdGenerated by Claude Code