Skip to content

Fix dashboard bugs: Run Now, AI Insights, token chart, Design QC, project switching, cron logging#4

Open
MyEditHub wants to merge 1 commit intocytostack:mainfrom
MyEditHub:fix/dashboard-bugs
Open

Fix dashboard bugs: Run Now, AI Insights, token chart, Design QC, project switching, cron logging#4
MyEditHub wants to merge 1 commit intocytostack:mainfrom
MyEditHub:fix/dashboard-bugs

Conversation

@MyEditHub
Copy link
Copy Markdown

This PR fixes 8 bugs found during real usage of the OpenWolf dashboard. No new features — all fixes.

Bug 1 — "Run Now" button silently did nothing

The button called client?.send() over WebSocket which drops silently if the socket is not in OPEN state. Replaced with fetch POST /api/cron/run/:taskId. The endpoint returns 202 immediately and runs the task in the background. If the task fails, a task_error WebSocket message is broadcast so the UI shows the actual error instead of resetting silently.

Bug 2 — AI Insights "Generate Now" opened the Claude desktop app

The cron engine was spawning the claude CLI binary from a background daemon. On macOS that binary spins up a Linux VM via the Virtualization framework and delegates auth to the desktop app — both fail from a headless process. Fix: if ANTHROPIC_API_KEY is set, call the Anthropic API directly via fetch. If not set, fail immediately with a clear error. The dashboard panel now shows a copy-able prompt to paste into a Claude Code session — how OpenWolf is meant to work (Claude writes data, the dashboard reads it).

Bug 3 — Token graph x-axis showed date only, not time

s.started.slice(0, 10) only kept the date. Changed to .slice(0, 16).replace("T", " ") to show YYYY-MM-DD HH:MM.

Bug 4 — Design QC only worked on localhost

The capture engine only detected dev servers. Added detectDeployedUrl() which checks package.json homepage, .env.production URL vars, and vercel.json aliases. Added a manual "Run Capture" button with POST /api/designqc/run endpoint. Fixed the engine not writing designqc-report.json after capture.

Bug 5 — Token comparison chart had hardcoded data and visual issues

Removed fabricated comparison data. Now uses real tracked values from the token ledger. Fixed the gray tail on bars (recharts renders a background behind each bar by default — set background fill to transparent). Fixed tooltip using undefined CSS variables — now uses explicit dark colors. Labels updated to be honest: "With OpenWolf (actual)" vs "Without OpenWolf (est.)".

Bug 6 — "Healthy" and "Live" badges were meaningless

The sidebar badge always showed green regardless of actual state. The header Live indicator added noise without value — if the page loaded, the daemon is running. Both removed.

Bug 7 — Dashboard showed wrong project after switching

All projects default to port 18791. Starting a second project's daemon failed silently because the port was already held, leaving the old project's dashboard visible. daemonStart now kills whatever is on the port before starting. Added POST /api/switch which hot-reloads the project in-place: stops the cron engine and file watcher, swaps the project root, restarts both subsystems, broadcasts the new project's full state over the existing WebSocket. No process restart needed. Added a project switcher dropdown in the dashboard header.

Bug 8 — Cron execution log was never written

The daemon writes cron-state.json on startup with only { engine_status, last_heartbeat }. When tasks completed and tried to append to execution_log, they hit TypeError: Cannot read properties of undefined — caught by the task's own catch block, making every successful run look like a failure. Fixed by merging stored state with complete defaults in readState() so execution_log is always an array.

Also: openwolf binary lost execute bit on every build

tsc does not preserve the +x bit. Added chmod +x to the build script and a postinstall hook so it is set automatically after every build and npm install -g.

…ject switching, cron logging

Bug 1 — "Run Now" button silently did nothing
The button called client?.send() over WebSocket which drops silently if
the socket is not in OPEN state. Replaced with fetch POST /api/cron/run/:taskId.
The endpoint returns 202 immediately and runs the task in the background.
If the task fails, a task_error WebSocket message is broadcast so the UI
shows the actual error instead of resetting silently.

Bug 2 — AI Insights "Generate Now" opened the Claude desktop app
The cron engine was spawning the claude CLI binary from a background daemon.
On macOS that binary spins up a Linux VM via the Virtualization framework
and delegates auth to the desktop app — both fail from a headless process.
Fix: if ANTHROPIC_API_KEY is set, call the Anthropic API directly via fetch.
If not set, fail immediately with a clear error. The dashboard panel now shows
a copy-able prompt to paste into a Claude Code session — how OpenWolf is meant
to work (Claude writes data, the dashboard reads it).

Bug 3 — Token graph x-axis showed date only, not time
s.started.slice(0, 10) only kept the date. Changed to .slice(0, 16).replace("T", " ")
to show YYYY-MM-DD HH:MM.

Bug 4 — Design QC only worked on localhost
The capture engine only detected dev servers. Added detectDeployedUrl() which
checks package.json homepage, .env.production URL vars, and vercel.json aliases.
Added a manual "Run Capture" button with POST /api/designqc/run endpoint.
Fixed the engine not writing designqc-report.json after capture.

Bug 5 — Token comparison chart had hardcoded data and visual issues
Removed fabricated comparison data. Now uses real tracked values from the token
ledger. Fixed the gray tail on bars (recharts renders a background behind each
bar by default — set background fill to transparent). Fixed tooltip using
undefined CSS variables — now uses explicit dark colors.

Bug 6 — "Healthy" and "Live" badges were meaningless
The sidebar badge always showed green regardless of actual state. The header
Live indicator added noise without value — if the page loaded the daemon is
running. Both removed.

Bug 7 — Dashboard showed wrong project after switching
All projects default to port 18791. Starting a second project's daemon failed
silently because the port was already held, leaving the old project's dashboard
visible. daemonStart now kills whatever is on the port before starting. Added
POST /api/switch which hot-reloads the project in-place: stops the cron engine
and file watcher, swaps the project root, restarts both subsystems, broadcasts
the new project's full state over the existing WebSocket. No process restart
needed. Added a project switcher dropdown in the dashboard header.

Bug 8 — Cron execution log was never written
The daemon writes cron-state.json on startup with only { engine_status,
last_heartbeat }. When tasks completed and tried to append to execution_log,
they hit TypeError: Cannot read properties of undefined (reading 'push') —
caught by the task's own catch block, making every successful run look like a
failure. Fixed by merging stored state with complete defaults in readState()
so execution_log is always an array.

Also: openwolf binary lost execute bit on every build
tsc does not preserve the +x bit. Added chmod +x to the build script and a
postinstall hook so it is set automatically after every build and npm install -g.
tkensiski added a commit to tkensiski/openwolf that referenced this pull request Apr 9, 2026
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