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
Open
Conversation
…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.
8 tasks
tkensiski
added a commit
to tkensiski/openwolf
that referenced
this pull request
Apr 9, 2026
Merge upstream dashboard bug fixes (cytostack#4)
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.
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 withfetch POST /api/cron/run/:taskId. The endpoint returns 202 immediately and runs the task in the background. If the task fails, atask_errorWebSocket 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
claudeCLI 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: ifANTHROPIC_API_KEYis set, call the Anthropic API directly viafetch. 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 showYYYY-MM-DD HH:MM.Bug 4 — Design QC only worked on localhost
The capture engine only detected dev servers. Added
detectDeployedUrl()which checkspackage.jsonhomepage,.env.productionURL vars, andvercel.jsonaliases. Added a manual "Run Capture" button withPOST /api/designqc/runendpoint. Fixed the engine not writingdesignqc-report.jsonafter 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
backgroundfill 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.
daemonStartnow kills whatever is on the port before starting. AddedPOST /api/switchwhich 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.jsonon startup with only{ engine_status, last_heartbeat }. When tasks completed and tried to append toexecution_log, they hitTypeError: 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 inreadState()soexecution_logis always an array.Also: openwolf binary lost execute bit on every build
tscdoes not preserve the+xbit. Addedchmod +xto thebuildscript and apostinstallhook so it is set automatically after every build andnpm install -g.