Skip to content

fix: scope dashboard notifications to the live daemon#1989

Open
whoisasx wants to merge 3 commits into
mainfrom
feat/1984
Open

fix: scope dashboard notifications to the live daemon#1989
whoisasx wants to merge 3 commits into
mainfrom
feat/1984

Conversation

@whoisasx
Copy link
Copy Markdown
Contributor

Summary

  • add a daemon-level dashboard notification store path and persist it in running.json
  • route dashboard notifier writes to the live daemon store when a daemon is running, falling back to the config-scoped store otherwise
  • make the mux notification broadcaster read the live daemon store so global/local config resolution cannot split dashboard notifications

Closes #1984

Tests

  • pnpm build
  • pnpm typecheck
  • pnpm lint (passes with existing warnings)
  • pnpm --filter @aoagents/ao-core test -- dashboard-notifications
  • pnpm --filter @aoagents/ao-plugin-notifier-dashboard test
  • pnpm --filter @aoagents/ao-cli test -- tests/lib/running-state.test.ts
  • pnpm --filter @aoagents/ao-web test -- server/tests/mux-websocket.test.ts
  • pnpm --filter @aoagents/ao-web test

Notes

  • pnpm test was run and currently fails on unrelated existing/local-environment failures: notifier-desktop integration expects osascript arguments but the macOS notifier path uses terminal-notifier, and cli path-equality canonicalizes /var to /private/var on this macOS host.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

Test Coverage Report

Metric Value
Lines covered 2320/3226
Lines not covered 906/3226
Overall coverage 71.9%
Per-file breakdown
File Coverage
packages/cli/src/commands/start.ts 1112/1535 (72.4%)
packages/cli/src/lib/running-state.ts 123/228 (53.9%)
packages/cli/src/lib/web-dir.ts 15/134 (11.2%)
packages/core/src/daemon-children.ts 161/215 (74.9%)
packages/core/src/dashboard-notifications.ts 52/58 (89.7%)
packages/core/src/process-utils.ts 5/5 (100.0%)
packages/core/src/windows-pty-registry.ts 0/28 (0.0%)
packages/web/server/mux-websocket.ts 852/1023 (83.3%)

Uncovered lines

  • packages/cli/src/commands/start.ts: L138-L139, L150-L152, L155-L157, L159, L161-L165, L168-L169, L171, L173-L177, L179-L186, L188-L190, L230-L231, L236-L254, L256-L263, L265-L266, L272-L278, L280, L311-L312, L326-L328, L337-L338, L341-L365, L410-L424, L426-L429, L431-L445, L473, L484, L508-L509, L512-L513, L521-L522, L529-L534, L572-L573, L597-L600, L614-L617, L627-L628, L635-L645, L648-L649, L673-L674, L677-L681, L689-L696, L703-L704, L741-L744, L759-L764, L781-L783, L785-L792, L794-L796, L798-L803, L805-L806, L925-L928, L976, L1009-L1028, L1098-L1099, L1109-L1111, L1183-L1184, L1190-L1191, L1193-L1194, L1197-L1204, L1206, L1254-L1259, L1292-L1293, L1299-L1300, L1324-L1328, L1333-L1338, L1341-L1346, L1353-L1359, L1361-L1368, L1370-L1376, L1425, L1445-L1446, L1551-L1552, L1604-L1621, L1685, L1719-L1721, L1744-L1751, L1778-L1786, L1807-L1808, L1842-L1843, L1851-L1862, L1865, L1893, L1899-L1900, L1903-L1911, L1921-L1922, L1931-L1932, L1979-L1981, L2010-L2012, L2090-L2095, L2125-L2136, L2169-L2170
  • packages/cli/src/lib/running-state.ts: L66-L67, L70-L77, L90-L91, L125-L128, L161-L162, L168, L197-L204, L212-L223, L234-L244, L258-L272, L284-L286, L300-L307, L312-L314, L318-L322, L327-L339, L344-L351
  • packages/cli/src/lib/web-dir.ts: L31-L39, L48-L53, L59-L79, L86-L101, L108-L117, L119-L120, L130-L137, L140-L142, L144-L146, L148, L152-L153, L155-L156, L158, L160-L162, L164-L166, L168-L170, L172-L173, L175-L178, L180-L181, L190-L193, L197-L207, L210-L212
  • packages/core/src/daemon-children.ts: L68-L70, L88-L94, L99-L100, L104, L130, L162, L238, L242, L246-L248, L252-L255, L263-L264, L266, L268-L271, L274, L282, L288-L290, L364, L475-L477, L481, L483, L491, L498-L499, L502-L504, L506-L507, L510-L512, L514
  • packages/core/src/dashboard-notifications.ts: L60, L106, L121, L208, L240-L241
  • packages/core/src/windows-pty-registry.ts: L37, L41-L46, L48, L55, L60-L63, L67, L69, L77-L79, L86-L89, L97-L100, L107, L112
  • packages/web/server/mux-websocket.ts: L119-L121, L123-L124, L157-L158, L164-L169, L242-L245, L303, L306-L308, L310-L311, L317-L319, L331-L332, L361-L364, L376-L377, L382-L389, L412-L417, L437-L439, L489-L490, L500-L501, L518-L521, L523-L527, L581, L587, L644-L645, L654-L656, L754-L755, L831-L832, L1026, L1081-L1083, L1105, L1182-L1183, L1191-L1195, L1217-L1225, L1259-L1265, L1271-L1272, L1279-L1283, L1288-L1290, L1298-L1303, L1306-L1312, L1326-L1367, L1422-L1423, L1431

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 21, 2026

Greptile Summary

This PR fixes dashboard notification routing so that all producers (the notifier-dashboard plugin and the NotificationBroadcaster in the mux server) write and read from a single daemon-level JSONL store rather than a config-scoped one, eliminating split-brain when different processes resolve different config paths.

  • Introduces a daemon-level store path (~/.agent-orchestrator/dashboard-notifications.jsonl) persisted in running.json, and a module-level cache (getLiveDashboardNotificationStorePath) that avoids re-reading the file on every poll tick as long as the daemon's PID is still alive.
  • Consolidates three previously duplicated isProcessAlive helpers into a single shared process-utils.ts implementation now exported from @aoagents/ao-core.
  • Routes the dashboard child process to the daemon store via AO_DASHBOARD_NOTIFICATION_STORE env var, with getLiveDashboardNotificationStorePath() as a dynamic fallback for the notifier plugin.

Confidence Score: 5/5

Safe to merge — routing logic is correct and the PID-keyed cache invalidates cleanly on daemon restart.

The daemon store path is deterministic and consistent across all three write/read paths. The only gap is a missing test-reset export for the module-level cache, which does not affect production correctness.

No files require special attention.

Important Files Changed

Filename Overview
packages/core/src/dashboard-notifications.ts Adds daemon-level store path, a PID-keyed module-level cache, and validation logic; cache has no exported reset function for tests.
packages/core/src/process-utils.ts New shared isProcessAlive helper with pid <= 0 guard and EPERM handling; consolidates three duplicated copies.
packages/web/server/mux-websocket.ts NotificationBroadcaster now resolves store path dynamically: envStorePath then live daemon store then config-scoped fallback.
packages/plugins/notifier-dashboard/src/index.ts resolveStorePath() prefers the live daemon store and falls back to config-scoped path.
packages/cli/src/lib/running-state.ts RunningState gains dashboardNotificationStore field; register() always writes it.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/core/src/dashboard-notifications.ts:81
The module-level `liveDashboardNotificationStoreCache` has no exported reset function. The codebase already has the `_clearProcessCacheForTests` convention (exported from `process-cache.ts` and re-exported from `index.ts`). Tests currently work around the missing reset by changing `HOME`/`USERPROFILE` env vars to shift the `runningStatePath` key, but this is an implicit coupling. A future test that needs to observe cache invalidation with the same HOME dir (e.g. same-PID daemon restart) would have no direct way to clear it.

```suggestion
let liveDashboardNotificationStoreCache: LiveDashboardNotificationStoreCache | null = null;

/** @internal – test-only */
export function _clearLiveDashboardNotificationStoreCacheForTests(): void {
  liveDashboardNotificationStoreCache = null;
}
```

Reviews (3): Last reviewed commit: "fix: validate dashboard notification sto..." | Re-trigger Greptile

Comment thread packages/core/src/dashboard-notifications.ts
Comment thread packages/core/src/dashboard-notifications.ts Outdated
Comment thread packages/core/src/dashboard-notifications.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a real-world mismatch where dashboard notifications could be persisted to a config-scoped JSONL store that the currently running dashboard daemon was not watching. It introduces a daemon-scoped notification store (persisted via running.json) and updates both notification producers and the dashboard broadcaster to prefer the live daemon’s store, with env/config fallbacks.

Changes:

  • Add daemon-level dashboard notification store path helpers and live-daemon resolution (running.json) in @aoagents/ao-core.
  • Update dashboard notification producer (dashboard notifier plugin) and consumer (mux notification broadcaster) to prefer the live daemon store (and allow an explicit env override for the dashboard process).
  • Deduplicate PID liveness probing by introducing and reusing a shared isProcessAlive() utility.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/web/server/mux-websocket.ts NotificationBroadcaster now prefers env-provided store, then live-daemon store, then config-scoped store.
packages/web/server/tests/mux-websocket.test.ts Adds coverage for preferring the live daemon store and env override behavior.
packages/plugins/notifier-dashboard/src/index.ts Dashboard notifier now persists to the live daemon store when available, falling back to config-scoped store.
packages/plugins/notifier-dashboard/src/index.test.ts Adds coverage for persisting to the live daemon store and updated warning text.
packages/core/src/dashboard-notifications.ts Adds daemon store path helper + live-daemon store resolution from running.json (with caching).
packages/core/src/process-utils.ts Introduces shared isProcessAlive(pid) helper.
packages/core/src/daemon-children.ts Uses shared isProcessAlive instead of local implementation.
packages/core/src/windows-pty-registry.ts Uses shared isProcessAlive for pruning registry entries.
packages/core/src/index.ts Exports isProcessAlive and new dashboard notification store helpers from core.
packages/core/src/tests/process-utils.test.ts Adds unit tests for isProcessAlive behavior (invalid PID, EPERM, ESRCH).
packages/core/src/tests/dashboard-notifications.test.ts Adds coverage around live-daemon store path caching behavior.
packages/cli/src/lib/running-state.ts Persists dashboardNotificationStore into running.json (defaulting to daemon store path).
packages/cli/src/lib/web-dir.ts Passes daemon notification store path to dashboard process via AO_DASHBOARD_NOTIFICATION_STORE.
packages/cli/src/commands/start.ts Computes/passes daemon store path when spawning the dashboard process.
packages/cli/tests/lib/running-state.test.ts Updates running-state tests to include the new dashboardNotificationStore field.

Comment thread packages/core/src/dashboard-notifications.ts Outdated
Comment thread packages/web/server/mux-websocket.ts Outdated
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.

dashboard notifications can be written to a store the live dashboard is not watching

2 participants