You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
dashboard/app.js is 4768 lines, single file, 16 panels inlined, no centralised state, polling-based sync via a private usePoll, cross-panel coordination via two DOM event buses (appBus / toastBus). It works, but adding anything new means scrolling, and the editor surface that the design mockup just deleted still occupies ~30% of the file. Refactor target: the updated mockup at design/agent-dashboard.html.
Constraints
TypeScript via tsup, like the rest of the codebase. Dashboard sources under dashboard/src/; tsup bundles to dashboard/dist/app.js; the asset server serves the bundled output. CDN imports (esm.sh URLs) stay external. HTM tagged templates, no JSX. Build infra landed in #29.
No state library. Self-rolled signal store if needed, kept under ~200 LoC. Don't add Redux / Zustand / Jotai for a 16-panel SPA.
One panel per PR. Big-bang refactor PRs are unreviewable; each migrated panel must land independently with its own tests where they exist.
Behavior identity. Every PR keeps the dashboard pixel-equivalent and behaviorally equivalent. No design changes (those go through design/agent-dashboard.html first).
Layered imports.panels/ may import from components/ and lib/. components/ may import from lib/. lib/ is leaf (no inward imports). Direction enforced by review, not tooling, until it bites.
Layout
dashboard/
index.html entry, served as-is
app.css styles, served as-is
app.js legacy entry; gets emptied panel-by-panel into src/
src/
lib/ pure utilities, framework-agnostic
components/ small reusable Preact components
panels/ top-level panel components (one per tab)
state/ future shared store, if needed
types.ts shared types
dist/ tsup output (gitignored)
tsconfig.json
Plan
Four stages, each producing one or more PRs. Stage n doesn't begin until stage n-1 is on main.
PR 3.2 Extract everything else in one PR: usePoll → lib/use-poll.ts, appBus / toastBus / showToast / ToastStack → lib/bus.ts, ErrorBoundary → lib/error-boundary.tsx, markdown rendering + hlLine (renderMessageBody / escapeHtml / renderSearchReplace / renderUnifiedDiff / langFromPath / renderHighlightedBlock / hlLine) → lib/markdown.ts. ~250 LoC moved across 4 new files. (Originally split across 4 PRs but each was a 30-line leaf extraction — not enough review value to justify the PR overhead.)
Stage 4 — migrate panels
Panels grouped by size to keep PR count reasonable. Each PR migrates a coherent batch to dashboard/src/panels/.
PR 4.1 Small batch: Overview, Tools, Permissions, Plans, Hooks. (#34)
PR 4.2 Medium batch: Settings, Memory, Skills, MCP. (Sessions deferred — depends on ChatMessage.) (#35)
PR 4.6Chat + Sessions + chat-internals (ToolCard, ChatMessage, 7 modals, lineDiff helpers). app.js shrinks 1562 → 125 LoC; net 4768 → 125 since the refactor began. (#39)
PR 4.7 New Edit review panel → panels/edit-review.tsx. Deferred — blocked on RFC #25 since the panel renders test_run / edit_claim events that don't exist in the kernel yet. Pick this up after the RFC's tracking issue lands its event-types stage.
Follow-ups (out of scope for the refactor itself)
Tighten @ts-nocheck in chat code. PR 4.6 used @ts-nocheck on chat-internals.ts and panels/chat.ts to bulk-migrate ~1300 LoC of JS-style code without typing each closure individually. A follow-up should remove those pragmas progressively, file by file, replacing any and untyped event handlers with proper Preact / DOM types.
Adding any new feature surface beyond what design/agent-dashboard.html already specifies.
Server-side changes — the existing API endpoints stay.
TUI side of the project — none of src/cli/** is touched.
Visual redesign — pixels stay identical until the panel is migrated, then catch up to the mockup.
Tracking
PRs reference this issue with Closes part of #<this>. Stage progress is the checkbox state above. Re-evaluate the plan if anything in design/agent-dashboard.html shifts substantially.
Why
dashboard/app.jsis 4768 lines, single file, 16 panels inlined, no centralised state, polling-based sync via a privateusePoll, cross-panel coordination via two DOM event buses (appBus/toastBus). It works, but adding anything new means scrolling, and the editor surface that the design mockup just deleted still occupies ~30% of the file. Refactor target: the updated mockup atdesign/agent-dashboard.html.Constraints
dashboard/src/; tsup bundles todashboard/dist/app.js; the asset server serves the bundled output. CDN imports (esm.sh URLs) stay external. HTM tagged templates, no JSX. Build infra landed in #29.design/agent-dashboard.htmlfirst).panels/may import fromcomponents/andlib/.components/may import fromlib/.lib/is leaf (no inward imports). Direction enforced by review, not tooling, until it bites.Layout
Plan
Four stages, each producing one or more PRs. Stage
ndoesn't begin until stagen-1is onmain.Stage 1 — build infra + extract pure utilities
dashboard/app.js→dashboard/dist/app.js, dashboard tsconfig, asset server serves bundled output. (#29)fmtUsd,fmtPct,fmtNum,fmtBytes,fmtRelativeTime) →dashboard/src/lib/format.ts. (#30)Stage 2 — drop the editor surface
EditorPanel+ drawer +codemirror.js+/api/files+open-fileevent +Editortab. Net −1535 LoC, bundle 137 → 121 KB. (#31)Stage 3 — extract shared infra
Pulls the cross-panel plumbing out of the god file. All paths under
dashboard/src/lib/.api()+ token bootstrapping →lib/api.ts. (#32)usePoll→lib/use-poll.ts,appBus/toastBus/showToast/ToastStack→lib/bus.ts,ErrorBoundary→lib/error-boundary.tsx, markdown rendering +hlLine(renderMessageBody/escapeHtml/renderSearchReplace/renderUnifiedDiff/langFromPath/renderHighlightedBlock/hlLine) →lib/markdown.ts. ~250 LoC moved across 4 new files. (Originally split across 4 PRs but each was a 30-line leaf extraction — not enough review value to justify the PR overhead.)Stage 4 — migrate panels
Panels grouped by size to keep PR count reasonable. Each PR migrates a coherent batch to
dashboard/src/panels/.Overview,Tools,Permissions,Plans,Hooks. (#34)Settings,Memory,Skills,MCP. (Sessions deferred — depends onChatMessage.) (#35)Usage+ uPlot chart loader. (#36)System. (#37)Semantic(+ 6 supporting components). (#38)Chat+Sessions+chat-internals(ToolCard, ChatMessage, 7 modals, lineDiff helpers). app.js shrinks 1562 → 125 LoC; net 4768 → 125 since the refactor began. (#39)Edit reviewpanel →panels/edit-review.tsx. Deferred — blocked on RFC #25 since the panel renderstest_run/edit_claimevents that don't exist in the kernel yet. Pick this up after the RFC's tracking issue lands its event-types stage.Follow-ups (out of scope for the refactor itself)
@ts-nocheckin chat code. PR 4.6 used@ts-nocheckonchat-internals.tsandpanels/chat.tsto bulk-migrate ~1300 LoC of JS-style code without typing each closure individually. A follow-up should remove those pragmas progressively, file by file, replacinganyand untyped event handlers with proper Preact / DOM types.@codemirror/*devDependencies. They were only used by the editor surface that refactor(dashboard): drop the editor surface (Stage 2 of #28) #31 removed; cleaning them up is a tiny but separatechore(deps)PR.Out of scope
design/agent-dashboard.htmlalready specifies.src/cli/**is touched.Tracking
PRs reference this issue with
Closes part of #<this>. Stage progress is the checkbox state above. Re-evaluate the plan if anything indesign/agent-dashboard.htmlshifts substantially.