Skip to content

tracking: dashboard refactor (4768-line single file → modular panels) #28

@esengine

Description

@esengine

Why

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.

Stage 1 — build infra + extract pure utilities

  • PR 1.0a Build infra: tsup bundles dashboard/app.jsdashboard/dist/app.js, dashboard tsconfig, asset server serves bundled output. (#29)
  • PR 1.0b Extract formatters (fmtUsd, fmtPct, fmtNum, fmtBytes, fmtRelativeTime) → dashboard/src/lib/format.ts. (#30)

Stage 2 — drop the editor surface

  • PR 2.1 Remove EditorPanel + drawer + codemirror.js + /api/files + open-file event + Editor tab. 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/.

  • PR 3.1 Extract api() + token bootstrapping → lib/api.ts. (#32)
  • PR 3.2 Extract everything else in one PR: usePolllib/use-poll.ts, appBus / toastBus / showToast / ToastStacklib/bus.ts, ErrorBoundarylib/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.3 Usage + uPlot chart loader. (#36)
  • PR 4.4 System. (#37)
  • PR 4.5 Semantic (+ 6 supporting components). (#38)
  • PR 4.6 Chat + 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.
  • Drop unused @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 separate chore(deps) PR.

Out of scope

  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttrackingTracking issue / umbrella for a multi-PR effort

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions