Six parallel auditors across cost, effectiveness, reliability, orchestration, security and the control plane. Every finding re-checked by an adversarial verifier whose job was to refute it. 118 raised, 11 refuted and dropped, 107 stand.
The money pipeline is genuinely good — idempotent per-run ledger, calibrated pricing, a working drill-down. Everything that reports health was fabricated, and everything that claims to learn is dead. The fleet does publish real work while three named learning loops, four monitors and two nav pages produce nothing at all.
The most damaging defect nobody had filed: on 94.2% of dispatches the fleet assembled your standing corrections under a header reading “hard rules — these override your defaults”, and then deleted them from the middle of the prompt before the model read a word. That is the mechanical explanation for the “reads like marketing” corrections you keep having to repeat.
All eight are live on the box and functionally verified — not proposed.
Your reported bug. acp-agents-sync.sh only ever pulled down a slug→id map;
nothing on EC2 ever called POST /api/agents, so an agent directory created on the box could
never reach the dashboard without hand-written SQL. Replaced with bin/acp-agents-reconcile.py
(every 15 min): the filesystem is the source of truth, it upserts what is missing, corrects drift and
flags orphans.
Two separate scripts POSTed status=online for every agent every 5 minutes. They stamped
last_heartbeat, stamped last_activity_at and cleared
current_task — so the dashboard could not show a dead agent even in principle, and
“what is this agent doing” was wiped four times an hour. Both disabled.
Status came from a flat last_heartbeat > NOW() - 10 minutes. Fleet cadences run from
per-minute watchdogs to the weekly synthesizer, so one window cannot describe them — which is exactly why
the fake heartbeat existed. Agents now carry expected_cadence_minutes read off the crontab;
API and alerter both judge against it. offline finally means something is wrong.
api/alerting.py used the same flat 10-minute rule, which is what drove the fake heartbeats
in the first place. It now uses the real cadence, skips on-demand agents entirely, and names the delay
instead of printing a bare timestamp.
A prospect's raw email body was interpolated unfenced into a tool-capable Claude process, on a
*/10 cron, with AUTO_REPLY_ENABLED=1 and no human gate. Anyone who ever received
a Cultura Builder outreach email was the attacker set. Tools removed, reply fenced as untrusted data.
The signature check read the header with an empty default and only rejected a wrong one, so
omitting it entirely was a free pass. Everything downstream trusted key.fromMe as your
identity — the code called it “unspoofable” — and fromMe unlocked both [WIKI]
capture (writes into the brain every agent then executes) and [[BUILD]] (launches a builder
with full permissions). The attacker supplies the body, so the attacker supplies fromMe.
Fixed without risking your ingest: unsigned requests are still accepted as messages, but
fromMe only confers authority on a signed request, and every unsigned attempt is
logged. Worst case is that WhatsApp capture degrades and says so — not a silent outage.
An internet-adjacent bearer-gated endpoint reachable from every Coolify container, passing neither a
permission mode nor a tool policy — i.e. arbitrary shell as ubuntu, which has passwordless
sudo. Tools removed, bearer comparison made constant-time, and the prompt moved off argv (it was sitting
on the 128 KB E2BIG cliff that caused the July outage).
The scanner deduped per fixture but capped nothing, so concurrency tracked the football calendar rather than the box: 15 daemons, ~1.4 GB, on a host with 3.4 MB of swap free. Now capped at 6; over-cap fixtures are logged by name and retried next scan, so nothing is dropped. Checked first that no shadow position was open.
context-budget.py kept the first 70% and last 30% of the assembled prompt and threw away the
middle. Because dispatch.sh assembles sections in a fixed order, the hole landed in the same
place every time. For falcão — the agent that publishes in your name — the deleted middle averaged ~41 KB and
swallowed, in order: the tail of Wiki Context, all of your standing corrections, all of
Recent Memory, all of the cross-agent briefing, and about half the voice guide.
Replaced with priority-aware shedding: drop the cheapest sections first, never the task or your rules, and state inline what was dropped. Same prompt, same budget, measured:
Confirmed live by asking falcão what it could actually see. It answered yes, then quoted one of your real corrections back verbatim — a Portuguese-grammar note from 13 July that it had never been able to read before.
dispatch.sh injects only
tail -60 of LESSONS.md, so older corrections are cut at source by design. And
LESSONS.md exists for just 2 of 29 agents — the mechanism that makes your corrections stick is
essentially unused.These consume dispatch slots, quota and attention, and produce nothing external.
| System | Evidence | Verdict |
|---|---|---|
| carcara | Paper mode day 130; eval date passed 100 days ago; 34 consecutive scans, 0 deployments; all four playbook strategies falsified by the agent itself | PARK |
| fti-intern | 92 NO TRADE verdicts in 13 days, zero executions all month; its own doctrine rejects longs in code | GATE IN CODE |
| cbuilder | “0 inbound today (streak: 126 consecutive days)”. Only required output is a memory log. | KILL |
| content-desk | 31 consecutive days of opus-generated briefs; deliveries succeeded: 0 | FIX SEND |
| beija-flor | PT edition has delivered nothing since 23 Jul — and it has 15 real external subscribers | FIX |
| falcão health audit | RED on 243 of 243 readings since 28 Apr | REBUILD |
| outreach brain | 1,166 emails, 760 performance records, no reply field in the schema; 0 proposals applied every Sunday | FIX LOOP |
| scorecards | 28 files a night; INJECT_SCORECARD is set nowhere in the tree | WIRE UP |
| skills marketplace | Live authenticated endpoint serving invented sellers and prices from a hand-written seed | DELETE |
| Logs / Inbox nav | Newest log row 23 Mar; newest conversation 5 Mar; 32 dead buttons | DELETE |
The 107 findings reduce to eight structural defects. Fixing symptoms without these changes nothing.
claude -p call sites, and until today zero carried a tool policy.fromMe was proof of you; tier is a query parameter; one admin secret satisfies admin, agent and user checks and lives in 48 files.error_log has zero writers fleet-wide, so the error count is structurally always 0 against 317 real failures in 30 days. All 217 crons report NULL status.WASender session key, PAT and webhook secret, WIKI_BEARER, the Telegram bot token and the
fallback API key are committed at HEAD and pushed nightly to GitHub — hash-verified identical to the live
values. The repo is private, so rotation is sufficient. Do not rewrite history: that repo
is the nightly backup of 9.5 GB of agent state.
ssh.brunopessoa.com answers with no Access application in front of it — an SSH listener
that bypasses the AWS security group and blinds fail2ban. coolify.brunopessoa.com, the deploy
control plane for the whole estate, is behind a password form alone.
Recompute the error count from agent_run, or post failures from the dispatch failure
branch. Exclude clean no-trade cycles and exit 75/76 first, or backfilling 317 rows will page you on
routine behaviour.
/home/ubuntu/clawd (1.7 GB of trading and season-desk state) and the 452-line crontab that
defines 173 jobs are backed up nowhere. Scrub the crontab before committing it — one line contains a
bearer token.
The highest-certainty saving in the report and a one-line change: the FTI worker polls every 6–8 minutes against a 5-minute cache TTL, so every cache write expires before it is ever read. Writes cost 4.4× what reads return.
Do not blanket-ban Bash — wiki-remember.sh is the knowledge-capture path and every agent
writes memory files. Log what would have been denied for a week, then enforce. Start with the
five pure-research agents.
Today an agent that publishes three posts a day and one that has produced nothing since April look identical: both green, both zero errors. Cost per delivered artifact is the headline that surfaces eight of these findings by itself — and it is the gate for every kill/park decision below.
The honest answer is not the one the numbers first suggest.
Every dollar figure in the per-agent ledger is notional. api_cost is 0.0 on all
32 agents; there is no API key on the box. Auth is the flat $200/mo Max plan, so “$4,038/mo of fleet spend” is
list-price equivalence, not a bill. Real cash is $526.74/mo across 14 items, and only Railway
($115) and EC2 ($71.74) are large — neither currently verifiable, because Cost Explorer is disabled and the
Railway credential is dead.
Verified cash savings available today: about $3/mo. That is the finding. Everything else needs measurement only you can unlock.
The scarce resource is not the card — it is the shared 5-hour usage window. The fleet has already lost 37 hours to a quota blackout, and a second full fleet-day on 22 Aug because the backoff breaker's pattern does not match the phrase “you've hit your weekly limit”. Recovering roughly 15–22% of that window is worth more than any line-item saving, and the truncation fix alone recovers ~41 KB per falcão run that you were paying for and discarding.
ssh. and coolify.BUILDER_ENABLED on or off until webhook identity is hardened furthercb-rep, garmin-coach, fti-oracle,
bruno-local — have no directory on the box. I left them alone: bruno-local
looks like your laptop and retiring it would be wrong. Say the word and the reconciler retires the rest.