Skip to content

feat(dashboard): interactive control panel — drive QodeX from the browser#51

Merged
QodeXcli merged 1 commit into
mainfrom
feat/control-dashboard
Jun 30, 2026
Merged

feat(dashboard): interactive control panel — drive QodeX from the browser#51
QodeXcli merged 1 commit into
mainfrom
feat/control-dashboard

Conversation

@QodeXcli

Copy link
Copy Markdown
Owner

Why

The goal: every capability controllable from the dashboard. This lays the foundation and ships the first batch — the read-only dashboard becomes a live control panel, and each new control is just one entry in an action registry.

What

  • dashboard-control.ts — action registry + dispatch. config.set goes through a strict whitelist of (path, type) knobs (prompt caching, efficient mode, memory mode, sub-agents, learning / episodic / failure-lessons) — the panel can never write an arbitrary config key. Plus memory.forget, schedule.setEnabled / remove, offload.apply. Pure validators (validateConfigSet, setDeep/getDeep) are unit-tested; only the appliers touch disk/the store.
  • dashboard-server.ts — a local control server. Binds 127.0.0.1 only; every request needs a random per-launch token (?k= / x-qodex-token) or it 401s — a CSRF-ish guard, since this mutates config + memory. handleRequest is factored out for unit tests; live smoke-tested (401 without token, state with token, HTML served, clean close).
  • Interactive HTML. buildDashboardHtml(d, {token}) renders live toggles/selects + schedule enable/remove buttons + a toast and the action JS when tokened; read-only otherwise (the old static render and --static still work). runDashboard starts the server and opens the tokened URL; qodex dashboard keeps it alive (Ctrl-C), --static writes the snapshot.
$ qodex dashboard
📊 QodeX control dashboard → http://127.0.0.1:53219/?k=…
   Live & local. Toggle settings, manage schedules, forget facts, apply offloading.

Security

Local-only bind + per-launch token; whitelisted config writes; unknown actions rejected. The mutating API is never reachable without the token printed to your terminal.

Tests

+19 (whitelist + coercion, setDeep/getDeep, dispatch unknown+reject, route auth/routing, live-vs-read-only render). Full suite 1366 green, tsc clean.

Next

The registry makes "all capabilities" incremental: provider add/remove, skill curate/promote, bot start/stop, /project worklog, model switch — each is one more action + widget.

…wser

Turns the read-only dashboard into a CONTROL surface, on a foundation that grows to "every
capability controllable" — each control is one entry in an action registry.

  - src/cli/dashboard-control.ts: the action registry + dispatch. config.set goes through a
    strict WHITELIST of (path, type) knobs (caching, efficient mode, memory mode, sub-agents,
    learning/episodic/lessons) so the panel can NEVER write an arbitrary config key; plus
    memory.forget, schedule.setEnabled/remove, offload.apply. Pure validators (validateConfigSet,
    setDeep/getDeep) are unit-tested; only the appliers touch disk/the store.
  - src/cli/dashboard-server.ts: a local control server — binds 127.0.0.1 ONLY, every request
    needs a random per-launch token (?k= / x-qodex-token) or it 401s (CSRF-ish guard, since this
    mutates config + memory). handleRequest is factored out and unit-tested; live smoke-tested
    (401 without token, state with token, clean close).
  - dashboard.ts: buildDashboardHtml(d, {token}) renders live toggles/selects + schedule
    enable/remove buttons + a toast and the action JS when tokened; read-only otherwise (so the
    old static render + `--static` still work). gatherDashboardData now includes control state +
    schedules. runDashboard starts the server + opens the tokened URL; writeStaticDashboard keeps
    the snapshot path. `qodex dashboard` runs the live server (Ctrl-C to stop); `--static` for the file.

+19 tests (whitelist/coercion, setDeep/getDeep, dispatch unknown+reject, route auth/routing,
live vs read-only render). Full suite 1366 green; tsc clean.
@QodeXcli QodeXcli merged commit a89aa24 into main Jun 30, 2026
2 checks passed
@QodeXcli QodeXcli deleted the feat/control-dashboard branch June 30, 2026 02:59
QodeXcli added a commit that referenced this pull request Jun 30, 2026
…idates (#52)

More of "every capability controllable", each one more action + widget on the registry/server
foundation from #51.

  - model.set — switch defaults.model from a dropdown of every model the configured providers
    expose (+ the current default).
  - memory.add — a "Remember a fact" input in the memory panel (writes via the store + mirror).
  - skill.promote / skill.reject — the quarantine of captured skill candidates is now listed
    with confidence, and promoted (re-checks the human-protection guard) or rejected inline.
  - gatherDashboardData surfaces `models` + `candidates`; new widgets render live (and degrade
    to read-only state without a token).

All four validate input before touching disk/the store; unknown/empty params are rejected.
+5 tests (live render wires the new actions + lists candidates; dispatch rejects empty input).
Full suite 1367 green; tsc clean.

Co-authored-by: Louise Lau <QodeXcli@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant