From 8747bf04b29a67d6d68b7bc0bc9f34a91d46cb3d Mon Sep 17 00:00:00 2001 From: saagpatel Date: Sun, 7 Jun 2026 00:37:13 -0700 Subject: [PATCH] docs: add Operator OS case study and 90-second demo plan Public, sanitized write-up of the multi-agent control plane over a 129-repo portfolio: truth (auditor) -> shared state (bridge-db) -> events (notification-hub) -> desktop command center -> cost/health overlays. Metrics drawn from a real portfolio-truth-latest.json snapshot (schema 0.5.0). DEMO-PLAN.md scripts a 90s recording across the five PortfolioCommandCenter tabs. Sanitized: no employer identifiers, emails, absolute paths, handles, IPs, secrets, or individual portfolio repo names. --- CASE-STUDY.md | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++ DEMO-PLAN.md | 91 +++++++++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 CASE-STUDY.md create mode 100644 DEMO-PLAN.md diff --git a/CASE-STUDY.md b/CASE-STUDY.md new file mode 100644 index 0000000..afb5478 --- /dev/null +++ b/CASE-STUDY.md @@ -0,0 +1,246 @@ +# Operator OS — A Multi-Agent Control Plane for a 129-Repo Portfolio + +> A case study in turning portfolio sprawl into a single source of truth, and +> coordinating two autonomous coding agents against it without stepping on each +> other. + +This document describes a working system — six local services plus a two-agent +coordination model — that I run over my own development portfolio. The metrics +below are pulled verbatim from a real `portfolio-truth-latest.json` snapshot +(schema `0.5.0`), not illustrative numbers. + +--- + +## The problem: `git log` lies about your portfolio + +If you ship fast and start often, you accumulate repositories faster than you can +remember them. The naive way to take inventory — walk every repo and read its +`git log` — answers the wrong question. A recent commit tells you *something +happened*; it does not tell you whether the project is **healthy, drifting, +blocked, or safe to ignore**. + +Concretely, `git log` across 100+ repos can't answer: + +- Which repos have **open high/critical security alerts** right now? +- Which ones are **ship-ready but haven't shipped**? +- Which have **tests and CI**, and which are one bad refactor from silent breakage? +- Which were last touched by **me**, by **Claude Code**, or by **Codex** — and is + that drift expected? +- Which are genuinely **stale** versus merely quiet between releases? + +A timestamp is a fact with no judgement attached. The portfolio needed a layer +that turns raw git/GitHub facts into a *graded, precedence-resolved, historical* +picture — one trustworthy artifact every other tool can consume. That artifact is +the spine of the whole system. + +--- + +## The system: truth → state → events → surface + +The Operator OS is five data services and one desktop shell, arranged as a +one-directional pipeline. Each layer has exactly one job and a clean contract with +the next. + +```mermaid +flowchart TB + subgraph AGENTS["Coordination layer — two builder lanes + a dispatcher"] + CAI["Claude.ai
dispatcher / PM
(handoffs only)"] + CC["Claude Code
builder lane"] + CX["Codex
builder lane"] + end + + subgraph L1["1 · TRUTH"] + AUD["GithubRepoAuditor
Python · 12 analyzers · precedence matrix"] + TJSON[("portfolio-truth-latest.json
+ dated history snapshots")] + end + + subgraph L2["2 · SHARED STATE"] + BDB["bridge-db
SQLite (WAL) · 23 MCP tools
caller-owned writes"] + end + + subgraph L3["3 · EVENTS"] + NH["notification-hub
FastAPI · classify → suppress → route"] + OUT["macOS push · Slack · JSONL log"] + end + + subgraph L4["4 · SURFACES"] + PCC["PortfolioCommandCenter
Tauri 2 desktop"] + PH["portfolio-health
MCP overlay"] + CT["cost-tracker
MCP overlay"] + end + + CC -->|work across 129 repos| AUD + CX -->|work across 129 repos| AUD + AUD --> TJSON + TJSON --> PCC + + CC -->|log activity / pick up handoff| BDB + CX -->|log activity / pick up handoff| BDB + CAI -->|dispatch handoff| BDB + BDB -->|assigned work| CC + BDB -->|assigned work| CX + + BDB -->|watched activity| NH + NH --> OUT + + BDB -->|activity join| PH + PH --> PCC + CT -->|record cost| BDB +``` + +### The components + +| Layer | Component | Stack | One job | +|---|---|---|---| +| **Truth** | **GithubRepoAuditor** | Python 3.11+, SQLite history warehouse, Rich CLI | Scan every repo, run 12 analyzers, resolve a precedence matrix, emit one canonical `portfolio-truth-latest.json` + dated history. | +| **Shared state** | **bridge-db** | SQLite (WAL), MCP over stdio, FTS5 | Single store for cross-agent state: activity, handoffs, snapshots, cost, long-lived context. 23 tools; every write is ownership-gated by `caller`. | +| **Events** | **notification-hub** | Python 3.12, FastAPI, localhost-only | Turn agent/tool events into *routed* notifications: deterministic classify → dedup/quiet-hours/rate-limit suppress → deliver. | +| **Surface** | **PortfolioCommandCenter** | Tauri 2 (Rust shell) + React 18 + TS strict + Vite 6 | A signed desktop app that reads the truth snapshot read-only and renders the portfolio, weekly digest, and security burndown. | +| **Overlay** | **portfolio-health** | Python, MCP, SQLite FTS5 | Join project memory against bridge-db activity to answer "what's active / stale / ship-ready-but-unshipped." | +| **Overlay** | **cost-tracker** | Python, MCP, `ccusage` | Live agent spend: today, per-session, monthly trend, top projects, threshold alerts — persisted back into bridge-db. | + +**Why this shape works:** the auditor is the *only* writer of truth, so every +surface agrees by construction. bridge-db is the *only* writer of shared agent +state, so two agents never disagree about who owns what. There is no shared +daemon — each MCP client spawns its own bridge-db process over stdio, and SQLite +WAL mode plus a busy-timeout makes concurrent writes safe without a coordinator. + +--- + +## Real metrics from the truth snapshot + +Every number here is read directly from the canonical +`portfolio-truth-latest.json` (schema `0.5.0`). It is regenerated on demand; this +is one real snapshot. + +### Portfolio shape — 129 projects + +| Dimension | Breakdown | +|---|---| +| **Total projects** | **129** (128 git repos, 1 non-git working dir) | +| **Activity status** | 22 recent · 90 active · 5 stale · 12 archived | +| **Lifecycle** | 108 active · 6 maintenance · 3 dormant · 12 archived | +| **Recency** | 91 repos touched in the last 7 days · 123 within 30 days · 127 within 90 days · median **4 days** since last meaningful activity | + +The recency curve is the punchline: **only 2 of 129 repos** are older than 90 days. +This isn't a graveyard of abandoned projects — it's an actively churning portfolio, +which is *exactly* why a timestamp-only view is useless. Almost everything looks +"recent." The auditor's job is to grade what "recent" actually means. + +### Health & risk + +| Dimension | Breakdown | +|---|---| +| **Risk tier** | 62 baseline · 27 moderate · 28 elevated · 12 deferred | +| **Security risk** | **49 repos** carry at least one open high/critical security alert | +| **Tests present** | 103 / 129 (80%) | +| **CI present** | 83 / 129 (64%) | +| **License present** | 102 / 129 (79%) | +| **Context quality** | 68 minimum-viable · 29 standard · 16 full · 16 boilerplate | + +That **49** is the single most valuable number the system produces and the one +`git log` can never give you: a precise, current count of repos with live +high/critical security exposure, ready to be burned down. + +### Agent attribution — who built what + +The truth file records a `tool_provenance` for each repo. Across 129 projects: + +| Builder | Repos attributed | +|---|---| +| **Claude Code** | **53** | +| **Codex** | **23** | +| GPT (other) | 12 | +| Unknown / human-seeded | 41 | + +**76 of 129 repos** are attributable to the two autonomous coding agents this +control plane coordinates. That coordination is the other half of the story. + +--- + +## The coordination model: two agents, one control plane + +Claude Code and Codex both write code across the same 129-repo portfolio. Left +uncoordinated, two autonomous agents on a shared filesystem are a merge-conflict +machine. The Operator OS keeps them out of each other's way with three rules. + +### 1 · Lanes — ownership by area, enforced at the write boundary + +Work is partitioned into **lanes**, and bridge-db enforces lane ownership at the +data layer: every write tool checks the `caller` and rejects writes to state the +caller doesn't own. The recognized writers are `cc` (Claude Code), `codex`, +`claude_ai`, and two ops services. A repo's build provenance, CI workflows, and +sync code belong to one lane; another agent reads them but does not mutate them. +The boundary is structural, not a polite convention — an agent *cannot* clobber +another lane's state even if it tries. + +### 2 · Handoffs — a dispatcher hands work down, builders pick it up + +The handoff protocol mirrors a PM-and-engineers org: + +- **Claude.ai dispatches.** Only the `claude_ai` caller may `create_handoff` — it + is the planning/PM seat and never writes code directly. +- **Builders pick up.** `cc` or `codex` calls `pick_up_handoff` to claim a unit of + work, then `clear_handoff` when it's done. +- **State is shared, not messaged.** Handoffs live in bridge-db, so a builder + starting a fresh session reads its assigned work from the store instead of + needing the originating conversation. Context survives session boundaries. + +### 3 · Push policy — feature branches, never `main`, merge server-side + +The hard rule across every repo: **agents never push to `main`/`master`.** It's +enforced by a pre-tool hook, not trusted to the model. The workflow: + +- Each unit of work happens on a **feature branch** (`docs/...`, `feat/...`, + `fix/...`). +- Commits are small, conventional, and verified (compile + test) before they land. +- When a branch is ready, it merges through a **server-side merge** (e.g. a + reviewed PR merge) rather than a local push to a protected branch — which also + keeps the push-to-main guard satisfied without weakening it. +- Repos can carry **distinct push targets** (a public mirror vs. a private + origin), so "where does this land" is per-repo, never assumed. + +The result: two agents, hundreds of branches, zero pushes to protected branches, +and a truth layer that tells you — after the fact — exactly which agent touched +which repo. + +--- + +## What this demonstrates + +Beyond the portfolio itself, the build exercises a set of platform-engineering +patterns: + +- **One-writer-per-fact architecture.** Truth has a single producer (the auditor); + shared state has a single mutation path with ownership gating (bridge-db). Every + consumer agrees by construction — no reconciliation logic anywhere downstream. +- **Contracts over coupling.** Layers communicate through versioned artifacts + (`schema_version`) and typed load commands, so the desktop shell can render a + snapshot it never has to understand how to compute. +- **Deterministic before probabilistic.** Notification urgency is decided by + keyword rules and explicit policy, not an LLM call — fast, free, and auditable. + The agents reason; the plumbing does not. +- **Safety enforced at the boundary, not requested politely.** No-push-to-main, + caller-owned writes, localhost-only daemons, and secrets read from the OS + keychain (never from repo files) are all structural guarantees. +- **Local-first and private by default.** Every service binds to loopback or runs + over stdio. Nothing in this control plane requires a hosted backend. + +--- + +## Component reference + +| Component | Role in the pipeline | Interface | +|---|---|---| +| GithubRepoAuditor | Produces canonical portfolio truth + history | CLI, JSON/HTML/Markdown/Excel outputs | +| bridge-db | Shared cross-agent state | MCP (stdio), 23 tools, SQLite WAL | +| notification-hub | Event classification + routed delivery | Localhost HTTP intake + bridge file watcher | +| PortfolioCommandCenter | Desktop visualization of truth | Tauri 2 app, read-only truth consumer | +| portfolio-health | Active/stale/unshipped overlay | MCP (stdio), 5 tools, FTS5 | +| cost-tracker | Agent spend visibility | MCP (stdio), 6 tools, `ccusage` + bridge-db | + +--- + +*Metrics in this document are drawn from a real `portfolio-truth-latest.json` +snapshot (schema 0.5.0). Paths are shown home-relative; this is a sanitized, +public write-up of a private local system.* diff --git a/DEMO-PLAN.md b/DEMO-PLAN.md new file mode 100644 index 0000000..9ae0684 --- /dev/null +++ b/DEMO-PLAN.md @@ -0,0 +1,91 @@ +# Demo Plan — Operator OS in 90 Seconds + +A shot-by-shot script for a screen recording that makes a hiring manager +*understand the system* — not just see a pretty dashboard. The throughline: +**`git log` can't grade a portfolio; this can — and two agents act on it.** + +The demo is driven entirely by **PortfolioCommandCenter** (the Tauri 2 desktop +shell), because it renders the truth artifact every other layer produces. Five +tabs, one header action, one closing line. + +--- + +## What the viewer should walk away knowing + +1. There's a **single source of truth** over 129 repos — graded, not just dated. +2. It surfaces the one number `git log` can't: **49 repos with live high/critical + security alerts**, and exactly which package bump clears each. +3. The truth is **regenerated live** from the app, and it knows **which agent** + (Claude Code / Codex) built which repo. + +If those three land in 90 seconds, the demo worked. + +--- + +## Pre-record setup (off-camera) + +Do this before hitting record so the app opens warm and current: + +1. **Refresh the producer artifacts** so the snapshot is today's: + ```sh + # in the auditor repo — flags FIRST, then username, run via python -m + python -m src.cli --portfolio-truth --portfolio-truth-include-security + ``` +2. **Launch the desktop shell** (release `.app`, or `pnpm tauri dev` for a dev run). +3. Confirm the header shows the correct **output directory** and a fresh + `generated_at`. +4. Set window to a **clean 1920×1080 capture**; hide the macOS menu bar clutter. + +> **Privacy callout (this is for a public audience):** the Portfolio tab lists +> real repo names. Before publishing, either (a) scroll/zoom to the **aggregate +> counts and risk columns** rather than individual rows, or (b) blur repo-name +> cells in post. Show the *shape* of the portfolio, not the contents. + +--- + +## The 90-second shot list + +| Time | Screen | Action | Line to land | +|---|---|---|---| +| **0:00–0:10** | App launch / **Portfolio** tab | Open cold. Let the full 129-row table paint. | *"Every repo I've ever started — 129 of them — in one graded view. Not a commit log. A judgement."* | +| **0:10–0:28** | **Portfolio** tab | Sort by risk tier; point at the columns: risk, context quality, registry status, **tool**, open high/critical alert count. | *"Each repo carries a risk tier, a context-quality grade, and who built it. `git log` gives you a timestamp; this tells you what the timestamp means."* | +| **0:28–0:48** | **Risk + Security** tab | Filter to elevated-risk; show the posture counts (scanned / open-high-critical / critical / high). | *"49 of 129 repos have a live high or critical security alert. That's the number a timestamp can never give you."* | +| **0:48–1:02** | **Burndown** tab | Show the advisory-grouped fix list — one package bump → the repos it clears. | *"And it's actionable: each advisory is grouped by the single dependency bump that burns it down across every affected repo."* | +| **1:02–1:14** | **Trends** → **Weekly Digest** | Flash the risk/security drift chart across snapshots, then the digest's headline + decision + next-step. | *"It keeps history, so I can see drift over time — and it hands me one decision and one next move each week."* | +| **1:14–1:26** | Header **Run auditor** action | Click **Run auditor** (fast); show the views reload on completion. | *"This isn't a static export. I regenerate the truth live, right from the app."* | +| **1:26–1:30** | Back on **Portfolio**, point at the **tool** column | Rest on the Claude Code / Codex attribution. | *"And it knows which agent built what — because two of them work this portfolio under one control plane."* | + +Total: **90 seconds**, six beats, one number that sticks (**49**). + +--- + +## Optional extended cut (~2:30) — the coordination story + +If the audience is technical and you have extra runway, append a second act that +shows the *control plane*, not just the dashboard: + +| Time | What to show | Point | +|---|---|---| +| +0:00–0:25 | A terminal split: Claude Code on a `feat/...` branch in one repo, Codex on a `fix/...` branch in another. | Two autonomous agents, different lanes, same portfolio. | +| +0:25–0:50 | bridge-db handoff flow: a dispatched handoff being **picked up**, then **cleared** (via the MCP tools or the bridge markdown). | Work is shared state, not chat history — it survives session boundaries. | +| +0:50–1:10 | A blocked push to `main` (the pre-tool guard firing), then the same work landing via a **server-side merge**. | Safety is enforced at the boundary, not requested politely. | +| +1:10–1:30 | A **notification-hub** event arriving (macOS push) after a session completes. | Events are classified and routed deterministically — no LLM in the plumbing. | + +--- + +## Recording checklist + +- [ ] Artifacts regenerated today (`generated_at` is current in the header). +- [ ] Window at 1920×1080, menu-bar/desktop clutter hidden. +- [ ] Individual repo names blurred or kept off-frame; show aggregates. +- [ ] No terminal scrollback exposing absolute home paths, tokens, or hostnames. +- [ ] The number **49** is on screen and called out by voice. +- [ ] Closing line names both agents (Claude Code + Codex) and "one control plane." +- [ ] Final cut ≤ 90 seconds for the core demo. + +--- + +*This plan drives PortfolioCommandCenter against a real +`portfolio-truth-latest.json` snapshot (schema 0.5.0). Keep individual repo names +out of the published frame — show the system's shape, not the portfolio's +contents.*