What we have learned

🔴 **GENERATED — do not hand-edit.** Written by `tools/ops/learn.py` from
`data/learnings/LEARNINGS.jsonl`. To add a lesson: `learn.py add`. Editing this
file directly means the next `add` silently overwrites your text.

Every entry is a correction someone made and the rule that came out of it.

Aga and Nic both write here; the ledger syncs both ways within ~15 minutes.

**4 lesson(s)** · scopes: all (1), analytics (1), ops (1), paid (2)

2026-08-13 — Round-trip test: a lesson recorded on the collaborator side, 13 Aug 2026.

Rule going forward: Prove the collaboration loop by writing from the collaborator checkout and reading it on the Mac — never by reading the sync code and assuming it works.

by nic · scope: paid · source: verification run · `LRN-2026-08-13-round-trip-test-a-lesson-recorded-on-the`

2026-08-13 — The fleet doctor reported all three WordPress logins and the Meta token as broken. They were all valid: Python's default urllib User-Agent gets 403 from WordPress's WAF where curl gets 200, and Meta answers an over-quota call with HTTP 403 '(#4) Application request limit reached' — a rate limit wearing an auth error's status code.

Rule going forward: A probe that produces FALSE failures is worse than no probe: it sends someone to rotate a working credential. Always send a real User-Agent, probe the endpoint the tools actually use (not /me), and treat Meta's (#4) as a retry-later warning rather than an auth failure.

by fleet · scope: analytics, paid · source: tools/ops/fleet_doctor.py, measured 13 Aug 2026 · `LRN-2026-08-13-the-fleet-doctor-reported-all-three-word`

2026-08-13 — Nic's Codespace silently came up with 22 of 43 credentials and reported no error, because .env.example was never in the sync manifest and his repo carried an old 22-name copy.

Rule going forward: .env.example is executable configuration, not documentation — postCreate.sh reads it to decide what to write. Any file that DRIVES behaviour must travel in the manifest alongside the thing it drives, and setup must be verified by booting a fresh Codespace, never by re-running setup over gh codespace ssh (an ssh session does not inherit the injected secrets).

by fleet · scope: ops · source: verified live in a real Codespace, 13 Aug 2026 · `LRN-2026-08-13-nic-s-codespace-silently-came-up-with-22`

2026-08-13 — The fleet proposed sharing tools/ops/FLEET_LOG.jsonl with Nic. It contains 28 CFO/cap-table/runway rows AND a row naming Nic's own salary, legal name and Wise transfer.

Rule going forward: Founder financials and the founder c-suite never leave Aga's machine. Before adding ANY file to the sync manifest, content-audit it for cash/burn/runway figures and personal data — withholding a file is not the same as removing the number, because the same figures get pasted into other shared files. tools/ops/fleet_log.py selfcheck now scans the whole shared set and fails on a founder figure.

by aga · scope: all · source: Aga, 13 Aug 2026: 'remember the one thing Nic does not have access to is financials and my founder c-suite' · `LRN-2026-08-13-the-fleet-proposed-sharing-tools-ops-fle`