CodeIssuesPull RequestsActionsSecurityInsights
✨ AI
More
Settings

Slack overhaul: kill the notification firehose + fix command understanding #3837

Merged⚡ AI-generatedXSccantynz wants to mergeclaude/slack-notifications-commands-jt6r5bmainopened Jul 12, 2026
ccantynzcommented Jul 12, 2026

Originally written by @ccantynz-alt on GitHub.
Imported from https://github.com/ccantynz-alt/jarvis-platform/pull/1


Why

Craig was getting hundreds of Slack notifications and couldn't control Jarvis through Slack — natural-language repair commands were misrouted or silently mishandled.

Root causes found

Notification flood

  • Every service posts straight to chat.postMessage with zero throttling, dedupe, or batching
  • Daily audit cron posted one line per platform (12 platforms now) — and always showed score ?/100 because /audit/run responds before the audit finishes; audit-runner then posted its own full report per platform on top → double spam every morning
  • Audit reports posted even when everything was healthy
  • Visual-change alerts fire on any pixel diff (md5 compare), so dynamic pages alert on every check
  • Every dispatch produced 2+ messages

Commands misunderstood

  • can you fix vapron signup starts with "can" → classified as a question → status report instead of a fix
  • hey jarvis ... matched the registered platform jarvis and routed commands there
  • Anything unrecognized was auto-dispatched to the orchestrator → "Which platform?" spam and spurious agent runs
  • Haiku fallback runs via CLI cold start (3–10 s) and fails silently to the wrong keyword guess

What changed

New src/notify-center.js — single gate for all unsolicited notifications:

  • Levels: critical (immediate, bypasses quiet hours/mute) / warning (immediate, deduped + rate-limited) / info (batched into a digest, default every 30 min)
  • Per-key dedupe cooldown, max-15-immediate-per-hour backstop (overflow demotes to digest with a one-time notice)
  • Quiet hours 22:00–07:00 NZ hold non-critical overnight
  • State (mute, queue) persists across service restarts
  • Slack controls: mute, mute 2h, mute all, unmute, digest, notifications
  • Replies to Craig's own commands bypass all of this — mute never mutes answers

New src/intent.js — keyword tier extracted, pure and unit-tested:

  • Strips hey jarvis address prefix and polite lead-ins before matching → can you fix X now dispatches
  • Unclear messages get a "didn't catch that" reply, never an auto-dispatch
  • Platform prefix matching tightened to 5 chars ("booking" no longer hits bookaride)
  • New notification-control intents

src/slack-bridge.js rewired:

  • All service-facing endpoints route through NotifyCenter with levels (/slack/report levels itself from audit status — healthy → digest)
  • Image alerts gated per-platform with cooldown before upload
  • Haiku classifier uses the HTTP Messages API (~300 ms) when ANTHROPIC_API_KEY is set, CLI fallback otherwise (debt #2 code path)
  • Dispatch now posts one message instead of two
  • New: POST /slack/digest, GET /slack/notify-status

src/orchestrator.js: daily audit cron no longer posts per-platform lines (audit-runner reports real results through the leveled path); skips platforms without audit configs. src/deploy-gate.js: gate-blocked alerts marked critical.

Docs/config: CLAUDE.md updated per Rule 0 (incl. stale platform list + debt items); secrets.env.example gains ANTHROPIC_API_KEY + notification tuning vars.

Verification

  • 24 unit tests added, all passing (npm test, node --test)
  • node --check clean on all services
  • Booted the bridge locally and exercised the HTTP endpoints: info → queued, warning → sent, repeat warning → deduped, healthy report → digest, force-flush → single digest message with all 3 queued items
  • /slack/test dry-run: hey jarvis can you fix the signup flow on vapron → normalized fix the signup flow on vapron → dispatch (Haiku CLI fallback also ran live and agreed)

Deploy notes (on the box)

  1. git pull && systemctl restart jarvis-slack jarvis-orchestrator jarvis-deploy-gate
  2. Add ANTHROPIC_API_KEY to /opt/jarvis/config/secrets.env to get ~300 ms intent classification (optional but recommended — clears debt #2)
  3. Verify: curl http://127.0.0.1:9203/slack/healthclassifier: "http-api", notify block present

🤖 Generated with Claude Code

https://claude.ai/code/session_01ASQBuvnQ97d4ZJvtxFBXUA


Generated by Claude Code

Cross-repo impact

See what breaks downstream if this PR merges.

Analyze →
⮌ Merged

This pull request was merged into main.

c comment · e edit title · m merge · a approve · r request changes · ? shortcuts