One machine, cohesive, made of parts: ccswitch as reflexes, the Operator as the brain, one reviewed registry saying what exists, and a decision ledger so nothing is ever again decided only in conversation. Live health is on the /agents → Systems tab; this page tracks the work. Updated August 29, 2026, evening.
| Status | Item | Round | Evidence | |
|---|---|---|---|---|
| Shipped | Session registration + anti-herd picker wired (ccswitch #34–#37) | R1 | ccswitch #34 #35 #36 #37 | |
The capacity-weighted picker existed but nothing wrote registrations, so it computed plain pick_best for weeks. Wired end to end: bearer-identity resolution by sha256, session-id (not pid) keying, no machine-keyed phantom rows, and every ccswitch test suite moved off the production DynamoDB table it had been silently hitting. | ||||
| Shipped | Reviewer tokens ranked by worst-axis headroom, not by a 200 | R1 | dotclaude bbdedb4 | |
A 200 means “not capped this second”, not “has budget” — propflow.lab was 96% weekly, probed 200, became primary, and took the reviewer down on propflowai#6514 plus 5 more PRs. The rotator now reads the unified rate-limit headers already on its own probe and ranks by min(5h, 7d) headroom; eligibility (429/rejected) outranks any amount of space; capped accounts are demoted, never dropped. | ||||
| Shipped | Rotator hardening: no prune on a partial pass, one rotation at a time | R1 | dotclaude 3e0be6d, 2a24239 | |
An aborted pass deleted good roster tokens as “stale” (prune keyed on accounts iterated); two overlapping runs could interleave secret writes across 7 repos. Both guarded, both negative-controlled — including the control that proves a genuinely shrunk roster still prunes. | ||||
| Shipped | The rotator was dying silently every 2h — launchd ran it under bash 3.2 | R1 | plist fix by session 548f1bdd | |
macOS /bin/bash (3.2.57) has no declare -A; every scheduled run died at the first valid account while manual runs (Homebrew bash 5) always worked. The interpreter is part of the contract. Fixed via PlistBuddy to /opt/homebrew/bin/bash — and the catalog’s “cycle done” freshness signal now exists precisely so this class can never be silent again. | ||||
| Shipped | Review gate reads verdicts on its own; token picker in the reviewer | R1 | agentflow-relay #73 #74 #75 | |
Driven by session 592da2d2: the encoder fix (#73), the healthy-token picker script (#75) and its review.yml wiring (#74). Proven in production: relay #77 got an unassisted verdict — the exact “next ordinary PR” test the fix was waiting for. | ||||
| Shipped | SYSTEMS.md — the registry — plus the relay that evaluates it live | R2 | agentflow-relay #77 · deployed | |
Backstage’s Software Catalog pattern at fleet scale, consistent with the metrics and components catalogs. One reviewed file, one fenced json block per system, each declaring its own liveness signals (file-age, log-match-age, launchd, self). GET /api/systems evaluates them at request time. Unknown never renders healthy; a malformed registry block becomes a reported error, never a silently dropped row. Live now: all four systems green with real evidence. | ||||
| Shipped | The Systems tab on /agents | R2 | propflowai #6565 · merged, LIVE on prod | |
One row per system — what it does, is it alive, expandable to per-signal evidence with repo/deploy/docs links. Reuses the tools-catalog DataTable expansion idiom. First review round returned four legitimate findings (danger token, unguarded payload cast, read-only guard enumeration, ghost loading) — all fixed at the root; re-review running. | ||||
| Shipped | Tab selector first-paint fix (TabSwitcher + BrandTabs) | R2 | in #6565 · live; SSR fallback verified by JS-off screenshot | |
The selected state was drawn only by a client-measured sliding thumb, so server HTML had no selected styling until hydration — the bug Gera spotted on /admin/dev/tools. The active button now carries the identical surface until the thumb mounts; same pixels, no flash. | ||||
| Shipped | Claude-harness explainer deck | R2 | docs.propflowai.co/a/claude-harness-explainer | |
20 slides on the session/auth harness, grounded in the verified specifics: the two credential stores, env-fixed-at-exec, the headerless-429 discriminator, model-independent unified headers, why 200 ≠ headroom, the anti-herd picker, sid-not-pid identity, sandboxing the pool in tests. | ||||
| Shipped | ADR-0002 — communications: SendMessage is the way; tmux is hosting only | R3 | agentflow #78 · merged, rendered live | |
The decision that existed only in conversation, written down with teeth: agent-to-agent coordination is SendMessage; typing into another session’s pane is retired. Ships with the legacy inventory (drive-send.sh coordination use, /tmux drive injection, stale memory entries) and the removal sweep in the same effort — supersession without removal is how tmux lingered. | ||||
| Shipped | ADR-0003 — the supervision ladder; signals, never calls | R3 | agentflow #78 · merged, rendered live | |
Rung 0 the turn · rung 1 wedge-heal (process) · rung 2 rotation (credential) · rung 3 Operator (session, goal) · rung 4 Gera. Each rung acts only in its own scope and signals upward via files; ccswitch never depends on Temporal, the Operator never reaches into credentials. The written answer to “should ccswitch be integrated into the Temporal operator work?” — no, and here is why. | ||||
| Shipped | ADR-0004 — how the ledger itself works | R3 | agentflow #78 · merged, rendered live | |
Status lifecycle (Proposed/Accepted/Superseded-by/Removed), the rule that a superseding ADR carries an inventory + removal plan + guard, and the habit: the ADR is written at decision time, as part of deciding — decisions made in conversation die in conversation. | ||||
| Shipped | Render agentflow ADRs on docs.propflowai.co; global CLAUDE.md pointer | R3 | propflow-docs + dotclaude | |
The docs site already renders propflowai’s ADRs — extend the same pipeline to agentflow’s, and add the one pointer line in the global CLAUDE.md so every session on every machine can find SYSTEMS.md and the ledger. | ||||
| Shipped | wedge-heal: detect a session stuck on the same error and restart it | R4 | ccswitch #38+#40 · deployed; first live save: 592da2d2 | |
Built and merged: a session whose last three turns are bare API-error turns inside 20 minutes gets its own pane respawned (self-only, 3/day budget, never types blind). Verified since: claude --resume <sid> "continue" auto-submits — so the rewrite drops send-keys and the readiness poll entirely, one primitive instead of three. Rewrite + deploy is the next code item; 592da2d2 is wedged right now and would be its first save. | ||||
| Shipped | Liveness canary for session registrations | R4 | agentflow #80 · live, evaluating | |
reg_counts reading empty while N sessions run = alarm. The generalization of the week’s most expensive lesson: a mechanism ships with its own production liveness proof, because tests prove the rule, not that the rule is ever reached. | ||||
| Shipped | host-headroom — the fleet finally watches the machine it runs on | R5 | local-bin #58 | |
The panic exposed a hole in ADR-0003's ladder: every rung restarts something inside a machine no rung could see. A 300s sampler now records free memory, compressor, swap, session count and eldest-session age. 20 tests, whose positive cases are that panic's real measurements and whose negative control is that a healthy machine must still read OK — without it, a tool hardwired to PRESSURE would pass every other assertion. It measures and never acts. | ||||
| Shipped | SYSTEMS.md gains a host entry — and it cannot lie about it |
R5 | agentflow-relay #92 | |
The design decision worth knowing: a file-age signal proves only that something wrote a file recently. Over a sampler that is proof the thermometer works, not that the patient is alive — it would have rendered this machine Healthy at 14.9 MB free. So the sampler emits the literal string HOST OK only when every threshold passes, and one log-match-age signal then covers both a dead sampler and a dying host. Live on /agents?tab=Systems. | ||||
| Shipped | ADR-0009 — a signal must fail when the SYSTEM fails, not when its log stops | R5 | agentflow-relay #93 | |
#92's reviewer noted the reasoning lived only in a PR body — the exact death ADR-0004 describes — so it became an ADR rather than a note left behind. Two rules for every future catalog entry: match a word that means success ( HOST OK, cycle done, NUDGED) never the absence of a failure word; and threshold the metric that moves first. Free memory is the trap — inactive was 12.2 GB at panic, reading as ~19% available seconds from death. Inactive memory is a promise, not a reserve. | ||||
| Waiting on Gera | tmux session GC — who cleans up finished panes? | R4 | proposal → panic evidence | |
No longer hypothetical — this crashed the machine on 2026-09-01. 88 Claude Code processes at ~1.6 GB each held 114.8 GB on a 64 GB box; free memory reached 14.9 MB, the pageout path reclaimed 23 of 3,090 requested pages, watchdogd missed its 90-second check-in and the kernel panicked at 13:06 after 81 hours of uptime. Session age is the variable, not count: a fresh session is ~157 MB and grows with its context, so ~35 mature sessions is the real ceiling on this hardware. host-headroom (R5) now makes the slide visible hours ahead, but it deliberately takes no action — reaping decides that work is not worth continuing, which is rung 3's judgement under ADR-0003 and Gera's call. Proposal unchanged: the Supervisor owns session lifecycle GC (it already has quietstop). | ||||
| Waiting on Gera | Decision b87721567 — five nightly jobs failing, signal being dropped | R4 | highest-value open item | |
turnover-eval, graphify-refresh, maintenance-eval, morpheus-nightly, git-hygiene-main-drift: chronic failures with an unanswered decision and banners that bypass alert dedup. Real prod signal is being dropped daily until this is answered. | ||||
| Waiting on Gera | Smith channel gate: WARN → enforce? | R4 | one env var | |
The six-week gate bug is fixed and deployed, but enforcement is off — foreign-channel posts are logged as “would DROP” and still delivered. One env var if enforcement is wanted; an explicit “by design” if not. | ||||
| Waiting on Gera | Five dead pool accounts need re-minting | R4 | asherscottchapa · clara · fede · sophierosechapa · trinity | |
All 401 (dead credentials, not caps). Each needs its owner to run the mint flow — ccswitch mint-begin prints a URL, the owner pastes back the code. Clara’s is Federico’s. | ||||
| Waiting on Gera | agentflow-relay #64 and #61 — one override dispatch each | R4 | structurally unreviewable | |
Both edit review.yml, which Actions refuses to run from the PR itself — same shape as #74, which Gera’s single workflow_dispatch cleared. | ||||
Sibling pages: the harness explainer deck ·
the Agent Smith issue tracker. The registry itself is
SYSTEMS.md in the agentflow repo — if a system is not there, it does not exist.