Dashboard · Infrastructure
Server
Shared team workspace on cm-server-01.
Total Jobs
32
Scheduled tasks
Send Messages
12
Via Max or SMS
Services
4
systemd managed
Workspaces
3
Primary, hot standby, remote
Infrastructure
Cloud
GitHub
GitHub Repository (Offsite Backup)
Offsite backup mirror. Server pushes every 15 min. Not the source of truth -- the server is.
Repo: closetmaestro/closet-maestro-executive-assistant
git push (15 min)
VS Code Remote SSH
VS Code Remote SSH
Ellensburg Shop
Server Cabinet
cm-server-01
Shared Workspace
Primary
cm-server-01 (Primary)
Lenovo ThinkCentre M910q. Single source of truth -- everyone works here via VS Code Remote SSH.
Tailscale: 100.100.255.41
LAN: 192.168.10.52
Repo: /opt/maestro/repo
Services (systemd)
maestro-dashboard (:8501)
maestro-colors (:8099)
max-gchat-bot (Pub/Sub)
foam-maestro (:8100)
User Groups
maestro-admin: charlie
maestro-team: charlie, jesy
maestro-intern: (ready for hire)
Scheduled Jobs
Git push to GitHub every 15 min
Token refreshes (QBO 6 AM, Hubstaff 6:30 AM)
Hubstaff/JT sync, Zoom/Plaud intake
Morning digest, grant scanner, SMS
cm-server-02
Hot Standby
Ready
cm-server-02 (Hot Standby)
Lenovo ThinkCentre M910q. Syncs from server-01 every 15 min. Can be promoted to primary if server-01 goes down.
Tailscale: 100.87.39.18
LAN: 192.168.10.53
Sync
rsync from server-01 every 15 min
Includes repo, .env, and all tokens
Watchdog
Monitors server-01 heartbeat every 15 min
Alerts Charlie via Google Chat if stale
Failover
Run: sudo /opt/maestro/promote-to-primary.sh
rsync (15 min)
Charlie's Desk
MacBook Air
VS Code Remote SSH
Charlie's MacBook Air
Connects to cm-server-01 via VS Code Remote SSH through Tailscale. Also has a local repo copy for offline/emergency use.
Philippines (Remote)
Jesy's Desk
MacBook
VS Code Remote SSH
Jesy's MacBook
Connects to cm-server-01 via VS Code Remote SSH through Tailscale. Can restart services with sudo.
Permissions (maestro-team)
Read/write all code files
Restart dashboard, Max bot, colors
Commit and push via git
No access to .env or tokens
How Changes Go Live
1 Connect to cm-server-01 via VS Code Remote SSH
2 Make your change (directly or via Claude Code)
3 Restart the service: sudo systemctl restart maestro-dashboard
4 Changes are live immediately. GitHub backup syncs within 15 min.
Services
systemd-managed services on cm-server-01. Auto-start on boot, auto-restart on crash.
maestro-dashboard Port 8501
systemctl restart maestro-dashboard
FastAPI operations dashboard. Internal use only (Tailscale).
maestro-colors Port 8099
systemctl restart maestro-colors
Colors and Gallery pages (colors.closet-maestro.com, gallery.closet-maestro.com). Airtable-backed, served via Cloudflare Tunnel.
max-gchat-bot Pub/Sub
systemctl restart max-gchat-bot
Max Google Chat bot. Listens for messages, runs clock monitor, sends alerts.
foam-maestro Port 8100
systemctl restart foam-maestro
Foam Maestro web app (foammaestro.com). Separate repo, served via Cloudflare Tunnel.
No automated messages before 8 AM PT. Silent jobs (git push, data intake, token refresh) can run earlier.
Scheduled Jobs
All cron jobs on cm-server-01 (maestro service user).
Wiki Ingest (web clips)
Daily, 5 AM PT (12:00 UTC during PDT)
Processes new clippings in references/raw/Clippings/ into the LLM-wiki at references/wiki/. High-confidence clips become wiki pages (Claude Sonnet 4.6 decides target page + cross-links). Low-confidence clips move to references/raw/needs-review/ for triage. Dry-run default; cron uses --apply. Runs 1hr after meeting ingest so wiki state is fresh for the morning brief. See projects/aios-upgrade/ for context.
data-intake tools/ingest_wiki.py --apply
Wiki Ingest (meetings)
Daily, 4 AM PT (11:00 UTC during PDT)
Three-stage pipeline that distills internal meeting transcripts (Zoom + Plaud) in context/meetings/ into the LLM-wiki. Stage 1: Haiku classifies plaud-* (customer vs internal), Sonnet 4.6 extracts structured candidates per chunk. Stage 2 (free): routes facts/decisions to append/create/needs-review buckets, redacts PII, drops status + actions to log. Stage 3: Sonnet 4.6 writes wiki pages. Customer-facing Plaud calls skipped; speaker attribution stripped; action items not auto-routed to Trello (logged only). Runs nightly so yesterday's meetings show up in today's morning brief. See projects/aios-upgrade/meeting-ingest.md.
data-intake tools/ingest_meetings.py --apply
AIOS Cost Report Messages
Weekly, Monday 7 AM PT (14:00 UTC during PDT)
Passive reality check on AIOS wiki ingest spend. Greps the past 7 days of estimated cost lines from .tmp/ingest_meetings.log and .tmp/ingest_wiki.log, sums them up, and DMs Charlie a one-paragraph summary via Max. Estimates are based on token counts x Sonnet/Haiku rates; authoritative numbers live at platform.claude.com -> Usage. Surfaces the spend so it doesn't drift unnoticed.
monitoring tools/aios_cost_report.py
Dashboard Cache Pre-warm
Every 45 seconds
In-process background loop that refreshes slow cache keys (cash, AR, DOR, jobs, capacity, GPM, pipeline, team, finance, procurement, stripe_payouts, utilization) so visitor requests always hit a warm cache. CACHE_TTL is 120s; loop runs every 45s.
infrastructure Built-in asyncio task in maestro-dashboard process
Git Pull from GitHub
Every 15 minutes
Pulls Charlies Mac-side commits (and any other contributor) from GitHub into the live repo at /opt/maestro/repo. Restores the auto-pull documented in references/jesy-server-access-guide.md, which was lost during the 2026-04-23 server-architecture migration.
infrastructure cd /opt/maestro/repo && git pull --ff-only origin main
Git Push to GitHub
Every 15 minutes
Mirrors commits from cm-server-01 to GitHub as offsite backup. Paired with Git Pull from GitHub for bidirectional sync.
infrastructure git push origin main
Heartbeat
Every 15 minutes
Writes timestamp for cm-server-02 watchdog to monitor.
infrastructure date > .tmp/heartbeat.txt
Hubstaff-JobTread Sync
Daily at 5 AM
Syncs Hubstaff time entries to JobTread projects. Creates/updates project mappings, logs hours. Silent.
operations tools/hubstaff_jobtread_sync.py --confirm
QBO Token Refresh
Daily at 6 AM
Refreshes QuickBooks Online OAuth tokens to prevent 100-day expiry. Alerts via Google Chat on failure.
infrastructure tools/qbo_token_refresh.py
Hubstaff Token Refresh
Daily at 6:30 AM
Refreshes Hubstaff API tokens to prevent staleness. Alerts via Google Chat on failure.
infrastructure tools/hubstaff_token_refresh.py
Zoom Summary Intake
Every 2 hours (6 AM - 6 PM)
Pulls Zoom AI Companion meeting summaries from subs@ Gmail. Saves to context/meetings/ for processing. Silent.
data-intake tools/zoom_summary_intake.py --pull
Plaud Email Intake
Every 2 hours at :15 (6 AM - 6 PM)
Pulls Plaud AutoFlow transcripts from subs@ Gmail. Extracts transcript and summary attachments, saves as markdown. Silent.
data-intake tools/plaud_email_intake.py --pull
Transcript Intake Health Check Messages
Weekly, Monday 8:30 AM PT
Backstop for silent intake failures. Checks newest file in context/meetings/; if older than 7 days, DMs Charlie via Max. Silent when healthy.
data-intake tools/transcript_intake_health_check.py
Morning Digest Messages
Daily at 8 AM
One consolidated Max message combining all manager checks. Includes daily checks always, weekly on Monday, biweekly payroll on 1st/15th, monthly reports on 1st.
max-platform tools/morning_digest.py
Grant Scanner Messages
Biweekly (1st and 15th) at 8 AM
Scans for relevant manufacturing/small business grants and sends findings.
operations tools/grant_scanner.py --send
SMS Scheduler - Friday Prompt Messages
Friday at 3 PM
Prompts team members (Israel, Jensen) about Saturday availability via SMS.
max-platform tools/sms_scheduler.py --action prompt
SMS Scheduler - Poll Replies
Every 15 min (Fri 3 PM - midnight, all day Sat)
Checks for SMS replies from team about Saturday availability.
max-platform tools/sms_scheduler.py --action poll
SMS Scheduler - Saturday Reminder Messages
Saturday at noon
Sends reminder to team members who haven't responded about Saturday availability.
max-platform tools/sms_scheduler.py --action remind
SMS Scheduler - Sunday Escalation Messages
Sunday at 9 AM
Escalates to Charlie if any team members still haven't confirmed Saturday availability.
max-platform tools/sms_scheduler.py --action escalate
Stripe Auto-Payout
Daily at 7 AM and 5 PM
Checks Stripe for available balance, creates individual payouts per charge with descriptive bank statement labels.
operations tools/stripe_auto_payout.py --execute
Drive Audit (Monthly) Messages
Monthly on the 1st at 9 AM
Scans My Drive + shared drives, writes audit report to .tmp/. Notify script pings Charlie via Max if My Drive root has >10 loose files or any duplicate set has >2 copies. Goal: keep root tidy continuously instead of big quarterly cleanups.
operations tools/drive_organizer.py --account charlie@closet-maestro.com audit --include-shared-drives && tools/drive_audit_notify.py
JobTread Projects Sync
Hourly at :05
Mirrors active JobTread jobs into the Airtable Projects table (JobTread Job ID/Number/Name/Status, Job Address/City). Dirty-checked: only writes when a meaningful field changed. Consumed by Procurement (packing_slip_ocr, procurement_email_watcher).
operations tools/jobtread_projects_sync.py --confirm
Reminders Sender
Every 5 min, M-F 8 AM - 7 PM PT
Reads tools/reminders/active.json and sends due reminders via Max bot to Charlie DM space. Set by /remind-me skill. Enforces no-early-messages and weekday-only rules internally.
operations tools/reminders/send_due.py
Compliance Expiration Check
Daily, 7 AM PT (14:00 UTC, PDT season)
Scans the 3 Airtable compliance tables (Customers, Vehicles, Credentials) in the Production Manager base. For any item whose expiration is within 90/60/30 days or already expired, ensures a Trello card exists on the Bookkeeping board > To Do list with contact info, draft request template, and a link back to Airtable. Idempotent: one open card per item, escalates window as days count down, auto-archives stale cards when the Airtable date moves forward (renewal acquired).
tools/compliance_expiration_check.py
Procurement: Vendor email watcher
Every 30 min, 8 AM - 4 PM PT (15:00 - 23:00 UTC), weekdays
Polls Gmail for new messages labeled Richelieu / Intermountain / Hafele. Extracts order number, tracking, ETA, line items via Claude Haiku and matches to currently-Ordered Airtable Purchase Requests. Auto-applies tracking to matched items; logs unmatched extractions to data/unmatched_shipments.json for triage on the Incoming view. Idempotent via data/processed_vendor_emails.json. See projects/procurement-v2/ for context.
data-intake tools/procurement_email_watcher.py
Labor ledger rebuild
Daily 5:30 AM PT (12:30 UTC during PDT) — 30 min after the Hubstaff/JT sync
Rebuilds labor_ledger.json over a 14-day Hubstaff window. Merges fresh sessions over existing review state (approvals, overrides, holds, pushed_at) via merge_ledger() — nothing Jesy has touched is lost. Without this, /labor stays stale and the staleness cron eventually escalates entries that were already resolved out-of-band. Added 2026-05-31 to close a gap in Phase 1.
data-intake PYTHONPATH=tools .venv/bin/python tools/maestro-dashboard/labor_ledger.py 14
TV Display Images Sync
Daily, 5:30 AM PT
Mirrors the TV Display Images + Project Photos Airtable tables (Production Manager base) into static/tv-images/ and writes a per-display manifest.json. Adding a new image: tick Show on Shop TV or Show on Office TV in either Airtable table, set Install Date for the Recent Install caption. Within ~10 min of the next cron run, the TV picks it up. Log: /var/log/tv_images_sync.log.
data-intake tools/tv_images_sync.py
HR Team Photos Sync
Daily, 5:15 AM PT
Mirrors the HR/1 - Team Photos Drive folder (charlie@ personal Drive) into tools/maestro-dashboard/static/team-photos/ as <firstname>.<ext>. Powers the TV top bar's circular profile photos when crew clock in (falls back to initials if no photo). Drop a new photo named '<Firstname>.jpg' in that Drive folder and within ~24 hr it shows up. Log: /var/log/hr_photos_sync.log.
data-intake tools/hr_photos_sync.py
Records Intake Messages
Every 15 minutes
Pulls scans Charlie sent from the Canon MF753Cdw to subs+records@closet-maestro.com, OCRs each PDF with Claude Sonnet 4.6, classifies into 6 folders on the Closet Maestro Records shared drive (Tax, Insurance, Legal & Entity, Banking & Credit, Property & Vehicles, or 00 - Inbox), renames YYYY-MM-DD - Sender - Topic.pdf, uploads, then DMs Charlie a one-line confirmation via Max. Unprocessable scans stay in Gmail inbox for manual review.
data-intake tools/records_intake.py
Records Stale Nudge Messages
Weekdays, 8 AM PT
Scans the Records Intake/Pending Review Gmail label. Items older than the configured threshold (default 48h) get a single combined DM to Charlie pointing at /records pending tab. Items older than 7 days auto-default into 00 - Inbox to stop blocking the queue. Single message per day, not per item.
monitoring tools/records_stale_nudge.py
Comms STOP Poll Messages
Every 15 minutes
Interim TCPA compliance poll until the /comms/inbound webhook ships. Lists inbound SMS to the CM Twilio number, flips sms_opt_out in customer_comms_prefs.json on STOP (hard-blocks future sends via the compliance gate), clears it on START, confirms pending opt-ins on Y/YES, logs every inbound reply to the comms log, and DMs Charlie a combined summary via Max.
monitoring tools/comms_stop_poll.py
Dashboard Hang Watchdog Messages
Every minute
Health watchdog for the dashboard backend. Probes localhost /api/v2/health every minute; on 2 consecutive hard hangs (single-worker uvicorn event loop wedged while systemd still reports active) force-restarts maestro-dashboard and DMs Charlie via Max when it self-heals. Added after the Aug 2026 ~5-day silent outage. Script: tools/maestro-dashboard/healthcheck.sh (root cron).
infra tools/maestro-dashboard/healthcheck.sh
Daily Timeline
When things run on a typical weekday.
5 AM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Hubstaff-JobTread Sync
JobTread Projects Sync
Labor ledger rebuild
TV Display Images Sync
HR Team Photos Sync
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
6 AM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
QBO Token Refresh
Hubstaff Token Refresh
Zoom Summary Intake
Plaud Email Intake
JobTread Projects Sync
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
7 AM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Stripe Auto-Payout
JobTread Projects Sync
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
8 AM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Zoom Summary Intake
Plaud Email Intake
Morning Digest
Grant Scanner
JobTread Projects Sync
Reminders Sender
Records Intake every 15 min
Records Stale Nudge
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
9 AM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Drive Audit (Monthly)
JobTread Projects Sync
Reminders Sender
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
10 AM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Zoom Summary Intake
Plaud Email Intake
JobTread Projects Sync
Reminders Sender
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
11 AM
Wiki Ingest (meetings)
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
JobTread Projects Sync
Reminders Sender
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
12 PM
Wiki Ingest (web clips)
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Zoom Summary Intake
Plaud Email Intake
JobTread Projects Sync
Reminders Sender
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
1 PM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
JobTread Projects Sync
Reminders Sender
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
2 PM
AIOS Cost Report
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Zoom Summary Intake
Plaud Email Intake
JobTread Projects Sync
Reminders Sender
Compliance Expiration Check
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
3 PM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Transcript Intake Health Check
JobTread Projects Sync
Reminders Sender
Procurement: Vendor email watcher
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
4 PM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Zoom Summary Intake
Plaud Email Intake
JobTread Projects Sync
Reminders Sender
Procurement: Vendor email watcher
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
5 PM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Stripe Auto-Payout
JobTread Projects Sync
Reminders Sender
Procurement: Vendor email watcher
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog
6 PM
Git Pull from GitHub every 15 min
Git Push to GitHub every 15 min
Heartbeat every 15 min
Zoom Summary Intake
Plaud Email Intake
JobTread Projects Sync
Reminders Sender
Procurement: Vendor email watcher
Records Intake every 15 min
Comms STOP Poll every 15 min
Dashboard Hang Watchdog