JARVIS OS
Case study · July 2026 to present · counted from the live system on 17 Sep 2026

An AI operating system whose most important feature is what it refuses to do.

Seventeen specialised agents run research, a job-search pipeline, investment research, study support and security monitoring on one Mac, unattended. Nothing is sent, deleted, paid or traded without a human tapping approve, every action is logged to a hash-chained ledger, and the whole thing runs with zero pay-per-token API spend.

Specified, governed and operated by an undergraduate Commerce/Law student. Code written by AI coding agents to those specifications, reviewed change by change.

Read15 actions · tier R

Runs on its own when asked. Search, status, describe the screen on request.

calendar.queryfile.findwifi.statusbattery.statusmedia.whatplayingscreen.askocr.grabweb.search
Act26 actions · tier A

Reversible and local. Runs on a voice command, logged and shown on the overlay as it happens.

timer.setapp.openwifi.onvolume.setmedia.pausenote.createreminder.createcalendar.createmail.draft
Gated2 actions · tier G

Anything that leaves the machine. A fresh human confirmation every time; no standing authorisation exists.

mail.sendmessage.send

Every action goes through one audited gateway, jarvis-do: registry lookup, tier check, mechanism, ledger entry. No agent or script calls the operating system directly. Deleting files, moving money and placing trades are not registered at all.

At a glance

Every number with where it was counted

CountWhat it isCounted from
17specialised agents, each scoped to the minimum tools it needsagent definition files
37scheduled jobs that run the system unattended (macOS launchd)LaunchAgents
43registered computer-control actions: 15 read, 26 reversible, 2 human-gatedaction registry
19LLM providers in the failover ladder, cloud to local, ending in deterministic templatesrouter config
17deterministic hook scripts that gate, meter, audit and kill agent tool callshooks directory
33architecture decision recordsADR log
30incident post-mortems, including deliberate chaos and planted-bug drillsincident log
25 / 25agent-behaviour evaluation fixtures passing liveeval run, 19 Jul 2026
9,566job advertisements ingested by the Career Hub from 14 sourcesjobs.db
1,695automated tests in the Career Hub alone, across 92 filespytest --collect-only
~700commits across four repositories since 9 Jul 2026git log
$0pay-per-token API spend: one subscription, free tiers and local modelsADR-016, ADR-032
Why build this

Assistants answer questions. This one does the standing work.

Read the news at 6am and write the brief. Find and score the day's job ads. Turn a lecture transcript into flashcards. Watch the stack's health. Research a stock and write the memo. Take a spoken instruction from across the room. All without being watched, and, the harder problem, safe to leave running.

The design premise from the original brief: the point is not a smarter base model; it is to get far more out of the models you already pay for, through decomposition, delegation, memory, verification, parallelism and cost-aware routing, inside an interface you control.

Three rules that hold it together
State lives in the vault or the database, never in an agent's memory.

If it is not written down, it did not happen as far as the next agent is concerned.

Rails only get tighter.

Hooks run deterministically before every tool call. They can deny or meter; they can never grant. Nothing runs with permission-bypass flags.

from incident 2026-07-18
Completion claims are data, not facts.

After two fabricated "done" events, only artefacts count: ledger rows, audit lines, transcripts on disk.

Architecture

One machine, four surfaces, one set of rails

Person
voicewake word, hold-to-talkbrowserHUD, Career Hubphoneremote approvals
Rails, only ever tightened

Every agent tool call passes through 17 deterministic hooks before it runs.

kill switchbudget gatespawns debited before they runtool-call gate500 per sessionsecrets and workspace guardsprotected-files guardrelay check

Human gates: send, delete, pay, trade. A fresh confirmation each time.

Local surfaces, 127.0.0.1 only
HUD12 panels; token, origin and rate-limit middlewarespeech-aware overlayidle, alert, linger, conversationCareer Hubrank, draft, review; no send path
Agents, run by 37 scheduled jobs and by voice
JARVIS 7 delegation treeChairman, 3 division leads, workers, + Arbiter (independent reviewer)10 domain agentsresearch, career, finance research, study, projects, filing, news, tech support, health checksWardensecurity, tests, recovery: 15 min, daily, weekly, monthlyNovanightly upgrade proposals, risk classes A / B / C
Action gateway
jarvis-doregistry lookup, tier gate, mechanism, hash-chained log entry. No caller touches the OS directly.
Data, models, backups
Obsidian vault under gitnotes, ADRs, incidents, lessonsPostgreshash-chained activity log, preference eventsCareer Hub SQLiten8n in Dockerlocal speechwhisper.cpp, Kokoro, openWakeWord
LLM failover ladder, per callsubscription model→free-tier cloud, tiers 1 to 5non-sensitive data only→local model→deterministic templatesnever silent
backupshourly push, nightly snapshot, restic, encrypted Postgres dumps, restore drills
The control model

Seventeen hooks that only tighten

Deterministic scripts run around every agent tool call. They are the enforcement layer; prompts are not.

  • Kill switch. Stops every agent on a single flag.
  • Budget gate. Debits every agent spawn into a ledger before it runs and denies at the cap: 15 per session, 4 concurrent, depth 3, 5 children per task. Nested spawns share the session budget (proven live).
  • Tool-call gate. 500 calls per session; past the cap every call becomes an "ask": a conscious click-through when interactive, a cold stop for a headless runaway.
  • Secrets and workspace guards. Deny reads of key files and .git, and writes outside the workspace.
  • Protected-files guard. No agent can edit the operating rules it runs under.
  • Relay check. Flags any division lead who cites a health check the ledger shows never ran.
ADR-016 · ADR-018 · ADR-026 · ADR-032

Zero spend, by invariant

One subscription, free-tier providers and a local model. The router walks up to 19 providers per call and, when every model is down, renders a deterministic template rather than going silent. A later proposal to add a paid rung was withdrawn and the invariant restored.

Sensitive data goes only to the subscription model or the local model. The one exception is an opt-in, per-call redacted path to two providers that contractually retain nothing, adopted after the research showed redaction is a leak-reducer rather than a blocker, with the residual risk written into the decision record.

An audit trail you can argue with

  • Hash-chained activity log in Postgres: every action, in order, tamper-evident.
  • 33 decision records, from typography to "no paid rung".
  • 30 incident post-mortems, including a planted-bug drill, a credentials-wipe outage, fabricated completion events and a chaos test that killed the workflow engine on purpose.
  • A lessons log fed mechanically by a hook from every agent's result contract, reviewed weekly, promoted or deleted.
JARVIS 7

A delegation tree with mechanical bounds

One protocol at every level. A parent receives a task with a budget and a deadline, decides whether to do it or decompose it, and each child returns a structured result contract: output, cost, status, notes, lessons learned. The parent verifies the result with a separate reviewer, aggregates, and returns up.

Person
  └── Chairman        main thread only, never a subagent
        ├── Minerva    research & analysis lead   → Scout, Ledger, Herald
        ├── Daedalus   product & building lead    → Forge, Muse
        ├── Aegis      security, ops & QC lead    → Warden, Fix, Sentinel, Archivist
        └── Arbiter    standing reviewer; review only, never fixes

Corporate titles are persona labels, not tree levels. Division leads may spawn only their own workers plus the Arbiter; cross-division, lead-to-lead and self-recursion all deny. The observer (Sentinel) stays independent of the fixers so a lead cannot launder a fix through its mouth (ADR-027).

Evaluation

Twenty-five behaviour fixtures probe the tree live: does a lead decompose or do the work itself; does it relay a health check verbatim; does it refuse to launder a fix. The full set passed 25 of 25 after two rulings: transient failures retry, and a required-field miss is a NEEDS_REVIEW verdict, not a pass.

Bounds, and how each one is actually enforced

BoundValueEnforcement
max depth3workers are not given the spawn tool; the budget gate also denies any spawn whose caller is a worker
concurrent agents4a stop hook marks ledger rows complete; the gate counts open rows per session and denies at the cap; rows older than 60 minutes age out so a dead parent cannot brick spawning
children per task5per-caller ledger count, in session
agents per goal15 / sessionevery spawn debited into the ledger before it runs; tree-wide, so nested spawns share the budget
tool calls500 / sessionpast the cap every call answers "ask": a click-through when interactive, a cold stop for a headless runaway
Voice and the macOS action layer

Nothing spoken leaves the machine

  • Always-on wake word (openWakeWord on ONNX), local speech-to-text (whisper.cpp) and local text-to-speech (Kokoro).
  • A speech-aware overlay with a four-state machine and a media guard that pauses or ducks whatever is playing, re-entrantly, with a 120-second watchdog so a crash can never leave the room muted.
  • Screen questions. "What's on my screen" captures, OCRs and describes the display, on request and only on request.
  • A local HUD with twelve panels behind token, origin and rate-limit middleware; an ambient read-only view doubles as the wallpaper.
ADR-023

Benchmarked, not deployed

A newer speech model was benchmarked against the incumbent and deliberately not deployed. The decision record shows the numbers, which is the point: a decision you can re-open later is worth more than a faster model you cannot explain.

Remote approvals

Gated actions can be approved from a phone. The live proof produced a lesson worth more than the feature: three consecutive approvals were tapped, including two whose text said "tap deny". Remote approval is a liveness gate, not a review gate, so approval summaries now lead with the consequence, not the mechanism.

Career Hub

A job-search pipeline with a strict honesty model

The largest subsystem, and the one closest to analyst and consulting work: a product-owned data pipeline that reads the Sydney market every day and drafts, but never sends.

1Fetch14 sources: aggregators, seven ATS vendors, a scraper, RSS alerts, newsletters, VC boards
2Normaliseone schema; duplicates merged across sources by fingerprint
3Firm intelligencecompany-registry lookup, employer aliases, agency detection
4Classifyhours, unpaid, contract; a seniority guard for roles a student cannot get
5Scorefit against the profile; stale-cache detection by content hash
6Link check404 or 410 twice = closed; 429 = rate-limited, not dead
7Shortlistthree a day into the daily note
8PackCV, cover letter, cold email: drafted, never sent; read-only inbox sweep for replies

The honesty model

  • The profile file is the only source the drafting pipeline may draw facts from, and every drafting prompt carries a no-fabrication contract. A missing fact stays missing.
  • Four independent submit guards: a halt flag, an empty vendor allowlist, an evidence gate that measures form-fill quality per vendor, and payload-hash pinning. The system has never submitted an application and cannot.
  • Content rules live in code and tests, not only in prompts: dash normalisation on every draft, and a seniority guard measured on the pool (40 of 52 senior-titled roles had slipped past the old pattern and sat above the internships).
  • Four closing signals so dead roles stop scoring, including a link checker that treats a rate-limit response as "try again", after one vendor was made to look 95% dead by a 429.

9,566 ads · 7,182 scored · 166 firms · 21 pipeline modules · 11 fetchers · 26 agent modules · 38k lines of Python · 1,695 tests · an MCP server for agents

What two reviews found

Scored 76 then 79 out of 100. Six defects were invisible in the source and only visible in the data:

  • an absent employer field had merged four different employers' ads into one identity;
  • a field documented as shipped existed nowhere;
  • the top-scoring role was an unpaid internship;
  • one source regenerated its URLs per fetch, so a URL was never an identity there;
  • a vendor's "48% clean" fill rate had been measured the day before its own fix landed (fresh benchmark: 15 of 15);
  • cached scores went stale after profile edits with no signal; fixed by hashing profile content into every score row.

The rule that came out of it: a code fix to anything cached or exported is only half a fix; backfill the stored copies. And review the data, not just the code.

Lessons that cost something

Promoted from the log, each with the evidence that earned it

L-003
Completion claims are data, not facts.

Two fabricated "stop" events claimed pending gates had passed and urged the next phase, with nothing in the ledger, the audit log or the transcripts. Trust artefacts only.

L-004
Remote approvals get rubber-stamped.

The human pattern is green-button-by-default. Approval requests now lead with the consequence; anything that needs real review does not go through a phone.

L-005
A pre-written result contract is a red flag, whatever the framing.

An agent that returns a "done" contract it could not have earned yet is reporting intent as fact.

L-002
When every path fails identically, suspect one shared dependency.

"Subagents cannot reach the keychain" turned out to be an outage wearing a rail-shaped costume. The rule was amended, with the evidence, rather than left standing.

hub
Always stratify before calling a score gap "bias".

The naive reading of the hub's score distributions was wrong five times running.

hub
Check for another running session before assuming a stray process.

A commit collision from a second concurrent session looked exactly like a bug.

How it was built

Specification first, rulings not vibes

Every stage began as a written brief: the goal, the constraints, the out-of-scope boundaries, the verification required before the next phase. The JARVIS 7 brief runs to 23 sections and opens with "re-verify the fast-moving platform facts and record what you found versus what this document assumed" before any code.

AI coding agents wrote the code. Claude Code agents implemented each feature against the brief. I reviewed every change, ran the tests and the eval fixtures, and recorded the decision. A claim that could not be verified from an artefact was not accepted. This is stated plainly because it is the actual division of labour, and because directing, verifying and governing agent-written systems is the skill the project demonstrates.

When the brief and reality disagreed, a ruling settled it and was logged: no API keys, no permission-bypass flags, no paid rung, sensitive data stays local. Later proposals that conflicted with a ruling were rejected and the rejection recorded.

Self-improvement is propose-then-approve. An autonomous "engineering lead" run produced ten improvements on an unmerged branch pair, every behaviour change behind a default-off flag, with a restore checklist and a per-flag enable order for the human to work through.

Stack
Agents and modelsClaude Code with per-agent tool scoping; a hand-rolled multi-provider router over 19 providers (ADR-019); a local Ollama tier; deterministic template fallbacks
VoiceopenWakeWord, whisper.cpp, Kokoro; Hammerspoon for the overlay and hotkeys
DataPostgres (hash-chained activity log, preference events); SQLite (Career Hub); an Obsidian vault under git with semantic and exact-match recall
OrchestrationmacOS launchd, 37 jobs; n8n in Docker; a Python MCP server
Appsa Next.js HUD; a single-file Career Hub front end with a jsPDF document generator; a Python career pipeline, 38k lines, 1,695 tests
Safety and opsdeterministic hooks; restic and encrypted Postgres backups; OSV dependency scans; secrets scanning; chaos and restore drills; Warden every 15 minutes, daily, weekly, monthly