Working with an agent on this repo
Written after a session that ran far too long and produced three reporting faults Alex had to catch himself. The diagnosis matters more than the apology, so this is the diagnosis.
What actually went wrong
Context length was a factor but not the cause. The cause was building before verifying, in a domain where a wrong number looks exactly like a right one.
Every fault had the same shape:
| Fault | Looked like | Was |
|---|---|---|
| 23 client websites | discovered | strangers' businesses that happened to resolve |
| Blended cost per lead | $58.63 | a recruitment lead averaged into client acquisition |
| "Last six months" spend | $1,071 | one month, under a six-month heading |
| Two clients at zero leads | no performance | click-to-WhatsApp, 65 and 83 conversations |
| Every client short on spend | drift | an off-by-one, 30 days counted from today-29 |
None of these were caught by tests, types or a passing build. All five were caught by comparing output against the source — which is why reconcileMeta now runs every three hours and answers 409 on a mismatch.
The rule that follows: for anything with an external source of truth, build the reconciliation first. Not after, and not when someone complains.
Session hygiene
Context is per session, and a long session is slow in a way no amount of care fixes.
- One work area per session. Meta access, then a new session for the media buying board, then another for ClickUp. A session that has been running six hours is carrying six hours of detail it no longer needs.
- The durable memory is this repo, not the transcript.
docs/register.mdsays what is built and what is not;docs/sop/holds the hard-won specifics; the CLAUDE.md table points at the rules. A fresh session that reads those starts faster than a long one continues. - Write the finding down when it is found, not at the end. Every gotcha in
docs/sop/was written the moment it cost an hour, which is why the second session does not pay for it again.
What to say to start a session well
Name the surface and the source of truth:
"Media buying board — the numbers must reconcile against Ads Manager's last-30-days."
That single sentence sets the acceptance test. Without it the work is judged on whether it looks right, and looking right is the failure mode.
What slows a session down
- Re-deriving state that is already written down. Read
register.mdfirst. - Long backfills held in-session. They belong in the background with a log.
- Building a second surface before the first is reconciled — the fault propagates.
- Exploratory querying without a question. One targeted query beats five orienting ones.
The standing constraints
These do not need re-deciding, and re-deciding them is itself a waste:
- Read-only, structurally. Meta carries
ads_readand no write scope; the WhatsApp transport cannot send; the ClickUp client hard-codesGET. Each is enforced by a test, not a habit. - A number states its scope. Window, purpose and period on the face of it. Three of the five faults above were figures that were arithmetically correct and did not say what they were.
- Recruitment never averages into client results.
purpose-rule.test.tsenforces it across ten services. - No guessed identifiers. A domain, a client match or a campaign purpose that cannot be evidenced is left empty and surfaced, never filled in with a plausible value.