Loop FIN-3 · Finance · reports to Shahbaz + Nish

Three numbers that must always match: platform, invoice, bank.

Monthly three-way match between what ad platforms say we spent, what we were invoiced, and what left the bank — the loop that makes another AED 720K structurally impossible.

Built — awaiting credentialsWave 4🕐 Monthly⚙️ Script, creds pending
Part 1 — the plain-english view

Nobody reconciled ad spend. That's how 14 months slipped by.

What it watches
  • Platform spend — pulled read-only from the ad accounts
  • Invoices — agency/platform invoices from mail and drive search
  • Bank-out lines — a monthly statement extract uploaded by Finance (deliberately manual in v1; don't over-automate the rarest step)
When & how it speaks

A monthly reconciliation table: the three columns side by side, unexplained gaps flagged coral, and a running total against the AED 720K precedent.

Why it exists

AED 720K went to ad platforms over 14 months with zero verified sales — and no one document ever showed spend, invoice and bank movement together. This loop is that document, monthly, forever.

AED 720K
the precedent — spend with no verified results, invisible because nothing reconciled it
3 sources
platform APIs, invoice search, bank extract — matched line by line
Monthly
cadence — tight enough to catch drift, loose enough to stay cheap

Monthly

After month-end

👀

Pulls the three sides

Platform spend, invoices, bank extract

🧮

Matches & flags

Line-level match; unexplained gaps turn coral

💬

Reconciliation table

To Shahbaz + Nish

Humans investigate

The loop flags; people resolve

What it will never doNever approves or blocks a payment.
Where it stands today · July 2026Built against fixtures and threshold-proven as part of the ads quartet — the matching logic, degraded-mode chain and digest all tested with synthetic data. It goes live the day the read-only ad-platform credentials land in the vault (one credential task serves this loop and the ads watchdog together).
Part 2 — under the hood

How it's wired: systems, models, and the path a number takes.

For implementers and the technically curious. The full build sheet — verified queries, thresholds, and build notes — lives on the specs page.

ReadsAd platforms (read-only)
Spend per account per month, via the shared ads adapter layer
ReadsMail + Drive search
Agency and platform invoices
ReadsBank extract
Uploaded monthly by Finance — the human step, kept human
Stepfin3_adspend_match.py
Three-way line matching, gap detection
DeliversMonthly table
Gaps flagged coral, running total vs the precedent
System we read Automated step State / memory Human decision
SystemRole in this loop
Ads adapter layerads_common.pyOne shared, environment-gated adapter for Google/Meta data used by all four ads loops — with a fixture mode so logic stays provable before credentials exist.
Google Workspacemail + drive searchWhere the invoices already are — searched read-only.
Agent Vaultcredential storeWhere API keys live. Loops get read-only credentials from the vault; nothing is hardcoded in scripts.
Hermesagent runtime on our serverThe scheduler that wakes the loop up. Each loop is a cron job under a Hermes profile; the planned bizops profile will host the business digests (IT loops run under vpsops).
Healthcheckshealthchecks.huxapps.comThe dead-man's switch. The loop pings it only after a clean run — if the loop dies or errors, the ping stops and Healthchecks raises the alarm independently. This is how 'never silent' is enforced by machinery, not promises.
Email renderer + gwsrender_email.pyAll digests pass through one shared renderer: Huxberry-branded HTML, tables for repeated rows, a coral 'needs your response' box when the loop has questions, and an arrow link on every record. Sent from the loops mailbox via the Google Workspace CLI.
Model / brainWhat it does here
None at run timedeterministic scriptA normal cycle is a plain Python script — no AI tokens are spent unless a diagnosis or judgment step is actually needed. AI wrote the script; the script does the rounds.
GPT-5.5 via Codexthe bulk-work modelWrote and maintains the mechanical parts — SQL, diffing, digest assembly. Effectively free on our existing subscription, so routine cycles cost almost nothing.
Claude Opusthe judgment modelReviews alert wording, thresholds, and anything a human will read and act on. Post-Fable, Opus owns everything that ships.
State & memory

Prior months' reconciliations — so the running total and repeat-offender gaps accumulate.

Delivery

Monthly email table; unexplained gaps highlighted; running total vs the AED 720K precedent always visible.

Safety rails

Read-only platform credentials from the vault; the token-expiry watchdog must include the Meta token from day one (it silently dies ~2 months in — a documented gotcha).

Before it can run for real
  • Read-only ad-platform credentials into the vault (Google developer token — the slow part — plus OAuth, and a Meta long-lived token)
  • Meta token wired into the credential-expiry check
Full build sheet →