Shadman's AI Operating System

Agent Playbook

Root brain · Harness control plane · Hermes runtime · Orbit operator

v5.2 · June 2026 Architecture map
Source
Process
Storage
Decision
Output
Personal AI Operating System
Unified knowledge system for capturing, indexing, and synthesizing context. Root.—just Root reading from a ROOT knowledge graph and corpus files. One question → Haiku classifies domain → reads corpus + ROOT search → Sonnet synthesizes → Telegram reply.
Ingest: how context gets in
Three parallel ingestion streams feed Root's knowledge graph. Granola and Confluence sync hourly to Obsidian vault. ROOT indexes the vault hourly, building a semantic graph. Wiki corpus syncs nightly.
Meeting transcripts
Granola API
Work wiki pages
Confluence API
Personal notes
_context/root/ + _wiki/
granola-obsidian-sync
hourly LaunchAgent, Granola public API
confluence-obsidian-sync
hourly LaunchAgent, Confluence API
wiki_ingest.sh
nightly 23:00, reads _wiki/ + _context/brain/
Obsidian vault (VibeCoding)
union of all sources, 2700+ notes
ROOT indexer
hourly (Haiku semantic + SQL), SQLite at localhost:8766
ROOT knowledge graph
vector index + entity graph, ready for semantic search
Why three streams? Granola captures meetings. Confluence captures work docs. _context/brain/ captures personal principles. All three merge into one vault, indexed by ROOT. Single source of truth for recall.
Query: how you ask Root
Telegram question → router → Haiku domain classifier → reads corpus + ROOT semantic search → Sonnet synthesizes → Telegram reply. One answer per question, zero stale context.
Telegram message
/ask [question]
ask_brain.py
main router script
Domain classifier
Haiku: finance|house|career|moonlight|family|work-relationships|content|principles
Corpus file
_context/brain/{domain}.md
ROOT semantic search
query vault for live context matching question
Sonnet synthesis
domain corpus + ROOT search results → answer
Telegram reply
plain text, within 90s
Why classify first? Each domain (career, finance, etc.) has its own corpus file. Haiku's fast classification ensures we load the right context before synthesis. No wasted tokens on irrelevant domains.
Output: the two scheduled briefs
Friday 13:30 CEST: nina_brief.py reads ROOT graph and generates weekly context brief. Sunday 10:00 CEST: weekly_actions.py scans completed tasks and surfaces open loops. Both pull from ROOT, both deliver to Telegram.
ROOT graph
2700+ notes, hourly updated
Obsidian Keystone/
captures from Telegram (via /note)
nina_brief.py
Friday 13:30 CEST
Context synthesis
Sonnet: summarize week across all domains
Telegram: Nina brief
plain text, weekly pulse
weekly_actions.py
Sunday 10:00 CEST
Open loops scan
Obsidian captures + completion signal matching
ROOT graph
indexed by hourly indexer
Telegram: Weekly actions
open commitments + new items + auto-closures
Archive
_work/agent-deliveries/actions/ and _work/agent-deliveries/nina-1on1/
Two outputs, one graph: Friday brief is context synthesis. Sunday brief is action management. Both read from the same ROOT index. No separate state machines, no duplication.
Job control plane (Hermes runtime)
The control tower around every scheduled job. It does not do the work, it supervises. Each job enters through one safe entrypoint, runs against a declared contract, and is checked on whether it produced what it promised, not just whether it exited cleanly. Deterministic plumbing, zero LLM.
Run: clock to verified outcome
Every scheduled job follows this path. The clock fires, the job runs through a supervised entrypoint, and at the end it splits: the job either kept its promise (proof recorded) or broke it (flagged, even if it exited clean).
The clock fires
macOS launchd, a scheduled time arrives
Enter the safe door
harness_run_once.sh, one stable entrypoint
Gatekeeper checks
harness_runner.py, real job? safe to run?
Read the contract
job-registry.json, what must this job produce?
Do the real work
jobctl.py runs the original script, timed + recorded
Did it deliver?
side-effect contract check, not the exit code
YES: promise kept
proof recorded in harness.db, marked verified
NO: promise broken
flagged broken even if it exited 0
Health report
jobctl doctor, all green or exactly what broke
The whole upgrade: a green checkmark used to mean the script finished. Now it means the work actually happened, and there is proof. 21 jobs declared, every run recorded, one command for system health.
Failure path: the silent miss, caught
The reliability upgrade in one flow. A job can finish with a clean exit code and still have done nothing. The contract check ignores the exit code and looks for the real result.
Job exits 0
the script says: I finished
Did the result appear?
expected file written? records updated?
Missing: flagged broken
recorded as failed, surfaced in doctor
Before: exit 0 was trusted, empty outputs slipped through for days. After: no result means broken, no matter what the exit code said.
AIOS Operator on Hermes
Orbit is the operational agent running on Hermes. It does not replace Root. It uses Root as context, then inspects live system state, fixes drift, schedules checks, and reports verified outcomes back to Telegram.
Ask Orbit: operational question
Telegram request → Hermes session → Orbit classifies the job → Root and live tools provide context → concise operator brief returns to Telegram.
Telegram message
what broke overnight? / give me a work pulse
Hermes session
loads tools, skills, memory, MCP
Orbit triage
infra | work pulse | revenue | memory | repair
Root context
corpus, ROOT search, session history, open loops
Live inspection
files, logs, launchctl, cron, browser, dashboards
Telegram operator brief
fact, diagnosis, action, verification
Mental model: Root answers what the system knows. Orbit answers what is broken, stale, actionable, or worth doing next.
Repair: verified fix path
For broken LaunchAgents, stale syncs, router failures, Hermes config, skills, or delivery failures. Orbit reads before acting, patches only the scoped problem, then verifies the result.
Broken signal
exit 78/143, stale log, auth, quota, missing output
Inspect actual state
plist + script + log + config + current process
Root cause
missing path, timeout, permission, quota, stale failure
Patch / reload
targeted edit, launchctl reload, config update
Verify
kickstart, health check, search smoke test, HTTP 200
Telegram report
what broke + why + real output
Rule: Orbit should not say “I would check.” It should inspect, fix when safe, and report what real verification returned.
Pulse: work, project, and revenue reality check
Scheduled or on-demand pulse that combines Root context with live metrics and recent artifacts, then separates live projects from stale, blocked, or noisy loops.
Prompt or cron
work pulse / PrintPick / CCG / educations.com
Root memory
meetings, work notes, corpus, open loops
Live signals
GA4, dashboards, cron outputs, files
Orbit triage
alive | stale | blocked | noisy | kill
Archive
_work/agent-deliveries/<category>/
Telegram pulse
what changed + next action
Use case: ask for “what changed?” or “what should I focus on?” when the problem spans memory, metrics, and current files.
Learning: memory and skills
After a non-trivial fix or repeated workflow, Orbit decides whether the lesson belongs in durable memory, a reusable skill, or only the session transcript.
Completed task
complex fix, user preference, new workflow
Classify learning
stable fact | preference | procedure | temporary state
Memory
compact stable facts only
Skill
repeatable procedure with pitfalls + verification
Future Orbit
less steering, fewer repeated mistakes
Boundary: Memory is for durable facts. Skills are for workflows. Stale task progress stays out of memory.
Building something similar?
This OS is a work in progress. I share what I learn on Substack and LinkedIn. If you're building personal AI infrastructure and want to compare notes, reach out.