Aga, 13 Aug 2026: *"I also need to know what can break. If something breaks, you will
know."*
Two people now work the same estate from two machines. Everything below is a failure
mode that has actually happened or been measured, not a theoretical one. Each entry
says what it looks like, why it happens, and what catches it.
The one-command answer to "is this checkout healthy?" is /doctor
(python3 tools/ops/fleet_doctor.py). The estate-wide answer is
python3 tools/ops/estate_selfcheck.py.
These are the dangerous ones. A loud failure gets fixed; a quiet one ships.
What happens: refresh_cockpit_daily.py needs twelve tools that deliberately do not
travel to a collaborator's checkout. Every one of those calls is soft-failed, so run from
a Codespace it does not crash — it produces a cockpit whose YouTube, Retention, Jobs,
Email, Social and Console panes keep their old committed values, stamps
<!--STAMP--> with "auto-refreshed today", and pushes.
Caught by: a host guard. The refresh now refuses to run anywhere except the sync hub
and prints what to do instead.
If you need a number corrected from a Codespace: fix the pull tool (the fix syncs to
both sides), edit canonical_strategy.json (human-owned), or record it with learn.py.
<!--MARKER--> blockWhat happens: your text survives the sync, then the 06:00 job overwrites it. Losing it
is indistinguishable from success.
Why: marker interiors are machine-owned and rewritten from data every morning.
The rule: canonical_facts.json is machine-owned — never hand-edit.
canonical_strategy.json is human-owned — edit freely, it renders into the markers.
They sit in the same directory and nothing in the file says which is which.
Loud counterpart: damaging or deleting a marker hard-fails the whole run. Only the
silent case needs care.
What happens: a presence check passes; the failure surfaces days later inside a fleet
run, far from the cause.
Caught by: /doctor authenticates every checkable credential against its live API.
Five (Amplitude, Google Ads, Apple Search Ads, App Store Connect, AppsFlyer) need a JWT or
OAuth exchange to probe, so they read PRESENT (not live-checked) — and that phrasing
is deliberate. Never report those as verified.
What happens: a scan whose pattern silently stops matching reports a clean estate.
Measured: the learning ledger's carrier alarm once counted 4 carriers on a day it had
none, because the substring learn.py also matches selflearn.py.
Caught by: every guard here is driven against fixtures in both directions on each run —
the privacy scanner is fed seven real founder-figure shapes it must catch and thirteen
legitimate ones it must not.
Looks like: the sync stops, both directions freeze.
Why: incoming commits touch a file with uncommitted local changes on the hub — often
because a generator rewrote a shared file. Nothing is in disagreement.
Fix: run a full sync (push first). The error now says REFUSED and names the files.
Was: two permanent landmines — context/GROWTH_CONTEXT.md and
.github/workflows/deploy.yml were tracked but unmanifested, so they showed dirty
forever and any edit would freeze the sync. Both are in the manifest now.
Both sides changed the same lines within one 15-minute window. The sync aborts, the work
tree is untouched, and the cockpit watchdog emails. This needs a human — it is correct
behaviour, not a bug.
LEARNINGS.jsonl and COLLAB_LOG.jsonl are merge=union in .gitattributes, so
simultaneous appends never conflict. Cost: interleaved lines may not be in timestamp
order. Every row carries its own ts; sort, never assume file order.
Cross-sync pauses. Nothing is lost — commits queue in git and flow on the next run.
Phase G moves the scheduled sync onto GitHub's servers to remove this dependency.
A deploy that is refused is the completeness gate working. build_docs_site will not
publish a partial tree, because a partial publish deletes the docs it could not build.
Run /doctor and read the DOC ESTATE section rather than working around it.
Two publishers, one estate. Both machines can /estate-sync. Pull first, publish
deliberately — Cloudflare Pages' free tier caps at 500 builds/month and deploy_guard
debounces bursts.
Status codes are useless for verifying a doc is live. Cloudflare Pages serves
index.html for any unknown path, so a missing doc returns 200 with the index in it.
Only a content-aware check finds it.
| If this happens | What to do |
|---|---|
| A credential leaks, or access must end | python3 tools/ops/codespace_secrets.py revoke --yes — removes all 49 in one command. Then remove the collaborator. |
| Meta reads as broken | Check for (#4) Application request limit reached — that is a rate limit wearing HTTP 403. Retry later; the token is fine. |
| WordPress reads as broken from a script | Send a real User-Agent. The WAF 403s Python-urllib while curl gets 200 on the same credentials — this reported three valid logins as dead. |
| A Cloudflare token "fails verification" | An account-scoped token fails /user/tokens/verify while working perfectly. Probe an account endpoint. |
| The Codespace comes up under-provisioned | .env.example is executable configuration — postCreate.sh reads it to decide what to write. If it is stale, credentials go missing with no error. |
| You want to re-run setup | Create a fresh Codespace. gh codespace ssh does not inherit the injected secrets, so re-running postCreate.sh over ssh writes zero credentials and destroys the good .env.local. |
| Claude asks Nic to log in | The CLAUDE_CODE_OAUTH_TOKEN secret is missing or expired. Aga re-runs claude setup-token. |
Billing: Codespaces usage on this repo is paid by caliacademy (Aga's account), not Nic's.
Never leaves Aga's machine: tools/ops/FLEET_LOG.jsonl (it carries CFO/cap-table rows
and a row naming Nic's own salary, legal name and Wise transfer), the founder c-suite seats
(tma-cfo, tma-ceo, tma-cxo, tma-coo, tma-founder-coach, tma-pm-lead),
EXPERT_PROMPTS/FINANCE, money-briefs/, the agent governance charter, and the war room.
Enforced, not remembered: fleet_log.py selfcheck scans the entire shared set on every
estate run and fails on any bank-cash, burn or runway figure. Operating metrics —
cash pace, the $15K target, cash-per-sale — pass clean; that distinction is the whole
point and it is fixture-tested both ways.
🔴 Adding a file to growth_manifest.txt is a disclosure decision. Content-audit it
first. Withholding a file is not the same as removing a number: the same cash and burn
figures had also been pasted into six other shared files.
token_youtube_tma_write.json, youtube.force-ssl — edit rights over 869 videos). Untracked now, but untracking does
not erase history. Rotation is Aga's decision and has not been done.
/metrics-check cites three scripts that do not exist (pull_analytics.py, build_report.py, raw_ga4.json). Surfaced by the new CITED-PATHS check.
FLEET-85). Every otherread source works with no new secret.