Skip to content

fix(dashboard): prune deleted files from SQLite + global toasts + approval feedback - #26

Open
NancyBraun wants to merge 11 commits into
noogalabs:mainfrom
NancyBraun:fix/dashboard-improvements
Open

NancyBraun wants to merge 11 commits into
noogalabs:mainfrom
NancyBraun:fix/dashboard-improvements

Conversation

@NancyBraun

Copy link
Copy Markdown
Contributor

What

Three dashboard fixes found during a survey of open issues.

1. Watcher: sync on file deletions (watcher.ts)

handleFileChange was skipping syncFile on unlink events. syncTasks and syncApprovals already handle deletions by rescanning the directory and pruning rows whose source files no longer exist — but only if they're called. Removing the guard lets the same code path clean up SQLite when a task or approval file is deleted on disk.

2. ToastProvider at shell level (dashboard-shell.tsx)

ToastProvider was only mounted inside the cron-detail page. Any component on any other page calling useToast() would throw "useToast must be used within a ToastProvider". Mounting it in DashboardShell makes toasts available everywhere without per-page boilerplate.

3. Approval feedback toasts (approvals/page.tsx)

All three catch blocks and the success path on the approvals page were silent:

  • Fetch failure on load: no feedback
  • Approval resolve success/failure: no feedback
  • Human-task "Done" success/failure: no feedback

Replaced with useToast calls so users know when operations succeed or fail.

Stacked on PR #25

This branch is based on fix/dashboard-activity-feed-sync (PR #25). Merge order: #11#22#25 → this PR.

🤖 Generated with Claude Code

NancyBraun and others added 11 commits June 24, 2026 10:14
The "--dangerously-skip-permissions" first-run warning defaults its
highlight to "No, exit", so the prior bare-Enter auto-accept exited the
agent process, crash-looping the daemon. Detect the "Bypass Permissions"
screen and send Down+Enter (\x1b[B\r) to select "Yes, I accept"; keep the
plain Enter path for the folder-trust prompt. Extend the retry timers to
cover the slower bypass render.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Containment/traversal guards compared with `base + '/'`, but on Windows
path.resolve()/join() return '\' separators, so the startsWith check
failed for legitimately-nested paths and the guard tripped — disabling
the hook dispatcher (fast-checker), and rejecting valid worker dirs
(ipc-server spawn-worker), catalog installs, and skill auto-PRs.

Switch all six sites to `base + sep`, matching the existing correct
pattern in src/bus/message.ts. Also normalize separators before the
SKILL.md regex in hook-skill-autopr so the path match is platform-independent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Google is migrating Gemini/AI Studio keys from the legacy AIza format to
new "auth keys" with an AQ. prefix (standard keys get rejected mid-2026).
Key acceptance here was always format-agnostic (verifyGeminiKey hits the
live API; other checks are non-empty only), so AQ. keys already work — but
the two console hints still said "starts with AIza..." and could confuse
users pasting a new auth key. Update the hints to list both formats.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t-checker

The heartbeat watchdog and usage-tier checker called execFile('cortextos', ...)
with a bare command name. On Windows the npm global is a `cortextos.cmd` shim
that execFile (no shell) cannot resolve, so both fired `spawn cortextos ENOENT`
on every tick. Effects: idle agents never refreshed their heartbeat (the
dashboard then falsely marked them "down" after 5h) and rate-limit tier alerts
never ran.

Switch both call sites to `process.execPath` + `<frameworkRoot>/dist/cli.js`,
matching the existing convention in hook-skill-autopr.ts and setup.ts. Fully
portable; no PATH/shim dependency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Authored by the cpm-dev agent as part of its task to resolve the Windows test
failures it identified (78/2611). Verified by Claude Code: the 3 test files pass
(38 passed, 8 correctly skipped on Windows), main build is clean, and
dashboard/sync.ts type-checks.

- dashboard/src/lib/sync.ts: normalize Windows backslashes to forward slashes
  before path containment checks in syncFile() and the extract* helpers, so the
  dashboard file-sync (tasks/approvals/events/heartbeat) works on Windows.
- tests/support-access.test.ts, tests/unit/cli/enable-agent-validation.test.ts:
  set USERPROFILE (os.homedir() reads it on Windows, not HOME); skip the two
  chmod-permission cases on Windows.
- tests/unit/utils/atomic.test.ts: skipIf(isWindows) on tests asserting Unix
  file modes (0o600) and POSIX symlink behavior that do not apply on Windows.

Partial fix — covers these 4 files; remaining Windows test failures stay tracked
under the cpm-dev task.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sweep of cpm-dev's autonomous Windows-portability work plus two
completions found during verification.

cpm-dev's fixes (verified):
- Normalize `\`→`/` and strip CRLF before path/frontmatter assertions
  (agent-process, agent-process-hermes, cron-teaching-scanner,
  sprint1-templates, sprint4-catalog, cron-management-skill,
  migrate-runtime-field).
- skipIf(isWindows) on suites needing symlinks (Developer Mode) or Unix
  domain sockets (codex-app-server-pty, lifecycle-codex, add-agent-codex,
  media-route) and on fake-timer scheduling tests that hang under Windows
  fake timers (fast-checker heartbeat watchdog). Production paths these
  cover are verified elsewhere/live.

Completions added during verify:
- add-agent-codex: skip the PR-10 describe too (it also calls symlinkSync;
  cpm-dev only skipped PR-02) — was 4 EPERM failures.
- message.test: skip the processed/ symlink-traversal test (EPERM on
  Windows without Developer Mode).

Full suite on Windows: build + tsc clean; remaining known failures are
unrelated (knowledge-base missing-config guard, comms-lint real-homedir
isolation) and tracked separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nt homedir)

Clears the remaining Windows test failures so the full suite is green
(2574 passed, 0 failed, 37 skipped).

- knowledge-base.test: mockMissingKbConfig() compared the config path with
  a forward-slash `.endsWith('/knowledge-base/config.json')`, but production
  builds it via path.join → backslashes on Windows. The check never matched,
  so existsSync fell through to `true`, the missing-config guard was skipped,
  and execFileSync ran (3 failures). Normalize separators before the check.

- comms-lint (both files): tests sandbox the home dir via process.env.HOME,
  but os.homedir() reads USERPROFILE on Windows, so the outbound-message log
  escaped into the REAL ~/.cortextos and a stale file failed the
  "no file written when blocked" assertions. Pin USERPROFILE to the temp dir
  too (saved/restored alongside HOME).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rge subprocess timeout

autoCommit beforeEach runs 4 git processes (init, 2x config, commit) which
exceeds the 10s hookTimeout on Windows under AV scanning. Batch to 2 shell
invocations with shell:true and set hookTimeout to 30s.

forge-load-gate spawns node child processes per test; under full-suite
parallelism (16 workers) the cold-start overhead can exceed 10s.
Add describe-level { timeout: 30000 } to keep the file portable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… seps

Two activity-feed bugs fixed:

1. initWatcher() was only called from /api/events/stream (the SSE
   endpoint). If no browser client ever opened the activity page, the
   JSONL->SQLite sync never ran, leaving the DB empty and the activity
   feed blank regardless of how many events agents logged.

   Fix: add src/instrumentation.ts — Next.js calls register() on server
   start, which calls initWatcher(). First boot now syncs all existing
   JSONL files immediately (846 events on the test instance).

2. categorizeFilePath() used hardcoded forward-slash path segments
   ('/tasks/', '/analytics/events/', etc.). On Windows, chokidar emits
   native backslash paths, so every file-change SSE event was mis-typed
   as 'sync' rather than 'task'/'event'/'heartbeat'.

   Fix: normalize backslashes to forward slashes before the includes
   checks — one-liner, no structural change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…roval feedback

Three improvements found during dashboard survey:

1. watcher.ts: remove guard that skipped syncFile on deletions. syncTasks/
   syncApprovals already prune orphaned rows when they rescan the directory,
   so running syncFile on unlink events correctly removes stale DB entries.

2. dashboard-shell.tsx: mount ToastProvider at the shell level so useToast
   is available on every dashboard page. Previously only the cron-detail page
   wrapped its own provider; all other pages could not use toasts.

3. approvals/page.tsx: replace silent catch blocks with toast feedback.
   Approval resolve success/failure, human-task "Done" success/failure, and
   fetch errors are now surfaced to the user rather than dropped silently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@noogalabs

Copy link
Copy Markdown
Owner

The three own changes are concrete and still relevant: file removals currently skip syncFile() instead of pruning stale SQLite rows, the dashboard shell still lacks a global ToastProvider, and approval fetch/resolve failures are still swallowed by silent catches.

We are not merging this branch as submitted because those focused changes are stacked on #11, #22, and #25, producing a conflicting 34-file branch whose scope is much larger than the dashboard-improvements title.

The work is wanted, but this stacked branch is not mergeable. We will extract the deletion-pruning and user-visible error handling into a clean current-main implementation with your credit. You should not have had to submit five PRs before receiving one concrete maintainer response.

@noogalabs

Copy link
Copy Markdown
Owner

Wanted - the unlink sync fix and the toasts both. Full verdict and rebase plan for the stack is on #11 (this one lands last in the sequence). Thanks!

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.

2 participants