RUBRIC Dashboard (agent ops console)

Installed: 2026-08-05 (session, from RoboNuggets zip robonuggets-rubric.zip) URL: https://rubric.unlikely.systems (tailnet-only) · localhost:5050 Service: rubric-dashboard.service (systemd, User=claude, Node 22) Repo/location: /opt/rubric-dashboard (unzipped release, CC BY 4.0, v2.0.0 — no git remote; update = drop new zip + re-apply configs)

One-page ops cockpit from Jay E / RoboNuggets — the operations counterpart to the rubric-second-brain (knowledge map, port 5210 / sb.unlikely.systems). Do not merge them.

Architecture

  • Scaffold server (templates/scaffold/server.js, port 5050, binds 127.0.0.1) auto-detects sibling template folders as tabs: Agents, Flows, Skill Trees, Crons, Team (+ Welcome, Icons).
  • Caddy vhost mirrors the sb pattern: public DNS A record → tailnet IP 100.97.131.0, real LE cert via lego DNS-01 manual (expires ~2026-11-03, same renewal dance as sb), MANDATORY remote_ip 100.64.0.0/10 guard (verified: tailnet 200, public 403).
  • No external network calls in server code; no exec; 1MB body cap (audited at install).

Fleet roster (scaffold/config.json)

claude-code (Crown), kilroy (Phantom), friday (Spark), shepherd (Sentinel), auto-validation (Fortress), recon-scanner (Orb), doc-extraction (Drift).

Status feeds

  • claude-code: UserPromptSubmit (active) / Stop (idle) hooks in ~/.claude/settings.json POST to /api/agent-status. Sessions opened before the hook install don’t report.
  • Everything else: /opt/scripts/rubric-status-bridge.py, claude crontab */5. Detects activity from docker logs (scheduler/worker/api, 6-min window) and hermes file mtimes (agent.log/gateway.log/sessions.json only — mcp-stderr.log churns when idle and must stay excluded). Transition-only POSTs (repeated idle POSTs would pin agents in the amber “recent” state). Also clears claude-code ‘active’ stale >4h (dead session).

Crons tab feed

/opt/scripts/rubric-crons-export.py (claude crontab, daily 5:10 ET) runs gen-routines.py then converts rubric-brain’s routines.json → /opt/rubric-dashboard/data/crons.json. Handles three schedule dialects: raw cron+TZ, arq strings (“every 1h ET”, “6:30 wd ET”), bare Kilroy cron. Forces ET for crontab entries (gen-routines mislabels them UTC — bug flagged for fix at source).

Skill Trees / Team quirks

  • Skill scanner skips dot-directories and only decorates auto-detected workspaces, so the scan root is a symlink shim: SKILL_TREE_ROOT=/opt/rubric-dashboard/workspace with agents/claude-code/.claude/skills → ~/.claude/skills and agents/KILROY/skills → ~/.hermes/skills.
  • Team tab scans agents/{ID_UPPERCASE}/.claude/skills (hence the uppercase KILROY dir) from its own root /opt/rubric-dashboard/team-root (separate so skill-tree attribution stays clean; team’s “shared” skills = ~/.claude/skills shown on every member by template design).

rubric-second-brain · kilroy · pipeline-shepherd · unlikely-systems custom URL pattern (memory project_unlikely_systems_custom_urls, now 2 instances: sb, rubric)

Pulse tab (custom, 2026-08-06)

Home tab (double-click home pref set): fleet health strip (shepherd / recon / extraction / kilroy, ok-warn-alert) + Dustin’s three daily cards (money now, stuck now, sent today) + the fleet-audit worklist. Not upstream — re-apply scaffold patches after any RoboNuggets update (list in templates/pulse/README.md).

  • Data: /opt/scripts/rubric-fleet-collector.py (claude crontab */15) → data/fleet.json
    • fleet-history.jsonl (trend line). Reads shepherd reports, recon/payment/email SQLite, Kilroy job registry, Supabase (document_extractions, projects AR). Thresholds Dustin-confirmed: recon alert oldest-pending >30d, extraction alert batch >24h, shepherd alert missed weekday report / warn rule >2x median (floor 10), kilroy alert failed job.
  • Worklist: data/worklist.json (15-item audit matrix, items 1–6 done via entirely-api 2582845) maintained by /opt/scripts/rubric-worklist.py — CLAUDE.md ritual step 4.
  • Server routes /api/fleet + /api/worklist gated on the pulse template marker.
  • Plan of record: /home/claude/RUBRIC_MASTER_PLAN_2026-08-06.md (merged 2-session design; audits mirrored at services/friday-capability-audit-2026-08-06.md and services/automation-fleet-audit-2026-08-06.md). Next: Health canaries + missed-run detector, Outbox, Money (after money-bug deploy), Queues.

Health tab (custom, 2026-08-06 — same session as Pulse)

“Red means broken” in full: 16 infrastructure canaries (containers, redis, API, disk, TLS expiries, backup freshness, Anthropic key validity, billing/token/ credit log scans, 4 systemd services), crontab missed-run detector (syslog CRON evidence vs both crontabs, worst-case-gap + 90min slack; arq tasks covered indirectly by system blocks — per-task arq detection deferred), and per-system detail cards incl. full Kilroy 13-job table, Friday 7d-activity tripwire, and auto-validation 7d outcomes. Click a red/amber canary to acknowledge (localStorage, auto-clears when the detail changes). Same collector feeds it (fleet.json health section). Patch list in templates/health/README.md.

Outbox tab (custom, 2026-08-06 — same session as Pulse/Health)

“What left the building”: 14-day reverse-chron feed of cert sends (grouped per-recipient tracking, deep links to entirely.it.com/projects/{id}), invoice sends, Kilroy cron deliverables (real response preview from the saved output markdown; silent runs hidden by a toggle), and remittances processed. Channel + branch filter chips, day grouping. Fed by fleet.json outbox section (collector v3). SMS channel deferred — whatsapp_service has no server-side send ledger yet (candidate future work alongside worklist item 10). Patch list in templates/outbox/README.md.

Money tab (custom, 2026-08-07)

The standing AR picture, gated on the 2582845 money-bug deploy (verified in running containers before build): 4 stat cards (AR outstanding / received 30d net / parked in smart-recon / written off), AR aging buckets by branch, open invoices flagged red past their branch p90 benchmark (15d default, BALT 34d, from the 2026-08-05 payment-lag analysis), and the parked pending-matches queue (confidence + age, >30d red). Cash excludes write_off rows per the standing convention and is net of reversals; payment_date parsed in both its mixed formats. Every figure reads stored ledger values — nothing recomputed. Fed by fleet.json money (collector v4); Pulse money card derives from the same query. Patch list in templates/money/README.md.

Queues tab (custom, 2026-08-07)

Mirror-don’t-move (the master plan’s Q4 decision): 12 read-only queue cards — owner review, holding pool (oldest-first + ages), open RFIs (count=exact: the true count is 1,480, exposed the moment the shepherd’s 1000-row cap was bypassed), desk-review prep, pending media, schedule/intake/cancel/ return-visit requests, escalations, smart-recon parked, failed-inspection flags (743 open, no portal page). Decision queues amber when non-empty; every card deep-links to the exact portal page where acting happens. Fed by fleet.json queues (collector v5). Patch list in templates/queues/README.md.

Control buttons (custom, 2026-08-07)

First write-side surface, per the “three safe idempotent buttons” decision: Refresh snapshot / Run recon scan / Resend briefing Telegram, on the Health tab with two-click confirm (arm for 4s, then fire). Backend: POST /api/action {id} in the scaffold server execFile of /opt/scripts/rubric-actions.py with a fixed allowlist on BOTH sides (no parameters ever reach a shell). Actions: collector re-run; run_reconciliation_scan via docker exec (same call as the 7:15 cron); latest saved morning-briefing Response re-delivered to Dustin via the Kilroy ops-notify HMAC-V2 webhook (host adapter 127.0.0.1:8644, secret from /opt/unlikely-api/.env). Explicitly NOT buttons: cron pausing, edits, client-facing sends. All three live-tested at build time.