Four root causes, measured against the loop's own run receipts, the rebuild that shipped the same night, and why it was wound down anyway.
Your instinct is right, and the reason is structural, not a tuning problem.
The Chief of Staff rebuilds its entire picture of your work from scratch every ten minutes by asking a language model to re-read everything and re-invent the list. Nothing carries a stable identity from one pass to the next, so nothing accumulates. Meanwhile the one thing it does act on, poking your agent panes to keep going, has a broken duplicate check, so it pokes the same stuck agent over and over.
Net effect over 167 runs: 3 useful writes, 95 pane pokes, and 79 throwaway planner tabs opened in your HerdR workspace. The useful output has no reader. The useless output has a megaphone.
Every run of the loop writes a receipt. This is what 167 of them add up to.
The loop hands a pile of evidence to Grok and asks for a work ledger back. It never says "here is the ledger you produced last time, update it." So Grok makes up fresh IDs each pass. The same real obligation shows up under a different name every time, which means status, follow-up dates, and history can never attach to anything.
The underlying sources barely moved all day: 59 task-sheet rows, 88 ClickUp tasks, 26 to 27 HerdR panes, constant across every run (receipt.json source_health). The output moved constantly.
| The same real obligation | Runs seen | Named as |
|---|---|---|
| Dad's Abbas PFS and K-1s for Brandon | 10 + 6 | gnty-abbas-pfs-k1s, gnty-abbas-pfs |
| HOUZN JE 14279 creator lookup | 10 + 6 + 1 | houzn-je-14279-creator, houzn-je14279-creator, houzn-je14279-audit-history |
| Magnus Health forms for Ace and Alara | 10 + 8 | magnus-health-packets, magnus-health-ace-alara |
| RiseSun FF&E open questions | 6 + 1 + 1 + 1 + 1 | risesun-ffe-wiring, risesun-ffe-factory, risesun-ffe-answers, risesun-ffe-remaining, risesun-factory-answers |
Source: 26 plan.json files under memory/grok-cos-control/runs/control-20260819*, counted 2026-08-19.
The most stable item in the entire day, the HOUUS accent-wall check, held its identity in only 19 of 26 runs. The item count per run swung between 11 and 64 while the inputs sat still.
The loop is allowed to nudge a stalled agent, with a six-hour rule against nudging the same one twice. The rule is keyed on a fingerprint of the message text:
# agents-runtime/scripts/grok-cos-control-loop.py:807
key = hashlib.sha256(f"{action['pane_id']}\n{wire_message}".encode()).hexdigest()
The message is free text written fresh by Grok on every pass. It is never byte-identical twice, so the fingerprint never matches, so the cooldown never triggers. On 2026-08-19 all 24 delivered nudges carried a unique fingerprint and zero were suppressed (state.json followups, entries dated 2026-08-19).
| Pane | Nudges | What it was doing |
|---|---|---|
| w9:pS | 15 | most-nudged pane of the three days |
| w3:p3E | 10 | waiting on you to open a HOUZN QuickBooks session |
| w3:p43 | 7 | waiting on your decision |
| w3:p4A | 6 | waiting on your decision |
| w3:p69 | 5 | waiting on your answer about who opens a login link |
Source: plan.json actions of type herdr_follow_up across all 167 runs. Pane w3:p69 was nudged four times in 44 minutes (runs 21:43:09Z, 21:57:42Z, 22:12:29Z, 22:27:24Z on 2026-08-19).
An agent stops because it needs something only you can give: a QuickBooks login, a deploy authorization, an answer. The loop sees a stalled pane and pokes it. The agent restates its blocker. The next pass reads that restatement as fresh evidence, regenerates the same interrupt, and pokes again fifteen minutes later.
The actual nudge text shows the loop knows it is futile. Verbatim, two consecutive pokes to the same pane:
21:57Z "Stay blocked on the view-as interview... Restate the
unanswered question: who must be able to open the link."
22:12Z "While MFA and who-opens-the-link wait on Ace, inventory
the THM access-control e2e noise..."
Across 26 planning runs on 2026-08-19 the loop emitted 66 items marked as needing you, carrying 61 distinct wordings. It asked you to open the HOUZN audit history five times in five different sentences. Nothing downstream can collapse that into one ask.
Source: plan.json ace_interrupts across 26 plans dated 2026-08-19: 66 items, 61 unique question strings.
The reconciled ledger is meant to feed Ops Morning and the Morning Brief quietly in the background. Nothing reads it. A search of the entire Morning Brief codebase for any reference to the Chief of Staff ledger returns no matches (agents-runtime/scripts/morning-brief/, searched 2026-08-19). This was flagged as owed after the 2026-08-16 duplicate-touchpoint incident and never built.
So the good half is invisible and the noisy half, agents waking up and talking in your HerdR panes, is the only part you experience. That is precisely the ratio you described.
The 2026-08-17 cutover switched the primary route to the native Grok bot and shut down three older background pollers. Those pollers were switched off for the session but left permanently enabled, so they were set to return on the next restart. The Mac Mini rebooted at 08:33 on 2026-08-19 (sysctl kern.boottime) and all three came back. The old loop resumed at 13:37Z and has been running alongside the native route ever since, which is the duplicate control plane the cutover explicitly warned against.
The native route, meanwhile, has dispatched nothing since 2026-08-18T04:08:44Z, 43 hours ago. It still authenticates and polls, it just has no work path (memory/herdr-cos-mcp/ledger.json, 8 dispatches, all dated 2026-08-17 and 2026-08-18).
com.thm.grok-cos-control-loop, com.thm.grok-cos-dispatcher, com.thm.grok-cos-catchup-dispatcher. Verified with launchctl print-disabled gui/501 and no residual processes.logs/grok-cos-dispatcher.out.log). No loss.launchctl enable gui/501/<label> then bootstrap.Ace, 2026-08-19: "this is the last shot." Every fix below is deterministic code with a test that names the defect it pins, not a prompt tweak.
state.json holds the stable slug and first_seen, and the planner is handed the previous ledger and told to update it. Grok supplies the narrative fields only.control-20260819T232313Z created 19 items, run control-20260819T232748Z carried 19 of 19, carry rate 1.0, with every item anchored on a real Master row, ClickUp id, or pane. The receipt now reports work_items_carried, work_items_new, and carry_rate, so a regression shows up as a number.launchctl disable, which survives a reboot. They had produced nothing but connection failures since 2026-08-17. Files and receipts retained.The rebuild worked. The product decision went the other way, and it was the right call.
Grok Bot lost to a surface Ace already owned.
Blink Shell over Tailscale attaches his iPhone and iPad to the same HerdR session his desktop uses, giving him every agent pane live. Verified 2026-08-20: Tailscale up, the Mini reachable at 100.77.44.93, session ace running, and his iPad already on the tailnet.
Against that, Grok Bot offered one comfort win (texting a bot instead of thumb-typing into a terminal) and one capability with no named workflow (a cloud browser that stays signed into SaaS), while holding GitHub, Gmail, Calendar, Drive, and ClickUp scopes on a beta product's shared cloud compute. Measured week-one yield was 3 task-sheet writes across 167 runs.
Nobody established that the thing wanted was a phone surface, and nobody checked whether one already existed, before a control plane was built for it. That is the actual root cause, and no code change addresses it.
Six jobs stopped and permanently disabled, so a reboot cannot restore them: two MCP services, two OAuth gateways, two Cloudflare tunnels. Confirmed after: zero residual processes, all four service ports free, and both public hostnames returning 530 with no origin. Nothing deleted, restore is one command loop recorded in the vault.
The local control loop still runs twice daily at 05:40 and 14:00. It is not the bot. It drives its planner through the Grok CLI subscription route, verified working on the downgraded $30 plan, and neither it nor the Morning Brief references any retired port, hostname, or service. Its one job now is putting real decisions into the 06:10 Morning Brief.
It is on probation, not permanent. One test, one week: if the "Waiting on you" block is not something Ace acts on, it comes out too and the stack carries zero Grok pieces.
An hour after writing "name the gap and verify it is real against what is already running, before building transport for it" into the vault, I proposed wiring a Discord phone buzz for a gap I had invented rather than one Ace named. He caught it: "do we need this? or are you just creating more noise?" He was right. He already has a daily push, the 06:10 brief, and a second notification surface is the exact duplicate touchpoint this system's own charter forbids. Rejected and recorded so no future session revives it. Writing the lesson down did not prevent repeating it one turn later. The check that catches it is asking who named the gap.