TMA Growth Cockpit · Sprint to MRR

New money in, churn money kept — past $15K, then the growth rate

Live · auto-refreshed 12 Aug 2026 05:37 (daily 06:00 job — Stripe ×2 + RevenueCat live) ✅ all 10 data sources refreshed today · ✓ watchdog 09:00 — 19/19 pipeline checks green · Aga & Nick · all figures USD · sources: Stripe ×2, RevenueCat, Meta, GA4, Google-via-GA4, AppsFlyer, Amplitude · instrument of TMA-STRATEGY-SOURCE-OF-TRUTH-JUL2026 (on any contradiction, the SoT wins) · daily: Today tab, 5 min · weekly: the deep tabs, 30 min together
📅 Time window — global · drives revenue, spend & daily flow on every tab
or custom:
★ At a glance — the whole company on one screen generated 2026-08-12 from the same live sources as every other tab · never hand-written
Repeatable net cash / month
$9,151
of $15,000 · 61.0% · gap $5,849/mo
Days to the horizon
78
to 2026-10-29 · break-even clock 2026-11-01
Live MRR
$11,213
web $7,800 / 540 · app $3,413 / 240
The finding that changes what we work on GA4 · 28d · the app funnel split by platform, 11 Aug 2026
Same screens, same 28 days🍎 iOS🤖 Android What we saw before (blended)
First workout started 99.7% 39.7% 74%
Trial started (of pricing views) 18.8% 7.5% 13.8%

Blended, this reads "26% never start a workout" — a product problem. Split, iOS loses 0.3% and Android loses 59% on identical screens. iOS is already performing at the level we would have set as a target. The blend was pointing every recommendation at the wrong half of the estate.

Also corrected: the iOS "52.7% delete rate" is not a delete rate — it is 29 delete events ÷ 55 install events over six days, and a delete on 28 Jul can belong to a May install. Normal shape for a paywalled fitness app.

Should we be doing MORE Apple Search Ads?

We can finally answer this — and the answer is: the branded lines are cheap and worth keeping, the non-branded experiment already ran and already failed.

1 · What actually runs is three Branded campaigns at ~$1.19 an install. US $89.14/70 · EU $73.12/66 · UK $14.61/12 — $176.87 for 148 of the 163 installs. That is cheap, and it is worth keeping. But branded is arithmetically capped: you can only buy as many searches for "the movement athlete" as people actually make, and those people already know us — our own listing is the top organic result for our own name. There is no volume to scale into.

2 · The "buy new demand" experiment already ran, and it already failed. The five paused campaigns are exactly that test — non-branded, competitive and demand-gen — and they burned $230.45 for 15 installs, about $15 each, one returning literally zero. Against branded at $1.19 that is a 12× gap between buying people who know us and trying to buy people who don't. They are already off. There is nothing to pause.

3 · Cheap is not the same as incremental — and we still cannot claim profit. The estate has been carrying "$18.98/install"; that is revenue per install, not cost, and its denominator (120 AppsFlyer installs) does not match Apple's 163. Putting $18.98 next to $2.50 would be a false profit claim, so CAC and ROAS stay unpublished until the revenue join is denominator-matched. Proving branded ASA is incremental needs a holdout, not a lower CPI.

The ten things worth doing next ranked by cash per minute of founder time · read LIVE from the tracked queue, so a closed row disappears from here by itself
1NIC-101 PARKED · 90 min
🔴 MAKE THE IN-APP CANCEL DOWNSELL PLAN-AWARE — annual leavers are shown a WORSE deal than our own standing offer. Measured 11 Aug: 84 of the 115 in the cancel queue are ANNUAL, and every can…
The cancel downsell offers ANNUAL members a WORSE deal than our own annual price. Every annual canceller who takes it costs us money — and 73% of cancellers are annual.
2NIC-100 ASSIGNED-DEV · 60 min
🤖 ANDROID: 32% OF USERS NEVER SUCCESSFULLY SIGN IN — and it is NOT a crash. RE-DIAGNOSED 11 Aug with Play vitals + a geo-controlled GA4 split. 🔴 THE CRASH THEORY IS REFUTED: Play Developer R…
Android loses 59% of users between finishing setup and workout 1; iOS loses 0.3% on the SAME screens. Largest single defect on the app rail, and it is a bug hunt, not a redesign.
3AGA-104 Aga · 20 min
💸 PAID COMPLIANCE SWEEP — 5 checks in the ad UIs, ~20 min, stops live rule breaches. (a) Google Ads → Campaigns: verify Competitive Non-Branded + Competitors Branded + PMax are PAUSED per th…
20-minute paid compliance sweep. Competitive Non-Branded took £83.67 for zero sales, MOF - Lead Form is spending into a sync dead since Dec 2025, and Google's budget stepped +43% with the measurement gate uncleared.
4NIC-98 DONE · 45 min
🔴 FIX /start-training/ — RE-MEASURED LIVE 11 Aug 13:10 MDT, and this row's numbers have moved: the DEAD $297 lifetime price is GONE (zero occurrences of '297' on the page) and 'checkouts-v3'…
/start-training/ is live RIGHT NOW showing the dead $297 lifetime price and the retired 4.9★ rating. It is a page we send buyers to.
5FLEET-33 Fleet · 90 min
📧 MOVE THE ASK IN 973 Nurture Sequence 1 NEW COPY FROM CLAUDE — from step 18 (day 57) to ~step 7, where 751 Nurture Sequence 1 proved it works. Measured 5 Aug via offer_reach_check.py: the o…
973 asks for the sale at step 18 — day 57. Move it to ~step 7 where the readers still are. 40,287 sends in 28 days sit behind that one decision.
6FLEET-34 Fleet · 90 min
📧 GIVE 758 Nurture Sequence 2 A PRICED OFFER BEFORE ANYONE ELSE MIGRATES IN — it holds 14,619 contacts and is TRIAL-DOOR ONLY: 11 emails, every CTA to /start-training/, no priced offer on an…
758 holds 14,619 contacts and carries NO priced offer at all. The biggest audience in the estate is being nurtured toward nothing.
7AGA-129 Aga · 20 min
📧 APPROVE: POINT ONE WEEKLY EMAIL AT THE QUIZ ROOT — one link decision in one already-scheduled send to the engaged list, CTA → https://quiz.themovementathlete.com/ (root, UTMs per the link …
Point one already-scheduled weekly email at the quiz root. One link, one decision, zero build — and the quiz is the only rail currently selling.
8NIC-94 DONE · 15 min
📧 THE RESULTS EMAIL TELLS EVERY LEAD THEIR PASSWORD IS "[Chosen Password]" — quiz_email.html line 24 is literal text, not a merge field, so the reader sees the words '[Chosen Password]' wher…
The results email tells every new lead their password is literally "[Chosen Password]". It is the first email a quiz lead receives.
9AGA-147 Aga · 5 min
🟢 GO/NO-GO: give '758 Nurture Sequence 2' (14,600 contacts) a quiz-root CTA slot — NP verdict lever 2, $0 ('fix the tap before the bucket'). Email currently sends the $97 quiz ~1 lead/8 days…
Give 758 (14,600 contacts) a quiz-root CTA slot. $0, and it is the 'fix the tap' lever, not a new campaign.
10AGA-119 Aga · 20 min
💷 THE ANNUAL OFFER TO THE ENGAGED — 🔴 DO NOT APPROVE YET, THE AUDIENCE HALVED. Measured live 11 Aug via the AC API: tag 237 'Engaged' holds 2,912 people, not the ~6,367 this row claimed and …
The annual offer to the engaged — but the audience HALVED on measurement. Read the new number before approving; 'the engaged list' is seven different tags, 1,666 to 19,826.

Not on this list because they are already in flight: AGA-153 (the Apple Search Ads key) and the still-has-access retention play. A list that hands back work already underway costs more time than it saves.

Where every lead actually came from — 28 days GA4 · generate_lead by lane · pulled 2026-08-12 · this is the honest picture of what feeds the funnel
Lane28dMTD7d Read
Paid ads18810478Buying leads, not customers — Meta bought 0 purchases for £261.79 in the first 9 days of August.
⚠ Attribution-dark (unmeasurable)1103323We cannot say where these came from. The biggest measurement hole we have.
TMA.com content CTAs625229TMA.com content CTAs. The capture layer only switched on 5–6 Aug — too young to judge until ~19 Aug.
Organic search (untagged)4488Untagged organic. Real, and the cheapest lead on the board.
Other referral1762Other sites sending us people.
BWA article CTAs822BWA article CTAs — 318 pages went live 5–6 Aug; this should climb.
Organic social753Instagram/Facebook/TikTok. Saves-per-reach 0.39% vs a 1.00% target is the lever.
AI answer engines666AI answer engines (ChatGPT, Perplexity). Tiny but real, and free.
Other432Unclassified but attributed.
🔧 Internal / QA traffic311Our own QA traffic — never a result.
YouTube descriptions333875 videos, fully tagged since 9 Aug. Measure per LINK, never per video.
Email322🔴 Only a handful attributed — email revenue is still DARK, the single biggest hole.
All lanes 455225 159

🔴 24% of leads are attribution-dark — we cannot say where they came from. That is the number that makes every other channel verdict softer than it looks, and closing it is worth more than any single channel's growth.

The two funnels, side by side
🌐 Web (the quiz)📱 App
Sells today? YES — the only rail selling renewals from 240 existing subs
Since 1 Aug 15 sales · $1,298 · AOV $86.56 $3,413/mo MRR
The one leak that matters S01→S02: keeps 46.8% (re-verified on clean August data) Android sign-in + first workout (iOS is fine)
Where the work should go One test on screen 1 One question to Nic, then decide

Everything downstream of quiz screen 1 is already healthy — from question 1 to the paywall the quiz barely leaks, and the assessment does not scare people off. That is why screen 1 is worth more than anything we could buy.

What is working, and what is not

✅ Working — the new quiz is the only rail selling: 15 sales, $1,298, AOV $86.56 since 1 Aug (the old v2-2 rail: zero in August). iOS post-install behaviour is excellent. Deliverability is healthy — bounce 0.03%, unsub 0.29%.

❌ Not working — cold paid on either platform (Meta: £261.79 for zero purchases, 1–9 Aug). Android, top to bottom. Email revenue is still DARK — the single biggest measurement hole we have.

⏳ Too early to judge — the owned-content capture layer switched on 5–6 Aug: first honest read ~19 Aug, full read ~2 Sep. Any "content produces N leads" figure whose window starts before 6 Aug is an artefact, not a result.

🎯 THE NUMBER — repeatable net cash / month LIVE+MODELLED
$8,159 / $15,000 to break even
month pace · $2,585 banked so far (day 12/31) · gap $6,841
Stripe recurring net $2,585 MTD (fees/refunds −23.6%) + app $1,481 — LIVE RC gross × calibrated ratio (iOS 1.0232×, ref 2026-07 · Play 0.7311×, ref 2026-07). One-time/promo cash excluded ($0 gross this month) — a promo lies.
● The call — what's binding today
RETENTION
Churn is out-running sales — 57 lost vs 35 won in 7d, and cash pace is 54% of $15,000. Every save is a sale you don't have to make.
MRR is the secondary number — valuation, not income. the $15K doc ↗
🧮 How $8,159 — and the $6,841 gap — are calculated (as of 2026-08-12 · click to open)
gap  = $15,000 − pace
pace = (Stripe recurring net MTD ÷ days elapsed × days in month) + app month
app  = RevenueCat gross MTD × calibrated store ratio
StepFigure
Stripe recurring net, actually banked (day 12/31)$2,585
÷ 12 × 31 → Stripe at full-month pace$6,678
+ app net this month · iOS $1,288 × 1.0232 + Play $223 × 0.7311 MODELLED$1,481
= pace — THE NUMBER$8,159
− break-even target$15,000
= gap$6,841
Three things that make this number easy to misread:
1 · It is a run-rate, so it moves EVERY day. Only $2,585 is actually in the bank so far; the rest is today's daily average projected to month-end. Early in the month a few good or bad days swing it hard. Never quote a gap figure without its date — e.g. the gap read ≈$7.3K on 25 Jul and $6,841 today, with nothing "going wrong" in between.
2 · Recurring only, net, one-time EXCLUDED. Stripe is net of fees and refunds (−23.6%), and $0 of one-time/promo cash this month sits outside it on purpose. This is a repeatable cash target — a promo flatters the month and then leaves. It is NOT total revenue, and it is NOT MRR.
3 · The app half is MODELLED, not counted. Apple and Google don't report net mid-month, so app revenue = live RevenueCat revenue × a ratio calibrated on the last mature closed month (2026-07). It self-recalibrates as real proceeds land. ✅ Settled 6 Aug 2026 against Apple's own financial report: ASC "Total Estimated Proceeds" and RevenueCat's App Store revenue are both NET, so the iOS ratio sitting near 1.0 is correct — the old "app cash may be ~15% high" warning is refuted.
Source: tools/finance/kpi_15k_sync.pykpi_15k.json, rendered into this tab. Never hand-typed — if a figure here looks wrong, fix the script, not the page.
The engine — customers won & lost LIVE every row adds up · Stripe ×2 + RevenueCat
Per day → monthyesterdaylast 7dMTD
✅ CUSTOMERS WON money committed 23553
① bought at a discountpays now · NO trial01015
② trial converted → payingcounted when it converts, not when it starts0916
③ app — new subscriptioniOS + Android21520
④ app — resubscribedcame back012
↑ ① + ② + ③ + ④ = customers won. This is why "4 won / 0 trials started" is normal — discounted buyers skip the trial entirely.
🎟️ Trials STARTED a commitment, not yet revenue — converts later 31126
  ↳ of those, died in trial01619
❌ PAYING CHURN payers whose access ended (dead trials excluded — they never paid) 75770
  ↳ all cancellations incl. dead trials77389
  ↳ cancel REQUESTS — decided to leave (leading)01119
NET PAYING CUSTOMERS = won − paying churn -5 -22 -17
⚠️ The ledger trap: the MRR/sub headline counts active subscriptions only — a live trial is a commitment that has not yet entered the book, so net ≠ won − all-cancellations. The arbiter is measured book movement: +5 subs and −$12 MRR over 7d.
What it takes — the ladder to $15,000 MODELLED
⭐ THE MIX — the biggest lever, and it costs nothing
48% of sales are annual
This month 15 annual · 5 quarterly · 11 monthly = 31 sales banking $2,865$92/sale. The same 31 customers on ANNUAL would bank $4,8671.7× the cash, zero extra traffic.
If annual-led ($157/sale)
44/mo
10/wk · 1.4/day · vs 31/mo today
If the mix doesn't change
75/mo
at today's $92/sale — 2.4× today's volume
Dial A — more leads
12/day
at today's 11.83% Lead→Paid · now 22/day
Dial B — better conversion
6.4%
at today's 22 leads/day · now 11.83%
Cash model: gap ÷ cash-per-sale. Churn is reported separately — 252/mo leaving at the current run-rate — because it erodes the renewal base that feeds NEXT month, and every save is a sale you don't have to make. The dials assume the web funnel carries it (app installs are store-driven, and app revenue is already inside the pace above, so it is never counted twice). Lead→Paid basis: 31 WEB payers (direct + trial-converted) ÷ 262 quiz leads, same MTD window — PROXY, not cohort-matched. App payers excluded: they never touch a quiz lead. Two dials, same target — lift lead volume or lift conversion. Clock: 12 weeks to the 2026-11-01 backstop (SoT: a backstop, not the target).
The three funnels · last 7d LIVE quiz · iOS · Android — kept separate
Funnel 1 · Quiz / assessment (this is what the cockpit used to call “Web”)
704 quiz visitors → 318 started → 172 gave an email (LEADS, 24.4%)133 reached the paywall → then ONE of two paths:
  10 started a carded trial (9 converted, 16 died)  ·  10 bought at a discount (no trial — pays immediately)  →  19 customers won
⚠️ two lead counters: GA4 172 vs AC 154 in the same 7d — a widening gap means tracking loss, not fewer leads.
🌱 Where those leads came from (generate_lead, 28d · 455 total):
62 TMA.com content CTAs (14%)  ·  8 BWA article CTAs (2%)  ·  3 YouTube descriptions (1%)  ·  6 AI answer engines (1%)  ·  44 Organic search (untagged) (10%)  ·  7 Organic social (2%)  ·  3 Email (1%)  ·  17 Other referral (4%)  ·  188 Paid ads (41%)  ·  4 Other (1%)  ·  3 🔧 Internal / QA traffic (1%)  ·  110 ⚠ Attribution-dark (unmeasurable) (24%)
Attribution-dark 24.2% (target ≤25% — until it falls, no row above can be trusted; those leads are mostly owned content + YouTube)
🔴 Clean-data baseline 2026-07-29 — earlier windows under-report owned content, so a content zero is a measurement artefact, not a verdict. Source: tools/seo/data_lead_lanes.json (pulled 2026-08-12).
Funnel 2 · iOS
71 free sign-ups (LEADS)29 saw the paywall (40.8%) → 1 started a trial
195 paying subs · net +7 over 7d · $827 gross
A free app account is a LEAD, not a customer — they become a customer only when they pay.
🍎 App Store funnel (Apple Analytics, last 6d · as of 2026-08-12):
55 installs (~275/mo)  ·  29 deletes — 52.7% delete rate  ·  net +26
🔍 87.3% of installs originate in App Store search  ·  📄 74.3% install without opening the product page
A 52.7% delete rate outweighs any metadata gain — that is a product/onboarding problem, not an ASO one. Source: tools/aso/aso_daily.py.
Funnel 3 · Android
58 free sign-ups (LEADS)19 saw the paywall (32.8%) → 0 started a trial
45 paying subs · net +2 over 7d · $162 gross
A free app account is a LEAD, not a customer — they become a customer only when they pay.
App gross new/churned subscriptions are readable only at app-TOTAL level — won 16 · churned 5 · net +11 over 7d — because RevenueCat's actives_movement chart cannot be segmented by store. Per store we CAN see paying subs, trials, revenue and net movement (above). App free-account → paying conversion: 3.96%.
Where leads come from LIVE yesterday · 7d · MTD on every row — a source with no pipe is still named, a hole, not an absence
Sourceyesterdaylast 7dMTD
Leads captured — these reach email
Quiz / assessment ✅ live
AC list 209 + GA4 quiz funnel — the measured channel
16154262
Lead magnets (guides, challenges) ✅ live
AC only — NOT wired to GA4, so no source/UTM attribution on these
02023
App sign-ups — emailed, but no source
App free sign-ups — iOS969121
App free sign-ups — Android65791
CORRECTED 5 Aug 2026 — the old note read the WRONG LIST and was false. App sign-ups DO reach AC: Django's activteUserAndToList() writes them to list 204 (TMA ACCOUNT ACTIVATED) + tag 167 free_signed_up_mobile_&_web, which triggers 992 TMA | Welcome Sequence AFTER APPSIGNUP AB TEST Aug4th. Tag 167: 11,859 subs, +2,024/30d. List 199 is a different, genuinely empty list — email follow-up IS live. Counts below stay GA4-sourced (split iOS vs Android) because AC cannot split by store. 🔴 OPEN: 992's trigger fires on ANY activation — 2 of its first 4 entrants were the wrong audience (a quiz lead and a paying customer).
Where the quiz leads came from (GA4 attribution)
TMA.com content CTAs02952
BWA article CTAs022
YouTube descriptions033
AI answer engines066
Organic search (untagged)088
Organic social035
Email022
Other referral026
Paid ads278104
Other023
🔧 Internal / QA traffic011
⚠ CAN'T SEE — attribution-dark102333
Whole live email estate is taggedall 1,456 email links carry UTMs. Attribution is set at lead time, so the 28d window heals over the next 28 days. Any dark remaining after that is NOT email — look elsewhere. AC's click-tracking redirect drops the referrer, so an UNtagged click arrives as (direct) and is unattributable forever after.
📧 Never reach email (2): themovementathlete.com (non-quiz), Bodyweight Training Arena (BWA) — visible in GA4, but no address is captured, so no follow-up is possible.
🔴 Owned-content lanes only became measurable 2026-07-29 — windows reaching earlier under-report them.
Definitions — what these words mean here
Lead — gave us contact details or created a free account. Not a customer.
Customer / WON — money committed. Exactly two ways in: (a) carded trial start — counted as won when it CONVERTS, not when it starts; (b) direct discounted purchase — pays immediately, no trial.
Cancel requested — decided to leave (leading signal). Cancel ended — access actually gone (the MRR hit). Paying churn — cancel-ended minus trials that died, because a dead trial never paid.
Net paying customers — customers won − paying churn.
Repeatable net cash — cash collected, minus one-time/promo, minus fees. The $15K target. MRR — the book normalised to a month; a valuation metric, not this month's income.
Tags: LIVE pulled from the vendor API today · CONFIRMED reconciled to money · LAGGED real but from a closed month · MODELLED calculated, assumption stated.
🎯 90-Day KPIs — one number per fleet, to the runwayhorizon 2026-10-29 · 78 days left · break-even clock 2026-11-01
⏳ The 90-day goal is the runway — 78 days to 2026-10-29, three days before the break-even clock.
Every fleet below owns exactly one number. Where a metric is DARK, the fleet's first goal is LIGHTING it, with a date — never a growth target on something we cannot measure. Definitions live in FLEET_CHARTERS.json; every Now value on this page is read from its source file at render time, so this tab cannot quote a stale charter.
FleetNowBy 2026-10-29Est. cash/moMeasurementOpen
🎯 Funnel / CRO biggest row
tma-funnel-cro-lead
annual 48.4% · $92.4/saleAnnual share ≥40% of web new sales ⇒ cash/sale ≈$82 (0.4×$157 + 0.6×$32.97 blended non-annual). The new $97-annual paywall shipped 31 Jul to do exactly this; the kill-switch (14-day RPV < $6.04) protects the downside.+$2,100–2,200LIVE
🛟 Retention & CS
tma-retention-lead
82 cancel-ends MTD · $1,184 MRR lostCancel-ends ≤85/month (from 110). Estimate is the day-90 run-rate of newly-retained MRR, gross basis, stated honestly: ~25 fewer cancels × ~$12.81 avg MRR, compounding, net of Stripe ~0.90 ratio and ~13%/mo re-churn of saved membe…+$600–800LIVE8
🔍 Search (SEO · AEO · GEO)
tma-seo-growth-owner
70 owned-content leads/28d (artefact until ~12 Aug)RE-BASELINE 26 Aug on the first clean 28d attribution window (7d pace already ≈40/28d — a 40 target would self-complete by window-healing alone). Then ≥80 owned-content leads/28d by 29 Oct.+$200–350LIVE·healing53
💰 Paid Ads
tma-growth-cmo
$1,071 vs $3,000 cap · CPT UNCOMPUTABLEWIRING GATED. Wiring by 22 Aug: CPT genuinely measurable (analytics brief tasks 5 AppsFlyer · 9 server-side purchase+dedup · 8 GA4→Ads import · 31 attribution in Stripe metadata). THEN: spend ≤$3,000/mo at CPT <$20. No scaling before the…$0 · the gateDARK on CPT14
📧 Email / Lifecycle
tma-email-lead
revenue DARK · 2,445 engaged-reachable · bounce 0.03% · unsub 0.29% (cumulative, plan sequences)WIRING Wiring by 29 Aug: email→revenue attribution live (brief tasks 17 last-funnel-step export + 27 email UTM→Stripe persist), AND the unsub gate cleared (3,450 held sends released only after a passing test batch ≤0.5%). THEN: measurabl…+$500–900DARK on revenue4
📱 Organic Social (TMA)
tma-social-growth-owner
486 organic web sessions/28d vs 1,200 target · 7 leads (real, tiny — a lead target is re-set after 4 clean weeks) · saves/reach 0.29% vs 1.00% ⚠️ the distribution lever · (128 PAID leads moved to P1 — they were never organic)Win back DISTRIBUTION first — a lead goal on 446 sessions is arithmetic that cannot close. Primary: organic social WEB sessions ≥1,200/28d by 29 Oct (2.7× today) driven by saves-per-reach ≥1.0% (now 0.41%, was 0.83% in June — this…$0 · the gateREBASELINED3
🤝 Partnerships & Affiliates (both directions)
tma-partnerships-growth-owner
≈£275/mo net (bank-traced 25 Jul — STATIC, no live source)Hold merchant side ≈£275/mo net with zero build hours; complete the publisher harvest (~4h: verify tmapicks-20 earnings, negotiate Kensui) and STOP per the standing verdict; outreach: ≥6 live placements from the listicle campaign.+$100–150STATIC
📊 Analytics / Data Truth
tma-analytics-lead
dark share 24.2%/28dWIRING Dark share ≤15% by 29 Oct. Route: email UTM audit daily (854 links fixed 31 Jul — judge ~28 Aug, attribution set at lead time) + magnet UTM wiring (P17/AGA-31) + the YouTube lane diagnosis + checkout UTM forwarding (NIC-16). Also:…$0 · the gateLIVE
🧮 The honest sum: $3,500–4,400/mo against a $6,841/mo gap — 51–64% of it.
It does not fully close on these alone, and that is stated rather than smoothed. Closing the rest needs volume recovering on top of mix — which is why the DARK fleets' wiring dates matter more than their eventual numbers: an unmeasured channel cannot be scaled, only guessed at. Lead→cash uses one stated method throughout: Δleads × 13.92% Lead→Paid (PROXY) × cash per sale.
🔦 The wiring gates — dates that come before any numbera DARK fleet cannot be judged until these land
💰 Paid Ads
2026-08-22
📧 Email / Lifecycle
2026-08-29
📊 Analytics / Data Truth
2026-10-29
🛠️ Capability fleets — a gate, not a numberthey reach Aga by exception only
FleetThe gate it holdsReaches Aga only when
🏛️ Product Councildual-axis composite + ranked backlog + exit-readiness verdictany deal-blocking finding; composite falling
🎨 Design / UX + Pixel GateTWO consecutive fresh-instance SHIPs, vision-only; DESIGN_LAW violations = BLOCKEDher eyeball gate before anything ships to 'ready'
🧪 QA FleetP0/P1 finding counts; release-gate checklistany P0 on a member-facing surface
🏋️ Master Trainer Paneltraining-science correctness sign-off on progression/engine changessafety findings only
🧘 Mobilitymobility doctrine compliancebuild-vs-doctrine gaps needing Nic
🖼️ Static AdsAD_SCORING_RUBRIC + FINAL ship verdictcreative approval before spend
🟡 Forge/Ath brand + YouTubeblind-judge SHIP gates (hook ≥58/70, editorial ≥75/100)READY_FOR_AGA scripts only; channel is PRE-LAUNCH (3 subs)
📤 Outreachtma-outreach-gate PASS on EVERY send (zero bad sends); campaigns ≤50; sends as Jesse Head Coachcampaign approval before dispatch; any partner-list conflict
📺 YouTube (TMA main channel)VIEWS, not leads. Measured 3 Aug 2026: 15,032 views/28d (~537/day) → ~199 REAL site sessions/28d at a 1.3% view→click rate, which is NORMAL (0.5–2% typical). Nothing is broken — the channel is small. A ≥30 leads/28d target would need ~3× the channel views, which ~2 long-forms/mo cannot deliver, so it was arithmetically unreachable and is withdrawn. 🔴 Sessions MUST come from tools/youtube-analytics/yt_traffic_truth.py, never a raw GA4 count: bulk description edits trigger ~4 link-validator hits per video, which manufactured ~3,700 fake 'sessions' in late July and were briefed as real traffic. Levers, both unblocked and near-zero Aga attention: retention recuts (avg view 34.5%) and new-upload packaging. Packaging REFRESH is measured as a rounding error here — median CTR 3.44% is healthy and all 43 candidates are worth +5,584 views LIFETIME.
👁️ watched, not graded: 258 real sessions/28d → 6 leads · 2.3% (crawler-excluded; raw GA4 is mostly our own link-validators)
views/28d falling 2 consecutive weeks · YPP policy risk · 🔔 TRIPWIRE: views/28d ≥45,000 (~3× today) — at that scale the same normal click rate produces material leads, so the lane RE-ENTERS the revenue tier and a leads goal becomes reachable. Re-open this charter then.
📋 Project Managementno row is called done until the LIVE artefact says so; every open row has exactly one valid owner, an honest estimate and a next actiona row stalled past its phase with no owner action; a done-claim the verifier reopened; a queue closed without a resolution
Source of truth: docs/company/GOVERNANCE/FLEET_CHARTERS.json → rendered FLEET_CHARTERS.md. Generated by tools/ops/aga_console_sync.py · 2026-08-12 14:31 MDT. Never hand-edit inside the KPI90 markers — edit the charter and re-run.
Go deeper
📄The growth review — 60-second versionas of 2026-08-11
If you read one thing: where every sale since 1 Aug came from, and what to do next.
Open ↗
★ MRR — the recurring book · SECONDARY: a valuation metric, not our monthly income. The operating number is repeatable net cash → $15K on the 🎯 $15K tab.
$11,176 / $25,000 goal
Web · Stripe $7,771 (538)  +  App · RevenueCat $3,405 (240)  =  778 paying subs · ▼ $37 vs 11 Aug
gap to $25K $13,984 11 weeks left need +$245/wk last wk −$345 → swing +$590/wk
● The ONE thing — for Nick
Execute the analytics wiring
Until it's done, every funnel number below is partial — trials, sources and paywall conversion can't be trusted. This is the unlock for the whole scoreboard.
20 tasks, priority-ordered; most are console/dashboard (no app release).
Open the analytics Master Brief ↗
Money this month ▾ MTD $15,675 all rails · MRR movement −$419
💰 Revenue — this month so far (ALL rails: Stripe ×2 + app)
$4,896 all rails · 1–12 Aug
Stripe ×2 $3,385 gross  +  App $1,511 (iOS $1,288 · Play $223)
Stripe net after fees & refunds: $2,585
one-time (promo carts): $0  ·  recurring payments: $3,385
Cash that actually arrived — matches your Stripe dashboard (+ app). “How much came in?”
Net MRR movement (web rail) · last 7d
−$419
Churn is the bigger number — and it's REAL: 0 of the queue bought lifetime.
New paying subs+6 · +$133
Cancellations−34 · −$552
Cancel-queue (period-end)106 · $1,487/mo at stake — R1 sent to 59
Windows: Stripe main · new = subs created · cancels = deletion events · June cancels PARTIAL (events retain 30d → Jun 8–30 only).
Why two numbers? This month’s cash (amber) is boosted by the one-time lifetime cart — it will not repeat. MRR (teal) is the secondary, valuation figure — book value, not income. The operating number is repeatable net cash → $15K, on the 🎯 $15K tab.
Funnel — visitors → paywall → paid (trial OR direct purchase — see note) single-cohort ·
🎟️ In trial right now
live snapshot · card-on-file web + app active trials
20
Web · Stripe18
App · RevenueCat2
How this is measured: each rail is a single ordered cohort — a later step can never exceed an earlier one (fixes the old “103%”). Web = the quiz screen flow (GA4 pageviews); iOS/Play = GA4's funnel API by device. The web “Trial 3” is not the whole story — most web buyers take the one-time lifetime cart, not the 7-day trial: 128 web buyers in 30d (46 lifetime/promo + new subs) [⚠ figure as of 16 Jul — not re-pulled this refresh], so the paywall is far from a dead end; a clean paywall→purchase rate needs the web purchase event fixed (Task 9). App trials need days to mature, so 30 days is the honest read. Guide / lead-magnet sign-ups live in ActiveCampaign and aren't wired here yet.
How our funnel actually works — read the "Trial" row this way (16 Jul): we don't have a normal trial→paid funnel. A lead becomes a paying customer at the paywall, two ways: (1) carded free trial — card up front, auto-charged unless cancelled, so trial-start already IS the purchase (~50% just don't cancel); (2) direct discounted purchase — a big share take a ~50%-off offer and pay immediately, no trial (these never show as "Trial" above). So the gate metric is Lead → Paid, by source — not "trial → paid" (~50%, card-on-file "didn't cancel"). The meter (brief Task 9) + the GA4→Ads import (brief Task 8 — "Task 3" in the 16-Jul Nic message) must count both paths, deduped by transaction_id → see the event catalog §1 & MESSAGE-TO-NIC-FUNNEL-CORRECTION-2026-07-16.
To make every number here trustworthy, finish the analytics wiring — the #1 to-do, for Nick. App trial & source attribution is still partial. → the Master Brief has all 20 tasks in order. Open ↗
loading spend check…
Revenue & spend · daily ▾ last 7d
💰 Revenue · daily · NET (Stripe ×2 — after fees & refunds)$9,866
gross $10,403 − fees $537 = net $9,866
August MTD net (Stripe ×2): $2,585 (1–12 Aug, 12th partial) · split (gross): recurring $880 · one-time $10,345
Red bar = net-negative day (refunds exceeded sales). App rail now daily via RC Charts API — see the per-source table below. PayPal: DARK (no API).
💸 Spend · daily (Meta + Google, live)$4,503
Meta + Google both live via API (Basic access 21 Jul) · GBP→USD @1.336 · TikTok/ASA off · budget $3K/mo ceiling, ramp Mo.1 ≈$40/day (SoT amended 9 Jul)
Meta spend: $481 MTD (£360) · $56.37 yesterday · $350 last 7d (live 12 Aug). Google spend: $561 MTD (£420) · $42.98 yesterday · $322 last 7d (live 12 Aug). Apple Search Ads: $30 MTD · 67 taps → 32 installs · $137 → $2,077 ATTRIBUTED (15.1× gross, 12.9× net) · $19.61/buyer on n=7 — ATTRIBUTED, not incremental: all campaigns are BRANDED, causation NOT KNOWABLE.
Flags — what the data says today, and what to do
LIVE

✅ R1 Wave A SENT 20 Jul — 24/24 delivered, 0 failures (3 variants: default · price-acknowledged · known-reason; plain-text 1:1 from Jesse via hello@, NOT AC). Replies to hello@ ARE the save mechanism. → Aga: answer hello@ replies <24h · 48h scorecard due 22 Jul (check_saves.py) → then Segments B/C (~54 of ~84 auto-skip, reason already known). Pending: T-30 watcher not yet scheduled · breakage alerting not wired (state: tools/retention/R1_SYSTEM_STATE.md).

AMBER

T2 (RC→Amplitude) — live status: ✅ LANDED — auto-check 12 Aug: 8 rc_* events visible (rc_cancellation, rc_expiration, rc_initial_purchase, rc_product_change, rc_renewal…). Next: reconcile volume ±5% vs RC, then steward flips all docs green. The gap: some lifecycle toggles may still be off — reconcile the live list above against RC (~6 renewals/day expected). Most likely a few per-event toggles in RevenueCat's Amplitude integration aren't all enabled yet.→ Nic (5 min): RevenueCat → Integrations → Amplitude → enable the remaining lifecycle events (renewal, trial started/converted/cancelled, expiration, billing issue, product change, uncancellation). Then reconcile ±5% vs RC (194 subs, ~6 renewals/day). Then merge purchase + rc_initial_purchase in Amplitude — but exclude the broken af_purchase (2 fires vs 194 subs) from the merged view.

RED

New-sub acquisition collapsed during the sale: June created 61 new subs (+$1,193 MRR); July is pacing 7 in 8 days. Some of that is the paid freeze — and some is the lifetime offer cannibalising would-be subscribers (cash now, no MRR later).→ When the cart closes ~12 Jul, watch the new-subs line recover on the toggle; if it doesn't by next weekly, that's the topic.

▸ Show all flags (10)
RED

Recurring intake $880/wk vs $3,951/wk total paid spend (Meta + Google). The engine spent 4.5× its recurring intake last week; promo cash masked it.→ Hold the Mo.1 ramp ≈$40/day ($3K/mo is a ceiling, not a target — SoT amended 9 Jul). No scale-up before lead→trial reads.

RED

Revenue cliff on ~12 Jul. 85% of last week's revenue was the lifetime cart — it closes in days. Next week's revenue line will drop; that is expected, not a new crisis.→ Pre-agree it now so nobody panics; watch the recurring line instead.

AMBER

Google campaign state (9 Jul, corrected — do not quote past spend as present): the earlier over-cap UAC configuration was Nic's mistake and he corrected it same-day. Current 3d actuals ≈ $68/day total: July-4 remarketing ~$22/day (ends with the cart ~12 Jul) · UK Play ~$10 · US Play ~$5 · AP/SA/LATAM throttled to ~$5/day each (~$21 combined) · PMax ~$4 · the 5 new Quiz Funnel Search campaigns (Branded £3 · Non-Br £10 · Comp-Br £15 · Comp-Non £12 · PMax £7.50, ~375 kw) show ~$0 spend so far. Fleet recommendation pending Aga: move the AP/SA/LATAM ~$21/day to $0 (payment-incapable geos) and hold Search inside the Mo.1 ramp (≈$40/day) once remarketing ends; conversion import (GA4→Ads) before any Search scale.→ Weekly review: confirm Search scope vs SoT "Category Search only" + wire the conversion feed first (Nic message: MESSAGE-TO-NIC-GOOGLE-RETARGETING-2026-07-09.md).

AMBER

Top-of-funnel is nearly off: spend collapsed to ~$30/day total (freeze real ✓) and leads followed — 6 on Jul 8, ~3/day from Meta.→ Expected during the freeze; the new quiz campaigns are now the main faucet. If leads don't recover to >15/day within a week of Google ramping, that's the weekly topic.

RED

The web funnel is now readable PER SCREEN — and the leak is exactly one screen: S01→S02 loses 51% (700 users/month). Everything after is healthy: assessment keeps 92%, the email screen converts ~89%, 375/month reach the paywall. Leak #2: paywall→card entry ~15–20%.→ Screen-1 A/B (#17, goal-question-first) is now the top web lever with an exact baseline. Full per-screen funnel: Web tab.

AMBER

Two session counts disagree ~12× (GA4 property-wide ~15.6k/wk vs quiz-scoped 3,969/30d).→ Weekly review: pin ONE denominator (quiz landing sessions) before any funnel % is quoted.

GREEN

Meta retargeting is the one paid tactic earning its keep — ROAS 2.4–4.8× on 14 purchases (small n).→ Keep it capped & always-on; verify with a holdout before believing the multiple.

Scoreboard — sale-readiness live   directional   needs wiring
MRR · the recurring book — secondary
$11,176
44% to the $25k goal · valuation metric, not monthly income — the $15K break-even gate is a cash gate, see the 🎯 $15K tab
New paying subs · 7d
6
need ~48/wk for $15k by Nov
Cancellations · 7d
34
target <15/wk · queue 112
Leads · 7d
75
AC: quiz 154/7d · all 308/7d · y'day q16 · live 12 Aug
Visitor → Lead
29%
CONFIRMED · 429 leads / 1,477 quiz visitors (30d)
Sign-up → Trial
can't see it
the trial event under-fires — any % would be made up. → fix: Task 1
Carded trial → paid (path 1 only)
29.5%
card-on-file "didn't cancel" · web/Stripe cohort (94 of 319). NOT the gate metric — blind to direct 50%-off buyers (path 2). Gate = Lead→Paid
Cost per Trial · by channel
not attributable
no channel tag on trials yet (rc_trial_started dark). Blended spend÷trials = false. → fix: Task 1
Saves / reactivations
A sent 20 Jul · saves read 22 Jul
win-back built 10 Jul · rate once sent
🔒 Dark — not measurable yet · each tile links to the exact fix in the Master Brief
Reviewed by the growth fleet (11 Jul) — how to read these: Funnel correction (16 Jul): the gate metric is Lead→Paid across BOTH checkout paths (carded trial-start + direct 50%-off purchase) — not "trial→paid." One event should mean "a new paying customer" (both paths, tagged by source, deduped), not "trial." Trial→Paid 29.5% is a real Stripe cohort but it's only path-1 "card-on-file didn't cancel," blind to direct-purchase buyers — don't read it as the funnel's health. Cost per Trial cannot be shown — a blended “spend ÷ all trials” is false because organic & app trials cost nothing from paid; a correct per-channel CpT needs trials to carry the campaign that drove them, which isn’t wired yet. What paid actually buys today: Google ≈ $1.91/install & $1.70/quiz-lead (MODELLED); Meta = a cost-per-lead (its pixel optimises on Lead, not trial). These are cost-per-click/install/leadNOT cost-per-trial. All of it flips to trustworthy once the wiring lands (rc_trial_started → identity → conversion imports) — the #1 to-do.
Spend & revenue tables ▾ by channel · by source · daily
Spend · daily · by channel · USD rolling · last 8 days · live (pulled 2026-08-12)
Channel5 Aug6789101112 (today, partial)7-dayStatus
Meta (FB/IG)$37$56$48$43$62$48$56$26$350LIVE
Google Ads (direct API)$52$47$49$50$40$41$43$36$322LIVE
TikToknot running$0OFF
Apple Search Adsnot running — gated (Phase 4)$0OFF
Measured total$89$103$98$93$101$89$99$62$672
Both accounts bill in GBP; shown USD @1.336 (hover a cell for native £). Meta + Google live via API · TikTok/ASA off.
CPL $7.24 blended (promo days dragged it; base days $4–6) · Cost per Trial: DARK — the gate that re-opens scaling · Meta optimises on Lead until CAPI repoints (#24).
🔒 Governance (SoT, amended 9 Jul): budget $3K/mo ceiling — ramp, not splash (Mo.1 ≈$40/day) · spend gated on lead→trial visibility · weekend lock · daily spend alert to Aga + Nick · lead quality reviewed weekly by source · no scale-up before lead→trial reads and screen-1 is fixed.
🆕 9 Jul: UAC paused ✓ ($0 on Jul 8–9) · 5 new "Quiz Funnel" Search campaigns live — Branded £3 · Non-Branded £10 (126 kw) · Competitor Branded £15 (158 kw) · Competitor Non-Br £12 (68 kw) · PMax £7.50 = £45/day ≈ $57/day plan, ~375 keywords, phrase-match, pointed at the free assessment. ⚠ above the SoT cap + PMax/competitor beyond "Category Search only" — weekly item. Cost appears here via GA4 (~1-day lag).
Revenue per source · daily · USD gross rolling last 8 days · pulled 2026-08-12 05:37 · auto-refreshed daily 06:00
Source5 Aug6789101112 (today, partial)8-dayStatus
Stripe · account 1 (web — subscriptions + promo carts)$320$279$147$491$376$456$100$0$2,168LIVE
Stripe · account 2 (Thrivecart recovery cart)$0$0$0$0$0$0$0$0$0LIVE
App · iOS (App Store · RevenueCat)$154$199$150$128$154$-9$50$194$1,021LIVE
App · Google Play (RevenueCat)$0$0$29$0$0$9$124$0$162LIVE
Total, gross — ALL rails$474$478$326$619$530$456$274$194$3,351
Stripe rows: presentment USD, exact (per-tx FX). iOS/Play rows: RevenueCat Charts API, gross minus same-period refunds — Apple/Google's ~15–30% store cut NOT yet deducted (proceeds view available). App MRR $3,405 (240 subs). NET after fees: Stripe 1 $1,434 · Stripe 2 $0. PayPal rail exists, not wired — DARK.
Funnel 1 · Web — the quiz, per screen generated by tools/finance/render_cockpit_funnels.py — never hand-edit inside the marker
Go deeper
📄Three quiz funnels, measuredas of 2026-08-11
Which of the three funnels to keep, what each paywall sells, and every sale traced one by one.
Open ↗
📄Checkout & attribution ground truthas of 2026-08-07
What is actually shipped in the checkout/attribution stack vs what is still open.
Open ↗
The spine — clean window GA4 · quiz.themovementathlete.com · 2026-08-09 → yesterday · unique users · crawler-free
S01 · Landed on the quiz310
S02 · First question — THE CLIFF still the #1 web leak, re-verified on August data. It did NOT get worse: the old Jun–Jul read was −51%, this is −59.4%. 40.6% keep126
P52 · Email capture reached the quiz body barely leaks — see the per-screen detail below 54.8% of Q169
Became a lead generate_lead 81.2% of capture56
R10 · Paywall viewed17.1% of landers53
Clicked buy add_to_cart — GA4 only, NEVER revenue truth; the money table is Stripe 9.4% of paywall5
▸ Every screen, in flow order (55 screens)
S01Landing100.0%310
S02Gender40.6%126
S03Age94.4%119
S04Goal94.1%112
S05LifeContext95.5%107
S06ValidationPath99.1%106
S07Obstacle99.1%105
S08ValidationObstacle96.2%101
S09Background100.0%101
S07cTrainingRecency98.0%99
S09cCaliAwareness100.0%99
S10bCommitment95.0%94
S10cDiagnosticReveal97.9%92
S11aShameRemoval100.0%92
S11cPeopleLikeYou98.9%91
S12aHookText100.0%91
S12bNineFoundations98.9%90
S10GoalDeepDive102.2%92
S12cWhyItMatters90.2%83
S12dSelfPrediction101.2%84
S13Goldilocks100.0%84
S13bPrediction100.0%84
S14TransitionAssessment101.2%85
Assessment_Push_Q192.9%79
Assessment_Pull_Q1102.5%81
Assessment_Squat_Q198.8%80
Assessment_Interstitial_1101.2%81
Assessment_ABS_Q197.5%79
Assessment_Plank_Q1102.5%81
Assessment_Back_Q198.8%80
Assessment_Handstand_Q197.5%78
Assessment_Interstitial_2101.3%79
Assessment_Dips_Q1100.0%79
Assessment_Side_Q196.2%76
Assessment_Interstitial_3100.0%76
P45Time98.7%75
P46Frequency96.0%72
P47Build101.4%73
P48FutureStakes101.4%74
P49Readiness97.3%72
P50Equipment100.0%72
P51Teaser97.2%70
P52Capture98.6%69
P53Processing81.2%56
P54Transition96.4%54
R01PatternFound101.8%55
R01CoachRead96.4%53
R02GapChain101.9%54
R03FullMap98.2%53
R04WhyProgramsFail100.0%53
R06Calibration98.1%52
R07Day1101.9%53
R08Journey94.3%50
R09Forecast102.0%51
R10Paywall103.9%53

Step % = share kept from the previous screen. Values over 100% are branch re-entries, not growth. Assessment *_Q2 screens are conditional routing and are excluded from the spine — they are not abandonment.

Which funnel, per version — YouTube crawler excluded GA4 · 2026-02-01 → yesterday · the honest human denominator
VersionLandedQ1Keep CaptureLeadPaywallPaywall / lander
/2026-v2-2/
v2-2 Time Horizon (old primary)
3,9591,83246.3%1,13993491423.1%
/2026/
Control (Long Form)
1,66371643.1%45032631318.8%
/2026-v2-3/
v2-3 (legacy)
1,28953841.7%35228727421.3%
/2026-quiz-checkout-v1/
v1 $97 checkout (new primary)
67633449.4%17113212418.3%
The money — Stripe, both rails 2026-05-14 → 2026-08-12 · paid sales only, page-load ghost intents excluded
RailStartsPaidCash AOVAug paidAug cash
quiz_checkout(v1)1615$1,298$86.5615$1,298
register(v2-2 rail)14390$2,348$26.090$0
register(Control rail)5750$4,163$83.270$0
checkouts-v3731$25$24.970$0
other75$207$41.490$0

🔴 The new quiz (quiz_checkout(v1)) is the ONLY rail selling in August. Quiz-conversion figures from before 1 Aug describe a different quiz that never sold — never blend the eras.

Funnel 2 · App — iOS and Android, separately generated by tools/finance/render_cockpit_funnels.py — never hand-edit inside the marker
Go deeper
📄App funnel — iOS vs Android, and the ASA verdictas of 2026-08-11
Is the 52.7% delete rate real, are Apple Search Ads working, and which platform is actually broken.
Open ↗
📄Android sign-in — the VA test, and what it foundas of 2026-08-12
RESULTS IN: the door works (3 taps, 25s) and NO blocking defect was found — so the Android gap is still unexplained. 6 P3 tickets, and 2 false alarms killed.
Open ↗
🕰️Native app deep analysisHISTORICAL · 2026-07-20
The 20 Jul teardown of the native app's events, funnel and instrumentation.
Open ↗
🍎 iOS — the App Store App Store Connect · window 2026-07-26 → 2026-07-31 (6d) · 🔴 Apple's reports LAG — this is not "today"
First-time downloads — the acquisition number 27 4.5/day ≈ 135/mo
All install events (incl. app UPDATES, restores, redownloads) 55 🔴 never quote this as acquisition
Deletes — fresh-install bounces 14 delete rows carrying a recent App Download Date
Deletes — older installs cleaned up 15 no download date ⇒ not a fresh bounce
Fresh-bounce rate (fresh deletes ÷ first-time downloads) 51.9% ours ran 45–70% by month in 2026 [ESTIMATE]; category-typical 40–60% [UNVERIFIED benchmark]

Where installs come from: App Store search 96.3% · App referrer 3.7%
🔴 Apple's "App Store search" bucket contains BOTH organic search and Apple Search Ads placements — it cannot separate paid from organic. Never quote it as "organic".

74.3% install without ever opening the product page ⇒ the search-result mini-listing (icon · title · subtitle · rating · first screenshot) is the real conversion surface. The product page only touches the other 25.7%.

Store discovery — its OWN window 2026-07-29 → 2026-07-31 (3d), which is NOT the installs window above:
1,996 impressions → 92 page views (4.61%) · 665.3 impressions/day.
🔴 Install-conversion is deliberately NOT shown. NOT COMPUTED — downloads cover 2026-07-31…2026-08-01 but impressions cover 2026-07-29…2026-07-31. A conversion rate across two different windows is not a rate. This block previously carried no window at all and the cockpit published 333 impressions/day — exactly half the real figure — because every consumer assumed it shared the 6-day installs window. Found and fixed 11 Aug 2026.

🤖 Android — Google Play Play Console device installs · package com.themovementathlete.app · pulled 2026-08-12
MonthDevice installs From countries that never bought
2026-0152236.4%
2026-0245733.9%
2026-0351936.8%
2026-0447348.6%
2026-0541737.6%
2026-064,10969.0%
2026-075,22167.2%
2026-084829.2%
🍎 vs 🤖 — the SAME funnel, split by platform GA4 · last 28d · pulled 2026-08-12 · the number the blend was hiding
Step (unique users)🍎 iOS🤖 Android
Onboarding started364268
Onboarding completed317 (87.1%)239 (89.2%)
First workout started316 (99.7%)95 (39.7%)
Workout completed254 (80.4%)61 (64.2%)
Pricing page seen229134
Trial started43 (18.8%)10 (7.5%)

🔴 app_removed is deliberately absent from this table: Apple does not report deletions to Firebase, so iOS reads 0 by instrumentation, not by behaviour. iOS deletion truth is App Store Connect only — the block at the top of this tab. Comparing the two platforms on GA4 removals would be comparing a real number with a missing one.

📲 Inside the app — BOTH platforms combined GA4 native streams · platform ∈ (iOS, Android) · last 28d · pulled 2026-08-12 · engagement only, never revenue
Onboarding started632
Onboarding completed88.0%556
First workout started73.9% of completed411
Workout completed cooldown-block proxy76.9% of started316
Pricing page seen363
Trial started — THE BINDING CONSTRAINT a free app signup gets NO fundamentals assessment: a few setup questions, an EXAMPLE workout, then the price. The thing being sold is never shown before the ask. 14.3% of pricing views52

🔴 GA4's app purchase event fires on INITIATION — purchase-users (102) exceed trial-users (52), which is impossible as a funnel. Never quote GA4 app purchases as revenue. Money truth is the stores + Stripe, below. Also live: app_installed 1,366 · app_removed 372 · comeback_after_7_days 282 · assessment started only 65 (it is paywalled — that number is not a defect).

💷 App money — the stores' own NET figures never hand-typed · asc_finance_reports.py + play_earnings_reports.py
iOS NET — last complete month (2026-07)£2,365.68
Play NET — last complete month (2026-07)£730.65
App rail MRR (RevenueCat, live)$3,405
App subscribers240

Both stores report NET. The iOS RevenueCat-vs-Apple ratio near 1.0 is CORRECT — two net figures agreeing. Play via RevenueCat is GROSS (ratio ~0.73). Never "fix" the iOS ratio to 0.85, and never pull a store month mid-month. No store revenue exists before May 2026.

📉 What the numbers actually say App Store Connect · window 2026-07-26 → 2026-07-31 (6d) · 🔴 Apple's reports lag ~10–12 days — this is never "today"
First-time downloads — the only acquisition number 27 4.5/day ≈ 135/mo
All Install events — incl. app UPDATES 55 🔴 the number the old cockpit line quoted
Deletes — fresh bounces / older cleanup 14 / 15 split by whether the row carries an App Download Date
Fresh-bounce rate 51.9% ours ran 45–70% by month in 2026 [ESTIMATE] · category-typical 40–60% [UNVERIFIED benchmark] — flag only above that
Baseline first-time downloads ≈119/mo 11 non-sale months, mean ≈4/day, range 85–158 — 🔴 "130–160/mo" is RETIRED (it described only the best months)
Search share of first-time downloads 96.3% the store is a search engine we rank in

What survives and matters: ~96.3% of first-time downloads originate in App Store search, and ~74% install without ever opening the product page — so the search card (icon · title · subtitle · rating · first 3 screenshots) is the conversion surface, not the description. 🔴 Apple's "search" bucket contains BOTH organic and Apple Search Ads placements and cannot separate them; the organic keyword split is NOT KNOWABLE from ASC at all.

🚢 Ship state — what is live, staged, blocked and parked listing pulled 2026-08-11 · re-pull with tools/aso/asc_listing_pull.py
ThingState DetailOwner Rests on
Promotional text on the LIVE version🔴 NOT DONE — ships TODAY, zero reviewlive 1.70.71 promotionalText is EMPTY — and this is the ONE field that ships with NO App Review; the copy is already written on 1.70.72Aga · 5 min in ASCCHECKED — data_asc_listing.json
Title + subtitle🔴 NOT FIXED BY 1.70.72both the live and staged appInfos still read Movement Athlete / Calisthenics & Gymnastics. Title/subtitle live in a SEPARATE record from the version — the 30 Jul fill guide never covered it. 🔑 App Information submits WITHOUT a build.Aga GO on strings → submitCHECKED — data_asc_listing.json appInfos
Keyword fieldSTAGED, not livelive: ab,butt,beachbody,tracker,gym,exercise,diet,planner,trainer,butt…
staged 1.70.72: bodyweight,workout,plan,progression,home,beginner,strength,mobil…
blocked on the buildCHECKED — data_asc_listing.json
Support URL fix + descriptionSTAGED on 1.70.72dead help.themovementathlete.comintercom.help/the-movement-athlete/en/; a dead support URL is a known App Review rejection reasonblocked on the buildCHECKED — APP_STORE_1.70.72_FILL_GUIDE.md
🔴 A BUILD ATTACHED TO 1.70.72THE SINGLE BLOCKING DEPENDENCY1.70.72 has sat in Prepare-for-Submission since 30 Jul with no build, so 'Add for Review' is greyed out. Every staged fix above waits on this one act — and so does any non-branded ASA test, because Search-Match targets off listing metadata.app team (via Nic)CHECKED — ASC state + fill guide
Screenshots + app preview videoPARKED — needs a designer (AGA-26)the search card is ~74% of first-time downloads and screenshot 2 ships “STRENGHT” in 40pt type; 8 legacy iPhone-8-era frames, zero iPad, retired cyan captions, 0 of 3 App Previews used. Interim with existing assets: pull the typo frame (7 good beats 8 with a typo) and lead with the assessment frame.designer brief written → Aga unparksCHECKED — ASO_MASTER §2 + queue
In-app review prompt (ratings velocity)Jira raised (AGA-39) · in-app ship UNVERIFIED297 iOS ratings vs Thenx 12,273 — ratings volume is the ranking ceiling and the only lever that COMPOUNDS. Modelled 8–20 new reviews/mo once live. Verify: is SKStoreReviewController actually called, on what event, and does it fire in a production build?3 questions for the app teamUNVERIFIED — ticket raised, ship not confirmed
🎯 Apple Search Ads — insurance, not a ROAS engine ASA API (platform own truth) · 2026-07-14 → 2026-08-12 · AppsFlyer for revenue
Spend / impressions / taps $133.30 · 7,084 · 245 3 campaigns RUNNING — all branded · 7 paused · 🔴 never divide this spend by the revenue below — different 30d windows; the ROAS file carries its own matched cost ($137.27) for exactly that reason
Tap-installs vs VIEW-installs 111 vs 222 🔴 two-thirds are view-through — the self-attribution mechanism
ASA-attributed revenue / purchasers $2,077 · 7 AppsFlyer, store GROSS · n is tiny (±1 buyer ≈ ±14%) · 1 of those buyers sits on a paused non-branded campaign
Organic, same window $5,946 · 24 purchasers 447 installs
🚪 The delete side is an ACTIVATION question — and it is measured elsewhere GA4 + AC funnel-stage fields · data_funnel_metrics.json
This window · net revenue vs paid spend last 7d
Go deeper
🕰️Stripe payment decline analysisHISTORICAL · 2026-07-06
Why payments fell May→June 2026 — the diagnosis that made retention the binding constraint.
Open ↗
💰 Net revenue (selected window)
Stripe ×2 · after fees & refunds ·
💸 Paid spend (selected window)
Meta + Google (GA4 link) · ROAS-style ratio:
↑ These two respond to the global picker (any window, banked daily data). ↓ The per-channel & per-source day-by-day tables below are a fixed reference pull (1–7 Jul) so the columns stay readable.
🛡️ Spend Guardian — surge early-warning total paid / day · Meta + Google · Mo.1 ramp pace ≈$40/day · updates with each data refresh
loading…
🔴 = over cap or a +300% jump (confirm it's a planned promo — if not, cut it today) · 🟢 = spend dropped · The July 4–6 peak ($920/day) was the planned lifetime promo. Since 8 Jul, frozen to ~$25/day. The 7am email now carries this same alert so a leak pings you before it runs for days.
Spend governance · daily, every paid channel · USD rolling · last 8 days · live (pulled 2026-08-12)
Channel5 Aug6789101112 (today, partial)7-dayStatus
Meta (FB/IG)$37$56$48$43$62$48$56$26$350LIVE
Google Ads (direct API)$52$47$49$50$40$41$43$36$322LIVE
TikToknot running$0OFF
Apple Search Adsnot running — gated (Phase 4)$0OFF
Measured total$89$103$98$93$101$89$99$62$672
CPL $7.24 blended (promo days dragged it; base days $4–6) · Cost per Trial: DARK — the gate that re-opens scaling · Meta optimises on Lead until CAPI repoints (#24).
🔒 Governance (SoT, amended 9 Jul): budget $3K/mo ceiling — ramp, not splash (Mo.1 ≈$40/day) · spend gated on lead→trial visibility · weekend lock · daily spend alert to Aga + Nick · lead quality reviewed weekly by source · no scale-up before lead→trial reads and screen-1 is fixed.
🆕 9 Jul: UAC paused ✓ ($0 on Jul 8–9) · 5 new "Quiz Funnel" Search campaigns live — Branded £3 · Non-Branded £10 (126 kw) · Competitor Branded £15 (158 kw) · Competitor Non-Br £12 (68 kw) · PMax £7.50 = £45/day ≈ $57/day plan, ~375 keywords, phrase-match, pointed at the free assessment. ⚠ above the SoT cap + PMax/competitor beyond "Category Search only" — weekly item. Cost appears here via GA4 (~1-day lag).
Revenue per source · daily · USD gross rolling last 8 days · pulled 2026-08-12 05:37 · auto-refreshed daily 06:00
Source5 Aug6789101112 (today, partial)8-dayStatus
Stripe · account 1 (web — subscriptions + promo carts)$320$279$147$491$376$456$100$0$2,168LIVE
Stripe · account 2 (Thrivecart recovery cart)$0$0$0$0$0$0$0$0$0LIVE
App · iOS (App Store · RevenueCat)$154$199$150$128$154$-9$50$194$1,021LIVE
App · Google Play (RevenueCat)$0$0$29$0$0$9$124$0$162LIVE
Total, gross — ALL rails$474$478$326$619$530$456$274$194$3,351
Stripe rows: presentment USD, exact (per-tx FX). iOS/Play rows: RevenueCat Charts API, gross minus same-period refunds — Apple/Google's ~15–30% store cut NOT yet deducted (proceeds view available). App MRR $3,405 (240 subs). NET after fees: Stripe 1 $1,434 · Stripe 2 $0. PayPal rail exists, not wired — DARK.
Revenue per month · by source · NET last 6 months · USD, net after all fees · pulled 2026-08-12 05:37 · auto-refreshed daily 06:00
SourceMar 26Apr 26May 26Jun 26Jul 26Aug 26 *6-mo
Stripe · account 1 (web)$7,320$7,903$10,532$5,356$21,426$2,585$55,122
Stripe · account 2 (recovery cart)$81$0$0$556$1,345$0$1,982
App · iOS (RevenueCat)$3,123$3,936$3,586$3,146$3,161$16,952
App · Google Play (RevenueCat)$134$155$506$976$1,771
Total, gross — ALL rails$10,524$11,973$14,273$9,564$26,908$2,585$75,827
* = current month, partial · — = report not closed yet. ALL figures NET after all fees. Stripe: net of Stripe fees & refunds (presentment USD, exact per-tx FX). iOS/Play: official net proceeds — Apple "Total Estimated Proceeds" + Google Play payout (GBP→USD @1.336), from the dashboards, updated monthly (not RevenueCat gross). PayPal rail exists, not wired — DARK.
Channel performance — what's earning, what's burning July MTD · small samples, treat as direction
Meta retargeting (warm)
PARTIAL
2.4–4.8×
£907 → 14 purchases
The one paid tactic working. Small n — verify with a holdout before believing the multiple. Keep capped & always-on.
Meta prospecting (cold)
LIVE
0.03–0.13×
£207 → 2 sales
Cold→lifetime was the July mistake. Cold now gets the free assessment only.
Google (July)
LIVE
$1,056 → 0
July MTD · via Ads API (live) · 0 attributed sales
Ads API now live (Basic access landed 20 Jul) — spend measured daily; run-rate low since the 8 Jul UAC pause (~$21/day · $183/7d). UNVERIFIED as "can't work" — OFF until the 4 gates clear. Brand-pause test = free answer (#14).
Email (AC)
PARTIAL
~6%
per-checkout-session conversion
Highest converter (last-click inflated). The revenue calendar starts this week — owned channel, £0.
Organic (app)
LIVE
$3,968
rev / 90d · 2.9% install→purchase
Best converter per install. Per SoT: organic is upside-only (social ~dead) — ManyChat ASSESS capture + creator shot + ASO #15; paid small-capped is the reach engine.
Source attribution health
PARTIAL
43–61%
of July SALES carrying source metadata
Nic's Stripe metadata LIVE since 2 Jul (utm_*, campaign, gclid, fbclid + 15 more columns). Unknown fell ~97% → ~39–57% depending on definition — reconcile at weekly. Rising as pre-metadata sales age out.
Email engine — the estate, its health, and what it is allowed to change scoreboard generated 11 Aug 2026 12:14Z · 28d window 14 Jul – 11 Aug · KPI = clicks + conversions, never opens
Go deeper
📄Audience integrity — who we may emailas of 2026-08-07
Which audiences exist, the funnel-stage labels, and the gate that stops a bad send.
Open ↗
📄The customer journeyas of 2026-08-10
Everything a person receives after the quiz — arrival, activation, the pitch, abandonment, win-back.
Open ↗
🎪AUDIENCE INTEGRITY — who we may email, and the gate that stops a bad send
11,057 app signups carry where they stopped (3,276 setup-stalls · 5,872 never-worked-out · 1,909 free-trainers) + the 15 quiz-signal tags. Four-layer payer exclusion, born from the lifetime leak: 22 of the 25 heaviest “free” users were lifetime members.
Open ↗
Arc health — every sending automation, worst first a slot under 200 sends in the window is DARK and may not be worked on
AutomationTierSendsCTRUnsubHealth
992 TMA | Welcome Sequence AFTER APPSIGNUP AB TEST AC2051.95%4.39%BREACH
988 TMA | Welcome Sequence AFTER APPSIGNUPC2,3111.34%1.69%BREACH
975 Onboarding | After The PurchaseC1,8100.83%0.99%OVER-HARDSTOP
991 NEW Re-Engagement - For people who stopped openingC9150.44%0.66%OVER-HARDSTOP
967 TMA | Welcome Sequence After LEAD MAGNETB4,1440.36%0.51%OVER-HARDSTOP
973 Nurture Sequence 1 NEW COPY FROM CLAUDEA40,2870.37%0.33%WATCH
758 Nurture Sequence 2A30,9910.21%0.19%OK
751 Nurture Sequence 1B7,3980.16%0.22%OK
750 TMA | Welcome Sequence After QuizC1120.0%0.0%OK

Six more automations sent under 350 in the window (986 · 760 · 976 · 977 · 978 · 990) and are DARK by volume — real, but not rankable.

Email-attributed revenue
DARK
the single biggest hole in the estate — target: attributable by 29 Aug
Bounce / unsub, plan sequences
0.03% / 0.29%
deliverability itself is healthy — the problem is offer fit, not inboxing
Worst eligible slot
2985
the ONLY slot the Evolution Law permits changing in its sequence
Month ⇄ month rolling · generated by tools/finance/render_cockpit_funnels.py — never hand-edit inside the marker
Go deeper
🕰️The July turnaround briefHISTORICAL · 2026-07-29
The freeze-paid → instrument → fix-leaks → scale sequence, and what it committed to.
Open ↗
Jul 26 (complete) ⇄ Aug 26 (month-to-date, day 12) NET, combined rails · generated from data_revenue_per_month.json · pulled 2026-08-12 05:37
Rail (USD, NET) Jul 26 — fullAug 26 — to date
Stripe · web$21,426$2,585
Stripe · recovery cart$1,345$0
App · iOS$3,161
App · Google Play$976
Total $26,908$2,585

The app rows are blank for the current month by design — a store month is never read before it closes. Jul 26's total includes the lifetime sale; strip it before calling it a baseline.

Every month on the board so next month can be compared to something real
MonthNET, all rails
Mar 26$10,524
Apr 26$11,973
May 26$14,273
Jun 26$9,564
Jul 26$26,908
Aug 26$2,585

Current MRR $11,176 · web $7,771 / 538 subs · app $3,405 / 240 subs · cancel queue 106 worth $1,487/mo.

How the week runs ~10 h/week · from docs/company/GOVERNANCE/AGA_OPERATING_CADENCE.md · process, not data
Monday — the board block (~4h)
  • Open 🕹️ Console first. It is generated from the tracked queues — never hand-written — so a finished task cannot appear on it and a new one cannot hide from it.
  • Read 🎯 $15K: the gap, the pace, and which fleet moved. Then 🛟 Retention — churn is the binding constraint and every save is a sale nobody has to make.
  • Decide the week's one thing, and say out loud what stays frozen. One chain; everything else is "not now".
Three ~2h console sessions
  • Clear only AGA TODAY rows — the ≤3 the board ranks by cash-per-founder-minute.
  • Approve or reject what is waiting on a ruling. A blocked decision costs more than a wrong one.
  • Anything that turns out to be doable from code goes back to the fleet rather than onto her list.
Every tab now proves its own freshness

Each pane carries a machine-written as-of date taken from the data file it renders from, and cockpit_freshness_check.py fails the daily run if any tab is over its age budget or any "go deeper" link 404s. If a tab is on screen, it is inside budget — you no longer have to wonder whether a number is current, which is the only reason this page is worth trusting.

When a tab raises a question

Every channel now links to its deeper analysis from its own tab — the "Go deeper" rail. For a question the docs do not answer, run /growth-fleet in Claude: plan first, then execute. Decisions get recorded in the decision ledger so that in six weeks we can score whether the call was right, not just whether it felt right.

🧪 Paid — what is actually running, and what it actually sold Google Ads + Meta pulled live 11 Aug 2026 · envelope ~$3,175/mo across ALL platforms combined
Go deeper
📄Apple Search Ads — the real cost, at lastas of 2026-08-11
What ASA actually costs ($407/90d, $2.50/install), why only branded still runs, and why we still cannot claim a ROAS.
Open ↗
📄The remarketing playbookas of 2026-08-10
The Google + Meta retargeting build Nic works from, with every figure pulled live.
Open ↗
📄Paid advertising — the full pictureas of 2026-08-11
Every pound of paid spend and what it actually returned, both platforms, promo eras separated.
Open ↗
Spend MTD — both platforms
$896
Meta $425.81 + Google $470.89 · against a ~$3,175/mo envelope
Meta purchases, 1–9 Aug
0
£261.79 spent · three ACTIVE campaigns, all OUTCOME_LEADS
Google PURCHASE conv, 1–9 Aug
6
£330.25 spent · 73 of its 87 conversions are LEAD FORMS, not sales
Google Ads — every enabled campaign, 1–9 Aug live pull · GBP · 🔴 `conversions` and `all_conversions` are different columns and are never summed
CampaignSpendClicksConvWhat the conversions actually are
Quiz Funnel | Competitors Branded | US£103.035820all lead forms — zero purchases
Quiz Funnel | Competitive Non-Branded | US£83.67160nothing at all
Quiz Funnel | Non-Branded | US£83.45222lead forms only
Quiz Funnel | PMax | US£45.574421 lead forms · 3 purchases (£0 value passed)
Quiz Funnel | Branded | US£14.53102 purchases £72.05 + 1 phantom £297 (see below)
Total£330.25876 PURCHASE · 73 lead form · 2 install · 6 session
Meta — three ACTIVE campaigns, all lead-objective £261.79 spent 1–9 Aug for zero purchases · account act_710789699289834
QLG | ADV+ ON | US | Variant 2ACTIVEOUTCOME_LEADS
MOF - Lead Form 🔴ACTIVEOUTCOME_LEADS — dead sync since 1 Dec 2025
QLG | ADV+ OFF | MC | ControlACTIVEOUTCOME_LEADS

🔴 NEVER SUM META ACTION TYPES. Meta reports one conversion under seven labels (purchase / omni_purchase / offsite_conversion.fb_pixel_purchase / onsite_web_purchase / …) with identical counts. Summing them made every Meta number exactly DOUBLE until it was caught on 11 Aug 2026. Take exactly one. lead is the aggregate; offsite_conversion.fb_pixel_lead is a subset of it.

What this means for the next £1
  1. Google Branded is the only line with a real, current sale on it — £14.53 for 2 purchases at £72.05. It is also the cheapest. Brand defence stays.
  2. Competitive Non-Branded took £83.67 and returned nothing. That is the first candidate to cut, at keyword level, not campaign level.
  3. Meta is buying leads, not customers — 0 purchases on £261.79 — and one of its three live campaigns posts into a broken pipe. Fix the pipe or pause the campaign; do not keep paying for both.
  4. Do not raise the envelope to test any of this. £896 of a ~$3,175 envelope is unspent; the constraint is not budget.
📉 App engagement-retention — baseline is the truth GA4 property 177471782 · platform in (iOS,Android) · cohortActiveUsers + Stripe full-history pull 24 Jul (16,065 subs) + RevenueCat v2 · ✅ VERIFIED · as of 2026-07-24 · INTERIM (pre-bug-fix)
Go deeper
📄The retention planas of 2026-07-24
Why members leave, what each save lane is worth, and which lanes are armed.
Open ↗
ENGAGEMENT: D7 ~20% / D28 ~6%, stable a year; 50%-off cohort HEALTHIER; July lifetime install-wave TOXIC (cheap-geo). MONEY (24 Jul, SKEPTIC-VERIFIED): churn rate FLAT 11–15%/mo for 22 months — no plan deteriorated post-March (mix-shift attack FAILED); the March bug wave left no measurable dent ON STRIPE (IAP rail pre-May unreadable). Annual first renewal ≈32% (30–34%, billing-accurate) = LOW END of the 30–45% benchmark, NOT below it — the earlier 20.5% 'fire' was REFUTED (bad threshold + trial-cancels in denominator). The base shrank 1,204→703 because adds (~100/mo) < ends (~130/mo); the June revenue drop was ~80% shrinking-renewal-base. 🔴 DECISIVE OPEN QUESTION: was the Jun–Jul adds trough (paid adds 61/56, weakest of 22mo) Google-rail channel-shift or a REAL acquisition collapse? The −8%-blended claim rests on Google CSVs nobody has re-verified; RC's size (217 subs) makes full absorption doubtful. One query settles it: RevenueCat Charts → New Subscribers by Store, May–Jul (15 Aga-min).
ENGAGEMENT retention (did they reopen the app) — NOT subscription retention (that is RevenueCat), not wired to any money number. MONEY retention now separately verified: see judgment + money_retention block. Promo calendar: BF lifetime = Nov→3 Dec · Memorial 50%-off = late May · July-4 lifetime = 4–12 Jul. REPORTING LAW: exclude promo windows from baselines; report CASH beside MRR (lifetime sells as one-time — invisible to MRR); combined-rail view Stripe+Google Play+Apple; NEVER read RevenueCat history before May 2026 (backfill-contaminated). Full read: docs/company/ANALYTICS/NATIVE-APP/NATIVE_APP_DEEP_ANALYSIS_2026-07-20.md.
Cohort era D7 D28 n read
BASELINE — Feb–Apr 2026 (pre-promo)20%6%1,378the truth
Long-run check — early 202519%6%1,259stable a full year
May 50%-off26%7%807HEALTHIER than baseline (attracts intent)
July lifetime (4–12)11%0%4,282TOXIC — 15× volume, ~0% D28, cheap-geo dump
Baseline splits (the honest product retention):
iOS
GA4 ✅
24% / 7%
D7 / D28
Android
GA4 ✅
16% / 5%
D7 / D28
Paying geos (US/UK/CA/AU/DE/FR)
GA4 ✅
24% / 8%
D7 / D28
Cheap geos (IN/PK/ZA)
GA4 ✅
14% / 2%
D7 / D28
🩸 The cliff: D0 100% → D1 ~10% (blended, promo-polluted) → D7 2% → D14 1%. The first-session-to-second-session gap is where users are lost.
🧭 Judgment: RETENTION PRIORITIES (24 Jul, skeptic-corrected): P0 SETTLE THE JUNE QUESTION — RevenueCat Charts → New Subscribers by Store May–Jul (15 Aga-min): channel-shift vs real adds collapse; this decides whether the company's #1 problem is acquisition or slow-bleed retention. P1 Annual first-renewal sequence — ≈32% renew (low end of 30–45% bench, NOT a fire); T-45/30/7 pre-anniversary via /email-fleet (known coverage GAP) + year-in-review recap; honest size +$170–450/mo (32→35–40%), a MODEST compounding lever. P2 Stripe-portal cancel intercept (Nic 1–2h; 93% of cancellers see no save offer; SAVE30 exists; confirm webhook sync first). P3 R1 saves continue + 976 Cancelled Win-Back copy through fleet gates (6/7 CTAs fail QA today). P4 AUGUST = first clean funnel read; tripwire weekly PAID annual adds ≥20 unpromo'd (Jul true paid adds = 56, not 64 — 8 never paid). P5 D1 activation cliff (durable, RN/product, with CPO). INVOLUNTARY: absolute FLAT ~15 subs/mo (the 11%→18% share rise = denominator artifact — voluntary fell); config already OPTIMAL; operative recovery number = $-VALUE 20–30% and falling (46% is count-based/eventual — never use it to size dollars). Win-back stays reason-gated (price→ANNUAL SAVE30 $109.90 reply-based; no-time→pause; bugs→fix-not-discount).
D7 ~20% · D28 ~6% (engagement) · money churn FLAT ~13%/mo · annual renewal ≈32% (low-end bench) · 🔴 settle June adds: RC by-store export GA4 APP · ✅ VERIFIED · INTERIM
⚙️ 990 Monthly→Annual Upgrade Engine (Jul 2026)ARMED · 1 tagged · 0 converted · 8 eligible today (as of 2026-08-11 05:40)
📌 WHERE WE LEFT OFF (2026-07-24): 24 Jul 2026 deep-dive complete + skeptic-verified (artifact Parts 1–4). Established: churn FLAT 11–15%/mo for 22 months, no plan deteriorated (mix-shift attack failed); March bug wave = no dent on Stripe (IAP pre-May unreadable); base shrank 1,204→703 = the real revenue story; annual first renewal ≈32% (the 20.5% 'fire' was REFUTED — lever is +$170–450/mo, modest); promo calendar folded (BF lifetime ~$31.6K · Memorial 50% May · Jul-4 lifetime ~$19.5K, 53%-new = upper bound); Android billing switched Stripe→Google ~Feb–Mar 26. NEXT SINGLE ACTION = P0: RevenueCat Charts → New Subscribers by Store, May–Jul (15 Aga-min) — decides whether the Jun–Jul paid-adds trough (61/56, weakest of 22mo) was Google channel-shift or a REAL acquisition collapse, i.e. whether the CEO's #1 lever is acquisition or slow-bleed retention. Until answered: assert NEITHER story.
❓ Open questions — answer these before re-judging anything
statusquestionhow to settleowner · effort
P0Jun–Jul adds trough: Google channel-shift or REAL acquisition collapse? (paid adds 61/56 vs ~100 baseline)RevenueCat Charts → New Subscribers by Store, May–Jul 2026 (or Play Console financial report). June doc's '−8% blended' rests on unverified Google CSVs; RC's 217 total subs makes full absorption doubtfulAga · 15 min
OPENDoes RevenueCat ingest Stripe, or is it IAP-only? (decides if combined MRR ≈$13.5K gross is double-counting)RC dashboard → project integrations pageAga · 5 min
OPENPayPal rail — still live? (no PAYPAL_* key in .env.local; rail fully DARK)If active: create read-only REST app in PayPal dashboard, add keyAga/Nic · 10 min
OPTIONALAnnual renewal ground truth (≈32% is an approximation via current_period_start)Count 2nd paid subscription_cycle invoice ÷ cohort that paid a first annual (Claude, Stripe API)Claude · 20 min
OPTIONALJuly lifetime '53% new customers' = upper bound (guest-checkout email blind spot)Match the 62 charge emails vs app account email list — feeds the CFO/CXO lifetime-cadence decisionNic+Claude · 30 min
OPTIONALDid the March bug wave hit IAP/free users? (unprovable on Stripe; RC pre-May contaminated)RC Charts churn export Feb–Apr 2026 — treat with epoch caveatAga · 15 min
📋 Retention task queue (SoT: tools/retention/retention_status.json)
#taskowner · sizestatus
P-990990 Monthly→Annual Upgrade Engine (Jul 2026) went LIVE 3 Aug — READ THE RESULT at 14 days (by 17 Aug 2026). The one number 980 never captured: CONVERSIONS. 980 pulled 26.7–29.2% open and 3.44–4.93% click on 3,310 sends but zero conversion tags were ever written, so its payoff is still unknown. This run has the checkout link + UTMs (utm_campaign=990-monthly-annual-upgrade-engine-jul-2026) so clicks reach Stripe metadata. Decision at 14d: keep $157 as-is, or move the $129 Stage-3 rate earlier. Live counters in the ⚙️ band above.Aga (read) · 10 minOPEN
P0Settle the June question — RC 'New Subscribers by Store' May–Jul export. BLOCKS the CEO priority call (acquisition vs retention)Aga · 15 minOPEN
P1Annual pre-anniversary renewal sequence T-45/30/7 + year-in-review recap — via /email-fleet (renewal = known lifecycle coverage GAP). Honest size +$170–450/moClaude fleet → Aga approves · 2–3 hOPEN
P2Stripe-portal cancel intercept: point in-app cancel at portal login (SAVE30 loaded). PRE-CHECK first: Nic confirms webhooks sync portal un-cancels to app entitlementsNic · 1–2 hOPEN
P3aR1 voluntary saves: Seg A sent 20 Jul (30 emails, 0 saves yet — T-30 offers arm at expiry, too early to judge). Seg B/C question-send awaiting authorizationAga authorizes · 30 minWAITING-AGA
P3b976 Cancelled Win-Back — reason-matched copy through /email-fleet gates (6/7 current CTAs fail QA); reason tags already applied daily by machineClaude fleet → Aga · 2–3 hOPEN
P4August clean read: first unpromo'd funnel month. Tripwire = weekly PAID annual adds ≥20 (July true paid adds 56, not 64). No panic-reads of Jun–Jul before thenClaude monitors · —SCHEDULED
P5D1 activation cliff (D0→D1 ~10%) — durable product fix in RN app; route via CPO → NicCPO/Nic · largeBACKLOG
GOVLifetime cadence decision: each event ≈$20–30K instant cash vs MRR-multiple hollowing ('53% new' = ceiling). Board-level dialAga + CFO/CXO · board itemOPEN
FIXCockpit lost its RETTODAY markers (today-line now renders inside this block instead). Restore markers only if the one-line Today strip is wanted backcockpit owner · 5 minNOTED
📄 Full analysis (Parts 1–4, skeptic-verified): data/customer-analytics/CHURN_BASELINE_PRE_MARCH_2026_ANALYSIS_2026-07-24.md (Parts 1-3) · baseline: Jan 2025-Feb 2026, promo windows excluded: ~100 adds/mo, ~130 ends/mo, 13.5%/mo blended churn, quick ratio 0.76
🛟 Retention — the cancel-queue save (R1) LIVE — Wave A sent 20 Jul (24/24, 3 reason-aware variants) · state: tools/retention/R1_SYSTEM_STATE.md
📄Retention Plan — the full strategy (R1/R2/R3 + the churn levers)
The deep-dive behind this tab: exit-survey findings, the ranked churn levers, and the R1/R2/R3 save sequence. This tab is the R1 send tool; the plan is the why.
Open ↗
R1 sends from hello@, plain-text, replies land in the hello@ inbox — replies are the save + the reason data in one. The machine now runs daily at 05:35: T-30 watcher emails new cancellers automatically (reason-aware — 70 queue members' exit-survey answers are acknowledged, never re-asked), replies get logged + a Jesse-voice draft in Gmail, and the numbers below refresh. Nothing auto-sends to a member; Aga approves every reply. Keys are read-only; un-cancelling is done by the member (portal link) or in the Dashboard.
R1 emails sent
AUTO
59
Seg A 59 · B 0 · C 0 · T-30 watcher today: 1
Replies
AUTO
8
0 new today · 0 Jesse-drafts waiting in Gmail
SAVED
AUTO
2
$35/mo recovered · 32 expired unsaved
Queue now
AUTO
106
$1,493/mo at stake · A 26 · B 59 · C 21
Machine
AUTO
✓ ran 12 Aug 05:39
daily 05:35 · exit-survey re-synced (5050 rows, 0 new) · replies → drafts in hello@ · watchdog-monitored
🛒 Quiz-checkout abandonment paywall viewers who declined · patched every 30 min by quiz_abandon_sync.py · owner: tma-quiz-checkout-abandon-owner · register §2.6
Quiz-checkout abandoners
AUTO
117
30d window · $11,349 at $97 · paywall-view→buy 17.9%
In the sequence
AUTO
0
synced 112 all-time · enrolment NOT armed (sentinel absent)
Machine
AUTO
✓ ran 12 Aug 14:34
every 30 min · mode sync · buyer-check at every stage · guardian-monitored · owner: tma-quiz-checkout-abandon-owner
💳 Failed-purchase lane purchase attempts that died at checkout · patched daily 05:55 by failed_purchase_lane.py · register §2.5 ↗
Failed-purchase drafts
AUTO
0
drafted today · 9 touched all-time (9 people)
Seen in window
AUTO
22
distinct people with a declined purchase in the scan window (incl. skipped: paid / suppressed / other lane) · $2,673 attempted by those we wrote to
Recovered
AUTO
0
$0 paid after we wrote · outcome metric
Machine
AUTO
✓ ran 12 Aug 05:56
daily 05:55 · mode draft · drafts only, never auto-sends · guardian-monitored
Cancel queue (live)
LIVE
106
$1,487/mo at stake · R1 sent to 59
Seg A · ends ≤30d
LIVE
26
$402/mo · the urgent ones — send first
Seg B · 31–180d
LIVE
59
$810/mo · no offer — reason capture
Seg C · >180d
LIVE
21
$274/mo · no offer — reason capture
Do this — the exact list

All commands run from the repo root (/Volumes/T9/projects/the-movement-athlete). Emails go via the same Gmail pipe as your 7am cockpit email.

  1. Preview Segment A (sends nothing): python3 tools/retention/send_r1.py --segment A
  2. Test one to yourself, check it on your phone (main inbox not Promotions; plain text; reply goes to hello@):
    python3 tools/retention/send_r1.py --segment A --live --limit 1 --to hello@themovementathlete.com
  3. Send all of Segment A (the 31 urgent): python3 tools/retention/send_r1.py --segment A --live
  4. WAIT 48 hours, then score it: python3 tools/retention/check_saves.py — this is your no-discount save rate, the number that decides whether discounting is even worth it.
  5. Then send B and C: --segment B --live then --segment C --live
  6. Score again at day 7 and 14: python3 tools/retention/check_saves.py
  7. If someone replies "it's the price": in Stripe, add coupon SAVE30 (30% off, duration once) to their existing subscription. Never send them a checkout link — it makes a 2nd subscription and double-bills them.
The three findings that reshaped R1
1 · QUEUE

The queue is mostly not urgent. 85 annual, 20 quarterly, 7 monthly — median 110 days of paid access left; only 31 end within 30 days. So B and C get no offer, just one question ("what made you turn renewal off?") — selling to someone paid through next spring reads as tone-deaf, and lapsed annual subs reactivate at only ~5% (RevenueCat). Their save offer fires automatically at T-30 via pre_expiry_watch.py.

2 · OFFER

Not 70% off — 30%. Your exit survey (3,704 price responses): 64.8% would pay nothing; of those who named a price, 78% said ~$9.97/mo ≈ a 24% discount. 70% gives away 3× what's needed and dilutes the MRR a buyer underwrites. Ladder: split the annual lump to monthly (no discount) → 30% next renewal only → 50% hardship on reply. Churnkey's own data: ~89% of discount-saved still churn within a year — so cap the depth.

3 · PAUSE

Pause rejected, with data. Only 7 of 676 web subs are monthly (the queue has 7) — pause is meaningless to an annual subscriber. And Stripe removed self-serve pause from the Customer Portal (no subscription_pause feature exists). Handle pause manually on reply; revisit only if the reason data shows real demand. No app release needed for any of this.

Two things you should know
DONE

Your Stripe portal is already live — the un-cancel link (billing.stripe.com/p/login/…) is in every R1 email, so members can turn renewal back on themselves. It does NOT touch your app backend — it writes to Stripe only; the app learns via webhooks (Nic's side). Safe for R1: renewing changes nobody's access today (they're all active + prepaid).

NIC · 1 ticket

Your cancel button is custom, not the Stripe portal — which is why only 7 of 112 cancels carry a reason (those 7 used the portal). Ask Nic to either route the cancel button through the Stripe portal, or write the cancel reason into Stripe cancellation_details via the API. That's what makes reason-capture + the auto save-offer work for everyone, not just this backfill. Leave "plan switching" OFF in Stripe until Nic confirms he consumes webhooks (it changes live subs and would desync entitlements).

Honest expectation: R1 recovers maybe $50–100/mo of Segment A's $503, plus whatever the T-30 trigger saves over the year. Worth doing, cheap, and it captures the reasons we're blind on for 93% of cancels. But the 4,434-response exit survey says the #1 churn lever is fixing app bugs (16% of cancels, 35% of "what would make me stay") — that's the RN team, and it's the real fix. Full context: tools/retention/AGA_RUNBOOK.md · strategy: Retention Plan ↗
Generated by tools/ops/aga_console_sync.py v2 · 2026-08-12 14:31 MDT · merged from every fleet queue + the analytics brief. Never hand-edit inside the CONSOLE markers — edit the fleet's own status file (or the brief) and re-run.
⚠️ 2 CLOSURE(S) WITHOUT A RESOLUTION — a defect closes on a re-verified artifact, never on intent: AGA-66 · FLEET-20
🤖 WHAT RAN WITHOUT YOU (last 24h) — 126 logged fleet action(s) · 33 scheduled jobs healthy
[P0 PM / fold-in batch] Folded the 12 Aug plan into Aga's to-do page per her instruction. Rewrote 7 stale walkthroughs in build_todo_page.py so the page never re-asks a given GO:… 08-12T14:26
[ops/hosting] Built Nic's ONE to-do list, generated from the queue. tools/ops/build_nic_todo.py renders owner=NIC from SEO_HUMAN_QUEUE.json: 11 live (impact desc, quickest… 08-12T14:25
🟡 [ops/operating-review] P5 DRAFT written for Aga's approval (nothing executed): docs/company/GOVERNANCE/TOP_TIER_LAW_DRAFT_2026-08-12.md. All 51 root-index top-tier rows dispositioned… 08-12T14:22
[ops/hosting] Staged the 3 orphaned documents on Aga's GO ('yes stage them, i want them accessible in docs') and repaired the estate's cross-doc links. paywall-annual-ab,… 08-12T14:16
[ops/hosting] Fixed the silent link breakage on the consolidated docs site. Consolidation re-homes each doc from a site root to /<name>/, which breaks its own absolute AND… 08-12T14:08
[ops/operating-review] P3 + MECHANISM 2 SHIPPED. P3: built .claude/hooks/hard-law-gate.sh — the first Stop gate for laws where an instruction is the wrong tool (Anthropic: 'the model… 08-12T14:08
[app-funnel / Android sign-in] Closed out the Android sign-in investigation and wrote the LLM handoff. Verdict: NO blocking defect exists - the door works (3 taps/25s, confirming NIC-94… 08-12T14:05
[P7 Search — SEO master doc updated (§12.17-F)] Aga asked for the SEO master to be updated. Wrote §12.17-F into the canonical living master (marketing/seo/TMA_SEO_GEO_ANALYSIS_AND_PLAN_2026-07-20.md) — the… 08-12T14:05
[P2 Email / paid-lead recovery] 🔴 FOUND THE THING THAT REFRAMES THE WHOLE MAGNET, by reading the Meta lead form's own thank-you object rather than assuming. The form does NOT deliver the… 08-12T14:03
[ops/operating-review] P2 SHIPPED — procedures relocated out of CLAUDE.md into their canonical homes. Method (relocation, never deletion, per Anthropic's 'context is never cruft'):… 08-12T14:01
[P2 Email / paid-lead recovery] Drafted the single recovery email for the 237 Facebook lead-form signups and it PASSES email_lint.py (all checks: locked footer, white canvas, dark-mode… 08-12T13:57
[ops/operating-review] WEEK 1 SHIPPED on Aga's GO (cap=15 approved). (1) P1: de-@-imported docs/DOCUMENT_MAP.md from CLAUDE.md — static preload 159,897 -> 87,386 B, ~23,400 tokens… 08-12T13:53
[P0 PM / FLEET-53 diagnosis] FLEET-53 SOLVED (read-only diagnosis agent): tag 237 Engaged is a rolling 28-day window maintained by AC 754 Part 1 - Engagement Tagging + 755 Part 2 -… 08-12T13:52
[P0 PM / Aga list pass 12 Aug (batch 2)] Executed Aga's three GOs + two page builds. (1) AGA-164 Stripe cancel ATTEMPTED — blocked by design: repo key is read-restricted (no Subscriptions Write);… 08-12T13:49
Jobs are watched for you: the every-30-min guardian restarts missed jobs and emails a 🔴 (Cc your Gmail) only when a real failure survives restarts; 🟠 FYIs stay in hello@. The 06:30 watchdog separately checks the numbers pipeline, and your 05:55 email carries the 🤖 Jobs line either way — so the daily line, not silence, is the signal. Guardian stamp: 2026-08-12T14:21
💰 Where the money is — pace $8,159 of $15,000 (54.4% · gap $6,841/mo)
● The call — what's binding today: RETENTION
Churn is out-running sales — 57 lost vs 35 won in 7d, and cash pace is 54% of $15,000. Every save is a sale you don't have to make.
🏁 Fleet scoreboard — KPI · 90-day goal · live valuehorizon 2026-10-29 · 78 days left · clock 2026-11-01
Definitions live in FLEET_CHARTERS.json; every "now" value below is read from its source file at render time — the scoreboard cannot quote a stale charter. DARK means the fleet's first goal is lighting the metric, per Aga's ruling.
FleetNow (live)90-day goalByEst. cash/moTagOpen
🎯 Funnel / CRO
tma-funnel-cro-lead
annual 48.4% · $92.4/saleCASH — annual_share_pct >= 402026-10-29$2,100–2,200LIVE
🛟 Retention & CS
tma-retention-lead
82 cancel-ends MTD · $1,184 MRR lostCASH — cancel_end_mtd <= 852026-10-29$600–800LIVE8
🔍 Search (SEO · AEO · GEO)
tma-seo-growth-owner
70 owned-content leads/28d (artefact until ~12 Aug)LEAD — content lanes >= 80 per 28d (post-rebaseline)2026-10-29$200–350LIVE·healing53
💰 Paid Ads
tma-growth-cmo
$1,071 vs $3,000 cap · CPT UNCOMPUTABLEWIRING — CPT measurable by 2026-08-22, then CPT < $20 within cap2026-08-22$0 (gate)DARK on CPT14
📧 Email / Lifecycle
tma-email-lead
revenue DARK · 2,445 engaged-reachable · bounce 0.03% · unsub 0.29% (cumulative, plan sequences)WIRING — email revenue attributable by 2026-08-29; growth target set 1 Oct2026-08-29$500–900DARK on revenue4
📱 Organic Social (TMA)
tma-social-growth-owner
486 organic web sessions/28d vs 1,200 target · 7 leads (real, tiny — a lead target is re-set after 4 clean weeks) · saves/reach 0.29% vs 1.00% ⚠️ the distribution lever · (128 PAID leads moved to P1 — they were never organic)DISTRIBUTION — organic web sessions ≥1,200/28d AND saves-per-reach ≥1.0%2026-10-29$0 (gate)REBASELINED3
🤝 Partnerships & Affiliates (both directions)
tma-partnerships-growth-owner
≈£275/mo net (bank-traced 25 Jul — STATIC, no live source)CASH — net contribution ≥ £275/mo + 6 placements2026-10-29$100–150STATIC
📊 Analytics / Data Truth
tma-analytics-lead
dark share 24.2%/28dWIRING — dark_share_28d <= 152026-10-29$0 (gate)LIVE
Honest sum of the goals: $3,500–4,400/mo against the live gap on the 🎯 $15K tab — it does not fully close the gap on these alone; that is stated, not smoothed. Capability fleets (Council · Design · QA · Trainer · Mobility · Static Ads · Forge/Ath · Outreach) carry gates, not numbers, and reach this console by exception only — full detail: docs/company/GOVERNANCE/FLEET_CHARTERS.md.
📋 The one list — every HUMAN task, every fleetFLEET-owned work is excluded by definition · impact desc, quickest first
🔴 89 open human items vs the ~10 the console is designed to hold. The ratified rule: promote routine work to T2 standing playbooks and close what no longer earns its place — never skim faster. Board agenda item.
#TaskOwnerFleetTimeImpact
1
AGA-146
🟢 GO/NO-GO: mail a 500-contact test segment of the 6,813 app-side contacts who finished the survey but never did a workout (NP verdict lever 1, $0,…
full detail →
🟢 GO/NO-GO: mail a 500-contact test segment of the 6,813 app-side contacts who finished the survey but never did a workout (NP verdict lever 1, $0, ranked DO-FIRST). The fleet drafts the activation email through /email-fleet + segment_guard.py and shows you the rendered email + segment PASS before anything sends — this row is only your GO to draft-and-show. Rates behind it are MODELLED (skeptic-flagged): read the 500-test click rate before touching all 6,813.
AGAP7 Search5 min●●●●●
2
AGA-147
🟢 GO/NO-GO: give '758 Nurture Sequence 2' (14,600 contacts) a quiz-root CTA slot — NP verdict lever 2, $0 ('fix the tap before the bucket'). Email…
full detail →
🟢 GO/NO-GO: give '758 Nurture Sequence 2' (14,600 contacts) a quiz-root CTA slot — NP verdict lever 2, $0 ('fix the tap before the bucket'). Email currently sends the $97 quiz ~1 lead/8 days while 14 sales came from everywhere else. SISTER ROW to AGA-129 (weekly broadcast repoint) — one GO can cover both. Evolution-Law compliant path: ONE slot change through /email-fleet, not an arc rewrite; fleet executes end-to-end on your GO.
AGAP7 Search5 min●●●●●
3
AGA-168
🧲 DECIDE: THE 10th LEAD MAGNET HAS 232 SESSIONS/28d AND NO WAY TO CAPTURE AN EMAIL. Measured live 12 Aug on…
full detail →
🧲 DECIDE: THE 10th LEAD MAGNET HAS 232 SESSIONS/28d AND NO WAY TO CAPTURE AN EMAIL. Measured live 12 Aug on themovementathlete.com/get-started-with-calisthenics/: the opt-in form's container is switched OFF on desktop, tablet AND mobile (the block source says UAGHideDesktop/UAGHideMob/UAGHideTab all true — deliberate, not responsive), so the rendered page has ZERO visible email inputs; the only visible form is the site search. Traffic is real and EXACT-matched: 232 sessions/28d, 442/90d. The page still routes people out via three quiz-root CTAs, so it is not converting nothing — it simply cannot take an email. 🔴 IT CANNOT JUST BE SWITCHED BACK ON: the form has NO destination configured (no afterSubmitAction, no confirmationType, no webhook, no email target on its 36 attributes; no Spectra entry store; and no Spectra submission has ever reached hello@ — the only 4 'Spectra' emails there are WP Engine vulnerability notices). Unhiding it alone would show visitors a form that silently discards them, which is worse than today. YOUR CALL, three options: (a) WIRE IT — I build the destination (AC via API + UTM hidden fields from the start) and then unhide, so it captures with source attribution from day one; (b) MOVE IT to Leadpages, matching the other 9 magnets, one consistent rail; (c) LEAVE IT OFF and let the quiz-root CTAs do the work, and I retire the dead form so nobody re-discovers this in three months. My recommendation is (a) if you want the email list to grow from content, (c) if the quiz is the only funnel you want to maintain — the honest case for (c) is that the page already routes to the quiz and a second capture path is another thing to keep alive. ⚠️ SIZE HONESTLY: at a typical 20-40% magnet opt-in this is [MODELLED] ~45-90 leads/28d, but that rate is an industry assumption, NOT measured on this page — the page has never captured, so we have no rate of our own.
AGAP7 Search5 min●●●●●
4
NIC-106
🔴 REPOINT 'QLG | ADV+ OFF | MC | Control' TO THE QUIZ ROOT — 5 min in Ads Manager. All 4 of its live ads still land on…
full detail →
🔴 REPOINT 'QLG | ADV+ OFF | MC | Control' TO THE QUIZ ROOT — 5 min in Ads Manager. All 4 of its live ads still land on https://quiz.themovementathlete.com/2026/ the old page that does NOT show the 97 dollar offer. Change the destination on all four to https://quiz.themovementathlete.com/ (the ROOT). Nothing else: leave url_tags, budgets, geo and the objective exactly as they are, and do NOT pause the campaign. EXACT LIST — adset 'General / T2 / FM 30-54 US/Canada' (GBP 9.62/day, geo US+CA): ad 120253084939360728 and ad 120253084939340728. Adset 'General / T2 / FM 30-54 AUS, FR, UK SING, NZ' (GBP 9.62/day, geo NZ GB IL AU FR): ad 120245527336080728 and ad 120245527336070728. WHY THIS AND NOT A PAUSE — measured live 11 Aug on the Meta API, 30 days, unified attribution: MC Control produced 129 leads at GBP 2.43 each, the biggest lead source on Meta (56% of the two QLG lines' 230 leads; 57 in the last 7 days). Pausing would cut Meta lead volume by more than half in the window we are banking leads for Black Friday. Repointing keeps all 129 leads/month and sends them to the page that shows the 97 AND enrols them into 993 SALES SEQUENCE, whose 10 Sep gate the whole paid plan waits on. Zero cash change either way — the account's daily budget is GBP 45.48 before and after. This is also exactly what Aga's 10 Aug ruling asked for ('RE-AIM into the ONE geo-locked lead line, quiz root'); NIC-97 was built as a clone, which the spec allowed, so MC Control itself was never touched. TWO OPTIONAL EXTRAS while you are in there: (a) drop IL from the second adset's geo — Israel is the only country in this campaign not on the buyer list (US UK CA AU DE SE NL FR); (b) pause the third adset 'General / T2 / FM 22-65 North America' — it holds a GBP 7.00/day budget but all SIX of its ads are paused, so it cannot deliver and spent GBP 0 in the last 7 days. Hygiene only, frees nothing. VALIDATION (2 min): after saving, open each of the 4 ads' preview and confirm the click goes to the quiz root and lands on the page showing the 97 offer, then confirm the campaign is still ACTIVE and its daily budget is unchanged at GBP 9.62 + 9.62.
NICP7 Search5 min●●●●●
5
AGA-139
🔴 TELL THE PHP DEV: calisthenicsacademy.co's Divi is 4.4.8 — the "only PBE" assessment is WRONG, and upgrading PHP first will break the site.…
full detail →
🔴 TELL THE PHP DEV: calisthenicsacademy.co's Divi is 4.4.8 — the "only PBE" assessment is WRONG, and upgrading PHP first will break the site. Measured live 10 Aug: the ACTIVE THEME on CA is Divi 4.4.8, and Elegant Themes only added PHP 8.0 support in Divi 4.8 — so the theme predates PHP 8 support by four minor versions. Page Builder Everywhere is real but is NOT the only blocker and is the smaller one (its entire footprint is ONE copyright line in one widget area — the widget is Divi's own, so it moves to Divi's native empty Footer Area #1 and PBE deactivates; no replacement plugin). Likely cause of the wrong assessment: BWA runs Divi 4.27.7 (per NIC-14), so a check done there would look clean — CA was never separately verified. ⚠️ We CANNOT read PHP version from outside WP Engine, so I cannot tell you what PHP CA is on today — ask the dev. THE ASK: before the dev touches PHP on CA, they update Divi first (Elegant Themes Updater is installed and active — needs the ET API key, so confirm the Divi licence is still live), and ideally the whole job moves onto Rocket staging as part of the migration instead of running on the live site. Full plan, plugin disposition table and verification commands: docs/company/HOSTING_MIGRATION_2026-08/CA_PHP8_DIVI_UPGRADE_ADDENDUM_2026-08-10.md
AGAP7 Search10 min●●●●●
6
AGA-161
🏋️ ONE BUILDER VISIT, ~10 MIN — THE WORKOUT-1 EMAIL + 2 CONDITIONS. 🔴 CORRECTED 12 Aug: part 2 is ONE arc, not two. The highest-intent moment in the…
full detail →
🏋️ ONE BUILDER VISIT, ~10 MIN — THE WORKOUT-1 EMAIL + 2 CONDITIONS. 🔴 CORRECTED 12 Aug: part 2 is ONE arc, not two. The highest-intent moment in the funnel carries no email at all — the morning after someone's FIRST workout (~48 people/day). My side is built and seeded: a nightly job reads Intercom, finds everyone whose workout count went 0 to 1, excludes payers four ways, and stamps the tag "workout1-yesterday" by ~03:30. The tag is the bridge — ActiveCampaign never has to see the app. What it cannot do is create an automation or add a condition. YOUR SIDE, three things in one sitting: (1) NEW AUTOMATION: trigger 'Tag workout1-yesterday is added' (Runs: Once) -> Wait until 8:00am contact time -> Send an email -> End. Use a PLACEHOLDER for the email (any template, subject 'W1 morning after', save and close) — do NOT open the designer; send me the automation id from the URL and I write the real body in by API, same as every email this week. Leave it Inactive. (2) On 750 TMA | Welcome Sequence After Quiz ONLY, add a goal block — copy the existing 'If customer - END' one — with the condition 'has tag workout1-done', which ends the automation. Its whole job is getting them to workout 1, so once they train the job is done, and two of its slots turn false (W3 'how did your first workout feel?' and W4 'have you pressed start yet?' would ask someone who trained yesterday whether they've started; W7's trial ask would repeat the morning-after email's ask days later). 🔴 992 and 967 are deliberately LEFT ALONE — doing a workout is not the same as being measured, so their 'get measured free' argument survives activation and neither contains a 'have you started yet' nudge. (3) AGA-145's promo-opt-out exclusion on 993 SALES SEQUENCE — same condition class, 2 min, and it is live with 121 people in it. Tell me the automation id and I do the rest.
AGAP7 Search12 min●●●●●
7
RN-01
📲 RN TEAM — IN-APP PAYWALL UI REBUILD. Sent to the RN devs 5 Aug; awaiting their estimate then build. 🔴 THE LINK TO SEND (standalone dev site, 6 Aug…
full detail →
📲 RN TEAM — IN-APP PAYWALL UI REBUILD. Sent to the RN devs 5 Aug; awaiting their estimate then build. 🔴 THE LINK TO SEND (standalone dev site, 6 Aug — the claude.ai artifact links died twice; Aga ruled the handoff gets its OWN site, never a page under the revenue plan): https://tma-paywall-brief.netlify.app/ — the brief; it links the design contract (/spec.html) and the package zip on the same domain. All three verified live 6 Aug. Scope is UI-ONLY across ALL THREE existing pricing pages (full price / 30% off / 50% off) — RevenueCat, purchase, restore, terms and analytics already wired; offers already configured. Estimate 5h max in 6 milestones. THE ASK ON THEM: all three pages on the ONE component via variant='full'|'off30'|'off50', not three rebuilds — three drifting copies is how the current bug survived, and separate rebuilds roughly double the cost. WHAT TO WATCH FOR ON RETURN: (1) no price literal anywhere in the UI — every figure derived from the store product at render time, retry state if offerings fail; (2) they confirm the estimate BEFORE starting rather than pushing past 5h; (3) the on-device pass includes a NON-USD currency, the actual defect being fixed. Also in the package: 7 broken strings below the fold. NOT in scope (Aga, 6 Aug): the RN-1 identity + push add-on — Nic is already working on those.
RNP7 Search15 min●●●●●
8
AGA-119
💷 THE ANNUAL OFFER TO THE ENGAGED — 🔴 DO NOT APPROVE YET, THE AUDIENCE HALVED. Measured live 11 Aug via the AC API: tag 237 'Engaged' holds 2,912…
full detail →
💷 THE ANNUAL OFFER TO THE ENGAGED — 🔴 DO NOT APPROVE YET, THE AUDIENCE HALVED. Measured live 11 Aug via the AC API: tag 237 'Engaged' holds 2,912 people, not the ~6,367 this row claimed and not the 6,038 the 31 Jul trust audit recorded — it has more than halved in 11 days and NOBODY HAS DIAGNOSED WHY (FLEET-53, taken by the fleet). That number is the denominator of the whole prize, so the modelled +$898/mo roughly halves with it. Two other things must clear first: (1) the draft DOES NOT EXIST — FLEET-07 is still open, so there is currently nothing for you to approve; (2) the unsub gate is still marginal (967 at 0.51% vs the 0.5% hardstop on today's scoreboard). Your decision when it reaches you is ONE thing: which week it sends, sequenced against FLEET-38 (50%-off falsifier) and AGA-118 (warm pool) — never the same week as either.
AGAP7 Search20 min●●●●●
9
AGA-129
📧 APPROVE: POINT ONE WEEKLY EMAIL AT THE QUIZ ROOT — one link decision in one already-scheduled send to the engaged list, CTA →…
full detail →
📧 APPROVE: POINT ONE WEEKLY EMAIL AT THE QUIZ ROOT — one link decision in one already-scheduled send to the engaged list, CTA → https://quiz.themovementathlete.com/ (root, UTMs per the link rule). Evidence: email produced exactly 1 quiz lead in 8 days and it landed on the DEAD 2026-v2-3 build (via 967 TMA | Welcome Sequence After LEAD MAGNET E2); ~14,600 sit in 758 Nurture Sequence 2 with no priced offer; 4 of the 8 provable $97 buyers came from owned surfaces — our highest-converting traffic, free. Flow on your yes: /email-fleet drafts it → lint gate → you see the RENDERED email → you approve the send. To-do #4 of the quiz-funnel CEO doc §19.
AGAP7 Search20 min●●●●●
10
AGA-134
🚀 APPROVE THE WELCOME PERSONALISATION DESIGN (W-D1–W-D4) — the abandonment engine extrapolated to the email estate, welcome sequence first. Read the…
full detail →
🚀 APPROVE THE WELCOME PERSONALISATION DESIGN (W-D1–W-D4) — the abandonment engine extrapolated to the email estate, welcome sequence first. Read the artifact (~20 min) and reply GO/amend on four calls: (D1) the personalised welcome deploys as a NEW automation + atomic entry-trigger swap replacing 750 TMA | Welcome Sequence After Quiz under the EVOLUTION LAW — THIS ROW'S ID IS THE WRITTEN OVERRIDE the law requires; (D2) stage-branched start — non-checkout leads get E1 at ~T+2h, only NEW quiz-reached-checkout waits to day 3–4 (refines your 4 Aug ruling; only they are in the $97 conversation the abandonment estate owns); (D3) the welcome ask = soft free-trial at E5 per SPEC-WELCOME doctrine, the $97 conversation stays the abandonment estate's (offer-ladder ruling — yours); (D4) instrument = 50/50 concurrent split (the AGA-64 manual AC setup) over swap+confounded pre/post. Doc: docs/company/ANALYTICS/WELCOME_PERSONALISATION_ENGINE_EXPANSION_2026-08-07.md · artifact: https://claude.ai/code/artifact/9bd17095-a7ac-4cca-be28-c5a5340d690a
AGAP7 Search20 min●●●●●
11
AGA-142
🔴🔴 ROTATE 3 PASSWORDS SITTING IN PLAINTEXT IN THE REPO — and remove a stale WordPress admin. Found 10 Aug in SUPPORT/Ca SUPPORT SOPs.txt (~20…
full detail →
🔴🔴 ROTATE 3 PASSWORDS SITTING IN PLAINTEXT IN THE REPO — and remove a stale WordPress admin. Found 10 Aug in SUPPORT/Ca SUPPORT SOPs.txt (~20 password lines, Calisthenics Academy era). ✅ CONTAINED: the file is tracked locally but I verified it is NOT on origin/main — it was never pushed, same shape as the July token.json find. I have added SUPPORT/ to .gitignore, which stops it reaching a remote but does NOT fix an already-committed secret — only rotation does, and history rewriting is hard-forbidden here. THE LIVE EXPOSURE, in priority order: (1) 🔴 jeffcowancc@gmail.com — its password is in the file AND that Gmail is currently an ADMINISTRATOR on calisthenicsacademy.co (WP user calisthenicsacademy-2). Anyone with that password can password-reset their way to full control of the site. Change the Gmail password, and tell me if that admin account should be REMOVED from WordPress — it is the old CA support person and I did not delete a user without your word. (2) The Drift and UserEcho logins for hello@calisthenicsacademy.co — both services we no longer use, so cancel rather than rotate. (3) An Intercom login on hello@themovementathlete.com — Intercom IS live and carries the app funnel data, so rotate this one properly. ALSO WORTH KNOWING: developer.mrski@gmail.com is a live administrator on that site — correct while the PHP work runs, worth removing when it finishes.
AGAP7 Search20 min●●●●●
12
AGA-118
📨 EMAIL THE ~1,020 WARM POOL (90d: ~570 saw the paywall + ~450 clicked buy, never paid) — the free version of the best paid audience we own, and it…
full detail →
📨 EMAIL THE ~1,020 WARM POOL (90d: ~570 saw the paywall + ~450 clicked buy, never paid) — the free version of the best paid audience we own, and it has NEVER been sent. Re-verified 6 Aug: newest AC broadcast with real volume is 24 sends (4 Aug) — nothing at this scale exists in the campaign log. Copy through /email-fleet; MUST pass tools/retention/send_collision_check.py and the broadcast-cadence doctrine before send.
AGAP7 Search45 min●●●●●
13
AGA-103
💷 THE CUT LIST — ~1h of clicking for ~$1,650-2,180/mo of certain recurring cash. Every one of the 17 fleets points at revenue; NONE points at cost.…
full detail →
💷 THE CUT LIST — ~1h of clicking for ~$1,650-2,180/mo of certain recurring cash. Every one of the 17 fleets points at revenue; NONE points at cost. The 5 Jul CFO Master Report found £2.9-4.3K/mo recoverable 'without cutting people or growth' — it has sat in a folder called RESCUED_TEMP_DOCS, is not in DOCUMENT_MAP, and has generated ZERO queue rows in a month. List is ranked and dependency-checked: TIER 1 = 6 clean kills, £533/mo, ZERO repo references (Kajabi 187 · Atlassian 130 · The One Percent 74 · Envato 71 · Paddle Retain 37 · Typeform 34). TIER 2 = one question each, £700-1,100/mo — 🔴 AWS £296/mo is the highest-value 5 minutes: the app runs on DigitalOcean and NOTHING in the repo references AWS. TIER 3 = Intercom £221, a real conflict needing your ruling (CFO says kill; canonical_strategy.settled says 'Don't drop Intercom' — but that ruling was made without the cost number in front of it). 🔴 I CHANGED 3 CFO VERDICTS: Tapfiliate £66 = KEEP, it returns ~£275/mo net (killing it would have destroyed 4x its cost); WP Engine already superseded by the Rocket.net decision (~£260/mo, own track); Intercom escalated not actioned. Confirm every cut on the NEXT STATEMENT, never the cancellation screen.
AGAP7 Search60 min●●●●●
14
NIC-101
🔴 MAKE THE IN-APP CANCEL DOWNSELL PLAN-AWARE — annual leavers are shown a WORSE deal than our own standing offer. Measured 11 Aug: 84 of the 115 in…
full detail →
🔴 MAKE THE IN-APP CANCEL DOWNSELL PLAN-AWARE — annual leavers are shown a WORSE deal than our own standing offer. Measured 11 Aug: 84 of the 115 in the cancel queue are ANNUAL, and every canceller sees $9.99/mo. That is $119.88/yr, and MEASURED over 516 people who ever took it (493 cancelled): median life 2.0 months, $34/taker — against annual-at-50% = $78.50. It defers churn by two months at 40% of the price. (1) BRANCH THE CANCEL DOWNSELL ON PLAN: annual → the 50% annual save; monthly/quarterly → keep $9.99/mo (price nine-ninetynine). 🔴🔴 MECHANISM — CORRECTED 11 Aug, READ THIS: the save at cancel-time MUST be a COUPON APPLIED TO THEIR EXISTING SUBSCRIPTION (a 50%-off duration=once coupon such as tma_v3_50off_once, so their next renewal bills $78.50 and auto-renew stays on) — NEVER a checkout link. At the cancel moment they STILL HOLD AN ACTIVE SUBSCRIPTION (88 of 115 have access, median 106 days), so a fresh checkout opens a SECOND subscription and DOUBLE-BILLS them. This is the exact defect the 10 Jul R1 rebuild already caught with /50promo/. The checkouts-v3/50off/12month/ link is correct ONLY for the truly-lapsed (access ended), i.e. the 976 Cancelled Win-Back arc — not for this screen. (2) ANSWER WHAT WE CANNOT SEE: does subscription_cancelled fire at renew-off (access still paid) or at access-end? (3) 🔴 IF PAUSE IS EVER BUILT it needs ENTITLEMENT GATING: Stripe's pause_collection leaves status=active, so an app gating on status alone grants FREE ACCESS — and portal subscription_pause reads enabled=false and is deprecated, so the real path is native POST /subscriptions/{id}/pause. Note the 10 Jul finding that our web cancel button is CUSTOM, not the Stripe portal, so portal settings do not govern this screen.
NICP7 Search1.5h●●●●●
15
E11
756/757 Abandoned Cart Reminder — UPLOAD THE 4-EMAIL 2026-08 ARC INTO FRESH SHELLS. 🔴 CORRECTED 7 Aug 2026: this row previously described the RETIRED…
full detail →
756/757 Abandoned Cart Reminder — UPLOAD THE 4-EMAIL 2026-08 ARC INTO FRESH SHELLS. 🔴 CORRECTED 7 Aug 2026: this row previously described the RETIRED July build (3 emails, AC field 56, %ABANDONED_CHECKOUT_URL%, entry off the 'Subscription Cart Abandoned' tag 63598). That artefact is dead — its Stripe trigger (checkout.session.expired) can never fire on Payment Element, and tag 63598 is now orphaned. THE LIVE ARTEFACT is marketing/email-sequences/quiz-checkout-abandon-2026-08/ (E1-E4, lint PASS 4/4, %TMA_QUIZ_PERSONA% conditional content, API entry via quiz_abandon_sync.py). Both current shells are UNUSABLE: 756's email lacks an unsubscribe link + renders raw markdown, 757's four emails are EMPTY (subjects r/r/e/e) — Aga paused both 5 Aug. So this is: fleet hands over the personalised rebuild (FLEET-42), Aga builds 4 FRESH shells and un-pauses 756 only. E3/E4 wait on the $97-window enforcement decision (AGA-109). Plan: ABANDONMENT_STRATEGY_2026-08-07.md sections 5.2 + 7.
NICP2 Email●●●●●
16
SOC-1
Nic S2 token (4 scopes) → IG + FB per-post flip LIVE on the boardNICP3 Social●●●●●
17
BRIEF-5
T5 — Fix the AppsFlyer conversion events ★ highest leverageNICNic wiring (brief)●●●●●
18
BRIEF-8
GA4 → Google Ads conversion import ("Task 3" in the 16-Jul message)NICNic wiring (brief)●●●●●
19
BRIEF-17
T4 — One canonical user identity across all SDKs the keystoneNICNic wiring (brief)●●●●●
20
AGA-157
🟡 HOLD UNTIL 13 AUG, THEN 2-MIN GO/NO-GO (fleet executes by API): set-level negatives on 'Quiz Funnel | Competitive Non-Branded | US'. 🔴 DO NOT RUN…
full detail →
🟡 HOLD UNTIL 13 AUG, THEN 2-MIN GO/NO-GO (fleet executes by API): set-level negatives on 'Quiz Funnel | Competitive Non-Branded | US'. 🔴 DO NOT RUN THIS BEFORE 13 AUG — Nic did the keyword surgery on 11 Aug (change log: 14:36:02 bid changes on 5 keywords in this campaign; 20:15:17-24 the 3 remaining spenders PAUSED — both halves of what was asked), and writing negatives on top of it would make his round unreadable. Two clean days (12-13 Aug) belong to him. THE READ ON 13 AUG: spend holding at ~GBP 6-9/day on hardware search terms → the set-level fix is needed, GO this row; a material sustained drop → his round worked, stand this row down and let the campaign have its clean fortnight to the 24 Aug gate. WHY THE ROW EXISTS REGARDLESS OF THE READ: 30-day totals are GBP 235.89 / 32 clicks / 0 conversions AND 0 all-conversions while both siblings converted (Competitors Branded GBP 311.57 → 24, Non-Branded GBP 241.33 → 6); all 60 still-enabled keywords are equipment phrases; the campaign carries ZERO negatives and ZERO shared negative lists; and the money has been buying 'backyard calisthenics setup' GBP 9.94, 'outdoor calisthenics gym' GBP 8.46, 'wooden parallettes calisthenics' GBP 7.91, 'parallettes' GBP 6.00, 'gornation pull up bar' GBP 4.77, 'dip bar for home' GBP 3.26 — hardware shoppers, and we sell a programme. The one round already readable is 7 Aug: it had four clean days after it and spend continued (GBP 7.61, 7.41, 6.22, 9.11). THE OPTIONS: (a) add hardware negatives at campaign level — bar, bars, parallettes, equipment, gear, machine, station, vest, kit, setup, buy, for sale, cheap; or (b) pause and rebuild on programme intent. Recommend (a) then read at the 24 Aug gate. ALSO CORRECTS OUR OWN STANDING ARGUMENT: 'never pause the campaign, 59 of 66 keywords are untested' is right in general but does not transfer here — the untested 60 are the same equipment-intent class that has already spent GBP 235.89 for nothing.
AGAP7 Search2 min●●●●
21
AGA-26
🍎 SCREENSHOTS + APP PREVIEW VIDEO (needs a designer, not a 5-min task — logging it so it isn't lost). (a) 🔴 Screenshot 2 ships 'STRENGHT' misspelled…
full detail →
🍎 SCREENSHOTS + APP PREVIEW VIDEO (needs a designer, not a 5-min task — logging it so it isn't lost). (a) 🔴 Screenshot 2 ships 'STRENGHT' misspelled in ~40pt type under the unsupportable claim 'THE MOST EFFECTIVE … ON EARTH', over a phone rotated so the text clips mid-sentence. (b) Apple uses only the FIRST 3 on the install sheet — the assessment (our actual differentiator) is at slot 3 shown on a LAPTOP in a phone listing, and the real proof (members + Red Bull/Forbes) is at slot 8 where nobody scrolls. Move the wedge to 2 and proof to 4. (c) 🔴 '0 of 3 App Previews' — no video at all. The preview autoplays at the top of the listing and is the strongest conversion element Apple offers; we have footage. Biggest unclaimed win on the page.
AGAP7 Search5 min●●●●
22
AGA-138
DECIDE on the Remarketing Playbook — REVISED 11 Aug after a growth-fleet review BLOCKED the original. ~5 min ·…
full detail →
DECIDE on the Remarketing Playbook — REVISED 11 Aug after a growth-fleet review BLOCKED the original. ~5 min · https://tma-remarketing-playbook.netlify.app (1) ⛔ STRUCK 12 Aug — nothing left in it: the dead $297 lifetime price is GONE from /start-training/ (measured live 12 Aug, 0 occurrences in the served HTML), and the rating half is your 11 Aug "leave this alone, backlog this" ruling on NIC-98 — not to be re-raised in any form, including as a sub-item. (2) Meta un-pause is DEMOTED to a small experiment — the "10 purchases at £2.41" that justified it was double-counted AND window-cropped; the honest figure is 5 purchases at £67.48 full-life, all of a $297 offer that ended 12 Jul. (3) Google abandoner ladder £12/day — rung 1 OK, rung 2 must move to days 17-30 so paid does not undercut the welcome email's only full-price ask on day 10.
AGAP7 Search5 min●●●●
23
AGA-145
🛑 ARMED ARC, MISSING SAFETY VALVE: every email in 993 SALES SEQUENCE promises 'reply STOP to promo emails' via the promo-opt-out tag — the tag exists…
full detail →
🛑 ARMED ARC, MISSING SAFETY VALVE: every email in 993 SALES SEQUENCE promises 'reply STOP to promo emails' via the promo-opt-out tag — the tag exists (id 63977) but the EXCLUSION never got built. DEPLOY_SPEC §7 step 2: add condition 'Tag does-not-exist promo-opt-out' to the standing exclusion on every promo send path (993's entry, and any promo broadcast segment). Until it exists, a member who opts out KEEPS receiving the arc — and 993 is now ACTIVE with 115+ in flight, so the promise is live. ~5 min in the builder.
AGAP7 Search5 min●●●●
24
AGA-164
🔴 BY 18 AUG — CANCEL THE DUPLICATE TRIAL on achatnet43@laposte.net (Laurent Frejaville). He holds TWO trialing annual $157 subs on two customer…
full detail →
🔴 BY 18 AUG — CANCEL THE DUPLICATE TRIAL on achatnet43@laposte.net (Laurent Frejaville). He holds TWO trialing annual $157 subs on two customer records, both trial_end 18 Aug 2026: sub_1U3MTMI6s6pBAbnm9BmlPxJ1 (card attached, pm_1U3MXJ…) and sub_1U3ABWI6s6pBAbnmVQgr1ADU (NO card). On 18 Aug the carded one bills correctly; the uncarded one attempts, fails, and starts sending dunning mail to a live paying member. CANCEL sub_1U3ABWI6s6pBAbnmVQgr1ADU in the Stripe Dashboard (Subscriptions → search the sub id → Cancel immediately). Same class as the 15 customers / $1,662.86 of overlapping paid periods in CANCELLATION_AND_WINBACK_STRATEGY_2026-08-11.md §2c — and nothing in the estate watches for it forming.
AGAP7 Search5 min●●●●
25
AGA-96
🔴 REVOKE THE EXTERNAL DEV'S WP ENGINE SFTP — the open half of AGA-41, split out 4 Aug so it cannot close with its parent. He currently holds live…
full detail →
🔴 REVOKE THE EXTERNAL DEV'S WP ENGINE SFTP — the open half of AGA-41, split out 4 Aug so it cannot close with its parent. He currently holds live SFTP to THREE production sites (themovementath · movementath · calisthenicsac, port 2222) and is mid-PHP-upgrade, so access is CORRECT right now — this is not a problem, it is a diary entry. 🔴 Do it the day the PHP work and the Rocket.net migration are signed off: WP Engine Portal → Sites → each environment → Users and SFTP → delete the user. Three deletions, one per environment. Why it matters more here than usual: this estate has been compromised before (BWA), the same contractor also received the credentials referenced in AGA-42, and a contractor's standing access outliving the job is the single most common way a fixed breach comes back. Check-back: ask the dev for a completion date and set this row's date from his answer, rather than guessing.
AGAP7 Search10 min●●●●
26
AGA-126
🗄️ OLD ARC — 1 decision left, ~5 min. The 12 rebuilt emails have NO entry trigger and no day order yet — they are files, not an automation. Confirm…
full detail →
🗄️ OLD ARC — 1 decision left, ~5 min. The 12 rebuilt emails have NO entry trigger and no day order yet — they are files, not an automation. Confirm you want them wired, and to which list, before anything is built in AC. (The Ricky Warren ruling is DONE — moved to the shoulder lane as a presale email.) Review: Memorial Day viewer → 🗄️ OLD tab.
AGAP7 Search10 min●●●●
27
AGA-128
🧪 ADD THE SPLIT STEP IN 991 — 10 min in the AC builder, and it is the ONLY thing left before the re-engagement test runs. You approved the split; I…
full detail →
🧪 ADD THE SPLIT STEP IN 991 — 10 min in the AC builder, and it is the ONLY thing left before the re-engagement test runs. You approved the split; I cannot build it. Open 991 NEW Re-Engagement - For people who stopped opening Before Sunset in the automation builder, add a SPLIT action immediately after the start and BEFORE the first email, set it 50/50, leave path A on the existing R1 (campaign 4109, 'You've ignored my last 19 emails. Fair.') and point path B at the new challenger, then let both paths rejoin so R2/R3 and the suppression logic are unchanged. The challenger HTML is at marketing/email-sequences/991-r1-challenger-3choice-2026-08/R1B-three-choices.html — open it first, it is already rendered on your screen. Keep the SUBJECT IDENTICAL on both arms; that is deliberate, the subject earns 28.24% opens and varying it would confound the only thing being tested. Read on CLICKS, never opens, at T+7d. Everything else is done: 8,765 clean contacts ready, bounce circuit-breaker armed, all QA gates passed.
AGAP7 Search10 min●●●●
28
AGA-136
📧 THREE CLAIMS DEFECTS IN THE LIVE T+1h ABANDON EMAIL — one ruling from you and they all go to Nic together. The email is 'Try the app on us — your…
full detail →
📧 THREE CLAIMS DEFECTS IN THE LIVE T+1h ABANDON EMAIL — one ruling from you and they all go to Nic together. The email is 'Try the app on us — your results are ready' (subject), the ~1h post-checkout send doing ~30 in 4 days at 29.3% open. Its copy (tma-paywall-spec.netlify.app/email, fetched live 7 Aug) publishes: (1) 🔴 4.9★ — the published figure is 4.8, settled 4 Aug and re-ruled by you 6 Aug; 4.9 is retired on every surface, and FLEET-14 already swept the estate to 4.8, so this one was missed because it lives in Django, not in AC or WordPress. (2) 🔴 'Backed by Lead Sports Accelerator — led by Adidas and ex-Red Bull executives'. Canon is 'Backed by the LEAD Sports Tech Accelerator — run by the Adidas family and ex-Red Bull executives'. It drops 'Tech' and turns 'run by the Adidas family' into 'led by Adidas' — a corporate endorsement we cannot evidence. THIS IS THE THIRD DRIFT OF THAT ONE STRING IN TWO DAYS (also found in D3 of the new sales arc, fixed there). (3) The T+0 results email additionally promises 'goodbye to that annoying joint pain in just 30 days' to EVERY quiz finisher — a dated outcome claim. WHAT I NEED: your yes on all three wordings, then they ship to Nic as one small deploy alongside NIC-94 (which already covers the '[Chosen Password]' literal in the same estate). Copy is rendered for you in the review doc: marketing/email-sequences/evergreen-sales-sequence-2026-08/REVIEW.html — the SendGrid group at the top.
AGAP7 Search10 min●●●●
29
AGA-46
🧭 DNS CLEANUP — EXIT SITEGROUND COMPLETELY (sale-readiness). **Dev brief ready to send: **…
full detail →
🧭 DNS CLEANUP — EXIT SITEGROUND COMPLETELY (sale-readiness). **Dev brief ready to send: ** https://claude.ai/code/artifact/57248822-249c-4e54-bc48-67fb3822bf57 · analysis: `docs/company/HOSTING_MIGRATION_2026-08/DNS_EMAIL_ESTATE_ANALYSIS_2026-07-31.md`. **5–7 h, 3 phases.** ✅ **4 of 5 decisions now CLOSED** (31 Jul): @calisthenicsacademy.co email → **move to Google Workspace as a domain alias, do NOT delete** · Resend/SES → **KEEP** (new web app transactional) · SendGrid → **leave, costs nothing, its records don't touch the SPF budget** · Cloudflare proxying → **NO, DNS-only** (Rocket.net already includes Cloudflare Enterprise; double-CDN would hurt). Dev/test hosts → routed to Nic, not you. 🔷 DNS moves BEFORE the hosting cutover — SiteGround runs a **24-hour TTL** so a bad cutover there takes a day to reverse on the 1.9M-impression site. Fits inside Rocket.net's staging window, delays nothing. 🔴 **THE ONE THING LEFT FOR YOU — before SiteGround is cancelled, check SiteGround → Email → Accounts for stored mail on calisthenicsacademy.co. Cancelling deletes mailbox contents permanently.** 📊 SPF measured live: **8 of 10 lookups used** — dropping SiteGround's include frees 2.
AGAP7 Search10 min●●●●
30
NIC-102
🍎 SHIP THE STAGED iOS KEYWORD FIELD — the LIVE one wastes ~86 of its 100 characters, and the good one is ALREADY WRITTEN and sitting unsubmitted.…
full detail →
🍎 SHIP THE STAGED iOS KEYWORD FIELD — the LIVE one wastes ~86 of its 100 characters, and the good one is ALREADY WRITTEN and sitting unsubmitted. Read live from App Store Connect 11 Aug 2026. LIVE (v1.70.71, READY_FOR_SALE): 'ab,butt,beachbody,tracker,gym,exercise,diet,planner,trainer,buttock,calisthenics,ladder,routine,diet' — 'diet' appears TWICE (Apple ignores the duplicate), 'calisthenics' is ALREADY indexed free from the subtitle 'Calisthenics & Gymnastics' so it is 13 wasted characters, 'butt'+'buttock' are both off-brand, 'beachbody' is a competitor brand, and only ONE term describes what we sell. ALREADY STAGED on v1.70.72 (PREPARE_FOR_SUBMISSION): 'bodyweight,workout,plan,progression,home,beginner,strength,mobility,pull,push,handstand,planche,core' — no duplicates, nothing already-indexed, dramatically better. ✅ SO THE ASK IS SIMPLY: confirm v1.70.72 is actually going out, and tell us roughly when. If it is stuck, say what on. This matters because 87.3% of iOS installs come from App Store SEARCH and 74.3% install WITHOUT ever opening the product page — the keyword field and subtitle ARE the conversion surface, and this costs GBP 0. Optional further gain, our proposal, 92/100 chars, skill-intent over generics: 'bodyweight,pullup,pushup,handstand,muscleup,planche,lever,dips,mobility,strength,progression'.
NICP7 Search10 min●●●●
31
NIC-110
💷 NIC — CUT 'Quiz Funnel | Competitors Branded | US' FROM £10/DAY TO £5/DAY, AND DO IT AFTER NIC-108 LANDS. It bids on rivals' brand names (mostly…
full detail →
💷 NIC — CUT 'Quiz Funnel | Competitors Branded | US' FROM £10/DAY TO £5/DAY, AND DO IT AFTER NIC-108 LANDS. It bids on rivals' brand names (mostly 'betterme'). It is the biggest line in the Google account — £314.77 over 30 days, 32%% of all Google spend, running at its £10/day cap — and it returns 24 conversions at £1.58/click. THE PROBLEM IS WHAT THAT COSTS PER OUTPUT: £13.12 per conversion, against PMax Search at £1.19, Branded at £1.74, and Meta's cheapest lead line at £2.43. It is 3rd of 5 Google lines by cost-per-conversion — better than Non-Branded (£40.07) and Competitive Non-Branded (no conversions at all), but 7.5x worse than the two that work. And 86%% of this account's conversions are not sales — 30d the account booked 105 leads + 4 add_to_cart + 4 Android installs against just 18 purchases (14 Purchase | Nic - Built on July 2026 + 4 Lifetime $297 Promo) — so those 24 are leads, and the 1-10 Aug Stripe audit found all 3 verified Google sales came from Branded, none from this line. 🔴 WHY CUT AND NOT PAUSE: competitor-brand search is genuinely in-market intent ('betterme alternative' is a person shopping), which a Meta cold lead-form fill is not, so the two lead types are not interchangeable at any price — and killing a line before knowing what its output feeds is the mistake the MC Control round already cost us. A halving keeps the intent flowing, halves the bleed and stays readable. 🔴 WHY AFTER NIC-108, NOT BEFORE: the freed £5/day has exactly one good home — PMax, the cheapest converter in the account and the only line actually at its budget cap (£150.32/30d against £5.00/day). Branded cannot absorb it: it spent £40.00 in 30 days against a £6/day cap, so it is volume-bound, not budget-bound, and money moved there will not spend. But PMax leaks 40%% of its budget into placements that return zero until NIC-108 fixes it — so moving money in first would just enlarge the leak. THE ORDER: (1) NIC-108 placements first; (2) then set this campaign's daily budget to £5.00 and raise PMax's to £10.00; (3) change nothing else — leave the keywords, the bidding, the geo and the objective alone. ALSO HOLD UNTIL AFTER 13 AUG: AGA-157's read on Competitive Non-Branded lands 13 Aug and two simultaneous Google changes make the account-level read unusable. VALIDATION (5 min): after saving, confirm the two daily budgets read £5.00 and £10.00 and the account's enabled total is unchanged at £36.00/day. THE READ, 10 SEP (the existing gate): if this line still shows zero Stripe-verified sales AND its cost-per-conversion is still above £10, pause it then — that is the kill condition, pre-registered now so the decision is not re-argued. If you think there is a reason to keep it at £10/day that these numbers cannot see, say so and it stands — you built it and you may hold information this analysis does not.
NICP7 Search10 min●●●●
32
P-990
990 Monthly→Annual Upgrade Engine (Jul 2026) went LIVE 3 Aug — READ THE RESULT at 14 days (by 17 Aug 2026). The one number 980 never captured:…
full detail →
990 Monthly→Annual Upgrade Engine (Jul 2026) went LIVE 3 Aug — READ THE RESULT at 14 days (by 17 Aug 2026). The one number 980 never captured: CONVERSIONS. 980 pulled 26.7–29.2% open and 3.44–4.93% click on 3,310 sends but zero conversion tags were ever written, so its payoff is still unknown. This run has the checkout link + UTMs (utm_campaign=990-monthly-annual-upgrade-engine-jul-2026) so clicks reach Stripe metadata. Decision at 14d: keep $157 as-is, or move the $129 Stage-3 rate earlier. Live counters in the ⚙️ band above.
AGAP6 Retention10 min●●●●
33
AGA-159
💸 15 MEMBERS PAID TWICE — $1,662.86 — FOR YOUR AWARENESS, and any money decision is entirely yours. Measured 11 Aug across every Stripe subscription…
full detail →
💸 15 MEMBERS PAID TWICE — $1,662.86 — FOR YOUR AWARENESS, and any money decision is entirely yours. Measured 11 Aug across every Stripe subscription since 2024: of 3,478 customers, 370 hold more than one subscription and 15 of those PAID for two overlapping periods. 🔴 THIS ALSO CORRECTS A CLAIM I MADE TO YOU: I said a live subscription plus a checkout always double-bills; you said our system recognises the email and lets them upgrade/rebuy — you were right, 355 of 370 resolve cleanly. But these 15 are real, and nothing in the estate was watching for them. The worst: andreszeledon@gmail.com $157 over 314 overlapping days · mattlahana@gmail.com $141.30 over 290d · moniquetavian@gmail.com $235.50 over 90d · bmwparts@outlook.com $78.50 over 176d · stoica.ciprian@gmail.com $235.50 over 44d · tomifaludi@gmail.com $199.88 over 43d. Nine more run 4-39 days; the full list is in the Win-back tab §2c. 🔴 NO REFUND ACTION FROM ME, EVER — your 11 Aug ruling, now a standing rule across the estate: the fleet surfaces the finding and stops. What the fleet IS doing without you: diagnosing HOW these happened, i.e. whether one specific path leaves the old subscription running, from Stripe alone. https://tma-customer-journey-2026.netlify.app
AGAP7 Search15 min●●●●
34
NIC-105
🔴 REMOVE THE THIRD-PARTY GTM CONTAINER FROM THE CHECKOUT — GTM-PPGJXHH is hardcoded in app/apps/templates/base.html and is NOT ours. Aga checked all…
full detail →
🔴 REMOVE THE THIRD-PARTY GTM CONTAINER FROM THE CHECKOUT — GTM-PPGJXHH is hardcoded in app/apps/templates/base.html and is NOT ours. Aga checked all 7 GTM accounts / 12 containers on 11 Aug: no match. It loads on every legacy /register/ checkout — the page that holds a live Stripe key — alongside our own GTM-TKGDZR9, and we cannot see what it fires. DELETE two blocks in that one file: the <script> at lines ~12-18 (head) and the <noscript> iframe at ~52-55 (body). Leave GTM-TKGDZR9 untouched. While in there, also delete the dead Universal Analytics tag UA-104067894-1 (line ~20) — UA was sunset by Google in Jul 2023 and sends nothing. Nothing else in the file changes. AFTER DEPLOY: load /register/yearly3/ and confirm only GTM-TKGDZR9 loads.
NICP7 Search15 min●●●●
35
NIC-108
🔴 NIC — STOP PMax BUYING PLACEMENTS THAT HAVE NEVER CONVERTED. 'Quiz Funnel | PMax | US | Sales OBJ' is the only LIVE campaign breaching the settled…
full detail →
🔴 NIC — STOP PMax BUYING PLACEMENTS THAT HAVE NEVER CONVERTED. 'Quiz Funnel | PMax | US | Sales OBJ' is the only LIVE campaign breaching the settled 'Category Search ONLY — no Demand Gen, no YouTube' ruling, and the breach is measurable: over the last 30 days its non-Search arms took £60.85 across 280 clicks and returned ZERO conversions — CONTENT/Display £28.37 (39,067 impressions, 210 clicks, 0 conv), SEARCH_PARTNERS £28.17 (48 clicks, 0 conv), YOUTUBE £3.28 (17 clicks, 0 conv), DISCOVER £1.03 (5 clicks, 0 conv). That is 40%% of the campaign's £150.32 spend buying nothing. 🔴 DO NOT PAUSE THE CAMPAIGN — its SEARCH arm took £93.07 and returned 78 conversions at £0.53/click, the lowest cost-per-conversion in the account. THE ASK: keep the Search delivery, stop the rest. PMax gives no clean channel toggle, so pick whichever you judge best and tell us which: (1) Account-level Excluded Placements + Content Suitability to cut Display/YouTube inventory; (2) campaign-level negative keywords + turn OFF Final URL expansion; or (3) the clean structural answer — retire PMax and move its £5/day into a standard Search campaign, which is what the ruling actually asks for. TWO CAVEATS TO CARRY, not decorations: (a) 86%% of this account's 'conversions' are email addresses, not sales — 30d the account booked 59 Leads-GTM + 46 generate_lead + 4 add_to_cart + 4 Android installs against only 14 Purchase + 4 Lifetime-promo — so PMax's 78 are leads; (b) PMax self-attributes generously (78 conversions from 174 clicks is a 45%% rate), so treat its Search figure as directional, not proven. VALIDATION (5 min): after the change, re-open the campaign's 'Where ads showed'/placement report 3 days later and confirm Display/YouTube impressions have gone to ~0 while Search impressions and conversions hold.
NICP7 Search15 min●●●●
36
P0
Settle the June question — RC 'New Subscribers by Store' May–Jul export. BLOCKS the CEO priority call (acquisition vs retention)AGAP6 Retention15 min●●●●
37
AGA-53
🔧 WP ENGINE ESTATE (moved from NIC-17, Aga ruling 2 Aug) — own the external-WP-dev workstream: (1) 69 outdated plugins across 3 environments + 11…
full detail →
🔧 WP ENGINE ESTATE (moved from NIC-17, Aga ruling 2 Aug) — own the external-WP-dev workstream: (1) 69 outdated plugins across 3 environments + 11 outdated themes — ask the dev for triage first (security releases · live envs only · Divi/Yoast/Redirection/WP Rocket handled carefully), update security ones, schedule the rest; (2) mobile Lighthouse 48 on calisthenicsac + themovementath — connect to the WP Rocket Delay-JS task, do together; (3) rule out the live WP Engine 404/wp-admin incident before diagnosing any 404 on our sites; (4) eyeball: 'Deleted install themovementdev' 30 Jul + bandwidth 401/550 GB (73%) with avg visits/day +63% — falsifiable hypothesis: the fixed 51-hop BWA redirect loop was inflating requests; next cycle should show requests fall with no traffic drop. PHP upgrade = separate dev, target 8.2 (Divi 4.27.7 tested only to 8.2), brief marketing/seo/DEV_BRIEF_bwa_php_upgrade_2026-07-29.md
AGAP7 Search20 min●●●●
38
AGA-101
🔴 BWTA EMAIL AUTH — bodyweighttrainingarena.com sends mail with NO SPF, NO DKIM and NO DMARC (all three verified live 5 Aug; a real received header…
full detail →
🔴 BWTA EMAIL AUTH — bodyweighttrainingarena.com sends mail with NO SPF, NO DKIM and NO DMARC (all three verified live 5 Aug; a real received header shows spf=none and DKIM signed by mail1.wpengine.com, i.e. unaligned). 100% unauthenticated on our biggest property and anyone can spoof it. NOTE: the zone is ALREADY on Cloudflare (heather/zeus.ns.cloudflare.com) — no new account needed, you just need the login. NIC CANNOT DO THIS (Aga ruled 5 Aug: he does TMA only). Three records + one Google Admin toggle, ~20 min, step-by-step supplied in chat. 🔴 Publish DMARC at p=none FIRST and monitor 2-4 weeks — never jump BWTA straight to reject.
AGAP7 Search20 min●●●●
39
AGA-141
🎯 750 WELCOME SPLITS — 🔴 REWRITTEN 12 Aug, BOTH of this row's blockers are DEAD. (1) 'AC returns split data BLENDED so no arm can be declared' is…
full detail →
🎯 750 WELCOME SPLITS — 🔴 REWRITTEN 12 Aug, BOTH of this row's blockers are DEAD. (1) 'AC returns split data BLENDED so no arm can be declared' is REFUTED — I re-checked live: campaigns/<id>/campaignMessages returns ONE ROW PER ARM with its own send_amt, opens, clicks and unsubscribes. All 24 arms across the 8 slots are readable right now. No build needed. (2) 'slot 6's arm sells the 50% off' is GONE — that arm's subject became 'fit in only one dimension' during the no-offer-in-welcome work, and the only '50%' left in those bodies is width:50% CSS. So the collision this row warned about no longer exists. WHAT IS ACTUALLY TRUE, and it is a different problem: at 2–21 sends per arm (c4149's arms have 3, 3 and 2) NONE of these tests can ever reach significance — they are decorative, not wrong. THE ONLY DECISION LEFT, and it is small: leave them (harmless, and per-arm data accumulates for whenever volume arrives) or collapse each slot to its best arm so the arc reads as one email per slot. I lean LEAVE THEM — they cost nothing now that the data is readable, and collapsing is a builder job for you. Say the word either way.
AGAP7 Search20 min●●●●
40
NIC-22
✅ REASSIGNED 31 Jul — the WP Engine security deletions moved to the EXTERNAL DEV (now Step 0 of the migration brief), not Nic. Nic's only remaining…
full detail →
✅ REASSIGNED 31 Jul — the WP Engine security deletions moved to the EXTERNAL DEV (now Step 0 of the migration brief), not Nic. Nic's only remaining involvement in the hosting migration is dropping DNS TTL to 300s ~48h before cutover. Original detail: `docs/company/HOSTING_MIGRATION_2026-08/NIC_BRIEF_DELETE_EXPOSED_FILES.md`.
NICP7 Search25 min●●●●
41
NIC-99
🟡 BUILD THE $97 WARM RETARGETING TEST — sequenced AFTER the 45-min sitting (keyword surgery + NIC-97 + MOF pause) and the 17-Aug CPL report. Spec:…
full detail →
🟡 BUILD THE $97 WARM RETARGETING TEST — sequenced AFTER the 45-min sitting (keyword surgery + NIC-97 + MOF pause) and the 17-Aug CPL report. Spec: ONE Meta campaign, objective OUTCOME_SALES, ~$5/day (~$150/mo from the freed budget), WARM audiences only (site visitors 30d · quiz-starters · quiz-checkout abandoners; EXCLUDE payers via the ever-paid set), creative = the $97 offer straight (no promo framing), destination = quiz root, keep url_tags. Judged ONLY on stamped Stripe sales (checkout_version=quiz_checkout + fbclid), 4-week read. Brief = tma-remarketing-playbook.netlify.app — use its corrected economics (£67.48 full-life per purchase during promos; the £2.41 is withdrawn), so expectations are honest: evergreen-$97 retargeting is UNTESTED, this is a test not a scale-up. Strategic kicker: the Nov BF retargeting push is Nic's build anyway — this warms the audiences, pixel events and creative learnings for it.
NICP7 Search60 min●●●●
42
NIC-100
🤖 ANDROID: 32% OF USERS NEVER SUCCESSFULLY SIGN IN — REAL, MEASURED, AND STILL UNEXPLAINED AFTER A FULL ON-DEVICE QA PASS (12 Aug). 🔴 DO NOT HUNT A…
full detail →
🤖 ANDROID: 32% OF USERS NEVER SUCCESSFULLY SIGN IN — REAL, MEASURED, AND STILL UNEXPLAINED AFTER A FULL ON-DEVICE QA PASS (12 Aug). 🔴 DO NOT HUNT A BROKEN SIGN-IN — there isn't one. A tester ran the whole flow on a real Android phone: signing up, signing in, the quiz→app journey, and every failure path. The door WORKS (quiz email → password → in, 3 taps / 25 seconds). Password reset WORKS (verified in our mail provider's logs). The crash theory was already refuted (Play vitals 0.00% crash, 0.10% ANR) and so was the cheap-geo theory (buyer-countries-only, Android 45.6% vs iOS 111%). What remains is the measurement: buyer-geo login iOS 239/242 = 98.8% vs Android 85/125 = 68.0%, and social_login_attempted fires 103x on iOS and ZERO on Android. 🔎 SO THE OPEN QUESTION IS NARROWER AND SHARPER: not 'what is broken' but 'why do a third of Android users abandon a flow that demonstrably works'. The leading candidates are all friction, not failure — no autofill (the emailed 20-character password must be hand-copied every single time), no show-password toggle, no forgot-password link at the moment sign-in fails, and an email-verification wall the app imposes on every quiz-created lead. Those are specced as TMA-A1..A6 in docs/company/ANALYTICS/ANDROID_AUTH_TICKETS_2026-08-12.md. 🔴 The next step is user-level data, NOT another QA script.
NICP7 Search60 min●●●●
43
P2
Stripe-portal cancel intercept: point in-app cancel at portal login (SAVE30 loaded). PRE-CHECK first: Nic confirms webhooks sync portal un-cancels to…
full detail →
Stripe-portal cancel intercept: point in-app cancel at portal login (SAVE30 loaded). PRE-CHECK first: Nic confirms webhooks sync portal un-cancels to app entitlements
NICP6 Retention2h●●●●
44
P1
Annual pre-anniversary renewal sequence T-45/30/7 + year-in-review recap — via /email-fleet (renewal = known lifecycle coverage GAP). Honest size…
full detail →
Annual pre-anniversary renewal sequence T-45/30/7 + year-in-review recap — via /email-fleet (renewal = known lifecycle coverage GAP). Honest size +$170–450/mo
AGAP6 Retention3h●●●●
45
GOV
Lifetime cadence decision: each event ≈$20–30K instant cash vs MRR-multiple hollowing ('53% new' = ceiling). Board-level dialAGAP6 Retention●●●●
46
E06
P1 sends Mon 28 Jul (Aga schedules the 3 drafts)AGAP2 Email●●●●
47
E08
Renewal protection arc spec DONE — awaiting Aga nod, then buildAGAP2 Email●●●●
48
T11
🔴 MEASURED LIVE 6 Aug 2026 — NOT FINISHED, and the finished half is on the wrong URL. The VA reported Part 4 done; audited with the new…
full detail →
🔴 MEASURED LIVE 6 Aug 2026 — NOT FINISHED, and the finished half is on the wrong URL. The VA reported Part 4 done; audited with the new tools/youtube-analytics/endscreen_audit.py (reads end screens off the public watch page at ZERO API quota): 5 of 9 carry the Link element, 4 DO NOT — missing on 4FoCnqGC-o0, y7X-GuNZF_Y, OyRj1z3sNgs, Z9C7aCRCgn8. AND all 5 that exist point at https://themovementathlete.com/calisthenics-assessment/?utm_source=youtube&utm_medium=organic&utm_campaign=yt_endscreen — the doorway Aga's 3 Aug ruling took OUT of the YouTube path. Not the VA's error: the brief specified that URL on 24 Jul, before the ruling, and nobody re-read it. GOOD NEWS: the Link element works, so YPP genuinely unlocked it and the 60-second test passed. TO DO: (a) swap the target on the 5 existing to https://quiz.themovementathlete.com/?utm_source=youtube&utm_medium=organic&utm_campaign=yt_endscreen ; (b) add it to the 4 missing with that same URL. End screens have NO Data API endpoint — creation is Studio-UI only, so this stays with V — but VERIFICATION is now free and repeatable: python3 tools/youtube-analytics/endscreen_audit.py --expect-url https://quiz.themovementathlete.com/ <ids>. || ORIGINAL: PART 4 — add the UTM'd assessment LINK to end screens on the top 9, now that YPP unlocked the Link element. 🔴 URL CORRECTED 6 Aug 2026 — USE THIS ONE: https://quiz.themovementathlete.com/?utm_source=youtube&utm_medium=organic&utm_campaign=yt_endscreen . The old instruction said https://themovementathlete.com/calisthenics-assessment/?...&utm_campaign=yt_endscreen which CONTRADICTS Aga's 3 Aug ruling that the assessment page comes OUT of the YouTube path: all 869 video descriptions were moved onto the quiz root, so end screens were about to become the last YouTube surface still feeding the retired doorway — and nobody would have noticed, because the old URL still 200s (verified live, 0 hops). A dead instruction that still resolves is worse than one that 404s. 🔴 VA instructed to TEST one video first and STOP if Link is still greyed out. Then ~40 more in batch 2. Context: flagship end-screen click rate is 0.6% vs 1.3% channel average — with no link element available until now.
VP4 YouTube●●●●
49
BRIEF-4
Switch Meta campaigns OFF the Lead objective → PurchaseNICNic wiring (brief)●●●●
50
BRIEF-11
Export each user's “last funnel step” to Customer.io / ActiveCampaign ★ best ROI on this pageNICNic wiring (brief)●●●●
51
BRIEF-10
Make the quiz funnel segmentable by traffic source in GA4 &mdash; CLOSED 7 AugNICNic wiring (brief)●●●●
52
AGA-62
📊 DO NOT READ THE AUGUST MIX YET — a note, not a task. Annual share reads **57.1%** vs July's 13.8%, which looks like the pricing page working. It is…
full detail →
📊 DO NOT READ THE AUGUST MIX YET — a note, not a task. Annual share reads **57.1%** vs July's 13.8%, which looks like the pricing page working. It is **4 sales out of 7**, on day 3 of the month. At n=7 that number is consistent with anything from 'no change' to 'huge win' — not decision-grade, and it must not be quoted to Nic, the board or a buyer. Same for retention's '4 cancel-ends MTD' vs July's 110. **Decision-grade at roughly 30–40 sales ≈ 13 Aug** at the current ~2.3/day. The pricing page shipped 31 Jul so this IS its first read and the direction is encouraging — just not yet a result. Close this row on 13 Aug with the real number.
AGAP7 Search1 min●●●●●
53
AGA-30
📬 WATCH FOR LISTICLE REPLIES — 🔴 SPLIT INBOX, and it matters for a few weeks. The 3 pitches sent 31 Jul (fitbudd info@, gymnasetips contact@,…
full detail →
📬 WATCH FOR LISTICLE REPLIES — 🔴 SPLIT INBOX, and it matters for a few weeks. The 3 pitches sent 31 Jul (fitbudd info@, gymnasetips contact@, thehybridathlete) went out BEFORE the outreach mailbox existed, so they were sent from hello@ and signed hello@ — those replies land in **hello@**. Everything from now on sends from **hi@** and is signed hi@, so those replies land there. Watch both until the first three are answered or go cold (~2 weeks), then hi@ only. Each pitch offers free full access plus an optional commission arrangement: if one says yes, provision the free account promptly — a slow reply to an inbound yes wastes the placement. 🔴 If they ask for commission TERMS, that is still OPEN (flagged 25 Jul, never ruled) — hold, don't improvise. Log: marketing/seo/listicle_outreach_log.json (append-only, prevents double-sending).
AGAP7 Search5 min●●●●●
54
AGA-102
🔗 RULING NEEDED — strip the BECOME AN AMBASSADOR / affiliate-program links from 759 Nurture Sequence 3 (38/38 emails) and 764 Nurture Sequence 4 (4…
full detail →
🔗 RULING NEEDED — strip the BECOME AN AMBASSADOR / affiliate-program links from 759 Nurture Sequence 3 (38/38 emails) and 764 Nurture Sequence 4 (4 HTML + 3 text of 15)? On 29 Jul you had these stripped from 751 Nurture Sequence 1 + 758 Nurture Sequence 2. 759 and 764 were never touched because ZERO people had ever entered them. That changed today: connecting the welcome arcs to 751 restored the ladder 751->758->759->764, so the first cohort will reach 759 for the first time ever. I did NOT extend your 29 Jul ruling to them myself — that is the exact over-generalisation you corrected me on today (applying a stuck-cohort ruling to new leads). ALSO FOUND while in there, and worth deciding together: 764 sends the SAME email twice, step 1 camp 3344 and step 3 camp 3856, identical subject 'Some people get stronger every year after 40.' and near-identical body (11,384 vs 11,436 bytes) — one should be deleted. AND 759/764 content has never been sent to a single person, so it has never had a QA or link-rot pass. Say the word and I do all three (I have a proven backed-up method — I stripped 20 emails today the same way).
AGAP7 Search5 min●●●●●
55
AGA-127
🎁 COMP PABLO MENDOZA FREE PREMIUM until the rebuild bugs are fixed — Jesse's reply (drafted, in his thread) promises 'I'll have it switched on —…
full detail →
🎁 COMP PABLO MENDOZA FREE PREMIUM until the rebuild bugs are fixed — Jesse's reply (drafted, in his thread) promises 'I'll have it switched on — nothing for you to do'. pmendozacaballero@gmail.com, sub ended 27 Jul, left over rebuild bugs + price, offered us a full bug list.
AGAP7 Search5 min●●●●●
56
NIC-109
🍎 NIC — WHICH REPORT DID THE $2,277 COME FROM? Your Slack note reads '$404 spend across June and July → $2,277 revenue → 5.6 ROAS'. THE SPEND…
full detail →
🍎 NIC — WHICH REPORT DID THE $2,277 COME FROM? Your Slack note reads '$404 spend across June and July → $2,277 revenue → 5.6 ROAS'. THE SPEND RECONCILES: Apple's own billing for 1 Jun–31 Jul is $377.32 (and $408.24 for 12 Jun–12 Aug), so $404 is real. THE REVENUE DOES NOT: AppsFlyer's aggregate partners report for the same window credits Apple Search Ads with $1,098.82 from 6 buyers — June $99.98 (1 buyer), July $998.84 (5 buyers). That is roughly HALF your figure, so one of the two systems is being read on a different basis and we should not publish either number until we know which. THE MOST LIKELY CAUSE, so you know what to look for: Apple's own dashboard attributes on Apple's window, which counts VIEW-through installs — over 12 Jun–12 Aug Apple recorded 165 tap-installs but 305 view-installs, and a view-inclusive basis roughly doubling credited revenue is exactly the shape of this gap. THE ASK: tell us which report and which exact date range the $2,277 came from (Apple Search Ads dashboard? AppsFlyer dashboard? RevenueCat? App Store Connect?) and whether its attribution setting includes view-through. If it is Apple's own view-through figure, both numbers are 'right' and we simply label which basis we quote from now on. 🔴 SEPARATELY, AND THIS IS THE PART THAT CHANGES A DECISION — Aga asked whether the ROAS is branded-only and the measurement says her instinct is right and stronger than she put it: 100%% of the attributed revenue in your window came from OUR OWN brand campaigns (Branded EU $763.89, Branded US-SR $334.93), while the 61%% of the spend that went to competitor and non-branded terms ($230.45 across Competitive-Branded, Non-Branded, Competitive Non-Branded, Non-Direct Competitive Demand Gen and Competitors_MC) returned 15 installs, ZERO buyers and $0.00. So the honest split is: branded 7.5x, non-brand 0.0x, blended 2.9x — not 5.6x across the board. Nothing to change in the account, those five are already paused; this is so the 5.6x is not quoted as if it were repeatable on new keywords.
NICP7 Search5 min●●●●●
57
V-01
📌 PIN 3 YOUTUBE COMMENTS — 5 minutes, 3 clicks in YouTube Studio. Their text is ALREADY CORRECT (I repointed all 40 to the quiz root on 12 Aug);…
full detail →
📌 PIN 3 YOUTUBE COMMENTS — 5 minutes, 3 clicks in YouTube Studio. Their text is ALREADY CORRECT (I repointed all 40 to the quiz root on 12 Aug); these three are simply not pinned, so they sink below viewer comments and are worth close to nothing. Videos: FLGLf5R5XkM · 0lPJpN1JmOM · PzJdqNuWwDU. DO: open each video's comments in Studio, find our channel comment (it already links to quiz.themovementathlete.com), and choose Pin. Verify free with: python3 tools/youtube-analytics/comment_audit.py <video_id> — it must show pinned=True quiz-root=True. 🔴 ALSO WORTH KNOWING WHILE YOU ARE IN THERE: 9 videos carry MORE THAN ONE of our channel comments competing for the pin (4fstTeS-MUQ TqdYJOGIQsc 1wWx1304S_A 1MFRTIH0pz0 SlaCyUauuVQ lRqo6Tjm2GA Wa89eMBcqQs gy6dOjw58_o Ue8_L6msDYc). The pinned one is correct on all of them, so this is tidiness, not a defect — delete the stragglers only if you are confident which is which.
VP7 Search5 min●●●●●
58
AGA-108
🏷️ GTM CONTAINER GTM-PPGJXHH — CHECK WHETHER IT IS YOURS UNDER A DIFFERENT GOOGLE ACCOUNT (10 min, one login). VERIFIED LIVE 5 Aug: the legacy…
full detail →
🏷️ GTM CONTAINER GTM-PPGJXHH — CHECK WHETHER IT IS YOURS UNDER A DIFFERENT GOOGLE ACCOUNT (10 min, one login). VERIFIED LIVE 5 Aug: the legacy checkout page https://app.themovementathlete.com/register/yearly3/ returns 200, is titled 'Register and pay', carries a LIVE Stripe key (pk_live) and loads TWO GTM containers — GTM-TKGDZR9 (ours, readable via tools/analytics/gtm_read.py) and GTM-PPGJXHH (NOT in the account our service credentials can see). ✅ GOOD NEWS FIRST, so this is not urgent: the money has already moved off this door. Stripe subscriptions created in the last 30d, split by checkout_version — v3 115, quiz_checkout 58, unattributed 48 — and the unattributed cohort ran 1-4/day all July, then STOPPED: last one 2 Aug, and 0 on 3, 4 and 5 Aug. So the legacy door is no longer producing sales; your redirect worked. WHAT IS ACTUALLY OPEN: (a) is GTM-PPGJXHH a container you own under a different Google login (agency, old account, Nic's, a previous contractor)? If yes, add google-analytics-claude-access@the-movement-athlete.iam.gserviceaccount.com as a user and the fleet can read it — the whole question closes. (b) If it is NOT yours, that is a third party firing tags on a page that holds a live Stripe key, which is the part worth knowing. DONE WHEN: you can say 'it is mine, access granted' or 'it is not mine'. Nothing else depends on this today.
AGAP7 Search10 min●●●●●
59
AGA-120
⏰ RULE THE DAY-5 TRIAL REMINDER — keep/change/kill, and name the rail that sends it. The checkout page PROMISES buyers a pre-renewal reminder; you…
full detail →
⏰ RULE THE DAY-5 TRIAL REMINDER — keep/change/kill, and name the rail that sends it. The checkout page PROMISES buyers a pre-renewal reminder; you verified on 10 Jul that a day-5 reminder exists, but which rail sends it (Django, AC or Stripe) was never established, so trial-ender coverage is unprovable. Recommendation on the plan page: KEEP, then one question to Nic to name the rail.
AGAP7 Search10 min●●●●●
60
AGA-130
🖱️ DECIDE HOW WE MEASURE CLICKS ON THE TRANSACTIONAL EMAILS — right now we measure NONE. Account-level click tracking in SendGrid is OFF (open…
full detail →
🖱️ DECIDE HOW WE MEASURE CLICKS ON THE TRANSACTIONAL EMAILS — right now we measure NONE. Account-level click tracking in SendGrid is OFF (open tracking is on), so all 1,106 emails delivered in the last 14 days recorded ZERO clicks by construction — including the abandon email 'Your login is in this email', which sends ~11-14/day at a 29.3% open rate and whose entire job is getting someone back to the checkout. We cannot tell whether one single person has ever clicked it. TWO WAYS, pick one. (A) RECOMMENDED, zero risk, no SendGrid change: put UTMs on that email's links pointing at the quiz root per the LINK RULE, and read the clicks in GA4 — needs one Django template change from Nic, and it measures the thing we actually care about (arrivals at the checkout, not pixel fires). (B) Flip SendGrid Settings > Tracking > Click Tracking to ON — one click, measures every transactional email at once, BUT 🔴 it rewrites links in activation and password-reset emails too, and a mail-security scanner pre-fetching a rewritten one-time link can consume the token and lock a real member out of their account. That risk is why this is your call and not something I switched on. If you pick B, the safe form is per-message click tracking on the abandon email only, which is also a Nic change.
AGAP7 Search10 min●●●●●
61
AGA-132
⏳ APPROVE THE 48H ENFORCEMENT FOR NIC — WHEN HIS QUEUE CLEARS (not now, your ruling). You ruled the $97 window BINDING on 7 Aug and said Nic is not…
full detail →
⏳ APPROVE THE 48H ENFORCEMENT FOR NIC — WHEN HIS QUEUE CLEARS (not now, your ruling). You ruled the $97 window BINDING on 7 Aug and said Nic is not to be interrupted for it. This row is the reminder to hand it to him later, not a task on his brief yet. WHAT HE'LL DO (~45 min): enforce the window at CHARGE time, not just in the UI — once an email has had a window, never mint it a second one; acceptance = an address 48h+ old sees $157 and Stripe charges $157. WHY IT MATTERS AND WHAT IT UNBLOCKS: until it ships, no recovery email may claim the deadline (the server never returns expired today and a lapsed visitor gets a fresh 48h), which is why the abandonment arc's E3 'your window closes tonight' beat cannot ship at all. Approve this and the arc gets its third email; leave it and the arc runs E1-E2-E4 honestly, which is a perfectly good sequence. NOT urgent, by your own ruling.
AGAP7 Search10 min●●●●●
62
AGA-66
MAKE A FREE TEST ACCOUNT — 10 minutes, unblocks the free-member audit. Three login-walled questions get answered the day the credentials exist: (1)…
full detail →
MAKE A FREE TEST ACCOUNT — 10 minutes, unblocks the free-member audit. Three login-walled questions get answered the day the credentials exist: (1) which upgrade CTAs a free member actually sees, (2) what the paywall state looks like from inside a free account, (3) whether the $9.99 step-down is reachable at all. Until the account exists these stay unanswerable and the free-member audit cannot start. (Was NIC-36; moved to Aga 3 Aug.)
AGAP7 Search10 min●●●●●
63
NIC-18
CONFIRM THE PHP STATE — the WP Engine activity log shows 'PHP update from version 8.4.0 to …' at 04:50 on 30 Jul under developer.mrski, and the…
full detail →
CONFIRM THE PHP STATE — the WP Engine activity log shows 'PHP update from version 8.4.0 to …' at 04:50 on 30 Jul under developer.mrski, and the portal separately reports '5 PHP outdated · 5 environments need updates'. We CANNOT read PHP version from outside (WP Engine doesn't expose it in headers or REST), so the current state is genuinely unknown to us. Two questions: (1) which environment did that update apply to, and to what version — if anything moved DOWN from 8.4.0 that matters; (2) is BWA still on 7.4.33? If NIC-14 is already done, say so and we close it.
WPDEVP7 Search10 min●●●●●
64
AGA-16
BWA plugin consolidation — TWO active redirect plugins at once (Redirection v5.9.0 with 19 rules, 17 carrying live hits; + SEO Redirection v9.19, NOT…
full detail →
BWA plugin consolidation — TWO active redirect plugins at once (Redirection v5.9.0 with 19 rules, 17 carrying live hits; + SEO Redirection v9.19, NOT REST-readable so its rules are unknown). 🔴 DO NOT click the dashboard banner offering to 'import 18 redirects' — duplicating rules across two engines is how you get loops. Order: 1) audit SEO Redirection's rule list in wp-admin and send Claude a screenshot 2) only then migrate anything unique into Redirection 3) deactivate SEO Redirection 4) delete the 3 dead plugins (SEOPress, All in One SEO, 301 Redirects — AIOSEO already left a broken llms.txt behind). Keep: Redirection, Yoast SEO.
AGAP7 Search20 min●●●●●
65
AGA-67
NOINDEX staging. + beta. VIA CLOUDFLARE, THEN CLEAR THE INDEX IN SEARCH CONSOLE — the half of NIC-43 that needs no deploy. Both hosts confirmed…
full detail →
NOINDEX staging. + beta. VIA CLOUDFLARE, THEN CLEAR THE INDEX IN SEARCH CONSOLE — the half of NIC-43 that needs no deploy. Both hosts confirmed served by Cloudflare (server: cloudflare, cf-ray present); neither serves a real robots.txt (the SPA catches the route and returns HTML), and both return HTTP 200 with no robots header. STEP 1 (Cloudflare, ~5 min): Rules -> Transform Rules -> Modify Response Header -> add X-Robots-Tag: noindex, nofollow for hostname staging.themovementathlete.com and beta.themovementathlete.com. No deploy, instant, one click to reverse. STEP 2 (Search Console, ~10 min): the promo URLs are ALREADY indexed, and noindex only takes effect when Google next recrawls — so after Nic's header is live, use Removals -> Temporary removal on app./register/monthly2/promo/ and /register/lifetimespecial/ to hide them within ~24h while the noindex does the permanent work. Order matters: do the removal AFTER the header exists, or it lapses in 6 months and they return. STEP 3 (~10 min, the interesting one): these are unlisted URLs, so ask HOW Google found them — URL Inspection -> 'Referring page' on both. If something public links to them, that link leaks the offer regardless of noindex, and noindex will not fix it. ACCEPTANCE: curl -I https://staging.themovementathlete.com/ and beta. both return X-Robots-Tag: noindex; both hosts and both promo URLs fall out of the TMA GSC property within ~2 weeks.
AGAP7 Search25 min●●●●●
66
NIC-14
BWA is on PHP 7.4.33 — end of life, no security updates, and WordPress will stop supporting it (min recommended 8.3). WP Engine portal change +…
full detail →
BWA is on PHP 7.4.33 — end of life, no security updates, and WordPress will stop supporting it (min recommended 8.3). WP Engine portal change + regression test. Flagged by the WP dashboard itself.
WPDEVP7 Search30 min●●●●●
67
P3a
R1 voluntary saves: Seg A sent 20 Jul (30 emails, 0 saves yet — T-30 offers arm at expiry, too early to judge). Seg B/C question-send awaiting…
full detail →
R1 voluntary saves: Seg A sent 20 Jul (30 emails, 0 saves yet — T-30 offers arm at expiry, too early to judge). Seg B/C question-send awaiting authorization
AGAP6 Retention30 min●●●●●
68
P3b
976 Cancelled Win-Back — reason-matched copy through /email-fleet gates (6/7 current CTAs fail QA); reason tags already applied daily by machineAGAP6 Retention3h●●●●●
69
P5
D1 activation cliff (D0→D1 ~10%) — durable product fix in RN app; route via CPO → NicRNP6 Retention●●●●●
70
E15
764 Nurture 4 confirmed ends in silence → wire shoulder hand-raise (#13 unblocked)AGAP2 Email●●●●●
71
T2
✅ MEASURED LIVE 6 Aug 2026 with the new tools/youtube-analytics/comment_audit.py (zero API quota) — THE VA DID THE WORK. All 40/40 videos carry a…
full detail →
✅ MEASURED LIVE 6 Aug 2026 with the new tools/youtube-analytics/comment_audit.py (zero API quota) — THE VA DID THE WORK. All 40/40 videos carry a channel comment; 37/40 are pinned. She executed Days 1-4. 🔴 BUT ALL 40 COMMENTS POINT AT THE RETIRED /calisthenics-assessment/ DOORWAY (utm_campaign=yt_pinned), not the quiz root — because the comments were written in JULY and the 3 Aug quiz-root retrofit rewrote DESCRIPTIONS ONLY. Third surface the retrofit missed, after the channel About text and the end screens. Not the VA's error in any of the three. OUTSTANDING FOR V (12 min): (a) PIN the 3 that are posted but unpinned — FLGLf5R5XkM, 0lPJpN1JmOM, PzJdqNuWwDU; (b) the duplicate cleanup the brief asked for was NOT done — 9 videos carry 2+ channel comments competing for the pin: 4fstTeS-MUQ, TqdYJOGIQsc, 1wWx1304S_A, 1MFRTIH0pz0, SlaCyUauuVQ, lRqo6Tjm2GA, Wa89eMBcqQs, gy6dOjw58_o (3 comments), Ue8_L6msDYc — delete the OLDER one on each. NOT FOR V: the URL swap on all 40 is MINE — comments.update works on our own comments (50 units each, 2,000 total), so it runs once the retrofit frees the quota. Filed as a FLEET row. Re-verify anytime: python3 tools/youtube-analytics/comment_audit.py --file <ids>
VP4 YouTube●●●●●
72
T5
Stage 2: resume long-form cadence (≥ 2/mo) + retitle top winners + retention repair (on Aga's go)AGAP4 YouTube●●●●●
73
T7
EDITOR REBALANCE (decided 21 Jul): Forge = majority; main TMA = protected floor ~2 long-form/mo on proven clusters (ring dips, strict muscle-up,…
full detail →
EDITOR REBALANCE (decided 21 Jul): Forge = majority; main TMA = protected floor ~2 long-form/mo on proven clusters (ring dips, strict muscle-up, push-up progressions, handstand, planche prereqs, pull-ups) + package-refresh top ~10 winners (no filming) + cut 2-3 reels per long-form. Reversed the earlier 'abandon main TMA' call after the 77%-organic finding. Dependency: Jesse batch-films monthly.
VP4 YouTube●●●●●
74
T10
RETITLE/RE-THUMB BRIEF for the top 5 winners -> marketing/youtube/YT_RETITLE_BRIEF_2026-07-23.md. 🔴 CTR + impressions are STUDIO-ONLY (not exposed by…
full detail →
RETITLE/RE-THUMB BRIEF for the top 5 winners -> marketing/youtube/YT_RETITLE_BRIEF_2026-07-23.md. 🔴 CTR + impressions are STUDIO-ONLY (not exposed by the Analytics API) — so priorities are [MODELLED] from views+retention. READ CTR IN STUDIO FIRST: below ~5.9% = packaging problem (retitle); at/above = retention problem (do NOT touch the title). Ring Dips flagship Ikeg_v5fvz4 = biggest prize (652 watch-h at 27.6% retention). 🔴 4FoCnqGC-o0 (What Muscles Do Push-Ups Work) = DO NOT RETITLE — 59.3% retention, it works; the lever is EXPANDING the 93s video. Discipline: one change, 14-day read, revert if flat.
AGAP4 YouTube●●●●●
75
T12
RETENTION RE-CUT BRIEF -> marketing/youtube/EDITOR_BRIEF_RETENTION_RECUTS_2026-07-24.md. 🔴 KEY MECHANIC: YouTube Studio Editor can TRIM/CUT a live…
full detail →
RETENTION RE-CUT BRIEF -> marketing/youtube/EDITOR_BRIEF_RETENTION_RECUTS_2026-07-24.md. 🔴 KEY MECHANIC: YouTube Studio Editor can TRIM/CUT a live video IN PLACE (same URL, keeps all views/rankings/comments) but CANNOT add footage. So: flagship Ikeg_v5fvz4 (381.6K impressions, 9.8% CTR, 27.2% retention, 3.1K lifetime watch-h) = TRIM ONLY, NEVER re-upload — 4 years of authority at stake. RC001-003 scripts contain a NEW cold open = requires re-upload; their originals earn only 26-38h/yr so that's acceptable, but AGA MUST DECIDE per video.
VP4 YouTube●●●●●
76
SOC-2
Nic S1 redirects (302 + query forwarding) → then revert the 11 UTM-forward snippetsNICP3 Social●●●●●
77
SOC-3
SMM/VA first manual logs Monday (TikTok · FB Group · production hours · inputs panel)VP3 Social●●●●●
78
BRIEF-1
Finish the RevenueCat → Amplitude connection &mdash; &#9989; VERIFIED DONE 6 AugNICNic wiring (brief)●●●●●
79
BRIEF-16
Rebuild Google UAC to optimise to the trial event (later)NICNic wiring (brief)●●●●●
80
BRIEF-26
Email deep-link infra — OneLink template + ESP wiring (the add-on's no-release half)NICNic wiring (brief)●●●●●
81
BRIEF-18
T7 — Native product &amp; lifecycle events (retention)NICNic wiring (brief)●●●●●
82
BRIEF-22
RevenueCat Paywalls SDK &mdash; remote paywall &amp; price control the one that ends the release cycleNICNic wiring (brief)●●●●●
83
BRIEF-23
RN‑5 — iOS ATE/ATT + AppsFlyer always-initNICNic wiring (brief)●●●●●
84
BRIEF-24
RN‑6 — install-UTM stitch + ➕ email deep-link add-onNICNic wiring (brief)●●●●●
85
BRIEF-25
RN‑7 — screen-level trackingNICNic wiring (brief)●●●●●
86
AGA-156
DECISION: 4,464 of 5,846 ActiveCampaign tags (76.4%) are one-person junk from the add_tag_to_quiz_contact() bug — 5,621 minted in a single day, 29…
full detail →
DECISION: 4,464 of 5,846 ActiveCampaign tags (76.4%) are one-person junk from the add_tag_to_quiz_contact() bug — 5,621 minted in a single day, 29 Oct 2025. The writer has been quiet since Nov 2025 so nothing is getting worse. Worth a bulk delete to make the tag manager usable again? Say go and I scope it (dry-run list first, nothing deleted without your sign-off).
AGAP7 Search5 min●●●●●
87
AGA-09
WP Rocket on BWA — turn on WebP compatibility + ShortPixel/Imagify bulk-convert (zero WebP on the site today; 30-50% off every image). Optional same…
full detail →
WP Rocket on BWA — turn on WebP compatibility + ShortPixel/Imagify bulk-convert (zero WebP on the site today; 30-50% off every image). Optional same screen: Delay JS execution, then click through a few pages.
AGAP7 Search10 min●●●●●
88
T13
RC001-003 re-cut decision. CLAUDE'S RECOMMENDATION: TRIM IN PLACE, do NOT re-upload, and do NOT prioritise them. Originals earn only 26-38 h/yr each…
full detail →
RC001-003 re-cut decision. CLAUDE'S RECOMMENDATION: TRIM IN PLACE, do NOT re-upload, and do NOT prioritise them. Originals earn only 26-38 h/yr each (~90 h/yr combined). A re-upload starts at zero authority, competes with the original, and the new-cold-open scripts are only needed for the re-upload path. The topics are ALREADY covered by the new production queue (11 handstand eps ready) — if we want a better shoulder-mobility-for-handstand video we should PUBLISH A NEW ONE, not resurrect a weak old one. Contrast: the flagship trim is worth doing because it's 3,100 lifetime watch-h at 27% retention — 30x the scale.
AGAP4 YouTube●●●●●
89
NIC-107
BACKLOG (Aga: park it, not to be raised again) — checkouts-v3 header renders '4.9 average rating'. House rule is 4.7/4.8; 4.9 is retired. Aga has…
full detail →
BACKLOG (Aga: park it, not to be raised again) — checkouts-v3 header renders '4.9 average rating'. House rule is 4.7/4.8; 4.9 is retired. Aga has seen it and ruled it PARKED on 11 Aug 2026. Pick up only if the header is being edited for another reason.
NICP7 Search5 min●●●●
📨 Dispatch view — each human's week in one blockMonday board, hour 4
👤 Aga — 50 open
  1. 🟢 GO/NO-GO: mail a 500-contact test segment of the 6,813 app-side contacts who finished… · 5 min · AGA-146
  2. 🟢 GO/NO-GO: give '758 Nurture Sequence 2' (14,600 contacts) a quiz-root CTA slot — NP… · 5 min · AGA-147
  3. 🧲 DECIDE: THE 10th LEAD MAGNET HAS 232 SESSIONS/28d AND NO WAY TO CAPTURE AN EMAIL.… · 5 min · AGA-168
  4. 🔴 TELL THE PHP DEV: calisthenicsacademy.co's Divi is 4.4.8 — the "only PBE" assessment is… · 10 min · AGA-139
  5. 🏋️ ONE BUILDER VISIT, ~10 MIN — THE WORKOUT-1 EMAIL + 2 CONDITIONS. 🔴 CORRECTED 12 Aug:… · 12 min · AGA-161
  6. 💷 THE ANNUAL OFFER TO THE ENGAGED — 🔴 DO NOT APPROVE YET, THE AUDIENCE HALVED. Measured… · 20 min · AGA-119
  7. +44 more (filter above)
👨‍💻 Nic — 29 open
  1. 🔴 REPOINT 'QLG | ADV+ OFF | MC | Control' TO THE QUIZ ROOT — 5 min in Ads Manager. All 4… · 5 min · NIC-106
  2. 🔴 MAKE THE IN-APP CANCEL DOWNSELL PLAN-AWARE — annual leavers are shown a WORSE deal than… · 1.5h · NIC-101
  3. 756/757 Abandoned Cart Reminder — UPLOAD THE 4-EMAIL 2026-08 ARC INTO FRESH SHELLS. 🔴… · — · E11
  4. Nic S2 token (4 scopes) → IG + FB per-post flip LIVE on the board · — · SOC-1
  5. T5 — Fix the AppsFlyer conversion events ★ highest leverage · — · BRIEF-5
  6. GA4 → Google Ads conversion import ("Task 3" in the 16-Jul message) · — · BRIEF-8
  7. +23 more (filter above)
🎧 V — 6 open
  1. 🔴 MEASURED LIVE 6 Aug 2026 — NOT FINISHED, and the finished half is on the wrong URL. The… · — · T11
  2. 📌 PIN 3 YOUTUBE COMMENTS — 5 minutes, 3 clicks in YouTube Studio. Their text is ALREADY… · 5 min · V-01
  3. ✅ MEASURED LIVE 6 Aug 2026 with the new tools/youtube-analytics/comment_audit.py (zero… · — · T2
  4. EDITOR REBALANCE (decided 21 Jul): Forge = majority; main TMA = protected floor ~2… · — · T7
  5. RETENTION RE-CUT BRIEF -> marketing/youtube/EDITOR_BRIEF_RETENTION_RECUTS_2026-07-24.md.… · — · T12
  6. SMM/VA first manual logs Monday (TikTok · FB Group · production hours · inputs panel) · — · SOC-3
📱 RN team — 2 open
  1. 📲 RN TEAM — IN-APP PAYWALL UI REBUILD. Sent to the RN devs 5 Aug; awaiting their estimate… · 15 min · RN-01
  2. D1 activation cliff (D0→D1 ~10%) — durable product fix in RN app; route via CPO → Nic · — · P5
🌐 WP dev — 2 open
  1. CONFIRM THE PHP STATE — the WP Engine activity log shows 'PHP update from version 8.4.0… · 10 min · NIC-18
  2. BWA is on PHP 7.4.33 — end of life, no security updates, and WordPress will stop… · 30 min · NIC-14
49 task(s) are FLEET-owned — the agents carry them; they never reach this console. Sources: P7 Search → marketing/seo/SEO_HUMAN_QUEUE.json · P6 Retention → tools/retention/retention_status.json · P2 Email → tools/email-plan/email_status.json · P4 YouTube → tools/youtube-analytics/yt_status.json · P3 Social → tools/social-pipeline/social_status.json · Nic wiring → docs/company/ANALYTICS/ANALYTICS-BRIEF-SITE/index.html (p-todo). A task not in one of these does not exist — write it there in the same session it is discovered.
📦 Pre-console archive — the hand-written tables that lived on this tab before 31 Jul 2026 (kept, not deleted)
📋 To-Do — everything, by priority the single working list · step-by-step detail: Master Brief ↗
📄 The Master Brief — the full step-by-step to send Nic & the RN team
Every task below, expanded: exact steps, where to click, what needs an app release, how it's verified. Click a task # to jump straight to it.
Open ↗
P0 = blocks revenue / a promise already made on a page / seeing a sale at all · P1 = points the money right · P2 = improves what works · REL = needs an App/Play-store release (external RN team). 18 of 20 need no release. Numbers match the Master Brief.
Who owns what: Nic = paid + wiring + web + backend (almost everything) · Aga = email + Intercom (Task 20, and the Intercom sends) · external RN team = only what needs an App/Play-store release (Tasks 17, 18, and the code half of 12) · Claude = dashboards, verification, weekly reconciliation.
🎯 THE MRR-30 FILTER — "Does it touch MRR within 30 days?" If not, it WAITS. (Aga, locked 10 Jul · SoT §3 — outranks every other priority scheme)
PAYER 1 · Launch the trial
500 signups/wk get a working front door. 20 ✅ done → only Task 19 left (Stripe wiring, Nic) → GO.
PAYER 2 · Fix the purchase signal
Tasks 9 → 5 → 2/3 (+1, 7, 8) — then ASA + Meta warm scale with eyes open.
PAYER 3 · Non-converter emails
R1 send (ready, 112 members) · Intercom pushes (reachable today) · Task 11 export · AC non-converter sequence. Free money.
Everything else — redesigns, new fleets, charters, net-new builds — WAITS behind these three, and nothing bad happens. New task? It gets a lane or it gets WAITS.
Revenue & decisions — Aga + Claude, no wiring needed highest-value, do these regardless of the build queue
PriorityActionOwnerStatusValue
P0 · nowSend R1 — cancel-queue save (112 members)AgaEmail assembled & hardened, CSV ready. Still 0 saved. Import to AC → send.$1,591/mo at stake — fastest MRR in the plan
P0 · by 12 JulJuly-4 lifetime cart — final sends + closeAgaCart closes ~12 Jul (2 days). Confirm Fri–Sun sends are scheduled; close on time.One-time cash; deadline is real
P0 · decisionApprove or amend the $3K/mo paid strategyAgaThe plan is built & on the 🧪 tab, awaiting your go. Nothing paid executes until this.Unlocks the whole paid engine
P1 · nowIntercom push: “your 3 free workouts are waiting” → signed-up, no-workout poolClaude drafts → Aga sendsReachable TODAY — ~40.9K app users are in Intercom, no release, no export needed.Free retargeting (~500/wk enter this pool)
P1 · nowIntercom push / 72h step-down → paywall-viewed, no-trial poolClaude drafts → Aga sendsSame Intercom path, reachable now.Free retargeting (~180/wk)
P1Launch ASA brand-defence keywordsNic (paid)We currently bid $0 on “the movement athlete” — a competitor can conquest it for pennies. ~$3–5/day.Protects the brand term cheaply
Build & wiring queue — by priority
HARD STOPS

1 · Trial launch (PAYER 1): Task 20 ✅ cleared 10 Jul — the only remaining blocker is Task 19 (checkout Stripe wiring, Nic — 📦 zip handed off 10 Jul, ~half a day, preview ↗). 2 · No cold ad spend before Task 9 (PAYER 2) — every paid dollar lands on the web checkout, whose purchase event is double-counted and misses ~1 sale in 5. ✅ 21 Jul: Nic shipped the server-side Stripe webhook + transaction_id dedupe — verify on 24h of fresh data, then this stop lifts.

Priority#TaskOwnerRelease?Blocks
P020 ↗AC Day-5 trial reminder automationAgaHard stop: no trial may run until this sends (promised on the checkout page)
P019 ↗Checkouts v3 — Stripe wiring (8 pages) · 📦 HANDED OFF 10 Jul — zip on Aga’s Desktop (brief + message inside) · preview: tma-checkouts.netlify.app ↗ · ~half a day · 50% = evergreen at Stripe (no window checks) · ⚠️ PR into custom_checkout_app only AFTER July-4 closes (Sun 12 Jul)Nic🟢 noAll trial + 50%-off revenue
P09 ↗Web quiz purchase event — server-side + dedupedNic🟢 noAll cold ad spend — ✅ 21 Jul: server-side Stripe webhook + transaction_id dedupe shipped (was 1.52× dup, 81% capture); ⏳ verify on fresh data
P05 ↗T5 — AppsFlyer conversion events ★Nic🟢 noRepairs Google + Meta + ASA at once
P01 ↗Finish RC→Amplitude (remaining lifecycle toggles + $amplitudeUserId)Nic🟢 noLead→Trial, Trial→Paid rows
P02 ↗RC→Meta CAPI ✅ set 16 JulNic🟢 noMapping live (app events: fb_mobile_purchase/StartTrial/Subscribe). Now dedup (Task 3)
P03 ↗CAPI dedup (event_id)Nic🟢 noTrustworthy cost-per-purchase
P14 ↗Meta: Lead objective → PurchaseNic🟢 noCold prospecting (after 2+3). Optimise to fb_mobile_purchase, NOT Subscribe (renewals inflate it)
P111 ↗“Last funnel step” export → CIO/AC ★Nic🟢 no~$1–2.6K/mo free retargeting
P18 ↗GA4 → Google Ads conversion import — ✅ purchase REGISTERS in Ads via an independent GTM tag, NOT the GA4 import (Nic 20 Jul) → GA4's 1.52× doesn't contaminate Ads; ✅ 21 Jul: transaction_id + VALUE + currency now on the tag (both new & legacy checkouts), and LEADS register too via a generate_lead GTM tag; if GA4 import ever enabled → SECONDARY only; ✅ published 22 Jul; ⏳ ads-UI check after checkout testing (Task 19)Nic🟢 noAny Google return
P17 ↗Apple Search Ads cost dataNic🟢 noASA pilot — Month 1 (first channel to spend)
P213 ↗Geo exclusions ET/TZ/NG/BD — forward guardrailNic🟢 noVerified live 16 Jul: NO active campaign targets these geos (~$4/30d Meta spillover only). Re-apply when UAC returns
P114 ↗Meta Custom Audiences (warm pool) ✅ done 16 JulAga🟢 noBoth built: quiz-leads-no-purchase + all-time customers
P110 ↗GA4 quiz funnel segmentable by sourceNic🟢 noReading paid landing→start
P26 ↗Meta pixel event = "TMA Page View" ✅ identified 16 JulNic🟢 noPassive View-Content CC; no campaign uses it — KEEP, don't delete
P212 ↗Intercom push — anon-install registrationRN team → Aga🔴 yesSigned-up pools already push-reachable (~41K, no release); only anon installs need this
P215 ↗Google Ads API Basic access — ✅ GRANTED 20 Jul; spend auto-pulls dailyNic🟢 noCampaign-level ROAS
P216 ↗Rebuild UAC → optimise to trialClaude→Nic🟢 noBlocked until 5+8
REL17 ↗T4 — canonical user identity (keystone)RN team🔴 yesEvery server-side integration
REL18 ↗T7 — native product + lifecycle eventsRN team🔴 yesD1/D7/D30 retention
MRR-30 lane map: PAYER 1 = 19 (20 ✅ done) · PAYER 2 = 9, 5, 2, 3 + enablers 1, 7, 8, then 4/14 · PAYER 3 = R1 send, Intercom pushes, 11 · WAITS (fails the filter for now): 6, 10, 12, 13, 15, 16, 17, 18 — each runs only when it unblocks a payer, or when the payers are done.
Production serving from checkout.themovementathlete.com is settled (Aga) — not a task. Full click-to-expand steps for every row live on the Master Brief.
📊 Analytics — what's connected, what's not the wiring state at a glance · full spec: Master Brief ↗
Go deeper
📄The analytics brief and boardas of 2026-08-07
What is wired, what is lying, what graduates next — the canonical build board.
Open ↗
📄 The Master Brief — the full step-by-step to send Nic & the RN team
The wiring detail for each system, expanded: exact steps, where to click, what needs an app release, how it's verified. Click a task # to jump straight to it.
Open ↗
🧾 Checkout & attribution — running ship ledger newest first · every row carries the LIVE check that proved it, never a dev message · ground truth: CHECKOUT_ATTRIBUTION_CODE_AUDIT_GROUND_TRUTH_2026-08-03.md
🔴 3 Aug

A MEASUREMENT DISCONTINUITY LANDED TODAY — do not compare any checkout number across it. Both estates stopped minting Stripe records on page load. So from 3 Aug: phantom trial/subscription counts collapse BY DESIGN (not churn, not a demand drop) and checkout conversion rate jumps BY DESIGN (the denominator stops counting bounces). The pre-3-Aug conversion rate was fiction and is not a baseline. Clean data starts 4 Aug · first honest read ~11 Aug · reliable ~17 Aug. The quiz abandoner audience also shrinks by design and gets higher-intent — judge that lane on recovered purchases, never list size.

DateEstateWhat shippedHow we verifiedCloses
3 Augquiz-checkoutIntent no longer mints on page load. Mints on password blur (≥8), tap-to-load on the card area, or pay. stampPaywallView kept, so abandon recovery keeps a real audience. Plan switches cancel the prior incomplete sub.Curled the served /static/quiz_checkout/stripe-client.js (200, 17,446 B): maybePrefetch 0 · DOMContentLoaded 0 · stampPaywallView 3 · cancel-incomplete presentNIC-41 ✓
3 Augcheckouts-v3create-intent deferred off bare page load. Mints on valid email blur (or prefilled warm email) so stamp-abandon-email still has an intentId. Coupon recreate() cancels the prior incomplete sub. Live on trial / 50off / normal / 30trial.Curled the served /static/checkouts_v3/stripe-client.js (200, 23,573 B): no load-time mint · stamp-abandon-email 3 · cancel-incomplete 2 · header names the changeNIC-19 ch.1 ✓
3 AugbothCode audit of the LIVE repos became ground truth — replacing an Apr-2026 clone. Established the two estates never share an abandon mechanism, and that pay-click identity, provision_buyer_from_intent, UTM→Stripe metadata writes and the server Meta CAPI webhook were already built and must never be re-proposed.Read MovementAthlete-Django + MovementAthlete-React-ProdTemp directlydoc ✓
31 Julquiz-checkoutQuiz checkout shipped; quiz root → /2026-quiz-checkout-v1/ preserving the query string; password login gate closed; buyer excluded from abandon sends via mark_purchased.Live page reads + Aga confirm 2 Augshipped
21–22 JulbothServer-side Stripe → GA4 + Meta CAPI purchase webhook (/payments/analytics/stripe-purchase/, event_id = PI id); Google Ads leads + value-bearing purchases; GTM published.200 OK on a real USD 9.99 paymentshipped
⬜ Still open on this estate re-verified live 3 Aug, after the ships above
TaskTimeWhat it is — and why it is still open
NIC-16~10m🔴 DO THIS FIRST — it is a measurement, not a build. One purchase with ?utm_source=nictest → read the Stripe intent metadata. The write already exists on both estates, so this test may close the task outright and tells us whether the real gap is only first-touch rehydrate for bare landings.
NIC-19
ch. 4 + 5
~1hch.4 debris sweep: /lead 404 · past_due backlog · success-page UI/analytics gate on succeeded · RETURN_URL TLS (proxy reflection, not a source typo). 🔴 ch.5 pe= recipient → Stripe metadata — THE EMAIL GATE, see below.
NIC-30
+ NIC-37
+ NIC-46
~60m
batched
One React rebuild+redeploy closes all three. Re-verified 3 Aug: the site still serves index-CEOCAHYQ.js, the same hash the defect was filed against — 7 app-test hits, addToCartValue:0 on 1wk_trial, the dead Buy button, and two "4.9★" strings against the settled 4.7 ruling.
NIC-34~1hQuiz success page needs an fbq Purchase with eventID parity against the CAPI webhook that already exists. Halved by the audit — do not scope it as greenfield.
NIC-45~30mPhase 2, correctly deferred — carry OBSTACLE / FUTURE_STAKES / AGE / GENDER into the checkout so recovery emails stop being generic. Nothing waits on it.
📨 How the abandon email actually works Nic, 4 Aug 2026 · canonical · read before quoting any abandoner number
QuestionQuiz estatecheckouts-v3
Is there an abandon email?Yes — subject "Your login is in this email" (free first workouts + login details)No — none today. An hourly job can TAG those people into AC for the recovery lane. Tagging is not a send — never report it as an abandon email.
Who gets itSomeone who opened the CHECKOUT page with an email on it (almost always prefilled by the quiz handoff) and did not buy. No password, no card needed — landing on checkout with an email is enough.n/a
When≈1 hour after the checkout visit.n/a
What does NOT trigger itStarting the quiz. Typing an email earlier in the quiz and never reaching checkout.n/a
Who is visible in StripeRecovery is fed by stamp-paywall-view (Redis), not Stripe buyer_email.Typed a valid email → Stripe customer + open payment/sub created, email on both records → visible even if they never pay. Bounced without typing an email → not in Stripe at all (the 3 Aug defer-mint working).
🔴 4 Aug

The two emails everyone mistakes for the abandon. "…your results are ready!" fires when they finish the assessment; "One Last Step: Verify Your Account" fires when the account is created/verified. Both hit the same person at almost the same second, so they sit together in the log and look like the abandon. They are not it, and "results are ready" was NOT rewritten into the abandon. The abandon is ~1h later, so it can never appear in the same second. Separately: live sending was held off by a safety switch on Nic's side — fixed 4 Aug, a new build was deploying to Azure Prod. ⚠️ Until that build is confirmed live, "no abandons in the log" proves nothing either way — verify before quoting it.

👥

"Gave us their email but never reached checkout" is a DIFFERENT audience — and the abandon email cannot see it. That lane only knows people who hit the checkout page. Email-only quiz drop-offs sit earlier in the quiz / in ActiveCampaign, and are a separate segment we can build if we want it. Do not assume abandoner counts include them, and do not size the recovery opportunity as if they did.

🎟️

Coupons & affiliates — Nic's recommendation, 4 Aug. Keep the free trial and the quiz checkout clean — no coupon box on either. Affiliates go to the FULL-PRICE checkout, which already has a coupon field; a prettier affiliate link can just redirect there. That also covers future coupons for our own list — same page, same box. A separate affiliate checkout is optional and branding-only — more to maintain, and not needed to support coupons. Do not scope one as a requirement.

📧 EMAIL

The email-revenue attribution chain is 2 legs of 3 complete.Leg 1 — AC estate reached 100% UTM-tagged (1,101/1,101 links, 0/21 automations dark) on 3 Aug. ✅ Leg 2 — both checkout estates already flatten utm_*/gclid/fbclid into Stripe metadata at create-intent. ❌ Leg 3NIC-19 change 5, the pe= recipient field, ~30 minutes. Until it lands we can say "email made this sale" but never which contact, which automation, which slot — so the Email/Lifecycle fleet stays DARK on revenue against its 29 Aug charter gate, and the Evolution Law cannot name a losing slot on conversions.

One row per system. This is the status view; the To-Do tab is the ordered work, and the Master Brief has every step. The whole chain (ad → lead → paid customer [carded trial OR direct purchase] → retention) is what these systems make visible.
SystemStatusWhat it needs
RevenueCathealthySource of truth — 194 subs. Nothing to fix; it feeds tasks 1, 2, 5.
Amplitudeconnected · partialRC→Amplitude connected. 8 of 15 lifecycle rc_* event types live in Amplitude · auto-checked 12 Aug Task 1 — enable the remaining lifecycle toggles + set $amplitudeUserId.
AppsFlyerevents brokenaf_purchase fires ~2× vs 194 subs → every paid app channel unmeasurable. Task 5 ★ repairs all three at once.
Meta Adsoptimising wrongTrained on 5,171 Leads vs 172 Purchases. Tasks 2, 3, 4, 6.
Google Adssignal shipped · verifyNow receives Leads + value-bearing Purchases via independent GTM tags (Nic 20–21 Jul, Conv ID 18226881983). ⏳ confirm in Ads UI. Tasks 8, 13, 16.
GA4partial · fix shippedApp events good; web purchase was 1.52× / 81% capture — Nic 21 Jul: server-side Stripe webhook + transaction_id dedupe live. ⏳ re-verify. Tasks 9, 10.
Apple Search Adsno cost dataBest-converting paid source but spend not flowing → CAC unknown. Task 7.
Web quiz + checkoutserver-side shipped · verifyWhere every ad dollar lands. Nic 21 Jul: server-side Stripe webhook + dual-checkout (new + legacy) capture live. Task 9 — verify on fresh data.
Native appidentity missingNo shared user id across SDKs. Tasks 17 + 18 — external RN team, store release.
Backend / CRMnot exporting funnel stageTask 11 ★ export “last funnel step” to Customer.io/AC → ~$1–2.6K/mo free retargeting.
Intercompush live · ~41K reachableChecked 10 Jul: ~40,900 signed-up app users are push-reachable NOW (no release) → the no-workout/no-trial retargeting can go by push today. But anonymous never-signed-up installs are not in Intercom (0 of ~41K devices lack an email) → Task 12 needs the RN loginUnidentifiedUser() change.
✅ 10 Jul

RevenueCat → Amplitude — live event status: 8 of 15 lifecycle rc_* event types live in Amplitude · auto-checked 12 Aug Enable any remaining lifecycle toggles + reconcile ±5% vs RC (Task 1). The 06:00 job re-checks daily.

✅ 21 Jul

Conversion tracking shipped (Nic): Google Ads now sees Leads (generate_lead GTM tag) + value-bearing Purchases (value + currency + transaction_id, both new & legacy checkouts); and a new server-side Stripe → GA4 + Meta CAPI webhook (/payments/analytics/stripe-purchase/) fires purchases even when the browser fails — 200 OK on a real USD 9.99 payment. Full analysis + screenshot proof: docs/company/ANALYTICS/TRACKING-SYSTEM/. ✅ 22 Jul: GTM published (Nic). ⏳ Ads-UI conversion check sequenced after checkout testing (Task 19).

Known data-quality notes (carried over from the old Wiring tab): · begin_checkout is page-load-inflated (3,037 fires/14d vs ~2 real intents/day) — any funnel % using it is fiction; fix = fire on Pay-tap only + session dedup (part of Task 9/10). · 32 new app events (onboarding, workouts, paywall) started flowing into GA4 ~8 Jul — good, and they power the per-source funnel. · The web purchase event detail lives in Task 9.
Claude owns, zero Nic hours: all dashboards, the weekly cost-per-purchase reconciliation (CAPI purchases ↔ Stripe/RevenueCat), frequency + hook-rate reporting, source-segmented funnel views, and verifying each task against the live APIs with the real counts.
🎪AUDIENCE INTEGRITY — who we can email, the funnel-stage labels, and the send gate
LIVE 7 Aug: 11,057 app signups carry WHERE THEY STOPPED (%TMA_FUNNEL_STAGE% — 3,276 setup-stalls · 5,872 never-worked-out · 1,909 free-trainers, backfill verified 0-errors) + the 15 NEW quiz-* tags. Four-layer payer exclusion (the lifetime leak: 23/25 heaviest "free" users were payers) and the blocking segment gate — no send without a PASS.
Open ↗

⛔ SETTLED — don't re-propose

The arguments that were heard and answered. 8 of 12 still binding. Every ruling carries what would legitimately reopen it — bring that evidence, not the argument again. Generated from canonical_strategy.json on every refresh; status is verified against live sources, never inherited from the source doc.

Don't rebuild the Django checkout.LIVE
WhyThe 8 Jul autopsy proved the payment step works — 72% of card-entries succeed — and the diagnosed dominant leak was offer×audience, not checkout UX. A full rebuild is 7–10 of Nic's days on an unverified hypothesis. Critically, that 72% only measures card-entry→success; it says nothing about arrive→card-entry, which page-load ghost PIs were erasing.What would reopen it
≥2 weeks of CLEAN arrive→card-entry data showing the rate is genuinely bad (<50–60% on mobile) AND session recordings localising where users drop. At ≥60% the page is not the leak — reallocate Nic upstream.
Since it was decided
The unlock is NEWLY REACHABLE: NIC-41 shipped 3 Aug (maybePrefetch removed on quiz-checkout), so the ghost-PI contamination that made arrive→card-entry unmeasurable is gone on that estate. The cockpit currently shows paywall→card-entry ~15–20%, but that is a DIFFERENT measurement than arrive→card-entry — do not treat it as the unlock being met.

Decided 2026-07-08 · source: Decision Matrix §1.4 + §7 · SoT §3 · status verified 2026-08-04 vs CHECKOUT_ATTRIBUTION_CODE_AUDIT_GROUND_TRUTH_2026-08-03.md §0

Don't migrate ActiveCampaign → Customer.io before the RC events fire AND deliverability is warmed.LIVE
WhyMigrating the email estate onto a platform that cannot see purchase/trial events buys a rebuild with no new capability — and moving a list mid-reputation-problem compounds a deliverability breach into a cold-IP one.What would reopen it
Both halves. RC events: ✅ CLEARED — 8 rc_* events live (rc_initial_purchase, rc_trial_started, rc_trial_converted, rc_renewal, rc_cancellation, rc_expiration, rc_product_change, rc_trial_canceled). Deliverability: ❌ NOT CLEAR — 991 breached at 6.9% hard-bounce, NIC-38 (list hygiene) open.
Since it was decided
One of two conditions met. The RC half cleared quietly — do not cite this ruling as if the events are still missing.

Decided 2026-07-08 · source: Decision Matrix §7 · status verified 2026-08-04 vs canonical_facts.rc_events_live (8 events, as_of 2026-08-04) + email self-learn W32

Don't add Adapty. Don't drop Intercom.LIVE
WhyRevenueCat Experiments already covers app paywall A/B with no migration, and Intercom already runs our in-app messages. Both would be tool churn paid for in Nic-days with no new capability.What would reopen it
RevenueCat Experiments proving unable to run a paywall test we actually need, evidenced by a specific blocked test — not a feature-comparison table.

Decided 2026-07-08 · source: Decision Matrix §6 + §7 · SoT §3 Tooling · status verified 2026-08-04 — no contrary evidence in the estate

Don't ship the quiz Screen-1 copy change blind — it goes inside the A/B. Keep "8-minute assessment".LIVE
WhyScreen 1 is the highest-traffic screen in the funnel; changing it untested destroys the baseline that makes every later test readable.What would reopen it
None — this is a method rule, not a moratorium. Ship the change AS a test, any time.
Since it was decided
Sharper now than when written: the per-screen funnel measures S01→S02 at −51% (~700 users/month), so A/B #17 (goal-question-first) has an exact baseline. This is the top web lever.

Decided 2026-07-08 · source: Decision Matrix §7 · status verified 2026-08-04 vs cockpit Funnel 1 · Web tab per-screen data

Don't report begin_checkout as a conversion metric while intents mint on page load.LIVE
WhyA page-load-minted PaymentIntent inflates begin_checkout ~75×, which corrupts every downstream rate and every bid optimisation fed by it.What would reopen it
Per estate, once intents mint only on real buyer engagement.
Since it was decided
SPLIT BY ESTATE — quiz-checkout is CLEARED (NIC-41 shipped 3 Aug: maybePrefetch removed; intent mints on password blur ≥8 chars, tap-to-load card, or pay; stampPaywallView retained). checkouts-v3 is STILL AFFECTED — startCheckout() always creates Customer + Subscription on load. Name the estate before quoting this.

Decided 2026-07-08 · source: Decision Matrix §7 · status verified 2026-08-04 vs CHECKOUT_ATTRIBUTION_CODE_AUDIT_GROUND_TRUTH_2026-08-03.md §0 (served-file read, 3 Aug)

Don't run two paywall variables at once, and don't call a winner before the test is actually powered.LIVE
WhyAt TMA's volume a proper split-test needs a few hundred trials per arm. Two variables at once makes any result unattributable; calling early manufactures a winner out of noise and then ships it.What would reopen it
None — this is permanent method. Bigger, bolder changes judged by DIRECTION are allowed when volume genuinely cannot power a split; that is a stated choice, not a licence to call a split-test early.
Since it was decided
Reinforced by facts.measurement_gate (16 Jul): dedupe of the 1.52× double-fire + the Lead→Paid meter are a HARD GATE before any A/B winner call, bid optimisation or budget increase.

Decided 2026-07-08 · source: Decision Matrix §7 · §0 "we may not have the volume" · status verified 2026-08-04 vs canonical_strategy.facts.measurement_gate

Scale iOS ads on cost per trial net of Apple's cut — never on installs.LIVE
WhyInstalls are the metric that lied: 2,878 Meta app-installs produced 1 purchaser. Cost per trial net of Apple's ~30% year-one IAP cut is the only figure that makes a scale decision safe rather than a guess.What would reopen it
None — this is the measurement rule for the channel. Scaling itself unlocks when trial-level read is live (RC→Meta CAPI, AppsFlyer conversion events, canonical user_id) and a few days of real cost-per-trial data exist.
Since it was decided
Meta app-install campaigns are KILLED, not paused. ASA brand defence (~$8/day) is the recommended iOS entry — we currently bid $0 on our own brand terms.

Decided 2026-07-08 · source: Decision Matrix §1.1 · status verified 2026-08-04 vs TMA-PAID-EXPERIMENT-ROADMAP-JUL2026.md

Google Ads → the web quiz is a GO, but Category Search ONLY. No to Demand Gen and YouTube.LIVE
WhyCalisthenics category CPCs are genuinely cheap (£0.80–1.80 UK), but through a leaky quiz and dark nurture that modelled out to ~£41–66 cost per trial — 2.5–4× the ~£16 ceiling. July's Google result (1,809 page-loads, 0 sales) wasn't proof Google can't work; it was proof that spending before conversion events are wired produces no usable information. Demand Gen and YouTube are low-intent and unproven for us.What would reopen it
Four gates, in order: (1) intents mint on real engagement, not page-load; (2) quiz Screen-1 fixed AND organic completion confirmed >25% from 200+ sessions; (3) Meta restarted and proven FIRST — prove one channel cold before opening the next; (4) offline-conversion import wired so bidding targets trial_started, not page-views.
Since it was decided
Being followed — the Paid Roadmap scopes Google to "Category Search only" per the SoT. A free adjacent test stands: a 14-day brand-keyword pause (£0) tells you whether branded spend is pure harvesting (~£100–150/mo recoverable) or genuinely incremental.

Decided 2026-07-08 · source: Decision Matrix §1.2 · status verified 2026-08-04 vs TMA-PAID-EXPERIMENT-ROADMAP-JUL2026.md L186

Don't scale paid before the funnels are readable and the spend is proven incremental.SUPERSEDED
WhyJuly 2026 spent into a blind funnel: 1,809 Google page-loads → 0 sales, and 2,878 Meta app-installs → 1 purchaser. Cheap traffic into a leaky, unmeasured funnel buys information you cannot read.What would reopen it
The principle stands; the MECHANISM was replaced. The gate is no longer a geo-holdout — it is the Paid Experiment Roadmap's ladder: measurement wiring first (RC→AppsFlyer S2S), then per-month release gates, then a CAPI-confirmed CPP circuit-breaker every $750 of spend (scale <$50 · hold $50–70 · no-increase $70–87 · pause >$87).
Replaced by
TMA-PAID-EXPERIMENT-ROADMAP-JUL2026.md V3 (10 Jul, 7-seat paid fleet, unanimous) — cockpit 🧪 Paid Roadmap tab

Decided 2026-07-08 · source: Decision Matrix §7 · §1.2 · status verified 2026-08-04 vs TMA-PAID-EXPERIMENT-ROADMAP-JUL2026.md

Don't serve lifetime to cold traffic — warm-list only.SUPERSEDED
WhyCold traffic's first paid step must be a matched offer (the free 8-min assessment), never a $297 lifetime cart. Serving lifetime cold was July's root cause: offer×audience mismatch.What would reopen it
None — this was REPLACED BY A STRICTER RULE, not loosened. Lifetime is now never sold at all, to anyone.
Replaced by
facts.never_lifetime (16 Jul): NEVER sell lifetime again — sells ~$413 LTV for ~$274, adds $0 MRR, cannibalises recurring.

Decided 2026-07-08 · source: Decision Matrix §7 · status verified 2026-08-04 vs canonical_strategy.facts.never_lifetime

Split the analytics build: Nic owns Phase 0 plus the two attribution-critical merges; the RN team builds native T4–T7 in parallel.SUPERSEDED
WhyNic was the constraint (~85–145h backlog), so native work moved in parallel — but the two merges that decide whether channel data ever joins up (T4 canonical user_id, T5 purchase callback) needed his review before landing.Replaced by
Ownership LAW, 10 Jul (Aga): Nic = paid + wiring + web + backend (16 of 20 tasks) · Aga = email + Intercom · external RN team = ONLY what needs an App/Play-store release · Claude = dashboards, live verification, weekly reconciliation.

Decided 2026-07-08 · source: Decision Matrix §1.3 · status verified 2026-08-04 vs SPRINT_DOC_REGISTRY.md changelog 2026-07-10

Don't promise a "10-day" analytics path until the RN team produces a TestFlight build from the prod branch.EXPIRED
WhyThe 10-day estimate assumed a parallel RN-team native build; if their environment needed setup first, that time would be discovered mid-sprint instead of budgeted up front.Replaced by
The ownership model it guarded no longer exists — 10 Jul: Nic owns everything including web quiz/checkout; the external RN team handles ONLY work needing an App/Play-store release (Tasks 17, 18, and the code half of 12).

Decided 2026-07-08 · source: Decision Matrix §7 · §1.3 · status verified 2026-08-04 vs SPRINT_DOC_REGISTRY.md changelog 2026-07-10

📚 Every sprint document — one click synced daily 06:45 · registry: SPRINT_DOC_REGISTRY.md
Go deeper
📄The sprint docs hubas of 2026-08-11
Every shared strategy, governance and job document in one place.
Open ↗
DocumentWhat it isAudience
Growth PlanPlan of record — two funnels, Sprint Contract, lever map, to-dos (its §5 dashboard = this cockpit). estate-synced daily since 20 Jul (source recovered into the shared repo — headline numbers auto-refresh)Aga + Nic
Decision MatrixApproved decisions + Sprint Contract §0.5, dated targetsAga + Nic
Strategy Source of TruthWins on any contradiction — amend first, propagate afterAga + Nic
Sprint brief — Nic ↗Nic's build list: wiring tiers, A/B #17, eventsNic
RC→Amplitude Taxonomy ↗LOCKED tracking plan — canonical rc_* names, namespace lawNic + analytics
Native Event Catalog ↗Native app event catalog & wiring specNic
Scoreboard Operating Model ↗How the numbers flow: pulls, gates, Sheet, cadenceAga + Nic
Measurement Architecture (internal)How our tracking works end-to-end (ad→lead→paid→retention) — the data-room measurement doc; incl. the 21 Jul conversion-tracking delivery + screenshot proof. docs/company/ANALYTICS/TRACKING-SYSTEM/Aga + Nic + buyer (DD)
Retention Plan ↗R1/R2/R3 churn defense (folded in as Retention-Now)Aga + Nic
Quiz Funnel VersionsThe three live quiz funnels compared — traffic by source, funnel, AOV, retention, lead quality per version; Nic's 7 Aug documentation recorded against a live wire-check (7 Aug 2026)Aga + Nic
Sprint Doc Registry ↗THE list — folded-in map, update protocol, sharing boundaryAga + Nic + CEO fleet
📚 Full docs hubEverything above in one page (+ Growth North Star Hub, Nic growth brief)Aga + Nic
If a document isn't listed here or in the registry, it is not part of the ongoing sprint. New doc → add its registry row first (owner: tma-doc-steward).
🔍 SEO + GEO — the organic-search asset GSC + GA4 live · EXECUTING BOTH SITES — BWA rolling · TMA W1 SHIPPED 23 Jul (7 pages live)

📚 THE SEO DOCS (canonical pair, tabbed): TMA + BWA/channel master = marketing/seo/TMA_SEO_GEO_ANALYSIS_AND_PLAN_2026-07-20.md (v1.3 — §12 TMA deep-dive · §12.6 priority queue P1–P15 · §12.7 standing rules/cadence) + its browsable HTML twin (same folder, tabs: CHANNEL PLAN | TMA DEEP-DIVE | 🤝 AFFILIATE SEO | 🍎 ASO | 📮 OUTREACH — new 24 Jul, = §12.10: affiliate content BLOCKED for SEO, commercial-intent traffic routes to the quiz; BWA buying-intent = 6 clicks/28d; own product beats commission ~10×. 🔴 SEO = lane 1 of 5 — the affiliate strategy folds one lane at a time: SEO ✅ → blog/content pages (next) → YouTube → social → email, each ruling in its own doc, all inheriting one channel-agnostic doctrine (EXPERT_PROMPTS/AFFILIATE/). Never re-derive doctrine per channel. Full verdict marketing/AFFILIATES/AFFILIATE_INCOME_ANALYSIS_2026-07-24.md, fleet /affiliate-income, and the cockpit's own 🤝 Affiliates tab). Fleet constitution: marketing/seo/PAGE_CONVERSION_FLEET_PLAN_2026-07-21.md. W1 shipped (23–24 Jul): 7 TMA pages live w/ conversion layer + homepage H1/title · 7 pre-footer banners fixed · nav+footer chrome → quiz root · 19 typo fixes · best-app rebuild in gates. 🔴 measurement gate: quiz-root 301 strips UTMs — Nic one-liner pending; all UTMs dark until then. NEW rules: quiz-ROOT links everywhere · L2 video-embed on every touched article · pricing law: content pitches $157/yr (~$3.02/wk), $24.97/mo BANNED.

📮 OUTREACH — publisher placements & partner reactivation · owner tma-outreach-lead · run it with /outreach-fleet · status 5 Aug: BUILT, GATED, and deliberately PAUSED on new cold pitching
🤖 START HERE — the full handoff is §9 of marketing/seo/OUTREACH_MASTER_2026-07.md, rendered as the 📮 OUTREACH tab of the SEO master HTML. §9 alone tells any person or LLM where the lane is, what exists, what is open and on whom, and what happens next. §0 is the 60-second version.
🔴 The strategic answer (4 Aug, §7): 1,211 AI-engine sessions over 180 days produced ZERO attributed leads — against ~12 expected at the site rate (p≈1/180,000, so not noise). The visitors are fine (homepage 169s, /progressing-with-bodyweight/ 541s, and they reach /pricing/) — the counting is broken, and it is our own doing: every internal quiz CTA carries utm_source=tma, and GA4 restarts a session on campaign change, so a ChatGPT visitor's origin is erased the instant they click. Cross-domain is already configured, so those UTMs buy nothing. Verdict: do NOT fund more listicle pitching yet — not because the mechanism is disproven, but because we could not tell if it worked. Fix AGA-73 → wait 28 clean days → re-read → then decide.
Where it stands: 3 cold pitches sent 31 Jul, 0 replies, their ONE follow-up due 5–7 Aug (then the campaign is closed — no third touch, ever) · 3 partner emails written and gate-passed, held for Aga (AGA-97) · 🔴 Rick Donohoe is the one that matters: 65 clicks, 2 customers, £37.47, actively converting, never once contacted.
Two gates now run in code: tma-outreach-gate checks the EMAIL · tools/seo/outreach_lint.py checks the DOCUMENTS the email is written from and blocks --send on failure — because the 31 Jul near-miss was a document, not an email. Adversarially tested 8/8 caught, 3/3 legitimate ignored; it immediately found a real miss the human review had passed over.
🔴 Open on Aga: send/hold the 3 partner emails · commission TERMS, unratified since 25 Jul — the first "what are the terms?" holds a live conversation indefinitely · 2 web forms (AGA-29) · watch BOTH inboxes (AGA-30 — the 31 Jul pitches reply to hello@, everything since to hi@). Open on Aga: AGA-73 (the internal-UTM hygiene fix).

🏛️ SEARCH FLEET (24 Jul): chartered under the CMO — tma-seo-growth-owner executing owner · lanes SEO/AEO/GEO/ASO-parked · daily brief (marketing/seo/SEO_DAILY_BRIEF.md: AGA TODAY ≤3 · NIC TODAY ≤3, zero tokens) · Mon self-learn adjudicates the 14-day watches + writes the weekly CMO/CEO report. 🤖 AI-SEARCH SQUAD: ChatGPT referrals = 70–100% post-landing survival (Nic, REPORTED) → 2 new seats: tma-ai-citation-hunter (supply: citations/panel/listicles) + tma-ai-landing-optimizer (demand: pre-sold visitor → quiz-start); GEO items promoted to the FRONT of the weekly batch; north star = AI-referred leads→customers. Week-1 order: Nic S1 → auto link-migration → doorway (=citable object) → GEO ×2 → Aga's 2 words → listicle send → schema (Nic) → 8 light passes → 1–2 rebuilds. Master: marketing/seo/TMA_SEO_GEO_ANALYSIS_AND_PLAN_2026-07-20.md §12.8–12.9.

LIVE · auto-synced 2026-08-12

GSC 28d: BWA 3160 clk · pos 5.5 · TMA 2014 clk · pos 8.6. Organic quiz-starts: 8/7d · 44/28d.
Link integrity: PASS — 19 published links preserve UTMs + _gl. SEO work logged: 31 title/meta live-changes · 5807 total actions (last 2026-08-11). conversion-layer draft live-pending (page 253529).
AGA TODAY (≤3): 1) 🟢 GO/NO-GO: mail a 500-contact test segment of the 6,813 app-side contacts who finished the survey but never did a workout (NP verdict lever 1, $0, ranked DO-FIRST). The fleet drafts the activation email through /email-fleet + segment_guard.py and shows you the rendered email + segment PASS before anything sends — this row is only your GO to draft-and-show. Rates behind it are MODELLED (skeptic-flagged): read the 500-test click rate before touching all 6,813. (5m) 2) 🟢 GO/NO-GO: give '758 Nurture Sequence 2' (14,600 contacts) a quiz-root CTA slot — NP verdict lever 2, $0 ('fix the tap before the bucket'). Email currently sends the $97 quiz ~1 lead/8 days while 14 sales came from everywhere else. SISTER ROW to AGA-129 (weekly broadcast repoint) — one GO can cover both. Evolution-Law compliant path: ONE slot change through /email-fleet, not an arc rewrite; fleet executes end-to-end on your GO. (5m) 3) 🔴 TELL THE PHP DEV: calisthenicsacademy.co's Divi is 4.4.8 — the "only PBE" assessment is WRONG, and upgrading PHP first will break the site. Measured live 10 Aug: the ACTIVE THEME on CA is Divi 4.4.8, and Elegant Themes only added PHP 8.0 support in Divi 4.8 — so the theme predates PHP 8 support by four minor versions. Page Builder Everywhere is real but is NOT the only blocker and is the smaller one (its entire footprint is ONE copyright line in one widget area — the widget is Divi's own, so it moves to Divi's native empty Footer Area #1 and PBE deactivates; no replacement plugin). Likely cause of the wrong assessment: BWA runs Divi 4.27.7 (per NIC-14), so a check done there would look clean — CA was never separately verified. ⚠️ We CANNOT read PHP version from outside WP Engine, so I cannot tell you what PHP CA is on today — ask the dev. THE ASK: before the dev touches PHP on CA, they update Divi first (Elegant Themes Updater is installed and active — needs the ET API key, so confirm the Divi licence is still live), and ideally the whole job moves onto Rocket staging as part of the migration instead of running on the live site. Full plan, plugin disposition table and verification commands: docs/company/HOSTING_MIGRATION_2026-08/CA_PHP8_DIVI_UPGRADE_ADDENDUM_2026-08-10.md (10m)
NIC TODAY (≤3): 1) 🔴 REPOINT 'QLG | ADV+ OFF | MC | Control' TO THE QUIZ ROOT — 5 min in Ads Manager. All 4 of its live ads still land on https://quiz.themovementathlete.com/2026/, the old page that does NOT show the 97 dollar offer. Change the destination on all four to https://quiz.themovementathlete.com/ (the ROOT). Nothing else: leave url_tags, budgets, geo and the objective exactly as they are, and do NOT pause the campaign. EXACT LIST — adset 'General / T2 / FM 30-54 US/Canada' (GBP 9.62/day, geo US+CA): ad 120253084939360728 and ad 120253084939340728. Adset 'General / T2 / FM 30-54 AUS, FR, UK SING, NZ' (GBP 9.62/day, geo NZ GB IL AU FR): ad 120245527336080728 and ad 120245527336070728. WHY THIS AND NOT A PAUSE — measured live 11 Aug on the Meta API, 30 days, unified attribution: MC Control produced 129 leads at GBP 2.43 each, the biggest lead source on Meta (56% of the two QLG lines' 230 leads; 57 in the last 7 days). Pausing would cut Meta lead volume by more than half in the window we are banking leads for Black Friday. Repointing keeps all 129 leads/month and sends them to the page that shows the 97 AND enrols them into 993 SALES SEQUENCE, whose 10 Sep gate the whole paid plan waits on. Zero cash change either way — the account's daily budget is GBP 45.48 before and after. This is also exactly what Aga's 10 Aug ruling asked for ('RE-AIM into the ONE geo-locked lead line, quiz root'); NIC-97 was built as a clone, which the spec allowed, so MC Control itself was never touched. TWO OPTIONAL EXTRAS while you are in there: (a) drop IL from the second adset's geo — Israel is the only country in this campaign not on the buyer list (US UK CA AU DE SE NL FR); (b) pause the third adset 'General / T2 / FM 22-65 North America' — it holds a GBP 7.00/day budget but all SIX of its ads are paused, so it cannot deliver and spent GBP 0 in the last 7 days. Hygiene only, frees nothing. VALIDATION (2 min): after saving, open each of the 4 ads' preview and confirm the click goes to the quiz root and lands on the page showing the 97 offer, then confirm the campaign is still ACTIVE and its daily budget is unchanged at GBP 9.62 + 9.62. (5m) 2) 📲 RN TEAM — IN-APP PAYWALL UI REBUILD. Sent to the RN devs 5 Aug; awaiting their estimate then build. 🔴 THE LINK TO SEND (standalone dev site, 6 Aug — the claude.ai artifact links died twice; Aga ruled the handoff gets its OWN site, never a page under the revenue plan): https://tma-paywall-brief.netlify.app/ — the brief; it links the design contract (/spec.html) and the package zip on the same domain. All three verified live 6 Aug. Scope is UI-ONLY across ALL THREE existing pricing pages (full price / 30% off / 50% off) — RevenueCat, purchase, restore, terms and analytics already wired; offers already configured. Estimate 5h max in 6 milestones. THE ASK ON THEM: all three pages on the ONE component via variant='full'|'off30'|'off50', not three rebuilds — three drifting copies is how the current bug survived, and separate rebuilds roughly double the cost. WHAT TO WATCH FOR ON RETURN: (1) no price literal anywhere in the UI — every figure derived from the store product at render time, retry state if offerings fail; (2) they confirm the estimate BEFORE starting rather than pushing past 5h; (3) the on-device pass includes a NON-USD currency, the actual defect being fixed. Also in the package: 7 broken strings below the fold. NOT in scope (Aga, 6 Aug): the RN-1 identity + push add-on — Nic is already working on those. (15m) 3) 🤖 FLEET — 'THE ENGAGED LIST' IS NOT ONE LIST. ✅ DIAGNOSED 11 Aug, one decision left. Live AC tag census: 7 Day Engagers 1,666 · 30 Day 2,567 · Engaged(237) 2,912 · 60 Day 6,153 · 90 Day 7,172 · 180 Day 12,296 · 360 Day Engagers 19,826 · Active Users 14,054. AGA-119 says 'the engaged (~6,367)' and names NO tag — that figure sits between the 60-day (6,153) and 90-day (7,172) cohorts, so the audience for the plan's headline email has never actually been defined. 🔴 THE CHOICE SWINGS THE AUDIENCE 12x AND THE MODELLED PRIZE WITH IT. Two further findings: (1) tag 237 'Engaged' — the one the cockpit reports as 'engaged-reachable' — appears in exactly ONE file in the estate (tools/email-plan/email_cockpit_sync.py:60) and in no doc, so it is a DASHBOARD METRIC, not a proven send audience; its fall from 6,038 (31 Jul trust audit) to 2,912 is consistent with a rolling-window tag shedding the June-July intake wave (2.4x May, Facebook-heavy — CONFIRMED timeline event), i.e. mechanical decay, not list death [PLAUSIBLE, not confirmed — the maintenance rule is undocumented]. (2) History warns against reaching for the big tags: past promos went to 12,000-44,747 and 60-90% of every one went to people who had not engaged in a year. REMAINING: pick the tag with tma-email-deliverability + tma-segment-integrity-officer, write the rule down, and register a >20% drift check in estate_selfcheck.py. (60m)

🌱 Where the leads come from (generate_lead by lane · 7d / 28d)
Attribution-dark: 24.2% (target ≤25% — the leads hiding here are mostly owned content + YouTube)

7d28dshare
TMA.com content CTAs296213.6%
BWA article CTAs281.8%
YouTube descriptions330.7%
AI answer engines661.3%
Organic search (untagged)8449.7%
Organic social371.5%
Email230.7%
Other referral2173.7%
Paid ads7818841.3%
Other240.9%
🔧 Internal / QA traffic130.7%
⚠ Attribution-dark (unmeasurable)2311024.2%
TOTAL159455
🔴 Clean-data baseline 2026-07-29 — windows reaching earlier under-report owned content and over-state dark. First honest per-page read 12 Aug.

Auto-refreshes daily (launchd com.tma.seodailysync) + on every SEO session; source of truth = master .md v1.2 + wp_changelog.jsonl + SEO_HUMAN_QUEUE.json.

EXECUTION LOG · 21 Jul

✅ 31 BWA page titles/metas refreshed LIVE (keyword-front, year, on-brand; originals in wp_changelog.jsonl, revertible; Google recrawling). ✅ WordPress write access unlocked both sites (Yoast meta API-writable on BWA). ⏳ best-calisthenics-workout conversion-layer built as a DRAFT (page 253529, live untouched, 9 blocks + QA clean) — awaiting Aga go → apply live + 14-day rankings watch. ✅ AI-citation baseline (AI_CITATION_PANEL_2026-07-21.md). ▶ IN PROGRESS: the citable Assessment landing page (deep-research + agent build).

🔴 AI-SEO GAP

A competitor (Wild Dynamics) owns the "calisthenics assessment / find my level" query — our own product's query. The quiz app itself can't be ranked/cited (it's a JS web-app); we need a citable content page about the assessment (→ button into the quiz). We also own no "best app" category slot and are mis-framed "not for advanced". Full lead-gap map: AI_CITATION_PANEL_2026-07-21.md.

FRAME

This is a CONVERSION + CTR play, not a ranking play. Organic is already the #2 channel (33,714 sessions/90d, behind only Direct) — ~9,800 content sessions/mo become only ~146 quiz-starts/mo (1.5%). BWA already ranks (pos 2–5 head terms); the click ceiling is AI Overviews. The lever is converting traffic we ALREADY have. Ranking/GEO moat work is real but 3–6 months = bench behind the churn fix.

THE GOAL — organic quiz-starts/mo: ~146 today → 250–450 in 6 months (honest, evidence-ledger-consistent — the 5–8%-conversion draft number was audited DOWN) → 1,000+ at 12mo only via the compounding stack (free-tool citations · listicle presence · programmatic skills hub · January search wave). AI-referral already arrives unprompted: ChatGPT 501 sessions/90d (+ Gemini 99, Perplexity 24) and converts +31%→several× vs organic.
AUDIT

Adversarial audit findings (20 Jul, live-checked):Crawl-delay: 10 sits in BOTH robots.txt — Bing honours it, and Bing powers ~87% of ChatGPT citations: we are literally throttling ChatGPT's index (5-min fix). ② ChatGPT already recommends our free assets + the QUIZ unprompted (homepage 253 · quiz 75+ · best-program 50 · 28-day challenge 32 · handstand PDF 29) — LLMs recommend TOOLS; double down on the citable objects. ③ TMA is absent from every ranked "best calisthenics app" listicle (Fitloop, GainStrong, Caliverse, Cali Move…) — the exact lists ChatGPT reads for the money query. ④ BWA hands only ~79 sessions/mo to product properties — the blog→product bridge barely exists. ⑤ GA4 "conversion" is mis-set to session_start — organic→lead is invisible until fixed.

Live search estate (28-day, to 17 Jul · CONFIRMED via GSC):
DomainClicksImpressionsAvg positionRead
bodyweighttrainingarena.com (BWA)3,5291.9M4.7the bigger asset ranks for high-intent head terms
themovementathlete.com2,119366K8.3brand hub; ~35% impressions on off-brand product-review pages
Page-level truth — where the money is:
PageTrafficVerdict
/best-calisthenics-workout/~800 clk/mo · pos 2–3.5THE lever ranks for "calisthenics workout" (476 clk), "workouts", "program", "routine". CTR suppressed to 0.5% (vs 7–10% expected) — AI Overview eats clicks. Fix = convert the ~800/mo already landing here, not chase rank.
/elbow-lever-progression/18 clk/molow priority "elbow lever" impressions are intent-polluted (plumbing hardware term). Little clean fitness demand.
"calisthenics workout plan" 1.1M impr0.01% CTRIGNORE SERP-feature artifact — same page/same position gets 50× the CTR on a real term. Not a real lever.
The SEO action · click to open What · Why · How
A Convert the ~800/mo on best-calisthenics-workout → quiz-starts ~$40–85/mo + measurement · SEO owner

What — Add a prominent, UTM-tagged quiz CTA to the BWA page that already gets ~800 organic visits/mo, then (bigger) redesign it as the highest-converting version. MODELLED conversion; CONFIRMED traffic.

Why — The traffic already exists and is mostly wasted. This is a conversion play, not a ranking play — days/weeks, not the 3–6 months SEO usually needs. It also wires the organic→quiz→paid measurement loop that makes this whole tab real. Gated on Task 19 (checkout must work, or we make leads not cash).

How — step by step
  1. Confirm Task 19 (checkout) works first — see the Growth Fleet tab, task 5.
  2. Quick win: add a mid-page + sticky CTA to best-calisthenics-workout — "Get YOUR personalised plan — free 5-minute assessment" (⚠ "60-second" is BANNED per Aga ruling — quiz avg is 3.2 min) — linking to the quiz with ?utm_source=bwa&utm_medium=organic&utm_content=best-calisthenics-workout.
  3. Watch GA4 for bwa / organic quiz-starts within 7 days; kill if <30/mo (intent mismatch).
  4. Full redesign: route through /quiz-design using the 7-point playbook below — conversion-decided aesthetics, MEDIA_INTEGRITY_LAW, 2× design-director SHIP.
  5. Prove the lift on this one page, then template to the other BWA pages.
BWA redesign — the highest-converting-page playbook (Aga-requested 20 Jul). Route through /quiz-design (conversion-decided aesthetics, MEDIA_INTEGRITY_LAW, 2× design-director SHIP):
1 · Match intent to offer exactly. Hero = "Get YOUR personalised calisthenics plan — free 5-minute assessment" (outcome-first; "60-second" BANNED per Aga ruling). The quiz literally IS what they searched for.
2 · Frame as a personalised assessment, not a generic free tool — higher perceived value, maps to the product.
3 · CTAs at every scroll depth — above fold, mid-article, sticky/end. The current single bottom CTA is where the traffic leaks.
4 · Real social proof beside the CTA — calisthenics-beginner testimonials from the tagged DB.
5 · Mobile-first + fast — organic search is mostly mobile; dated pages leak hardest there.
6 · UTM-tag every CTA — measures the organic→quiz→paid loop AND makes this tab's numbers real.
7 · Don't touch what ranks — keep the URL, headings, body that earn pos 3.5. Conversion LAYER over the page, never risk the rankings.
⚠ GATE

The BWA redesign only pays if the checkout works (Task 19). Beautifully-converted traffic into a broken paywall makes leads, not cash — Task 19 gates the value of the whole play.

🔧 DO NOW — 5 QUICK WINS (Aga executing 21 Jul)

Non-technical, click-by-click. Full guide: marketing/seo/DO_NOW_SEO_TASKS_2026-07-21.md. Log into bodyweighttrainingarena.com/wp-admin first. Order: ①② first (biggest + easiest), ⑤ → Nic.

#Task · whyExact stepsWho · time
Remove robots.txt "Crawl-delay:10" — it throttles Bing = throttles ChatGPT indexingWP admin → Yoast SEO → Tools → File editor → in the robots.txt box delete the line Crawl-delay: 10Save. Verify: visit /robots.txt, no "Crawl-delay". (TMA site → Nic.)Aga · 5 min
Retarget the footer "TAKE A FREE ASSESSMENT NOW!" button — it leaks every page's hottest click to a legacy un-tracked pageDivi → Theme Builder → edit the Footer template → click the button's gear → Link tab → paste https://quiz.themovementathlete.com/?utm_source=bwa&utm_medium=blog&utm_campaign=footer&utm_content=footer-cta → ✓ → Save.Aga · 10 min
Bing Webmaster + IndexNow — the ChatGPT front door (instant indexing)bing.com/webmasters → sign in → "Import from Google Search Console" (verifies both sites) → Sitemaps: submit sitemap_index.xml → URL Submission: submit /calisthenics-level-assessment/.Aga · 25 min
Fix the page title (show the year) — Divi is overriding YoastDivi → Theme Options → Integration (ensure Yoast controls the title); then Pages → the assessment page → Yoast box → confirm SEO title has "(2026)" → Update. If fiddly → Nic.Aga/Nic · 5 min
Consolidate SEO plugins (keep Yoast) — 3 conflict; ⚠️ redirect riskHAND TO NIC. Backup first → confirm redirects live in the Redirection plugin → deactivate All in One SEO + SEOPress → keep Yoast. Do NOT DIY.Nic · 30 min
🎯 "THOUSANDS OF LEADS" LEVERAGE PLAN (21 Jul) — leads = sessions × conversion (~9,800 sess/mo → 146 quiz-starts = 1.5%); fastest lever = convert traffic we already have:
TierMoveStatus
🥇 T1Prove best-cal overlay → roll across top 20 pages (3–5× conversion, same traffic — THE big lever) · internal-link every article → the Assessment pagepilot draft ready; rollout on 14-day-watch pass
🥈 T2Build the citable "Calisthenics Level Assessment" page (own "find my level" vs Wild Dynamics) · comparison page + listicle outreach · claim the open "assessment-first/adaptive/injury-safe" category slot▶ BUILDING NOW (assessment page)
🥉 T3Proprietary 100k-user data pages · programmatic skills hub (skill_tree.json) · digital PR + Bing/IndexNowcompounding, months
⚙️Needs Aga/Nic: Bing/IndexNow · plugin consolidation · modified-date un-freeze · GA4 key-event fix · publish gates · outreach sendqueued
THE ORGANISED TO-DO — every task opens: Why · Step-by-step · Who · EXECUTING (live changes logged/revertible; publishes gated to Aga)

⚡ THE EXECUTION MODEL (Aga's "fastest possible way" question — answered): BWA runs WordPress with the REST API live and Application Passwords enabled (verified this session — plus Yoast/SEOPress/Redirection endpoints). One 5-minute password creation (task 0.0) and Claude edits titles, metas, content, creates draft articles, and manages redirects DIRECTLY — no Nic paste-loop. Rule of engagement: Claude does everything Claude can (all writing, all page edits as drafts, all analysis, generators, monitoring); Nic only for true technical (GA4 admin, robots.txt/server, theme/CSS, plugins, data exports); Aga only decides (approves batches, clicks Publish, sends outreach). Safety: Claude never publishes live — everything lands as a DRAFT or revision for one-click approval.

TIER 0 — THIS WEEKnear-free, high leverage · ~1 focused Claude day + ~3 Nic hours total
0.0 WordPress API access for Claude — THE execution unlock AGA 5 min · CLAUDE then does ~70% of this plan directly

Why — Verified live: BWA's REST API is enabled with Application Passwords. With one credential, Claude executes tasks 0.4, 1.2, 1.3, 1.5, 1.6, 1.7, 2.3, 2.4 itself (as drafts) instead of producing paste-jobs for Nic. This single task collapses the plan's calendar time by weeks. It is also the answer to "how do we publish articles easily" — Claude writes → REST draft → you click Publish.

Step by step
  1. Aga (or Nic): BWA WP Admin → Users → your profile → scroll to Application Passwords → name it claude-seo → Add → copy the generated password once.
  2. Repeat on themovementathlete.com (same 2 minutes — Claude verifies its REST API first, expected same).
  3. Drop both into .env.local as BWA_WP_USER/BWA_WP_APP_PW + TMA_WP_USER/TMA_WP_APP_PW (never in code — house rule).
  4. Claude builds tools/seo/wp_publish.py — read/update/create posts + titles + meta, drafts-only by default, with a change-log of every edit.
  5. Test: Claude pulls one post, makes a trivial draft revision, Aga confirms it appears in WP admin. Then the whole Tier-1 batch runs through it.

Redesign path (the "how can we redesign" question): content-level redesign (overlays, CTAs, capsules, sections) = post-HTML → Claude via API. Site-level design (theme/CSS/templates) = one-off Nic snippet or child-theme change — Claude writes the exact CSS/PHP, Nic installs once.

0.1 Remove Crawl-delay: 10 from both robots.txt CLAUDE drafts · NIC uploads 5 min

Why — Audit find: both domains tell crawlers to wait 10s between requests. Google ignores it, but Bing honours it — and Bing's index powers ~87% of ChatGPT citations. We are literally rate-limiting the index that decides whether ChatGPT can cite us (~8,640 URLs/day ceiling, slow fresh indexing).

Step by step
  1. Claude drafts both replacement robots.txt files (delay line deleted; sitemaps + wp-admin rules unchanged).
  2. Nic replaces them (Yoast → Tools → File editor, or server file) on BWA + TMA.
  3. Verify in browser at /robots.txt — no Crawl-delay line.
  4. Bing WMT (0.2) then re-crawls at full speed within days.
0.2 Bing Webmaster Tools + sitemaps + IndexNow, both domains NIC/AGA ~45 min · CLAUDE monitors

Why — ChatGPT search retrieves from Bing's index — a page Bing hasn't indexed cannot appear in a ChatGPT answer, regardless of Google rank. Bing WMT also ships a FREE AI Performance report (new Feb–Jun 2026) = a zero-cost citation tracker for Copilot/Bing AI. This is the gate to the entire GEO play.

Step by step
  1. Aga/Nic: bing.com/webmasters → sign in (any Microsoft account) → "Import from Google Search Console" — verifies both properties in two clicks, no DNS work.
  2. Confirm sitemaps imported (BWA sitemap_index.xml, TMA wp-sitemap.xml); submit manually if not.
  3. Nic: enable IndexNow on both sites (Yoast/SEOPress toggle or the official IndexNow plugin) → every new/updated URL pings Bing within minutes.
  4. Open the AI Performance report, screenshot the baseline (citation share = our starting line).
  5. Claude (day 7): review index-coverage, list any unindexed money pages, submit them manually.
0.3 Fix GA4 conversion config + cross-domain NIC ~1–2 hrs · CLAUDE verifies after · cross-domain ✅ 23 Jul (key events still open)

Why — The property's "key event" is currently session_start — meaningless — so every organic-conversion report is polluted, and the real lead signal (survey_started) isn't counted as a conversion anywhere. Until this is fixed we cannot prove any lift from any task in this plan. Also: BWA→quiz is cross-domain; if stitching is off, blog-driven quiz-starts mis-attribute and the overlay test (1.1) can't be read.

✅ 23 Jul — cross-domain half CLOSED (Aga): GA4 "Configure your domains" verified already correct (BWA + all TMA subdomains listed), AND the GTM Conversion Linker typo (bodyweighttrainingare.combodyweighttrainingarena.com) fixed + container published in GTM-TKGDZR9 — BWA gclid/ads cross-domain linking now works (allow 24–48h). Remaining in this task: steps 1–2 (key-event toggles) + the 48h verify.

Step by step
  1. Nic: GA4 Admin (property 177471782) → Events → toggle OFF "key event" on session_start.
  2. Toggle ON: survey_started, take_personalized_assessment, landed_on_pricing_page (and AppOnboarding_completed).
  3. Admin → Data Streams → web stream → Configure tag settings → Configure your domains: ensure themovementathlete.com, bodyweighttrainingarena.com, quiz. + checkout. + app. subdomains are ALL listed ✅ done 23 Jul — was already configured; GTM Conversion Linker typo also fixed + published same day.
  4. Claude (48h later): re-runs the organic probe, confirms clean conversion counts, updates the cockpit numbers.
0.4 CTR-recovery rewrite — /best-calisthenics-workout/ CLAUDE writes + ships draft via API · AGA picks variant

Why — Our flagship ranks pos 3.5 for "calisthenics workout" (88,956 impressions/28d) but wins only 0.54% of clicks — the snippet loses even when shown. Title + meta + first-200-words is the ONE lever that can't hurt rankings (H1/URL/headings untouched — SEO-owner veto enforced). Honest recovery: 0.54%→1.2–1.8% = +600–1,100 sessions/mo MODELLED.

Step by step
  1. Claude drafts 3 title/meta variants (year + outcome + differentiator) + a front-loaded answer capsule for the first 200 words with proprietary stats.
  2. SEO-owner veto pass (nothing that ranks gets touched).
  3. Aga picks the variant (2-min decision).
  4. Claude ships it as a draft revision via the WP API (0.0) — or hands Nic the paste if 0.0 isn't done.
  5. Publish → IndexNow ping → Claude watches CTR weekly via gsc_pull.py; auto-flag a revert if position drops >0.5 for 2 weeks.
0.5 AI-citation prompt panel — baseline CLAUDE fully — no Nic

Why — We can't manage what we can't see: today we have zero visibility on whether ChatGPT/Perplexity/AIO cite us vs Caliverse/Cali Move/Fitloop for the queries that matter. A fixed panel makes citation share a tracked number, free.

Step by step
  1. Claude builds the panel file — 20–30 fixed prompts across 5 classes: branded ("is The Movement Athlete good"), category ("best calisthenics app"), concept ("what are microprogressions"), data ("how long to learn a pull-up"), comparison ("Cali Move vs Movement Athlete").
  2. Claude runs the baseline across ChatGPT, Perplexity, Gemini, Google AIO — logs per prompt: are we cited? our terms used? who won the slot?
  3. Saves to marketing/seo/AI_CITATION_PANEL.md with date-stamped runs; monthly re-run = geo-strategist standing duty.
  4. Output: the citation-gap list that feeds task 1.3/1.4 targeting.
TIER 1 — THIS MONTHbiggest absolute lead impact — converts traffic + citations we already own
1.1 Ship the BWA conversion overlays (top-5 pages) AGA: Phase-1 GO · CLAUDE builds · NIC if theme-level

Why — ~9,800 sessions/mo convert at 1.5%. The overlay plan (already written, evidence-led, rankings-safe by the Overlay Law) lifts the biggest pages. Ledger-honest expectation: +50–150 starts/mo MODELLED (L-015). ⚠ Gated on Task 19 checkout — converted traffic into a broken paywall makes leads, not cash.

Step by step
  1. Aga: Phase-1 GO on BWA_CONVERSION_LAYER_PLAN_2026-07-20.md (the open decision from the 20 Jul session).
  2. Live-check Task 19 checkout first (house rule: verify live).
  3. Claude builds the P1 overlay for best-calisthenics-workout — hero-adjacent CTA, mid-page CTA, end CTA, UTM law (utm_source=bwa), "5-minute assessment" copy (never "60-second" — BANNED).
  4. Ship via WP API as draft → Aga approves → publish. Theme/CSS-level pieces (sticky-bar test) → Claude writes, Nic installs.
  5. 7-day GA4 watch (clean after 0.3): kill if <30 starts/mo pace; else template to pages 2–5.
1.2 Public "Free Calisthenics Level Assessment" page — the citable tool CLAUDE writes all · AGA publishes

Why — LLMs recommend TOOLS: our own GA4 shows ChatGPT already sends people to the quiz unprompted (75+ landings/180d) with no dedicated public page selling it. /calisthenics-assessment/ already exists and ranks (14 clk/28d, pos 9.4) — upgrading it into THE citable free-tool object is near-zero build for the highest-leverage GEO asset we can own.

Step by step
  1. Claude rewrites /calisthenics-assessment/: answer capsule ("What is the free calisthenics assessment?"), what-you-get, how-it-works, proof, FAQ schema, quiz CTA with UTM. Copy: outcome-first, "5-minute" (never "60-second").
  2. SEO-owner veto pass; ship as WP draft via API → Aga publishes.
  3. Claude adds a contextual link to it from the top-20 articles (folds into the 1.3/1.5 batch edits).
  4. IndexNow ping; add "free calisthenics assessment" queries to the prompt panel; watch GSC position + AI-referral landings monthly.
1.3 Double-down on ChatGPT's already-cited pages (top-20 list) CLAUDE writes + drafts via API · AGA approves batch

Why — The engines already chose these URLs (homepage, /the-best-calisthenics-program/, free guides, 28-day challenge…). Reinforcing an existing citation compounds far faster than begging for a first one — we feed pages the models already trust.

Step by step
  1. Claude takes the exact top-20 AI-landing list (already pulled from GA4 this session).
  2. Per page: front-loaded answer capsule, ≥1 proprietary stat per section, visible "Updated July 2026", 5-question FAQ block.
  3. Ships the whole batch as WP draft revisions via API, with a one-page change summary for Aga.
  4. Aga approves → publish → IndexNow each → panel (0.5) tracks citation change monthly.
1.4 Listicle insertion — "best calisthenics app" lists + our comparison page CLAUDE preps all · AGA sends outreach

Why — The money query ("best calisthenics app") is answered by ChatGPT from ~9 ranked listicles — TMA is a named winner in NONE (Fitloop, GainStrong, Caliverse, Cali Move, Hybrid Calisthenics own the slots, several smaller than us). Getting added is worth more than any on-site tweak for the recommendation query class. We even have an affiliate program page to offer.

Step by step
  1. Claude builds the target sheet: the ranked listicles + contact/affiliate route per site.
  2. Claude drafts per-site outreach: affiliate commission offer, free review access, honest product blurb, 4.9★ + 100k-users data, review-ready screenshots.
  3. Aga sends from her real address (relationships are human — no automated outreach).
  4. Claude writes OUR honest comparison page ("The Movement Athlete vs Cali Move vs Caliverse vs Fitloop") — balanced tone, structured table, no trash-talk (AI systems skip promotional hit-pieces). Publish via API draft.
  5. Track adds + citation change on the panel monthly; iterate targets.
1.5 Fact-density + front-loaded capsules — top-10 traffic pages CLAUDE writes + drafts via API · AGA approves

Why — Adding statistics is the single strongest on-page GEO tactic (+≈41% AI visibility), and ~44% of ChatGPT citations come from the first third of a page. Our proprietary numbers (96 levels, 25 pull-up progressions, 100k+ users) are the uncopyable version of this.

Step by step
  1. Claude takes the top-10 GSC pages not already covered by 1.3.
  2. Per page: answer capsule after every question-H2 · ≥1 specific number per section · comparison table where natural · "Purpose" line per exercise (CLAUDE.md standard).
  3. Batch as API drafts + change summary → Aga approves → publish + IndexNow.
1.6 Prune TRUE off-brand review content CLAUDE decides list · AGA approves · NIC toggles noindex

Why — Leg-press/cable-machine/gym-gloves/belt reviews (~35% of TMA impressions) train Google AND the LLMs that we're a generic review site — diluting the exact entity ("the progressive-calisthenics authority") that GEO depends on. Audit nuance: calisthenics-adjacent gear (gloves for bars, dip bars) gets KEPT/merged, not pruned.

Step by step
  1. Claude produces the definitive URL decision table from GSC data: PRUNE (true off-brand) / KEEP+MERGE (calisthenics-adjacent) / UNTOUCHED — with clicks + any affiliate-revenue flags.
  2. Aga approves the list (some pages may earn affiliate income — her call).
  3. Nic sets noindex,follow per URL (Yoast bulk edit) — NOT deletion.
  4. Observe 4 weeks in GSC; then decide delete vs 301 per page. Reversible at every step.
1.7 Freshness pass — top 20 pages CLAUDE via API · AGA approves

Why — A visible current year lifts AI citation odds ~30%; Perplexity cites <30-day content ~82% of the time; live titles still saying "2024 picks" actively signal staleness to both Google and the engines.

Step by step
  1. Claude drafts per-page: updated title year, refreshed stats, visible "Updated July 2026" line.
  2. Batch as API drafts → approve → publish + IndexNow.
  3. Standing rule: quarterly repeat (geo-strategist duty; calendar it).
TIER 2 — MONTH 2–3the content moat — 10× faster via generation
2.1 Programmatic skills hub — 100+ pages generated from skill_tree.json CLAUDE builds generator + pages · NIC hosts · AGA approves structure

Why — The single strongest topical-authority play: nobody else has 102 skills / 496 progression rungs with video, machine-readable and drift-locked. The audit re-scoped this from "months of editorial" to a generator project (1–2 weeks) — the exact pattern that already emits our internal skill-tree docs. Ship by Nov–Dec to catch the January search wave.

Step by step
  1. Claude writes the generator: skill_tree.json + media DB → 100+ static pages (per-skill: full ladder, capsules, FAQ+HowTo schema, timeline placeholders, hub interlinks) + the master hub page.
  2. Aga approves the template on 3 sample pages (design + copy voice) before the batch.
  3. Hosting decision with Nic: WP import via API vs static subfolder — Nic wires whichever.
  4. Publish the batch → IndexNow → hub into site nav → panel watches "X progression" citation share.
2.2 Publisher-entity stitching BWA→TMA CLAUDE writes schema · NIC installs site-wide

Why — Today a ChatGPT citation of BWA builds a brand nobody buys. Publisher schema + a visible "a The Movement Athlete publication" byline makes every BWA citation feed the TMA entity — the thing ChatGPT's parametric memory actually learns.

Step by step
  1. Claude writes the Organization/publisher JSON-LD (BWA publisher = The Movement Athlete, sameAs links) + the byline + consistent Jesse author bio ("Head Coach" — per ruling, never "Founder").
  2. Nic adds site-wide (theme header or SEO-plugin slot).
  3. Validate with Google's Rich Results test; panel watches branded-query citations.
2.3 Proprietary data pages ×3–5 — "real data from 100k+ members" NIC data export FIRST · CLAUDE analyses + writes

Why — Original research is the highest-citation content type (data-rich pages show ~340% higher AI citation); nobody can copy our progression timelines. Perplexity cites it within days; ChatGPT durably.

Step by step
  1. ⚠ BLOCKER CHECK FIRST — Nic/Aga confirm what user progression data is actually exportable. House rule: only verifiable numbers ship; if the export can't support "average time to first pull-up," we don't claim it.
  2. Claude analyses the export → real timelines by age/frequency/starting level.
  3. Claude writes pages 1–3 (pull-up, push-up, handstand — highest search volume) to the answer-capsule + table standard; API drafts → approve → publish.
  4. Each page feeds 3.1's PR pitches (same data, distributed).
2.4 Consolidate cannibalising clusters (planche · front-lever · pull-up · push-up) CLAUDE maps + writes · NIC 301s

Why — Authority for each skill is split across multiple mediocre pages (front-lever spread over 4+ URLs at 0.1–0.4% CTR). One definitive guide per skill concentrates links, relevance, and snippet strength.

Step by step
  1. Claude maps each cluster from GSC (URLs, clicks, impressions) → names the keep-URL per cluster.
  2. Claude writes the merged definitive guide into the keep-URL (API draft).
  3. Aga approves → publish → Nic sets 301s from the merged-away URLs (Redirection plugin — has REST, Claude can stage them).
  4. GSC watch 4 weeks; expect a temporary wobble then a consolidation lift.
2.5 Schema rollout — Organization + Person + Article/FAQ/HowTo CLAUDE specs exact config · NIC configures ~2 hrs

Why — Google AI Overviews and Gemini lean on structured data; Person schema builds the Jesse entity. Plugin configuration, not a dev project.

Step by step
  1. Claude writes the exact plugin settings + custom JSON-LD blocks (Organization both homepages; Person/Jesse on author pages; FAQ on top guides — 40–60-word factual answers; HowTo on instruction pages).
  2. Nic applies (~2 hrs) — ⚠ BWA runs SEVERAL SEO plugins at once (Yoast + SEOPress + AIOSEO namespaces all live in the API) — Nic should consolidate to ONE; plugin overlap = duplicate schema + bloat.
  3. Validate top 20 with Rich Results test; GSC Enhancements watch.
TIER 3 — MONTH 2–6off-site — where ChatGPT's parametric memory is won · all moat content live by Nov–Dec for the January wave
3.1 Digital PR — distribute the data stories CLAUDE drafts everything · AGA sends

Why — Brand mentions correlate ~3× more strongly with AI citation than backlinks; the same claim distributed across many publications lifts citations up to +325%. This is how ChatGPT's training-memory learns "The Movement Athlete = progressive calisthenics authority."

Step by step
  1. Angles from 2.3's data pages ("average time to first strict pull-up across 100k members" etc).
  2. Claude drafts the pitch kit + target list (fitness/health/longevity pubs + journalist-request platforms).
  3. Aga sends (human relationships); Claude logs placements.
  4. Panel + Bing AI report track the citation lift over 90 days.
3.2 Reddit + Jesse entity + podcasts CLAUDE preps material · HUMANS post/speak — non-delegable

Why — Reddit/forums feed Perplexity heavily; podcasts (transcripts crawled) build the Jesse entity. Must be genuinely human — astroturfing risks bans and brand damage, so Claude preps, never posts.

Step by step
  1. Claude builds a progression Q&A answer bank in Jesse's voice using canonical terminology ("Head Coach", collaborative-team positioning per rulings).
  2. Jesse/Aga genuinely participate in r/bodyweightfitness etc. 2–3×/week from the bank.
  3. Claude drafts the podcast one-pager + pitch list; target 3–5 appearances in 6 months.
  4. Consistent bios everywhere (entity coherence).
3.3 Interactive progression calculator — second citable tool CLAUDE builds · NIC hosts

Why — "How long will it take me to get X skill?" is un-answerable by a static AI reply — engines cite the tool instead. Reuses skill_tree.json; sequenced after 1.2 proves the tool-citation pattern.

Step by step
  1. Claude builds a static-JS prototype (inputs: current level, frequency, age → timeline from skill-tree + data-page numbers).
  2. Aga approves; Nic hosts on BWA; answer-capsule landing page around it (Claude).
  3. IndexNow + panel tracking.
TIER 4 — PARALLELmeasurement & hygiene — Claude-only, near-zero cost
4.x Measurement & hygiene bundle CLAUDE fully (llms.txt upload: NIC 5 min)
  1. 4.1 Quantify the GA4 AI-referral→survey_started join (script exists from this session) — turns lead claims MODELLED→CONFIRMED.
  2. 4.2 Paid AI tracker (Profound/Peec/Semrush AI) considered ONLY after the free panel + Bing AI report prove the channel.
  3. 4.3 Claude writes llms.txt both domains (zero cost; helps Perplexity/Claude marginally; NO ChatGPT expectation — OpenAI doesn't read it). Nic uploads.
  4. 4.4 Monthly GEO-mechanics re-verify (this field moves fast) + quarterly freshness pass — geo-strategist standing duties.
⏸ HOLD

Nothing executed. Expert seat tma-geo-strategist built + registered (reports to SEO owner). The two decisions for Aga: ① GO on Tier 0 (near-free, this week) ② Phase-1 GO on the BWA overlays (1.1, gated on Task 19). Full analysis: marketing/seo/TMA_SEO_GEO_ANALYSIS_AND_PLAN_2026-07-20.html (open locally) / .md (canonical v1.1).

📺 YouTube — organic lead engine auto-synced daily from yt_status.json · master doc: marketing/youtube/YT_MASTER.md · goal: thousands of leads + sales
Go deeper
📄The YouTube VA task sheetas of 2026-08-06
What the VA is executing on the channel right now, and what is blocked.
Open ↗
CORRECTED

The "84% ads / paid surface" label was a single 28-day ad burst. Over the trailing 365 days the main channel was 77% ORGANIC (~236K views, 55K from search) with ~zero ad spend for 11/12 months. It's a real evergreen-search asset — the problem is conversion + supply + retention, not traffic.

The strategy — staged path to thousands of leads (honest: "thousands/mo" = a 9–18mo compounding build, not a 30-day lever)
StageWhatTarget
1 · Instrument + convert ≈doneAssessment CTA + UTM on every search-earning video (49 done). Converts the ~20K organic views/mo we already get; makes YouTube→lead measurable for the first time.~250–400 quiz-starts/mo · 45–125 trials/mo MODELLED
2 · Rebuild supply + retentionResume long-form ≥2/mo on proven clusters · retention repair (THE ranking lever) · retitle/re-thumbnail winners (human, 1-at-a-time) · chapters.~500–1,000 quiz-starts/mo MODELLED
3 · Scale proven converters2nd search cluster (assessment-intent) + amplify the videos GA4 proves convert (organic + targeted paid on known winners).thousands of leads + hundreds of sales/mo MODELLED
🔴 Law: YouTube = link-and-landing (ManyChat/comment-to-DM does NOT work on YT). Descriptions = safe to batch (prepend-only). Comments = the account-risky action → vary text, ≤20–40/day, never bulk. Titles/thumbnails = human, 1-at-a-time. IG/TikTok organic stay DARK (proxy-only).
SYNCED 12 Aug 2026

🔴 CORRECTED 3 Aug 2026: the 'sessions EXPLODED 210→897/28d' claim was an ARTIFACT — editing a description triggers ~4 link-validator hits that GA4 logs as youtube sessions, and a bulk pass over ~870 descriptions manufactured ~3,700 of them. REAL YouTube→site traffic is ~7/day (~199 per 28d), engaging at 38%. Proof: 26 Jul, the one day the job did not run, drew 32 sessions against 700–850 on edit days; plus 0.21% Apple vs 37% site-wide, hour peak/trough 2064:1, Belgium 700 vs US 53, 4-second sessions. YouTube Partner won 24 Jul; the growth machine and 12-lever ledger stand. Leads are genuinely small, not dark — and the honest question is now 'the channel barely sends traffic to the site', not 'the traffic does not convert'. · Stage: CAPABILITY fleet (ruled 3 Aug 2026) — graded on VIEWS, exception-only. Levers: retention recuts + new-upload packaging. Tripwire back to REVENUE: views/28d ≥45,000.

Instrumentation
Videos with the assessment CTA49 live
Comments posted / remaining29 posted · 20 to go (human-paced, ~10/day)
End screens9 / 0
Live funnel — YouTube organic → lead (old pre-retrofit baseline 106 sess → 0 leads / 90d — NOT comparable: it predates both the UTM work and the crawler contamination)

129 REAL youtube sessions (~9.2/day) · 3 leads · 0 checkouts (28d, GA4 pull 2026-08-12)

🤖 GA4 raw says 9,1879,058 of those are our own link-validators, triggered ~4-per-video by bulk description edits (verified 3 Aug: the one day we skipped the job drew 32 vs 700–850). Never report the raw number as traffic.

🔴 CHARTER RULING — 3 Aug 2026: this lane is a CAPABILITY fleet, graded on VIEWS.
15,032 views/28d × a NORMAL 1.3% view→click = ~7 visits/day. A ≥30 leads/28d target needs ~3× channel views, which ~2 long-forms/mo cannot deliver — unreachable, not unmet.
Withdrawn: the ≥30 leads/28d target · the 'DARK on outcome' KPI wording · the $200–350/mo cash line
Effect on the plan: fleet booked revenue $4,000–5,080 → $3,800–4,730 against a $5,667/mo gap (deliberately honest)
🔔 Tripwire: views/28d ≥ 45,000 (~3× today) re-opens the charter and returns the lane to REVENUE
Still running: retention recuts + new-upload packaging (unblocked); retrofit; weekly self-learn
Task tracker
✅ DONE (VA confirmed 24 Jul): end screens on the top 9 (Video+Subscribe). Link element was greyed out at the time — now re-doing with links, see T11.Aga/VA
✅ DONE (VA confirmed 24 Jul): all 9 posted comments pinned.VA (dispatched 21 Jul)
✅ MEASURED LIVE 6 Aug 2026 with the new tools/youtube-analytics/comment_audit.py (zero API quota) — THE VA DID THE WORK. All 40/40 videos carry a channel comment; 37/40 are pinned. She executed Days 1-4. 🔴 BUT ALL 40 COMMENTS POINT AT THE RETIRED /calisthenics-assessment/ DOORWAY (utm_campaign=yt_pinned), not the quiz root — because the comments were written in JULY and the 3 Aug quiz-root retrofit rewrote DESCRIPTIONS ONLY. Third surface the retrofit missed, after the channel About text and the end screens. Not the VA's error in any of the three. OUTSTANDING FOR V (12 min): (a) PIN the 3 that are posted but unpinned — FLGLf5R5XkM, 0lPJpN1JmOM, PzJdqNuWwDU; (b) the duplicate cleanup the brief asked for was NOT done — 9 videos carry 2+ channel comments competing for the pin: 4fstTeS-MUQ, TqdYJOGIQsc, 1wWx1304S_A, 1MFRTIH0pz0, SlaCyUauuVQ, lRqo6Tjm2GA, Wa89eMBcqQs, gy6dOjw58_o (3 comments), Ue8_L6msDYc — delete the OLDER one on each. NOT FOR V: the URL swap on all 40 is MINE — comments.update works on our own comments (50 units each, 2,000 total), so it runs once the retrofit frees the quota. Filed as a FLEET row. Re-verify anytime: python3 tools/youtube-analytics/comment_audit.py --file <ids>VA (dispatched 21 Jul)
Confirmed 21 Jul: end-screen 'Link' IS greyed out (no approved associated website). End screens use Video + Subscribe for now; assessment link still lives in description + pinned comment.Aga
✅ RESOLVED 24 Jul — CHANNEL IS NOW A YOUTUBE PARTNER (Aga accepted terms; API confirms isChannelMonetizationEnabled=true). The earlier ~845h watch-hour gap estimate is MOOT — eligibility cleared by a route the duration-classified estimate didn't model. 🔴 UNBLOCKS: end-screen LINK element + website CARDS across all 875 videos (was the single biggest conversion ceiling). Also unlocks monetisation on 1.27M lifetime views. NEXT: VA verifies the Link element is actually clickable (Part 4 of the VA sheet).Aga/Nic (parked)
✅ DONE 23 Jul — BRAND BUG closed. All 51 episode briefs specified #0C71C3, HARD BANNED by Brand Brief v1.3 (the only SoT per CLAUDE.md); briefs carried a FABRICATED carve-out ('applies to the app-rebuild, not YouTube') — false. ROOT CAUSE fixed in agents/13-THUMBNAIL-DIRECTOR.md + fleet_config.json (brand_blue -> brand_accent #00D4AA). All 51 episode JSONs rewritten incl. nested frame_primary/frame_alt/shotsheet graphic specs; originals backed up to marketing/youtube/scripts/thumbnail-colour-backup-2026-07-23/. All 49 Notion cards rebuilt. 🔍 LIVE-VERIFIED on the board: 49/49 carry #00D4AA, 0 carry the banned hex. Ath fleet unregressed. Ritesh now sees brand-correct thumbnail briefs.Aga (decide) + Claude (apply)
✅ SUPERSEDED + FIXED 24 Jul. v1 schedule picked 8 on search-demand alone and spanned SIX footage clusters — contradicting the batch-by-footage instruction in the same message (Aga caught it). v2 = TWO clusters, one switch: ring-dips EP001/EP002 → muscle-up EP006/EP041/EP009/EP043/EP039/EP003. Notion prioritised P0-P9 at '03 Ready to EDit'. Message: marketing/youtube/RITESH_MESSAGE_FINAL_2026-07-24.md. 🔴 LESSON: selection must be scored on FOOTAGE CLUSTER + collision + gate score together — demand alone produces an unworkable edit order.Aga (approve)
Run yt_lead_report.py weekly from early Aug — first YouTube→lead numbersClaude
Stage 2: resume long-form cadence (≥ 2/mo) + retitle top winners + retention repair (on Aga's go)Aga+Claude
EDITOR REBALANCE (decided 21 Jul): Forge = majority; main TMA = protected floor ~2 long-form/mo on proven clusters (ring dips, strict muscle-up, push-up progressions, handstand, planche prereqs, pull-ups) + package-refresh top ~10 winners (no filming) + cut 2-3 reels per long-form. Reversed the earlier 'abandon main TMA' call after the 77%-organic finding. Dependency: Jesse batch-films monthly.Editor + Jesse
RETITLE/RE-THUMB BRIEF for the top 5 winners -> marketing/youtube/YT_RETITLE_BRIEF_2026-07-23.md. 🔴 CTR + impressions are STUDIO-ONLY (not exposed by the Analytics API) — so priorities are [MODELLED] from views+retention. READ CTR IN STUDIO FIRST: below ~5.9% = packaging problem (retitle); at/above = retention problem (do NOT touch the title). Ring Dips flagship Ikeg_v5fvz4 = biggest prize (652 watch-h at 27.6% retention). 🔴 4FoCnqGC-o0 (What Muscles Do Push-Ups Work) = DO NOT RETITLE — 59.3% retention, it works; the lever is EXPANDING the 93s video. Discipline: one change, 14-day read, revert if flat.Aga (approve) + Claude (applies 1 at a time)
🔴 MEASURED LIVE 6 Aug 2026 — NOT FINISHED, and the finished half is on the wrong URL. The VA reported Part 4 done; audited with the new tools/youtube-analytics/endscreen_audit.py (reads end screens off the public watch page at ZERO API quota): 5 of 9 carry the Link element, 4 DO NOT — missing on 4FoCnqGC-o0, y7X-GuNZF_Y, OyRj1z3sNgs, Z9C7aCRCgn8. AND all 5 that exist point at https://themovementathlete.com/calisthenics-assessment/?utm_source=youtube&utm_medium=organic&utm_campaign=yt_endscreen — the doorway Aga's 3 Aug ruling took OUT of the YouTube path. Not the VA's error: the brief specified that URL on 24 Jul, before the ruling, and nobody re-read it. GOOD NEWS: the Link element works, so YPP genuinely unlocked it and the 60-second test passed. TO DO: (a) swap the target on the 5 existing to https://quiz.themovementathlete.com/?utm_source=youtube&utm_medium=organic&utm_campaign=yt_endscreen ; (b) add it to the 4 missing with that same URL. End screens have NO Data API endpoint — creation is Studio-UI only, so this stays with V — but VERIFICATION is now free and repeatable: python3 tools/youtube-analytics/endscreen_audit.py --expect-url https://quiz.themovementathlete.com/ <ids>. || ORIGINAL: PART 4 — add the UTM'd assessment LINK to end screens on the top 9, now that YPP unlocked the Link element. 🔴 URL CORRECTED 6 Aug 2026 — USE THIS ONE: https://quiz.themovementathlete.com/?utm_source=youtube&utm_medium=organic&utm_campaign=yt_endscreen . The old instruction said https://themovementathlete.com/calisthenics-assessment/?...&utm_campaign=yt_endscreen, which CONTRADICTS Aga's 3 Aug ruling that the assessment page comes OUT of the YouTube path: all 869 video descriptions were moved onto the quiz root, so end screens were about to become the last YouTube surface still feeding the retired doorway — and nobody would have noticed, because the old URL still 200s (verified live, 0 hops). A dead instruction that still resolves is worse than one that 404s. 🔴 VA instructed to TEST one video first and STOP if Link is still greyed out. Then ~40 more in batch 2. Context: flagship end-screen click rate is 0.6% vs 1.3% channel average — with no link element available until now.VA (dispatched 24 Jul)
RETENTION RE-CUT BRIEF -> marketing/youtube/EDITOR_BRIEF_RETENTION_RECUTS_2026-07-24.md. 🔴 KEY MECHANIC: YouTube Studio Editor can TRIM/CUT a live video IN PLACE (same URL, keeps all views/rankings/comments) but CANNOT add footage. So: flagship Ikeg_v5fvz4 (381.6K impressions, 9.8% CTR, 27.2% retention, 3.1K lifetime watch-h) = TRIM ONLY, NEVER re-upload — 4 years of authority at stake. RC001-003 scripts contain a NEW cold open = requires re-upload; their originals earn only 26-38h/yr so that's acceptable, but AGA MUST DECIDE per video.Ritesh (brief written, unsent)
RC001-003 re-cut decision. CLAUDE'S RECOMMENDATION: TRIM IN PLACE, do NOT re-upload, and do NOT prioritise them. Originals earn only 26-38 h/yr each (~90 h/yr combined). A re-upload starts at zero authority, competes with the original, and the new-cold-open scripts are only needed for the re-upload path. The topics are ALREADY covered by the new production queue (11 handstand eps ready) — if we want a better shoulder-mobility-for-handstand video we should PUBLISH A NEW ONE, not resurrect a weak old one. Contrast: the flagship trim is worth doing because it's 3,100 lifetime watch-h at 27% retention — 30x the scale.Aga (decide)
✅ ANSWERED 6 Aug 2026 BY ME — no human needed, and the answer is NO. Queried the YouTube Analytics API (insightTrafficSourceType) month by month, then bisected by week. ADVERTISING views: Jan-15 Jun = 0 · 16-30 Jun = 23,545 · 1-7 Jul = 45,523 · 8 Jul onward = 1, 7, 1 · ALL of August = 0. So a campaign ran ~16 Jun - 7 Jul, bought 69,068 views at 4.4 s/view (5,043 minutes = 84 watch-hours total), and has been OFF for a month. NOTHING TO KILL. Its window maps onto the 2-12 Jul LIFETIME $297 promo plus a late-June warm-up, so it was almost certainly the promo push. 🔴 THE FINDING THAT OUTLIVES THE TASK: those 69,068 views are 40% of the channel's Jan-Jul view total and they are worth ~4 seconds each — so ANY view-count read spanning 16 Jun - 7 Jul is inflated by paid garbage. Same class as the crawler artefact in yt_traffic_truth.py, different source. Do not compare a Jun/Jul view number to anything, and if this campaign type is ever re-run, kill it on sight. || ORIGINAL: ⚠️ L9/P011: ADVERTISING traffic = 69,076 views → 84 watch-hours (~4.4 sec/view), 3rd-largest view source. Skeptic catch. Is ANY YouTube ad campaign live? If yes it is buying 4-second garbage views — kill it. Answer + action by 28 Jul.Aga/Nic — SAME DAY
✅ PROVEN 6 Aug 2026 IN PRODUCTION DATA — no DebugView walk needed. The gate asked whether generate_lead fires with source intact. Live GA4 (property 177471782, last 28d): generate_lead fired 377 times, attributed across 17 NAMED sources — tma 36, (not set) 29, startup2013.lpages.co 10, bodyweighttrainingarena.com 5, l.facebook.com 4, youtube.com 3, ActiveCampaign 2, linktr.ee 2 and more. Source attribution is intact and the pixel works; the companion events all fire too (form_start 531, form_submit 433, add_to_cart 1,160, begin_checkout 871, purchase 517). ⚠️ ONE AMENDMENT TO THE TASK AS WRITTEN: it specified the chain '/calisthenics-assessment/ -> quiz -> generate_lead', but Aga's 3 Aug ruling took that doorway OUT of the YouTube path, so the chain to care about is now quiz-root -> generate_lead. The gate it protected — 'every lead prediction is gated on this' — is satisfied either way. YouTube's own 3 leads/28d are real but tiny, exactly consistent with the crawler finding that true YouTube traffic is ~7 sessions/day. || ORIGINAL: 🔴 L1/P007 THE GATE: prove the lead pixel end-to-end — UTM-tagged session through /calisthenics-assessment/ → quiz → generate_lead fires in GA4 DebugView with source intact. Every lead prediction is gated on this + the Nic redirect brief (P006). By 31 Jul.Claude+Nic
Done so far
  • 49 videos: unique UTM'd assessment CTA prepended to descriptions (backed up)
  • 9 comments posted + verified public
  • Copy capability: tma-youtube-copywriter + tma-youtube-copy-guardian + LAW + template bank
  • GA4 measurement wired (yt_lead_report.py); baseline captured
  • '84% ads' myth corrected everywhere; 3 seats in charter
  • 🎬 Gated production fleet built (parity w/ Forge/Ath): blind hook+editorial judges, validator, full editor package, ElevenLabs voice.
  • 🤖 Autonomous Workflow engine (tma_yt_bulk_workflow.js + gate-only) — produce→judge→revise→card in background.
  • ✅ 49 episodes produced + carded editor-ready (EP001-046 + RC001-003), 43 gold; zero filming, from existing footage.
  • 📁 113-video footage-cluster map + 110-video production queue + 940-clip Kaana editor DB (ALL_FILMING_FOOTAGE.csv).
  • 🗂️ Notion board organised by Topic (12 movement families) for batch editing; Kaana raw-clip links on every card.
  • 🎥 KAANA LOOK LAW documented (red aesthetic; all CDN clips usable via Ritesh AI-transform) — propagated to DOCUMENT_MAP + fleet masters.
📱 Social — scoreboard & attribution workstream board: Social Scoreboard ↗ · Nic tasks: Attribution Brief ↗
Go deeper
📄The social scoreboardas of 2026-08-11
Per-platform reach, saves and leads, with every tile stamped by verification state.
Open ↗
SYNCED 12 Aug 2026 06:31

Leads 142 / 28d (next rung 30/wk) · 11,378 social sessions · youtube 9,293s/6L · facebook 1,073s/84L · instagram 964s/51L · pinterest 48s/1L · untagged 1257 · YT tagged 100% (866/869, auto ~195/day) · leads = generate_lead only · every tile stamped VERIFIED/MANUAL/MODELLED/DARK/MOCK

✅ Done (state as of 2026-07-24)
  • Scoreboard v2 LIVE (world-class board, same URL) — 5-state verification stamps, Paid-DARK north star, ONE-focus banner, 8 platform scorecards, CMO+Director FIX verdicts applied
  • YouTube per-video attribution: 869 descriptions staged, retrofit auto-applying ~195/day (com.tma.ytretrofit 09:15)
  • Doorway CTA leak (530→1) CLOSED — UTM-forward script live on doorway + 10 magnet pages (temp variant-pin; revert with Fix 1)
  • Per-asset leads = generate_lead only (key_events defect fixed at source)
  • New seat tma-social-media-director (governance charter row added)
  • Nic social tasks folded into tma-nic-attribution-brief.netlify.app (S1-S4; S5 quiz colour removed by Aga)
▶ Next — pick up here
  • Nic S2 token (4 scopes) → IG + FB per-post flip LIVE on the board
  • Nic S1 redirects (302 + query forwarding) → then revert the 11 UTM-forward snippets
  • SMM/VA first manual logs Monday (TikTok · FB Group · production hours · inputs panel)
  • Retrofit completes ~27 Jul → tagged % hits 100, focus banner rotates to next gap
  • WoW chips + sparklines unlock automatically at 2+ daily snapshots
⛔ Blocked / waiting
  • IG/FB per-post DARK until S2 token (owner Nic, pending since 2026-07-23)
  • Paid-from-social DARK until Phase-0 / master-brief Task 2 (RC→Amplitude leaking: rc_trial_started 3/30d vs ~128 web)
  • Pinterest parked awaiting Aga's rule
Files: SoT tools/social-pipeline/social_status.json (incl. workstream — edit there, never here) · board generator build_dashboard.py · sync social_sync.py · daily 06:30 com.tma.socialdash · YT retrofit com.tma.ytretrofit 09:15 · social md docs/company/ANALYTICS/NIC_SOCIAL_TASKS_2026-07-24.md · memory social_scoreboard_v2_worldclass_2026-07-24
📧 Email Execution Plan the repeatable rail · 23 tasks, 4 phases · full doc: Email Plan ↗ · distinct from the Email engine metrics tab
Go deeper
📄The email execution planas of 2026-07-20
The sequence-by-sequence build and fix queue for the whole email estate.
Open ↗
🎪AUDIENCE INTEGRITY — who we can email, the funnel-stage labels, and the send gate
LIVE 7 Aug: 11,057 app signups carry WHERE THEY STOPPED (%TMA_FUNNEL_STAGE% — 3,276 setup-stalls · 5,872 never-worked-out · 1,909 free-trainers, backfill verified 0-errors) + the 15 NEW quiz-* tags. Four-layer payer exclusion (the lifetime leak: 23/25 heaviest "free" users were payers) and the blocking segment gate — no send without a PASS.
Open ↗
📊 Email scoreboard auto-synced 12 Aug 2026 05:25 · source: tools/email-plan/email_status.json — edit THAT, never this block
Reachable engagedIn value loops nowList healthEmail revenue
2445 15792 across 11 sequences bounce 0.03% · unsub 0.29% (cumulative, plan sequences) DARK (native rail unattributed; Stripe UTM job = plan task #17)

THU 23 Jul gate: 967 test batch TRIPPED the unsub wire (1.07% vs 0.5% gate; bounces/opens healthy) → 3,450 WAVES HELD pending arc maturation + Postmaster complaints glance — the test batch did its job. 758 pristine. 976 static 0.56% (cancelled-audience artifact, no deterioration). Aga's held-7,629 release RUNNING (979 at 3,498). Payment-recovery: first 18 SENT Thu AM; 4 new drafts today; FIRST RECOVERY logged. P1 annual sends Mon 28 Jul.

Task state
R1 cancel-save Wave A
976 Cancelled Win-Back: switched on + triggers fixed (ROUTE:WinBack + wb-eligible only)
98 win-backs + 238 warm → sequences (ID-verified)
967 Lead-Magnet Welcome test batch 500 in
P1 annual arc on shells 4077-79 (lint-PASS, address-free)
🔄Thu gate RAN: 967 unsub 1.07% > 0.5% → WAVES HELD (re-read ~Mon after arc matures + Postmaster glance)
⏭️P1 sends Mon 28 Jul (Aga schedules the 3 drafts)
🔄976b general arc for the 491 (only 10 have survey reasons) — fleet writes next
⏭️Renewal protection arc spec DONE — awaiting Aga nod, then build
Coverage audits #20/#21/#22 DONE — 3 reports in plan2026-07/
Sunset/archive ~8-15K dead after held waves — DELIVERABILITY only (saves $0 on the bill; AC locked till Apr 2027)
⏭️756/757 Abandoned Cart Reminder — UPLOAD THE 4-EMAIL 2026-08 ARC INTO FRESH SHELLS. 🔴 CORRECTED 7 Aug 2026: this row previously described the RETIRED July build (3 emails, AC field 56, %ABANDONED_CHECKOUT_URL%, entry off the 'Subscription Cart Abandoned' tag 63598). That artefact is dead — its Stripe trigger (checkout.session.expired) can never fire on Payment Element, and tag 63598 is now orphaned. THE LIVE ARTEFACT is marketing/email-sequences/quiz-checkout-abandon-2026-08/ (E1-E4, lint PASS 4/4, %TMA_QUIZ_PERSONA% conditional content, API entry via quiz_abandon_sync.py). Both current shells are UNUSABLE: 756's email lacks an unsubscribe link + renders raw markdown, 757's four emails are EMPTY (subjects r/r/e/e) — Aga paused both 5 Aug. So this is: fleet hands over the personalised rebuild (FLEET-42), Aga builds 4 FRESH shells and un-pauses 756 only. E3/E4 wait on the $97-window enforcement decision (AGA-109). Plan: ABANDONMENT_STRATEGY_2026-08-07.md sections 5.2 + 7.
✅ Quiz→AC write-back VERIFIED HEALTHY 23 Jul — mid-Jul 'stall' was a FALSE ALARM (lists 202/200/tag 242 discontinued, not broken; leads flow to Stage 1/2 + .TMA LEAD [APP+QUIZ] + 750)
Payment-recovery: 18 first sends OUT (Thu 07:00) · 4 new drafts · 1 recovery already logged · daily drafts 05:50
❌ AC billing ANSWERED 22 Jul: Commit-Annually LOCKED till 9 Apr 2027 + downgrade collapses discount 56%→35% (50K=$840>$761) — archiving saves $0; sunset for DELIVERABILITY only
⏭️764 Nurture 4 confirmed ends in silence → wire shoulder hand-raise (#13 unblocked)
🔄Aga's held-7,629 release RUNNING (979 in-flight 3,498, wave 1 out)
🗑️ TAG CLEANUP Phase 1 ✅ COMPLETE (23 Jul): 28,476 zero-sub tags deleted, 0 errors; 34,389→5,827 tags; protected trigger-tags verified alive; P2/P3 proposals next
≈6 WKS

Expected: ~$1,100–2,500/mo new + ~$150–300/mo defended. estimates Email alone doesn't close the $4K gap — it builds the repeatable rail and stops the leaks. Every living contact ends in exactly one loop; ~8–15K dead contacts sunset for deliverability (saves $0 on the bill — AC locked till Apr 2027); new leads self-route forever.

The 4 phases
PhaseWhat
1 · Money nowR1 cancel-save (✅ Wave A sent) · annual-offer 3-email series → the 6,050 warm non-customers ($157 via the trial door, no discount, ~$700–1,500/mo) · switch on 976 Cancelled Win-Back · 967 test batch of 500
2 · Fill the spineRoute every routable contact into a circulating nurture; wire the shoulder-course revenue lane for spine-finishers
3 · Build defencesDunning, abandoner coverage, front-door fixes — stop the bleed
4 · Shrink to a healthy listAfter the held group finishes: sunset ~8–15K dead contacts for stronger sender reputation (deliverability only — no billing saving, AC locked till Apr 2027)
1 Annual-offer 3-email series → the 6,050 warm non-customers $700–1,500/mo · Aga review + fleet

What — A one-off 3-email series to the 6,050 people who open our emails regularly but never bought, pitching the annual plan ($157) through the free-trial door. No discounts. MODELLED

Why — Engaged-only targeting is the post-2024 Gmail/Yahoo deliverability rule (mail openers → whole domain lands better), and a short 3-email arc with ONE offer beats endless drips. Based on our real 26.5% warm open + 1.5–2.5% click rates.

How — step by step
  1. Email fleet writes the 3 emails in Jesse's voice (angle-audited, all quality gates), opens them rendered in your browser.
  2. Aga (15 min): read, redline, approve.
  3. Claude re-checks the 6,050 live, tags bc:annual-jul26 (undo-list saved), gives you the exact clicks.
  4. Aga (~20 min guided): Campaigns → New → target the tag → paste → schedule (5–9am, one/morning).
Aga's email to-do — what needs YOU, in order

☐ Switch on 976 Cancelled Win-Back (1 min) + reply GO → fires 98 win-backs + 238 warm
☐ Say yes to the 967 test batch of 500 (5 min)
☐ Review the 3 annual-offer emails when they land (15 min) → ~20-min guided setup
☐ Three 1-min screenshots: 764 ending · 754/755 inactive window · Settings→Billing
☐ Review 976b + renewal emails when rendered → ~20-min guided builds
☐ Approvals: 982 clean-up · retire 978 Evergreen · archives
☐ Read 3 verification reports: abandoner · dunning · trial coverage (10 min)
☐ One AWOS carve-out ruling for the estate-repair builds (2 min)
☐ Tell me the finish date of your held-group release (unblocks the cold routing + archive)

Full plan (23 tasks, laws, provenance, ID files): tma-email-plan-2026.netlify.app ↗. Also folded into the $15K master doc §⑲. Deployment stays propose-only → Aga.
📈 Growth Fleet — the current portfolio verdict re-run 11 Aug 2026 · supersedes the 20 Jul reading entirely
Go deeper
📄The recommendation — for the CMOas of 2026-08-11
If we only do five things to $15K, these are the five.
Open ↗
📄The maverick takeas of 2026-08-11
87 divergent ideas ranked by effort vs impact — deliberately never blended into the fleet's view.
Open ↗
THE RECOMMENDATION — the five things, if we only do five
The full growth review: every sale since 1 Aug traced one by one, the complete paid picture, the no-paywall question answered, and the to-do list split into done and open.
Open ↗
🃏THE MAVERICK TAKE — the divergent bench, in its own voice
87 ideas from six blind generators plus a challenger, ranked by effort vs impact. Kept deliberately separate from the fleet's view and never blended into it.
Open ↗
What changed since the 20 July reading
  • The new quiz sells and the old ones did not. Since 1 Aug: 15 paid sales, $1,298.46, AOV $86.56 — all on quiz_checkout(v1). The v2-2 rail has taken zero in August and checkouts-v3 has taken $24.97 in its entire life across 71 starts.
  • Cold paid is settled, not open. It has never worked on either platform; everything that ever sold is paused; the remaining live Meta campaigns bought 0 purchases for £261.79 in the first nine days of August.
  • The app rail's constraint is the paywall, not acquisition — 50 trials from 362 pricing-page views (13.8%), because a free app signup is asked to pay before ever seeing the assessment, the placement or the skill tree.
  • The owned-content capture layer is too young to judge. It switched on 5–6 Aug; the first honest read is ~19 Aug, a full read ~2 Sep. Any “content produces N leads” figure whose window starts before 6 Aug is an artefact.
🎯 Growth 80/20 — by channel the vital 20% vs the 80% to stop · from the Growth Provocation Framework · re-generated every /grow run

Loading… (run tools/finance/build_growth_8020.py)

SoT: docs/company/GROWTH-TEAM/growth_8020.json · method: GROWTH_PROVOCATION_FRAMEWORK.md · full page: GROWTH_80-20_BY_CHANNEL.html

🤝 Affiliates — both directions of the money first audit in the programme's history · 24 Jul 2026 · docs: marketing/AFFILIATES/ · commands /affiliate-fleet (out) + /affiliate-income (in) · 📕 MASTER HUB (start here — every affiliate doc linked from one page): marketing/AFFILIATES/AFFILIATE_MASTER_HUB.html

📮 Outreach to partners lives in the OUTREACH lane — writing to an existing affiliate (reactivation) is governed by marketing/seo/OUTREACH_MASTER_2026-07.md and gated by tma-outreach-gate, which routes every target COLD vs PARTNER against the export in this tab. 🔴 A partner pitch may never re-offer a commission they already have — that was the 31 Jul near-miss (4 of 10 targets were already ours). The terms and the partner relationship stay owned here; the email is written and gated there. Full doctrine: the 📮 OUTREACH tab of the SEO master.

READ FIRST

Two completely different businesses share the word "affiliate". Never conflate them. MONEY OUT = the Tapfiliate programme where we pay partners to send us subscribers (773 partners). MONEY IN = us earning commission by recommending other people's gear on BWA/TMA/YouTube. Different direction, different economics, different fleet. Verdicts differ: OUT = worth fixing. IN = harvest 4 hours and stop.

Money OUT — net contribution /mo, modelled
≈£275
≈£500 gross − £159 commission − £66 Tapfiliate. Clears its own cost ~2–5×
Partners who never sent a click
92.1%
711 of 772. 8 people = 100% of commission; 2 = half of it
Money IN — publisher income /mo
$5–50
Ceiling <$150/mo at any sane effort. Fails MRR-30 by 2 orders of magnitude
Fleets built 24 Jul
12 seats
6 merchant-side + 6 publisher-side, both in the charter
⬅️ MONEY OUT — the Tapfiliate partner programme (we pay them) full doc: AFFILIATE_AUDIT_AND_10X_STRATEGY_2026-07-24.md · reproducer analyse_affiliates.py
🔴 THE TRAP

The export is NOT the channel — never quote it as lifetime. The CSV shows $588.74 revenue / $187.32 commission. The bank shows £1,748.18 of real affiliate commission actually paid. Rick Donohoe was paid £435.65 on 24 Jul — the day of the export — against $37.47 in it. And Benjamin Whitehead was paid £1,312.53 across three payments and does not appear in the export at all (7× every affiliate in it, combined). The export carries no date range and no date column. Step 0 of any cycle: read the Tapfiliate date-range filter.

CFO ANSWER

This closes the open question in ANALYZING_OUR_TMA_FINANCIALS.md"affiliate revenue > £66/mo? No → kill Tapfiliate". The answer is NO, don't kill it. It clears its own cost roughly 2–5×. It has simply never been asked to do more.

The eight producers — the entire revenue base (window unknown; absolutes only, never rates)
PartnerClicksSalesRevenueCommRateRead
Abel Ramos elevateforlife.com91$157.00$78.5050%Annual sale. Best EPC in the file ($8.72)
Rick Donohoe calisthenics-101.co.uk653$74.92$37.4750%4.6% click→sale — the model partner PROTECT
Chris Lynn couponbirds.com51$157.00$31.4020%🔴 Coupon intercept — 26.7% of window revenue on 5 clicks
Antônio Nunes132$74.96$14.9920%Review aggregator
Trung Nguyen2662$49.95$9.9920%0.75% — volume, no quality (EPC $0.04)
Katy chmela1221$24.97$4.9920%0.8% — same
Eslam Seleem · Veronica Earnhart1 · 11 · 1$49.94$9.9820%Likely self-referral
Segmentation — never averaged: 8 producers (1.0%) · 53 sent clicks, made nothing (494 clicks) · 711 dormant (92.1%). Concentration: 2 partners = 50% of commission, 4 = 80%.
Five root causes — all cheap to fix
1 · No ownerNever anyone's job, number, or review. An org failure, not a strategy failure. Fixed 24 Jultma-affiliate-lead.
2 · Zero assets🔴 The onboarding email promises promo videos, graphics, banners and an email sequence behind [PROMOTIONAL ASSETS FOLDER LINK]the placeholder was never filled. Partners were recruited and given nothing to post.
3 · Stale front door/affiliate-program/ is 89 words, still titled "Calisthenics Academy", footer © 2025. No terms, payout schedule, tier rules, or proof. Advertises "20-50% · 45-day" — and no document anywhere says how you reach 50%.
4 · Inbound-only recruitment773 signups dominated by coupon aggregators and freemail opportunists. 15 coupon/deal domains registered. Nobody has ever gone out and recruited a calisthenics creator.
5 · Broken conversion → no trafficCorrected by benchmark. EPC $0.187 sits exactly on the bottom of ClickBank's best fitness offers ($0.18–$0.47); merchant RPC $0.587 is 2.3× benchmark. The traffic converts fine — 1,002 clicks has no statistical power. A supply problem wearing a conversion problem's clothes.
Also: no affiliate agreement or T&Cs exist at all · AC list 159 [TMA] AFFILIATES = 205 contacts vs 773 in Tapfiliate, not synced · Tapfiliate is export-only, no API credential.
The 10× levers — ranked by net cash per hour of Aga's time. 10× ≈ £3,400/mo net ≈ a quarter of the gap: real, but NOT the growth answer alone.
#LeverEffortMRR-30Conf
1Verify attribution before judging anyone. 494 clicks → £0 sits on top of the documented UTM-stripping defect (530 tagged visitors → 1 kept its tag). An under-attributed partner is indistinguishable from a bad one.~1hHIGH
2Find out who Benjamin Whitehead is. £1,312.53 paid, invisible in the platform. If it's a repeatable partner type, that is the 10×.~15mHIGH
3Exclude coupon domains + write the agreement (brand-bidding ban, clawback, ≥60-day payout hold for the money-back guarantee, no trial bounty — a documented fraud magnet).~2hMED-HIGH
4Build the promo kit that was promised. Assets already exist — ASSESSMENT-KIT-2026-07/ + TESTIMONIALS-DATABASE/. Nothing to create, only assemble. Unblocks every partner at once.~4h30–60dHIGH
5🎯 Hand-recruit 10 partners — weighted to COMPARISON writers. Head-to-head "TMA vs X" content converts 3–8% vs 0.5–1.5% for "best fitness app" listicles. One partner at ~650 clicks/mo × 2% × $157 ≈ $2,000/mo = 3× the whole window's revenue. Start with Jari Dohmen / calisthenicsworldwide.com (physio + ex-director Dutch Calisthenics Union, podcast, multi-channel) — 18 clicks, 0 sales, never contacted — and re-contract Rick Donohoe.~1 quarter60–90dMED
6🔴 REWEIGHT commission to annual — do NOT raise it. We already pay 31.8%, at/above the top of every published band (SaaS 20–30%). But $157 × 40% = $62.80 in one payment gets a creator out of bed; $24.97 × 30% = $7.49/mo does not. The two annual sales = 53% of revenue from 17% of sales.~3hMED-HIGH
NOT RECOMMENDED

A mass blast to the 711 dormant affiliates. Reactivation runs 12–18% under 90 days dormant but only 3–5% at 180+ days — and this list has been dormant since inception. Expected yield: ~20–35 who do something, realistically 0–5 who ever sell. A list of customer-referrals and coupon scrapers caps at 10–15% activation even with excellent onboarding. Against a real deliverability risk to the whole sending domain, it's a bad trade. If anything: one 3-email sequence to the ~53 who once sent a click, then archive (3 touches capture 93.2% of all replies) — and only with tma-email-deliverability's PASS.

➡️ MONEY IN — publisher income (we recommend others' gear) full doc: AFFILIATE_INCOME_ANALYSIS_2026-07-24.md · doctrine: EXPERT_PROMPTS/AFFILIATE/
VERDICT

HARVEST + NEGOTIATE (~4 hours). DO NOT BUILD. Worth $5–50/mo today, realistically <$150/mo at any sane effort ceiling, against a $4,000/mo gap to break-even — it fails MRR-30 by two orders of magnitude. Not an execution problem: we sell a $157/yr subscription at ~100% margin, so on any click we could monetise either way, our own product wins by ~10×. Affiliate income is only rational on traffic that will never buy TMA.

🔴 The calisthenics trap — our audience self-selects AGAINST buying equipment. BWA top-300 queries, 28 days:
SegmentQueriesClicks
Mentions equipment at all2658
ANTI-purchase ("no equipment", "DIY dip bars", "build your own")1842
└ Genuine equipment interest816
└ └ Actual buying intent ("best parallel bars")36
Six clicks in 28 days. BWA's 6th-biggest page is /build-dip-station/ — an article that exists to help people avoid buying one. Total commercial-intent traffic across the whole estate: ~370 visitors/month. Anyone pitching "you have 1.9M impressions, monetise them" is counting the 99.6% who will never buy a product.
What we already had — nobody had counted it
AssetVolumeState
TMA.com Amazon posts10 posts · 222 links, all tagged tmapicks-20 · ~300 clicks/moEarnings never once verified HARVEST
BWA commercial pages/best-calisthenics-gloves/ 42 clk · /parallel-bars-buying-guide/ 24 clk (28d)Live, ranking, not deliberately monetised
YouTube — Kensui vests8 videos carrying a discount link + code MOVEMENTATHLETE · ~115 views/moTerms unknown NEGOTIATE
THE LAW

The Own-Product Test. own_EPC = P(quiz-start) × P(lead→paid) × LTV × margin. tma-affiliate-cannibalisation-guard holds a HARD VETO — no affiliate link ships on any page, video, email or app surface without its PASS. A $3 commission never gets to displace a $157/yr subscription.

🏛️ The two fleets both under tma-partnerships-growth-ownertma-growth-lead · both propose-only · registered in the Governance Charter
CommandSeatsOwns
/affiliate-fleet
money OUT
tma-affiliate-lead · -economics · -recruiter · -activation-manager · -integrity · -skepticNet contribution after commission · activation rate · click→paid · EPC · concentration. Integrity vetoes calling revenue "growth" untagged. Skeptic blocks unlabelled windows, inflated denominators, gross-for-net, multipliers without absolute dollars.
/affiliate-income
money IN
tma-affiliate-income-lead · -analyst · -deal-broker · -placement-engineer · -cannibalisation-guard · -income-skepticNet publisher income · the Own-Product Test · FTC/Amazon-ToS compliance · the sponsorship flip (brands paying us). Cannibalisation guard holds a hard veto.
Both fleets carry the same standing duty: size the prize in absolute dollars before recommending work, and rank yourself DOWN when the honest ceiling is small.
❓ Open — Aga only, ranked
1What date range did you select when exporting the Tapfiliate report? Everything downstream depends on it. If unsure — re-export with 2018-01-01 → today.blocks all rates
2Who is Benjamin Whitehead? £1,312.53 paid across 3 payments, invisible in Tapfiliate. Off-platform deal, JV, or a differently-named account?highest-value unknown
3Is Rick Donohoe's £435.65 (24 Jul) a Tapfiliate payout or a separate arrangement? It doesn't reconcile to his $37.47.reconciliation
4Do the promised promo assets exist outside the repo (Drive/Dropbox), or were they never built?unblocks lever 4
5What is the real 20%→50% tier rule, and who is on 50%? Written nowhere; the only statement is a contradicted 2024 email.needed for terms
6Keep coupon/deal sites in the programme at all? Recommendation: no, and the agreement should say so.Claude recommends NO
75-min Tapfiliate dashboard check: does it pay recurring/rebill commission, and is the payout hold configurable to ≥60 days?gates lever 6
Evidence & provenance
  • Platform = Tapfiliate ($89/mo ≈ £66, charged monthly Jan–Jun 2026 on the Revolut virtual card) — proven by the export's own delivery email from noreply@tapfiliate.com to hello@ (exact filename match) + tapfiliate.js on the live page. NOT ThriveCart (that's the lifetime-recovery rail only). [VERIFIED]
  • £1,748.18 payoutstransaction-history-wise.csv (Whitehead ×3, AUD) + Revolut statement (Donohoe, 24 Jul). [VERIFIED]
  • All export figures reproducible via python3 marketing/AFFILIATES/analyse_affiliates.pyif a doc disagrees with the script, the script wins.
  • ClickBank fitness EPC $0.18–$0.47 / CVR 0.38–0.91% (22 Jan 2025, platform's own stats) [STRONG] · SaaS commission 20–30% recurring across 2,600+ programmes [MODERATE] · comparison content 3–8% vs listicles 0.5–1.5% [MODERATE] · reactivation 12–18% <90d vs 3–5% at 180d+ [WEAK, vendor].
  • ⚠️ Evidence-quality caveat: ~90% of published affiliate benchmarks are authored by affiliate-software vendors, most disclose no methodology, and two 2026 sources citing the same survey give incompatible numbers. Only peer-reviewed source found: Edelman & Brandi, JMR 52(1), Feb 2015 (fraud governance). Planned against the pessimistic end throughout.
  • ⚠️ Known gap: the benchmark sweep was briefed against ThriveCart before the platform was correctly identified — its platform-capability section is void and excluded. Hence open question 7.
  • Publisher-side figures: GSC API live 24 Jul · WP-REST content scan · YouTube analytics export.
⚙️ Daily Jobs — every scheduled machine + the hello@ email rail source of truth: Automation Job Register ↗ · Audit findings ↗ · hello@ email rules ↗ · verified live 31 Jul 2026
FOR ANY LLM

This tab is the pick-up point if you're starting cold. Everything that runs on a timer or touches the customer inbox is here and in the register above. The standing rule: nothing auto-sends to a member — every member-facing message is a Gmail DRAFT in hello@ that waits for Aga. The only armed exceptions are the R1 T-30 watcher and the upgrade stages (templated, pre-approved copy — never a personal reply).

✅ ALL GREEN

Daily job tracking — 34 TMA jobs · auto-checked 12 Aug 05:37 from the tma_job_run success stamps (ground truth), not launchctl.

🛟 Member-facing lanes — TODAY (12 Aug) zeros with green jobs = no trigger events, not a stall — each lane's log has the per-person why
LaneTodayContext
R1 cancel-savesegment sends 1 · T-30 watcher 1 · saves 2 ($34.96)queue 108 · drafts waiting 0
Dunning (failed renewals)drafted 0 · auto-sent 0drafts <14h old send at the next 08:00/20:00 pass
Failed purchasedrafted 0 · recovered 0 all-time22 in 90d window — 0 on most days is normal (~9 people/30d)
Quiz-checkout abandonsynced to AC 0 · abandoners 112/30d · $10,864 at stakeenrol DISARMED — 756/757 not yet live
JobScheduleWhat it doesLast successToday
abandondraft06:052026-08-11 06:05
asopull05:152026-08-12 05:15✓ ran
backup01:302026-08-12 01:34✓ ran
cockpitemail05:5507:00 cockpit digest email to Aga (incl. the 🛟 retention rail block)2026-08-11 05:55
cockpitrefresh05:2506:00 full cockpit rebuild + deploy (revenue, funnel, this band, estate sync)2026-08-11 11:55
cockpitwatchdog06:30 · 09:00Checks the DEPLOYED cockpit is fresh; alerts if stale2026-08-11 09:00
emailmetrics06:10Pulls AC email metrics into the data/email-analytics scoreboard2026-08-11 06:14
emailselflearn08:12 MonWeekly email self-learning loop2026-08-10 08:33
everpaid02:102026-08-12 02:10✓ ran
failedpurchase05:55Failed-purchase lane — ONE personal note per died-at-checkout buyer (drafts only)2026-08-11 05:55
forgeassets07:40 MonFORGE asset pipeline batch2026-08-10 07:40
funnelstage02:302026-08-12 02:34✓ ran
growthsyncevery 15 minGrowth workstream auto-sync into the cockpit2026-08-12 05:22✓ ran
inboxtriage06:10Support triage — briefs + reply drafts for inbound no lane owns; emails Leih's page. NEVER sendsnever
jobguardianevery 30 minEvery 30 min — detects missed/failed jobs, kickstarts (max 2), then alertsnever
jobselftest04:10 Sun2026-08-10 12:44
mondaybrief07:00 MonMonday board brief build2026-08-10 07:00
morningpulls05:00Morning data pulls (GA4/Stripe caches for the day's reads)2026-08-12 05:00✓ ran
n973to75809:40Migrates contacts from 973 into 758 Nurture Sequence 2 (batch feed)2026-08-11 09:40
offerreach07:10 Mon2026-08-10 11:20
paymentautosend20:00 · 08:00Sends dunning drafts older than 14h (twice daily) unless needs_aga() holds them2026-08-11 20:00
paymentrecovery05:50Dunning lane — drafts personal notes for failed RENEWALS (T1/T2/T3 by invoice age)2026-08-11 05:50
pmbrief05:45Daily PM/CEO brief (incl. the 🤖 FLEET TODAY band)2026-08-11 05:45
quizabandonevery 30 minQuiz-checkout abandoners → AC fields + tag `quiz-checkout-abandoned`; 756/757 enrol gated on sentinel2026-08-12 05:18✓ ran
r1daily05:35R1 cancel-save rail — reply drafts into hello@, T-30 watcher (LIVE sends), saves board, upgrade engine2026-08-11 05:40
seodailysync05:35SEO daily brief + task-surface sync2026-08-12 05:35✓ ran
seoselflearn08:45 MonWeekly SEO self-learning loop2026-08-10 08:46
socialdash06:30Social dashboard rebuild2026-08-11 06:31
socialkpislack06:45Social KPI post to Slack2026-08-11 06:45
socialselflearn06:35 MonWeekly organic-social self-learning loop2026-08-10 06:35
transcriptcompress03:30 SunWeekly Claude transcript compression2026-08-10 11:02
workout103:152026-08-12 03:19✓ ran
ytchannelabout09:05YouTube channel About check2026-08-11 09:05
ytselflearn08:30 TueWeekly YouTube growth self-learning loop2026-08-11 08:30
📅 14-day ran-grid ✓ ran clean · ✗ failed · · no run recorded
Job30311234567891011today
abandondraft·············
asopull············
backup············
cockpitemail········
cockpitrefresh·······
cockpitwatchdog········
emailmetrics········
emailselflearn········
everpaid············
failedpurchase········
forgeassets········
funnelstage·········
growthsync·······
inboxtriage·············
jobguardian········
jobselftest·············
mondaybrief········
morningpulls·······
n973to758········
offerreach·············
paymentautosend········
paymentrecovery········
pmbrief········
quizabandon·······
r1daily·······
seodailysync·······
seoselflearn········
socialdash········
socialkpislack········
socialselflearn········
transcriptcompress········
workout1·············
ytchannelabout········
ytselflearn········
🟢 The two lanes that DRAFT into hello@ — the answer to "what creates drafts"
JobWhenWhat it drafts
com.tma.r1daily
retention/r1_daily.py
05:35 dailycheck_replies.py — replies to R1 cancel-save notes → churn reason logged → Jesse-voice reply drafted in-thread (STOP/bounce → suppressed, no draft). reply_fulfil.py — same for the 986 Welcome-Lifetime + 976 Win-Back reply arcs.
com.tma.paymentrecovery
retention/payment_recovery_lane.py --draft
05:50 dailyDunning — up to 3 notes to members whose renewal failed, by invoice age (T1/T2/T3). fixed 24 Jul was silently dead 22→24 Jul (wrong python — see trap below). Approved drafts sent by send_payment_drafts.py --send.
Three retention lanes — which failed payment each one sees
LaneOwnsStatus
R1 r1_daily.pyVoluntary churn — members who chose to cancel (cancel_at_period_end)live
Dunning payment_recovery_lane.pyInvoluntary renewal failure — billing_reason=subscription_cycle, open invoicelive (drafts)
Failed-purchase failed_purchase_lane.pyPurchase attempt died — failed charge, no invoice (new OR returning). ≈9 people/30d, ~$2.7K attempted; mostly $297 lifetimes declined by emerging-market issuersarmed 31 Jul (drafts)
Failed-purchase armed 31 Jul as com.tma.failedpurchase (05:55 daily, drafts only) after the pre-flight Aga set: CRO copy review → full-family bug audit → docs. ONE note per person, ever · two variants by decline code (never blames the buyer for a bank block or the bank for a typo) · no links — the conversion mechanic is a reply · skips anyone who ever paid, is suppressed, or is owned by R1/dunning · cannot auto-send (subject+state differ from the dunning lane; guarded by an import-time assert). Detail: register §2.5 ↗ · copy law: hello@ email rules ↗.
🔍 AUDIT · 31 JUL

Before arming, the whole job family was audited for bugs — 30 findings, 8 fixed the same session. Full register: Job Audit Findings ↗.

FixedWhat it would have done
C1 · nothing watched replies to payment emailsEvery dunning/failed-purchase note promises "Reply STOP and I won't email you again" — but no scanner watched those subjects, so a STOP never reached suppress.csv and the next touch drafted (and auto-sent) anyway. The fix immediately surfaced a real reply unread since 28 Jul. Live replies now flagged 🔴 NEEDS AGA; STOPs suppress automatically.
C2 · upgrade engine would break on armingA KeyError on a field that never existed — members would be tagged into 990 Monthly→Annual Upgrade Engine (and start receiving it) while the log row was never written, so Stage 2/3 could never fire. Invisible in dry runs.
H2 · could have emailed a paying memberThe "has this person ever paid?" check wasn't paginated — a serial retrier's successful charge could fall off page 1. Now paginated and fails safe (a Stripe error counts as paid → don't email).
M7 · the whole hello@ rail could go darkFour lanes + the guardian refresh one shared Gmail token with a non-atomic write; two interleaved writes corrupt it → every lane dead until manual re-auth. Now atomic.
H1 · H3 · C3(part) · M11Malformed plist (job silently unloaded + crashed the ops tooling) · "one note per person" was really per-charge · crash-mid-run re-drafted the same notes · pending charges could be told they failed.
Top open item (not blocking): the dunning↔autosend pair still shares a non-atomic state file with no locking — an overlapping run can clobber sent stamps and double-send. Next work block. 11 further items ranked in the findings doc. Standing rule added: never use a bare limit=N Stripe list for a safety check or a count — that class of bug has now bitten twice in two days.
📚 The full documentation — right here generated from the source markdown on every refresh, so it can never go stale. Click a title to expand.
⚙️ Automation Job Register what runs, when, and what touches a member

AUTOMATION JOB REGISTER — the hello@ rail + every scheduled job

CANONICAL register of (a) every lane that SENDS or DRAFTS from hello@themovementathlete.com, and (b) every scheduled job running on Aga's Mac. If a machine emails a member, drafts a reply, or refreshes a dashboard on a timer, it is listed here.

Verified live: 24 Jul 2026 (launchd dumped, logs read, dry-runs executed, Gmail drafts enumerated). Owner seat: tma-retention-lead (lanes) · tma-coo-systems (the machine) · Aga approves every send.

📅 DAILY TRACKING (added 6 Aug 2026, Aga's ask): the cockpit ⚙️ Daily Jobs tab now opens with a GENERATED tracking band — per-job ran-today (from the tma_job_run.py success stamps, not launchctl), the 🛟 member-facing-lanes-today table (sends · drafts · saves per lane, same sources as the 06:00 Slack digest), and a 14-day ran-grid. Generator: tools/ops/job_status_band.py, runs inside the 06:00 cockpit refresh; history: tools/ops/jobs_daily_track.csv. This register remains the editable prose source — it renders into the same tab; edit here and the cockpit follows at the next refresh.


0a. 🔴 COPY LAW — read before touching any lane email

tools/retention/HELLO_EMAIL_RULES.md governs every 1:1 email sent from hello@. Set by Aga 31 Jul 2026. One sentence decides everything: it has to look like Jesse just typed it. No bold, no underline, no italics, no template, no images — readability comes from short paragraphs. Links are real clickable anchors in standard blue (never a bare URL to copy-paste), with CRO-reviewed, honest anchor text. This is NOT the marketing estate — the AC/CIO fleet rules (locked footer, email_lint, designed template) do not apply here and would destroy what makes these convert.

0. The standing rule

Nothing auto-sends to a member. Every member-facing message is created as a Gmail DRAFT in hello@ and waits for Aga. Three explicit exceptions: the two lanes armed --live (R1 T-30 watcher, and the upgrade stages once UPGRADE_LIVE is set) — both send templated, pre-approved copy, never a personal reply — and Aga's 14-hour rule (28 Jul 2026), under which com.tma.paymentautosend sends dunning-lane drafts older than 14h unless needs_aga() holds them. That third exception is scoped to the dunning lane's exact subjects + state file and cannot reach any other lane's drafts (audit-verified 31 Jul).


1. The hello@ rail — what it actually is

Clickable links (31 Jul 2026) Lane emails whose body contains a URL are now multipart/alternative: text/plain unchanged (bare URL — the fallback, and what needs_aga() reads) plus a minimal HTML twin where the URL becomes a real standard-blue anchor (#1155cc — deliberately not a brand colour; a normal blue link is what a normal personal email looks like). CRO-set anchor text, different per lane on purpose: dunning = "Fix your billing →" (task-framing — an existing member with a known fault; and critically it does NOT over-promise, because the destination is the Stripe login page, not a card form — "Update your card" would mis-set the first-screen expectation on a billing page, the worst place to create doubt); R1 cancel-save = "Keep training →" (outcome-framing, low-pressure — they chose to leave and the email's real goal is a reply; administrative language reads as the process they already rejected). Arrows kept: in a plain-text-style email they are the only visual cue the text is clickable. Future A/B: dunning "Restore your access →", R1 "Turn renewal back on →". Built by r1_lib.build_message() / text_to_html(). Deliberately NOT the marketing template — no logo, footer bar or background; these are 1:1 notes from Jesse and reading as a campaign would convert worse. Bodies with no link (failed-purchase, guardian alerts) stay pure plain text, untouched. Aga's trigger: "make a link an actual clickable link — like click here instead of a dead link they need to copy and paste."
Account hello@themovementathlete.com (Google Workspace)
Auth OAuth token at tools/Gmail Connection/token.json, auto-refreshed by r1_lib._creds()
From / Reply-To The Movement Athlete <hello@themovementathlete.com> — set in tools/retention/r1_lib.py:34-35
Why Gmail, not ActiveCampaign Plain-text, personal, lands in the main inbox (not Promotions), and replies come back to a human inbox — the replies ARE the save
Why never AC-spoofed From The domain is p=reject. A founder note spoofed through AC fails DMARC.
Shared engine r1_lib.py (creds, Stripe pull, suppression, portal URLs) + check_replies.py (_gget / _gpost / _make_draft)

2. 🟢 THE DRAFT-CREATING LANES — the answer to "what puts drafts in hello@"

Two scheduled jobs create drafts. Nothing else does.

2.1 com.tma.r1daily — 05:35 daily — the R1 reply assistant

/opt/homebrew/bin/python3 tools/retention/r1_daily.py

Its heartbeat runs 5 steps; two of them create drafts:

Step Script What it drafts
2 check_replies.py Walks hello@ for replies to R1 cancel-save emails → appends the reason to reason_log.csvCOMPOSES a genuine Jesse-voice reply to the member's ACTUAL email (local claude CLI, compose_reply() — Aga's 7 Aug 2026 rule after the Pablo Mendoza failure, where the keyword classifier answered only the price line of an 8-paragraph email). Guardrails: responds to every point, plain text, no invented facts/dates, only the standing 30%-off-renewal offer allowed, 60–180 words; output validated, and on ANY failure it falls back to the old PRICE/OTHER templates. Draft goes inside the same Gmail thread. STOP → suppressed, no draft. Bounces → member suppressed, no draft.
2b reply_fulfil.py Same mechanic for the lifecycle arcs that use "hit reply and I'll send it over" — 986 Welcome Lifetime Members + 976 Cancelled Win-Back. Both send from + reply-to hello@, so they land in the same inbox R1 watches.

Other steps (no drafts): 0 exit-survey sync · 1 T-30 pre-expiry watcher (sends live) · 3 saves scoreboard · 3b upgrade engine · 3c upgrade Stage 2/3 · 4 r1_status.json · 5 cockpit <!--R1STATUS--> patch.

Idempotent via replies_state.json / reply_fulfil_state.json.

2.2 com.tma.paymentrecovery — 05:50 daily — the dunning lane

/opt/homebrew/bin/python3 tools/retention/payment_recovery_lane.py --draft

Up to 3 personal plain-text notes to members whose card failed, timed off invoice age (T1 ~1d · T2 ~4d · T3 ~8d; 10–21d = single final note; >21d = skipped, that's win-back territory). Auto-exits the lane the moment the invoice is paid. --draft = create drafts for review (current mode). --live = send directly (not armed).

Approved drafts are fired by the one-shot companion send_payment_drafts.py --send, which hard-filters to this lane's exact subjects + payment_recovery_state.json, so it can never touch an R1 reply draft.

2.3 🔴 Two kinds of failed payment — only ONE is covered

The lane filters billing_reason == "subscription_cycle" (payment_recovery_lane.py:144). That is a deliberate, load-bearing choice, and it means:

Type of lead Stripe shape Covered?
1. Existing member, renewal failed (card expired/declined) subscription_cycle invoice, status=open, attempt_count ≥ 1 Yes — T1/T2/T3 drafts, auto-exit on payment
2. Purchase attempt died (new OR returning customer, card declined at checkout) Failed charge with NO invoice — the sub goes incomplete, expires, invoice is voided not open 🆕 failed_purchase_lane.py (built 24 Jul, drafts-only, not scheduled)
3. Plan change/upgrade failed subscription_update ❌ No (1 open, 0 failed attempts — immaterial today)

Why type 2 is invisible: a first-payment failure never produces an open invoice. Stripe marks the subscription incomplete, then incomplete_expired, and voids the invoice. The lane scans open invoices, so it can't see them — and neither can R1 (whose queue is cancel_at_period_end=true).

Size of the gap (verified live 24 Jul, 90-day charge sweep): 524 failed charges — 486 invoice-backed (dunning lane's job) and 38 with no invoice, collapsing to 23 distinct people, of whom 9 are actionable inside 30 days ≈ $2,673 attempted. Closest existing machinery is the cart-abandonment build (756/757), which targets people who never reached payment — not people whose card was declined at it.

What they actually are: almost entirely $297 lifetime attempts declined by emerging-market issuers (BD · ET · NG · TZ · EC · LB) on a large single cross-border charge, plus a few high-intent repeat triers (jonaekstrom SE — 5 attempts across 2 cards; nurlomen07 BD — 5; fizan18 EC — 5, who eventually converted). The checkout is NOT broken — tested and refuted 24 Jul: in the same 4–8 Jul window 30 charges succeeded ($5,428.71) including $297 lifetimes from AU/ES/MY/GB/HK/US/CA, and Aga's own test card succeeded at 15:58 immediately after two of her cards declined at 15:54–15:57.

Open product question for Aga: for a declined emerging-market card, "try again" is weak. The useful offer is an alternative — a different card, PayPal, or stepping down to a monthly plan. That is an offer decision, not an email one.

2.5 🆕 failed_purchase_lane.py — the third lane (built 24 Jul 2026)

Sibling of R1 (voluntary) and the dunning lane (involuntary renewal). Scans failed charges with no invoice, collapses to one row per person, and drafts ONE personal note — deliberately not a 3-part drip, because ~9 people/month does not justify one.

  • Copy varies by decline reason — "your bank blocked it" (card_declined, authentication_required) vs "the card details weren't accepted" (incorrect_number, incorrect_cvc, expired_card). Never blame the wrong party.
  • Reply mechanic, no invented URL — "hit reply and I'll send you a fresh link." Same proven rail as R1; replies land in hello@ and are picked up by reply_fulfil.py (true since 31 Jul 2026 — audit finding C1 proved nothing watched these subjects before then).
  • Skips: founder's own card tests · deny-list · suppressed · in the R1 queue · owned by the dunning lane · anyone who EVER paid successfully · <12h old (let Stripe's retry play out) ·

    30d old (cold).

  • Modes: dry (default) · --draft · --live · --days N. State failed_purchase_state.json · log failed_purchase_log.csv.
  • Status: 🟢 ARMED 31 Jul 2026 as com.tma.failedpurchase (05:55 daily, --draft), after Aga's pre-flight: CRO copy review → full-family bug audit → documentation. See JOB_AUDIT_FINDINGS_2026-07-31.md for the 30 findings and what was fixed.

How this lane works (the operating description):

Who it emails People whose purchase attempt died at checkout — a failed charge with no invoice (Stripe marks the sub incompleteincomplete_expired and voids the invoice, so neither R1 nor the dunning lane can see them). ~9 people/30d, ~$2.7K attempted, mostly $297 lifetimes declined by emerging-market issuers.
When 05:55 daily, between dunning (05:50) and the cockpit refresh (06:00).
What it produces ONE Gmail draft per person, ever — deliberately not a 3-part drip; ~9 people/month does not justify one. Drafts wait in hello@ for Aga.
Copy Two variants chosen by decline code — bank-block (card_declined, authentication_required, insufficient_funds, do_not_honor) vs card-details (incorrect_number, incorrect_cvc, expired_card). Never blames the buyer for a bank block or the bank for a typo. 3+ attempts adds an apology line. CRO-reviewed 31 Jul: "cross-border charge" (names the real mechanism for the BD/NG/ET audience), "call your bank to approve it" (the British "give your bank a nudge" didn't travel). Load-bearing element per the review: the dual exit — "if you still want in, reply" carries equal weight to "if the timing was wrong, reply and say so" — which is what makes it read as service, not chasing.
Conversion mechanic A reply. No links in the body at all (nothing for spam filters or the needs-Aga gate to trip on). Jesse then sends a fresh link personally.
Skips founder's own card tests · deny-list · suppress.csv · anyone in the R1 cancel queue · anyone the dunning lane owns · anyone who EVER paid successfully (paginated + fails safe: a Stripe error counts as paid) · <12h old (let Stripe's retry play out) · >30d old (cold) · pending charges.
Can it auto-send? No. send_payment_drafts --auto matches on exact equality with the dunning subjects + its own state file; this lane's subject and state differ. Guarded by an import-time assert so a future copy edit can't silently break it.
Replies + STOP Watched since 31 Jul (audit C1): STOP → suppress.csv automatically; a live reply is surfaced as 🔴 NEEDS AGA in the daily run and counted into r1_status.json. No auto-draft — a drafted "here's your link" with no link is worse than nothing.
State / log failed_purchase_state.json (atomic, saved after every draft) · failed_purchase_log.csv
Reaches Aga 06:00 Slack post + 07:00 cockpit email both carry a 🛟 Retention rail — hello@ block, rendered from ONE shared source (tools/retention/retention_digest.py) so the two can never disagree. Headline is what NEEDS her: drafts waiting (live Gmail count, so carry-over from previous days is included) and 🔴 live payment replies; R1 queue and failed-purchase recovery follow as context. Best-effort by construction — any failure renders empty and the money post is untouched.
Daily read Writes failed_purchase_status.json every run, in every mode (drafted today · people seen in window · touched all-time · recovered = paid after we wrote, the outcome metric · attempted $), then patches the cockpit's <!--FPSTATUS--> block in the 🛟 Retention · R1 tab. It does NOT deploy — the 06:00 refresh (5 min later) does, same as r1_daily. Added 31 Jul after Aga asked where the daily analytics sat: the lane had been armed with documentation but no daily read, the exact drift this estate keeps getting bitten by.
Modes dry (default) · --draft (scheduled) · --live (not armed) · --days N

Why parked: a new set of checkouts is being built, and they will feed richer information through Stripe. Rather than tune a lane against today's thin signal, we wait and build against the better one. The existing lanes (R1 + dunning) keep running unchanged in the meantime.

🔴 ASKED OF NIC — sent 24 Jul 2026, awaiting confirmation. Do this AT BUILD TIME, not as a retrofit: the new checkouts must write plan_slug · plan_id · coupon · user_id · buyer_email into PaymentIntent metadata. Today's PIs carry an empty metadata object, which is the single reason plan and coupon have to be inferred from the charge amount. Baking it in while the checkouts are being written costs nothing; retrofitting it later costs a Nic ticket. Same hook as cart-abandon Path B — one change serves the cart-abandon bridge, this lane, and Stripe→app user-id attribution.

Un-park checklist: new checkouts live ✅ (checkouts-v3, verified 30 Jul) → confirm PI metadata is populated ✅ CLOSED by Nic, verified 30 Jul PM (the completed v3 trial's intent carries buyer_email + user_id, its customer carries email/name/django_user_id/consent_at — stamped at pay-click; the 24 Jul ask is DONE for everyone who clicks pay. ⚠️ blur-stamp persistence for abandoners still unconfirmed, and the v3 flow mints phantom subs at page load = noise in any scan — both on Task 1, tma-nic-attribution-brief.netlify.app) → re-run --days 30 dry → Aga approves the copy → --draft → read → arm.

2.6 🟢 com.tma.quizabandon — every 30 min — quiz-checkout abandonment sync (NEW 3 Aug 2026)

tma_job_run.py → quiz_abandon_sync.py --sync

The bridge that ended the "silent doorbell" (756/757 Abandoned Cart Reminder active since Oct 2025 with entered: 0). Reads unpaid quiz-checkout subscriptions from Stripe (metadata: email · persona · offer · plan) → writes AC fields TMA Quiz Persona / Offer / Plan + tag quiz-checkout-abandoned. Sync mode emails NOBODY. Enrolment (756 in-window E1–E3 → 757 day-4 E4) requires BOTH the QUIZ_ABANDON_ENROL_ARMED sentinel (Aga creates to arm, deletes to disarm — the UPGRADE_LIVE pattern) and the job being switched to --enrol.

Who Paywall VIEWERS who declined (intent is created on checkout page LOAD — they are NOT card-abandoners; copy law: never "you almost paid"). ~10/day, honest recovery sizing $900–1,500/mo at the 3–5% benchmark.
Safety Buyer-check (paginated, fails-safe) at sync AND before EVERY enrolment stage — a buyer can never enter (NIC-21). Suppression honoured. On 756 entry the contact is pulled out of 750/751 (frequency ceiling). Per-person atomic state writes.
Sequence E1 ≤60min mirror-their-plan · E2 +22h objection+guarantee · E3 +40h honest $97-window expiry (the REAL Django-served deadline — no fake revives) · E4 day-4 quarterly $49.97 STANDARD safety net (Aga ruling 3 Aug — no coupon; "$49.97 ≈ half of $97" IS the frame). Exit after day 4 → SPEC-REENGAGEMENT.
Owner .claude/agents/tma-quiz-checkout-abandon-owner.md (doctrine: SPEC-CART-ABANDONMENT). Copy: /email-fleet only, slug quiz-checkout-abandon-2026-08.
State / status quiz_abandon_state.json · quiz_abandon_status.json → cockpit <!--QZABANDON--> (Retention tab) + retention digest (Slack 06:00 / 07:00 email).
QA gate docs/company/GOVERNANCE/QUIZ_ABANDON_QA_2026-08.md must be green before the sentinel is ever created.

2.4 🔴 Failure mode: a typo'd email makes the whole lane silent

Recovery runs entirely on the address Stripe holds. If that address is wrong, Stripe's own dunning emails and ours both go nowhere, and the invoice just ages out.

Live example (24 Jul): invoice in_1TwYSDI6s6pBAbnmTgXXQivY, $157 Yearly V3 renewal, carries ryanlion2010@ico**u**d.com — a missing l. The same member exists correctly as cus_SgECxPLlzALrAn / ryanlion2010@icloud.com, and the app has the correct address (that's what the failure notification quoted). Two customer records, one typo, zero deliverable recovery mail. Fix = correct the email on the failing customer record in the Stripe Dashboard (the repo's Stripe keys are read-only by design), before the T1 draft is sent.

Worth a periodic sweep: any lane email whose recipient bounces should be reconciled against the app's own address for that user id.


3. The SENDING lanes (hello@, no drafts)

Script Trigger Sends
send_r1.py manual, per segment The R1 cancel-queue save note (A ≤30d gets the offer; B/C get the question only)
pre_expiry_watch.py --live inside r1_daily step 1 Auto-note the day a cancelled sub enters the 30-day window
send_upgrade_stage.py inside r1_daily step 3c Monthly→Annual Stage 2 (day ≥17, human touch) + Stage 3 (day ≥27, $129/yr, 7-day deadline). DRY until the sentinel file tools/retention/UPGRADE_LIVE exists.
send_concierge.py manual 1:1 concierge note to ACTIVE monthly members. Dry unless --live.
tools/finance/daily_cockpit_email.py com.tma.cockpitemail 05:55 (was written here as 07:00 — WRONG since the 6 Aug morning-chain retime; the plist has said 05:55 all along, corrected 11 Aug 2026) The daily cockpit brief — to hello@, internal only. Rebuilt 25 Jul: leads with repeatable net cash → $15K (MRR demoted to secondary), reads kpi_15k.json/data_flow_daily.json from the 06:00 run and degrades gracefully if absent

4. Full scheduled-job register (launchd, ~/Library/LaunchAgents/)

Job When Runs Touches hello@
com.tma.r1daily 05:35 daily retention/r1_daily.py drafts + live T-30 sends
com.tma.paymentrecovery 05:50 daily retention/payment_recovery_lane.py --draft drafts
com.tma.paymentautosend 20:00 + 08:00 daily retention/send_payment_drafts.py --auto — 🔴 the only job that SENDS member email with no human in the loop. Aga's 14-hour rule (28 Jul 2026): a lane draft older than 14h sends itself. Absolute exception: needs_aga() HOLDS anything carrying a link outside the allowlist, a checkout, a discount/promo code, an offer, or an unfilled placeholder — those wait for Aga indefinitely. Logs auto-sent to payment_recovery_log.csv; logs /tmp/tma_payment_autosend.* SENDS
com.tma.cockpitrefresh 05:25 daily finance/refresh_cockpit_daily.py — 🔴 11 Aug 2026: two ordering bugs closed. It now runs seo/lead_lanes_refresh.py as its FIRST 0d-quater step, because the GA4 lead-origin table was written only by seodailysync at 05:35 — ten minutes after this chain embedded it, so Aga's "where leads come from" table was a full day stale EVERY day (measured: kpi generated_at 05:28 carrying ga4_lanes pulled the previous date). It also runs finance/sales_yesterday_pull.py before the Slack post. Both are policed by finance/tracker_freshness.py, whose AGE and CHAIN-COHERENCE checks fail loudly on Aga's own screen if either regresses — (deploys cockpit; since 25 Jul also runs flow_metrics_pull.py → step 0e and kpi_15k_sync.py → step 4a, which own the 🎯 $15K tab. 4a must stay AFTER canonical_facts.json is written. It also posts to Slack — that lane is NOT gated by --no-deploy)
com.tma.emailmetrics 06:10 daily email-analytics/collect_metrics.py
com.tma.workout1 03:15 daily · PLIST WRITTEN, NOT YET LOADED (arming is Aga's, with the AC automation) retention/workout1_moment.py --apply — THE WORKOUT-1 MOMENT lane. Reads Intercom workouts_finished_number for every 90d-active contact, diffs against last night's snapshot (workout1_state.json), and tags everyone who went 0 → ≥1 since the last run with workout1-yesterday (an AC automation starts on that tag, waits until ~8am, sends one email, ends — AC never has to see the app) plus a permanent workout1-done (the welcome arcs' skip-condition, so an active trainee stops being asked "have you started yet?"). Payer-excluded FOUR ways: Intercom plan prefix · live Stripe both accounts · the EVER-PAID set (lifetime is a one-time CHARGE) · the segment gate before any send. 🔴 First run SEEDS ONLY and refuses to tag — with no prior snapshot every existing member looks like a first-timer; this is the absence of data, not an overridable flag. 🔴 Refuses outright above MAX_COHORT=400/day — that means a stale snapshot or an Intercom backfill, not 400 first workouts. Snapshot advances ONLY after a successful tagging pass, so a crash re-runs the same diff rather than losing the cohort. Why a count diff and not a timestamp: Intercom exposes no last_workout_at (measured 11 Aug across all 76 attributes). Health: workout1_moment.py --health. Seeded 11 Aug 2026 with 15,410 contacts. Doctrine: WELCOME_CTA_DOCTRINE_2026-08-10.md §0 — this is one of the two legal trial asks — (writes AC tags; sends nothing)
com.tma.funnelstage 02:30 daily retention/funnel_stage_export.py --apply — stamps TMA_FUNNEL_STAGE (survey_unfinished/no_workout/no_trial) + TMA_FUNNEL_STAGE_AT onto EXISTING AC contacts from Intercom funnel state (90d-active, payer-excluded via plan-prefix + live Stripe cross-check; segment D = abandon-fleet's, never stamped; never creates a contact). Changes-only via funnel_stage_state.json; blind-crawl canary aborts exit 2; clears the stage the day a person converts (stale-label hole closed 7 Aug); self-verifies 8 read-backs per run (non-zero exit → guardian alerts); runs via tma_job_run.py so com.tma.jobguardian kickstarts it after a missed window and alerts on failure. Health: funnel_stage_export.py --health. 🔴 Send gate: any send on these segments needs segment_guard.py PASS (live re-pull + every-email Stripe check + freshness), per Audience Data Dictionary rule 5. Armed 7 Aug 2026 on Aga's D2 GO — master: docs/company/ANALYTICS/AUDIENCE_INTEGRITY_MASTER_2026-08-07.md — (writes AC fields; sends nothing)
com.tma.morningpulls 05:00 daily finance/morning_pulls.py
com.tma.cockpitwatchdog 06:30 daily finance/cockpit_watchdog.py14 checks (was 13). 🔴 Added 7 Aug 2026: ac-automationsretention/ac_automation_state_check.py, which snapshots every ActiveCampaign automation's status and alerts when one silently changes state. Born the day 750 TMA | Welcome Sequence After Quiz was paused 16:41 and un-paused 18:03 with no replacement arc — 82 minutes in which a new quiz lead got two transactional emails and then nothing, found only by accident because a naming-rule lookup printed the live status. Read-only (GETs only; it cannot pause or resume anything). Exit 2 = UNDETERMINED, not a pass — it refuses to report "no changes" from an empty or truncated fetch. Deliberately not in HEALS: a state change needs a human decision, never a self-heal. — (alerts)
com.tma.socialdash 06:30 daily social-pipeline/refresh_social_dashboard.py (venv python; fixed 24 Jul — was .sh via /bin/bash, exit 126 every run). Extended 3 Aug: step 1/4 now pulls Instagram per-reel insights (ig_insights.py), deliberately non-fatal so a bad IG day cannot take the board down
com.tma.socialkpislack 06:45 daily social-pipeline/slack_daily_kpi.py --post — posts the daily social KPI digest to Slack #social-fleet-kpis-updated via SLACK_SOCIAL_WEBHOOK in .env.local. Reads ONLY social_status.json, so it can never disagree with the board; runs 15 min behind socialdash so it always reads fresh data. 🔴 Never quotes GA4's raw YouTube session count (crawler artefact) — uses live.youtube_traffic.real_28d_equivalent 💬 posts to Slack (no member email)
com.tma.seodailysync 05:35 daily seo/seo_daily_sync.py --deploy (fixed 24 Jul — logs were on T9, spawn failed exit 78; now /tmp/tma_seo_sync.*). Extended 24 Jul: also writes the zero-LLM marketing/seo/SEO_DAILY_BRIEF.md (5 fleet KPIs + AGA/NIC ≤3 human lists from marketing/seo/SEO_HUMAN_QUEUE.json) and mirrors the human lists into the cockpit SEO-LIVE block
com.tma.pmbrief 05:45 daily ops/pm_board.py brief --write — the PM fleet's morning CEO briefmarketing/seo/PM_MORNING_BRIEF.md: what ran without Aga (24h ledger), what needs her (incl. Nic rows awaiting --nic-approved), her ranked top 3, open load per pod, and the integrity flags. Reads all five pod queues through aga_console_sync's own extractors so it can never disagree with the cockpit. 🔴 Runs after seodailysync (05:35) so the queue lists are already fresh, and before Aga's 06:00 start — the whole morning chain was moved earlier on 6 Aug 2026 because it had been building her lists at 06:40, after she sat down. Deterministic only; the judgement layer (the ONE cash constraint) comes from /pm-fleet in session
com.tma.socialselflearn 06:35 Mon social-pipeline/social_selflearn.py — the weekly organic-social self-learning loop (reads social_status.json, adjudicates the week's hook/format experiments, refreshes the board). Row added 10 Aug 2026 — it had been running unregistered since 5 Aug and was found by the guardian's new register-drift check on that check's very first pass.
com.tma.seoselflearn 08:45 Mon seo/seo_selflearn.py (venv python; logs /tmp/tma_seo_selflearn.*) — zero-LLM weekly loop: adjudicates the 14-day GSC watches on every fleet-shipped page (KEEP / WATCHING / REVERT-FLAG — flags only, never auto-reverts), writes the CMO/CEO weekly to marketing/seo/reports/SEO_WEEKLY_REPORT_<date>.md, re-ranks SEO_HUMAN_QUEUE.json, flags the monthly AI-citation panel when due
com.tma.cockpitemail 05:55 daily finance/daily_cockpit_email.py ✉️ sends to hello@
com.tma.mondaybrief 07:00 Mon finance/monday_brief.py ✉️ internal
com.tma.emailselflearn 08:12 Mon email-analytics/run_selflearn.py
com.tma.forgeassets 07:40 Mon forge-assets/run_weekly.py (homebrew python; logs ~/Library/Logs/tma/com.tma.forgeassets.*) — refreshes the FORGE asset DB: catalog → Drive ingest → vision (new content-hashes only, so a quiet week is nearly free) → manifest → verify_forge_db.py gate. 🔴 Written in Python, not bashtma_job_run.py is explicit that system binaries cannot touch /Volumes/T9 under launchd (§6). 🔴 Logs every run to the fleet ledger including no-ops, and shouts if the Drive source was skipped — an unreachable source is ABSENT, not empty
~~com.tma.ytretrofit~~ RETIRED 10 Aug 2026 was youtube-analytics/apply_retrofit_all.py --apply — the retrofit COMPLETED (869/869 staged descriptions applied, 0 remaining, verified in quizroot_apply_state.json) so the daily run had become a pure no-op with three unmaintained hard-exit gates. Plist moved to ~/Library/LaunchAgents/_retired-tma/ (reversible). The guard jobs (ytchannelabout) stay
com.tma.ytchannelabout 09:05 daily youtube-analytics/channel_about_guard.py --apply — keeps the YouTube channel's About text on the UTM'd quiz root. Added 6 Aug 2026: the 869-video retrofit moved every description off /calisthenics-assessment/ but never touched the channel's own About prose, which still carried the old untagged doorway — it hid because the 4 structured channel links were all correctly tagged, so the links audit passed and nobody audits prose. 🔴 Runs at 09:05, deliberately BEFORE ytretrofit at 09:15 — the retrofit spends 9,800 of the 10,000 daily units, so anything after it is quota-dead (proven 6 Aug: even a 1-unit videos.list 403'd). Checks by parsing the public About page = 0 units when correct, and spends the 50-unit channels.update only when the text is actually wrong. Ships as a guard, not a one-shot patch, per the retrofit's own lesson that doctrine without a compliance check decays into decoration
com.tma.ytselflearn 08:30 Tue youtube-analytics/yt_selflearn.py — (pulls GA4+YT, scores prediction ledger, writes weekly CMO/CEO report to marketing/youtube/performance/weekly-reports/, refreshes yt_status.json)
com.tma.growthsync every 15 min finance/growth_repo_sync.py --pull-deploy
com.tma.n973to758 09:40 daily · TEMPORARY, self-completing retention/migrate_973_to_758.py --batch 2000 (homebrew python; logs /tmp/tma_n973to758.*) — Aga-approved 29 Jul reroute of the ~8,799 contacts parked in 973 Nurture Sequence 1 NEW COPY FROM CLAUDE into 758 Nurture Sequence 2, 2,000/day to avoid a send spike. Add-verify-then-remove per contact; guard skips the add if already in 758; state+log in tools/retention/migrate_973_to_758_{state.json,log.csv}. Prints DONE and no-ops when the source is empty → then unload + delete this row (expected ~2 Aug 2026) — (triggers 758 Nurture Sequence 2 sends to migrated contacts)

| com.tma.failedpurchase | 05:55 daily | retention/failed_purchase_lane.py --draft — the third retention lane (§2.5): ONE personal note per person whose purchase attempt died at checkout. Armed 31 Jul 2026 after CRO copy review + the full-family audit (JOB_AUDIT_FINDINGS_2026-07-31.md). Cannot auto-send | ✅ drafts | | com.tma.transcriptcompress | 03:30 Sun | ~/Library/Scripts/tma/compress_claude_transcripts.sh (canonical: tools/ops/compress_claude_transcripts.shre-copy to ~/Library/Scripts/tma/ after editing; runs from home because §6 applies to bash reading the script off T9 too, not just python). Gzips Claude Code session artefacts >7 days old across ALL ~/.claude/projects — the disk hog is per-session subagents/ fan-out logs (60–100 MB each), which REGROW structurally. Skips files any process holds open (lsof-checked); compresses, never deletes; log ~/.claude/transcript-compress.log. Armed 5 Aug 2026 after swap exhaustion froze the Mac (5.3 GB → 3.7 GB same day). Launchd execution proven live via launchctl start before this row was written. 🔴 CORRECTION 10 Aug 2026: that proof predated the 6 Aug wrapharden_launchd.py then set /bin/bash as the interpreter of the Python wrapper, and the job never ran once after wrapping (exit 2 every attempt, masked by seed-credit). Interpreter fixed to python3 10 Aug; first real wrapped run compressed 181 files / 110 MB freed, verified in ~/.claude/transcript-compress.log | — | | com.tma.jobguardian | every 30 min + at boot | ~/Library/Application Support/tma/bin/job_guardian.py (boot volume; source: tools/ops/job_guardian.py) — the §6c safety net: detects + kickstarts missed windows, alerts on failures. Deliberately unwrapped so it runs with T9 unplugged. Hardened 10 Aug 2026: 🔴 red alerts (CRITICAL-job miss · deterministic failure · never-ran · T9 unplugged · guardian crash) Cc Aga's Gmail, max one per problem per day; 🟠 FYIs stay hello@-only (12h dedupe). Dedupe stamps only on confirmed delivery. Emails via a vendored stdlib Gmail sender on the off-T9 token (~/.config/tma/gmail_hello_token.json) so the "T9 unplugged" alert can actually send. Stops kicking a job that fails identically twice (deterministic → 🔴 with log tail instead). Detects never-ran jobs (seed credit expires after 3d — the transcriptcompress shape). Re-bootstraps not-loaded plists once/day. Writes guardian_history.jsonl (rolling 7d — feeds the 05:55 email's 🤖 Jobs line + the console band). Watched back by cockpit_watchdog check 15 (guardian_status ts <45 min) | ✉️ alert emails only | | com.tma.everpaid | 02:10 daily (NEW 10 Aug 2026) | retention/ever_paid_build.py — rebuilds the payer-exclusion set incrementally (~50s; watermark = prior built −2d overlap; auto-FULL every 14d to unwind late refunds; atomic write that refuses an empty set). Kills the RC3 outage class: funnel_stage_export.py (02:30) and segment_guard.py both gate on this file being <48h old, and nothing used to refresh it — both also now self-heal via retention/ever_paid_fresh.py as backstop | — | | com.tma.abandondraft | 06:05 daily (NEW 10 Aug 2026) | retention/quiz_abandon_manual_notes.py --draft — the personalised quiz-abandon notes previously drafted only when someone typed the command by hand. Drafts only; --live deliberately does not exist — Aga sends | ✅ drafts | | com.tma.inboxtriage | 06:10 daily (NEW 11 Aug 2026) | retention/inbox_triage.py --draftthe lane for inbound no other lane owns. Classifies hello@ (support · out-of-office · sensitive · vendor · unknown-sender), builds the full customer brief (support_brief.py), drafts a personalised reply, labels the thread SUPPORT — LEIH SENDS, and emails Leih's morning page to hello@. 🔴 NO --send MODE EXISTS (Aga, 11 Aug: "for support emails that you didn't craft, i need you to NOT send them ever — they need to be sent by Leih, only, or Aga"), and send_payment_drafts.py refuses that label explicitly, proven by its own selfcheck. Sensitive mail (refund · injury · legal · anger · press) gets NO draft and is flagged NEEDS A HUMAN DECISION. Out-of-office is detected on the RFC 3834 Auto-Submitted header (never the subject) and becomes a dated row in follow_up_queue.py, +1 day — never a reply, never engagement, never a STOP. | ✅ drafts + emails the page to itself | | com.tma.offerreach | 07:10 Mon (NEW 10 Aug 2026) | email-analytics/offer_reach_check.py — refreshes data/email-analytics/campaign_automation_map.json, which sequence_scoreboard.py red-banners at >14d. Producer was unscheduled; the map would have crossed the line ~20 Aug | — | | com.tma.backup | 01:30 daily (NEW 10 Aug 2026) | ops/backup_snapshot.pyhard-linked incremental snapshots of the whole asset estate to ~/TMARepoBackups/, 14 kept. Replaces scripts/backup_repo.sh, which made a FULL ~54 GB copy per run, was never scheduled, excluded APP ASSETS/, and had grown to 233 GB — taking the boot disk to 97% full, the exact condition that froze the Mac in August. --link-dest means every snapshot after the first costs only the delta while staying a complete browsable tree (measured: a 65 GB tree for 12 GB of real disk). Includes .git (9.8 GB) — the origin remote is dead, so the history exists in exactly one place. Refuses to keep a snapshot missing any of marketing/ docs/ data/ tools/ CLAUDE.md, and prunes itself if free space drops under 40 GB. Watched by cockpit_watchdog check 17 (stale >36h or incomplete → 🔴). 🔴 These live on the SAME MAC — they survive the T9 drive dying and accidental deletion, NOT theft, fire or the Mac dying. An offsite copy is still an open decision for Aga. | — | | com.tma.jobselftest | 04:10 Sun (NEW 10 Aug 2026) | ops/job_selftest.pytests the smoke detector. Every guard in this estate was proven by inducing a real failure on 10 Aug; nothing re-proved them afterwards, and protection systems rot silently (the watchdog's own alert emails pointed at /tmp paths dead for 12 days). This drill re-induces all six weekly: hung job → killed at timeout (124) · flaky job → absorbed by retry · exit-0-without-writing → rejected by --proof (65) · bash-wrapped plist → caught by the lint · backdated ever-paid set → self-heals · deadman endpoint → rejects a bad secret, accepts a real beat. Writes tools/ops/job_selftest_status.json; a FAILED drill surfaces in Aga's 05:55 email, as does a drill that has not run in >9 days | — | | com.tma.asopull | 05:15 daily (NEW 10 Aug 2026; RETIMED from 06:20 → 05:15 on 11 Aug 2026 — at 06:20 it landed AFTER both daily surfaces (Slack 05:29, email 05:55), so every morning both rendered the PREVIOUS day's App Store pull. Now first in the morning chain. Backup: ~/Library/LaunchAgents/com.tma.asopull.plist.bak-2026-08-11) | aso/asc_analytics_pull.py --download then aso/aso_daily.py — refreshes data_aso_daily.json (App Store installs/deletes funnel). Was unscheduled: the cockpit card + Slack post quoted a 31 Jul pull as current for 10 days. Both surfaces now also render "as of " + a ⚠ STALE tag past 10d | — |

Since 29 Jul 2026 (§6c) every job above runs THROUGH tma_job_run.py — same interpreter, plus T9 mount-wait, persistent logs (~/Library/Logs/tma/<label>.log — NOT /tmp anymore), and success stamps. New job? Write the plist, run harden_launchd.py --apply, add its row here.

Wrapper hardened 10 Aug 2026: every job now gets a timeout (default 45 min per attempt, --timeout overrides — funnelstage/everpaid/n973to758 carry 7200s; a hung job used to hang FOREVER, invisible) and one transient retry after 90s (--retry, default 1 — zeroes the 503/timeout class that produced the only 4 genuine failures in ~2,000 runs). Stamps record retries + timed_out. 🔴 The wrapper's plist interpreter is ALWAYS python3 — reusing the job's own interpreter is the bug that bricked transcriptcompress for 4 days (bash "ran" the .py wrapper → import: command not found, exit 2, never once executed; fixed in harden_launchd.py the same day).

Exit-code semantics settled 10 Aug 2026: for CHECKER jobs (cockpitwatchdog), exit 0 = "the checks RAN" — findings are the checker's own emails, deduped one per finding per day. Exit ≠0 is reserved for "the checker itself could not run". The old semantics (findings → exit 1) made the guardian kick a healthy watchdog into an alert storm — up to 6 duplicate emails/day about one item, plus a false "watchdog MISSED" alarm.

com.ghm.* and com.aga.* jobs belong to Gut Healing Mama / other projects — not TMA, not listed here.


5. State & log map (tools/retention/)

File Holds
r1_status.json Machine state read by the watchdog, the cockpit and any LLM
sent_log.csv Every R1 note sent, by segment
reason_log.csv The churn-reason ledger (214 rows, 24 Jul)
replies_state.json · reply_fulfil_state.json Idempotency for the two draft lanes
suppress.csv STOP replies + bounces — never emailed again
payment_recovery_state.json · payment_recovery_log.csv Dunning lane state; mode = draft / draft-sent
upgrade_log.csv · upgrade_stage_log.csv · concierge_monthly.csv Monthly→Annual engine (990 Monthly→Annual Upgrade Engine)
known_reasons.csv · survey_state.json Exit-survey cross-reference (5,022 rows, 24 Jul)
Job logs ~/Library/Logs/tma/<label>.log (since §6c, persistent, rotated; /tmp paths are dead)
Success stamps ~/Library/Application Support/tma/stamps/<label>.jsonlast_success = the "did it run?" truth
Guardian status ~/Library/Application Support/tma/guardian_status.json (mirror: tools/ops/guardian_status.json)

6. 🔴 Known failure mode — the python-path trap

Any launchd job that reads /Volumes/T9 MUST use /opt/homebrew/bin/python3 or tools/finance/venv/bin/python. NEVER /usr/bin/python3.

Apple's CommandLineTools python has no Full Disk Access, so it cannot even open a file on the external volume — the job dies before your script runs:

/Library/Developer/CommandLineTools/usr/bin/python3: can't open file
'.../payment_recovery_lane.py': [Errno 1] Operation not permitted

This silently killed com.tma.paymentrecovery from the day it was loaded (22 Jul) until 24 Jul — it never produced a single draft. Every draft in that lane had been made by hand. A launchd job that fails this way leaves an empty stdout log, so it looks idle rather than broken.

6a. The sibling trap — a job that needs a CLI, not just python. com.tma.seodailysync ran green for days while silently failing its last step: the plist set no PATH, so subprocess.run(["netlify", ...]) died with FileNotFoundError: 'netlify' after every data pull had succeeded. The sync worked; only the deploy was lost, so the cockpit quietly served stale SEO numbers. Fixed 29 Jul by adding the standard block every other TMA job already carries:

<key>EnvironmentVariables</key>
<dict><key>PATH</key><string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string></dict>

Law for new jobs: if the script shells out to ANY CLI (netlify, gh, ffmpeg), the plist must set PATH. launchd's default PATH is /usr/bin:/bin:/usr/sbin:/sbin — Homebrew is not on it. Verify with launchctl print gui/501/<job> | grep PATH.

Health check (run any time):

launchctl list | grep com.tma            # col 2 = last exit status; non-zero = failing
tail -5 /tmp/payment_recovery.err /tmp/tma_r1_daily.err

6b. 🔴 Second failure mode — a POWER-OFF silently skips the day (found 29 Jul 2026)

launchd does NOT backfill a StartCalendarInterval job whose window passed while the Mac was powered off. (It does catch up after sleep — power-off is the gap.) The morning of 29 Jul the machine booted at 06:39, so the 05:35 (com.tma.r1daily) and 05:50 (com.tma.paymentrecovery) windows were simply lost: no reply scan, no dunning drafts, no status refresh, and the live T-30 pre-expiry notes never went.

How to spot it — the signature is different from §6:

§6 python-path trap §6b power-off skip
launchctl print runs climbing, non-zero exit runs = 0 · last exit code = (never exited)
/tmp logs present but empty absent entirely (/tmp clears on boot)
State files stale stale, and uptime is younger than the missed window

Confirm in one line: last reboot | head -3 — if the boot time is after the job's window, the run was skipped, not broken.

Catch-up runbook (what was run on 29 Jul):

/opt/homebrew/bin/python3 tools/retention/check_replies.py     # drafts only, safe
/opt/homebrew/bin/python3 tools/retention/reply_fulfil.py      # drafts only, safe
/opt/homebrew/bin/python3 tools/retention/payment_recovery_lane.py   # DRY first, always
/opt/homebrew/bin/python3 tools/retention/r1_daily.py          # ⚠️ step 1 SENDS LIVE — Aga approves first

All four are idempotent (state files), so a catch-up run cannot double-send. r1_daily.py needs Aga's word every time because its T-30 watcher sends live member email.

✅ CLOSED 29 Jul 2026 (PM) — see §6c. The guardian + wrapper now make this class of miss self-healing and loudly-alerted. The catch-up runbook above remains valid for manual use.


6c. 🟢 THE FIX — wrapper + guardian (installed 29 Jul 2026, verified live)

Every com.tma.* job now runs THROUGH a wrapper, and a new 18th job watches the other 17. Built + verified the evening of the §6b incident. Source of truth: tools/ops/ in the repo.

1. tma_job_run.py — the universal wrapper (installed at ~/Library/Application Support/tma/bin/, runs under each job's ORIGINAL python so TCC/FDA identity is unchanged — §6 law respected, bash never touches T9): - Waits up to 15 min for /Volumes/T9 to mount instead of dying at spawn (the T9 WorkingDirectory was removed from every plist and moved into the wrapper — launchd can no longer kill a job at boot because the volume wasn't mounted yet). - Persistent logs: ~/Library/Logs/tma/<label>.log (timestamped per run, 5 MB rotation). /tmp logs are GONE — §6b's "logs absent after reboot" can't recur. - Success stamps: ~/Library/Application Support/tma/stamps/<label>.jsonlast_success moves only on exit 0. This is the machine-readable answer to "did it actually run today?"

2. com.tma.jobguardian — the safety net (every 30 min + RunAtLoad at boot; deliberately UNWRAPPED and on the boot volume so it runs and alerts even with T9 unplugged): - Parses the live plists each pass (plists ARE the manifest — new jobs auto-covered, nothing to drift), computes each job's most recent scheduled window, compares to its stamp. - Missed window + 25 min grace → launchctl kickstart the job (max 2 kicks per occurrence, then alert-only). A power-off morning now self-heals within ~30 min of boot. - Also checks each pass: job loaded at all · non-zero last exit · T9 mounted · Gmail token freshness (<14 d) · installed wrapper/guardian hash vs repo copy (drift self-reported). - Alerts: macOS notification + email to hello@ (existing r1_lib rail, deduped 12 h/issue) + status JSON ~/Library/Application Support/tma/guardian_status.json (mirrored to tools/ops/guardian_status.json when T9 is mounted).

Verified on install night: wrapped paymentautosend ran clean under launchd (homebrew python through wrapper, TCC intact) · stamp rewound to simulate a §6b miss → guardian KICKED the job, it ran, re-stamped, next pass clean · guardian caught a real same-night issue (cockpitrefresh netlify 403, transient — redeployed OK) and its alert email landed in hello@ at 21:05.

Operational notes: - harden_launchd.py --apply is idempotent — re-run it after editing wrapper/guardian in the repo, or to enrol a NEW job (new jobs get wrapped + stamped + guarded automatically; write the plist, run --apply). --audit = read-only table. - Plist XML comments were stripped by the rewrite — the annotated originals live in tools/ops/launchd_snapshots/2026-07-29-2059/ (+ ~/Library/LaunchAgents/tma-backup-*). - launchctl kickstart can BLOCK while a service is inside its ThrottleInterval — the guardian's kick calls carry a 120 s timeout for this reason. - ✅ Root cause closed same session: pmset repeat wakeorpoweron MTWRFSU 05:20:00 applied with Aga's password (via osascript admin-privileges dialog — plain sudo has no TTY under the ! runner) and verified: pmset -g sched → "wakepoweron at 5:20AM every day". The Mac is awake before the earliest window (05:35), so launchd's no-backfill-after-power-off gap cannot bite. The guardian remains the net beneath it. To inspect/remove: pmset -g sched · sudo pmset repeat cancel.


7. Runbook — approve and send what's waiting

# What's sitting in hello@ right now (dry, sends nothing)
python3 tools/retention/send_payment_drafts.py

# Send the approved dunning drafts (this lane only — never touches reply drafts)
python3 tools/retention/send_payment_drafts.py --send

# R1 reply drafts: open hello@ → Drafts → read → send by hand.
# They are personal 1:1 replies. Read them; the reply IS the save.

Send-time doctrine: mornings. Read tools/retention/R1_SYSTEM_STATE.md (current state + work queue) and tools/retention/AGA_RUNBOOK.md (how to send) before touching a lane.


8. State of play — 24 Jul 2026 (verified live)

  • hello@ drafts: 0. All cleared this morning — 4 dunning drafts + 1 R1 reply draft (Trevor) sent.
  • Dunning lane: 22 drafts created all-time, 22 now sent, 1 recovery all-time.
  • R1 cancel queue: 111 subs · $1,556.93/mo · A 28 · B 61 · C 22. Segment A sent: 30.
  • Replies: 2 total (+1 bounce). Reason ledger 214 rows. Exit survey 5,022 rows.
  • Upgrade engine: 30 eligible, 0 tagged — still gated, waiting on AC 990's entry trigger being set to upgrade-eligible + the UPGRADE_LIVE sentinel file.
  • All 14 TMA jobs loaded (13 + com.tma.seoselflearn added 24 Jul PM); com.tma.paymentrecovery fixed and re-bootstrapped today.

8b. 🛰️ THE OFF-MACHINE WATCHER — the one alarm that survives the Mac (10 Aug 2026)

Every other guard in this document runs ON Aga's Mac. If the Mac powers off, panics, or loses its login session, every job and every alarm about those jobs goes silent together — and silence is indistinguishable from health. That was the last uncovered failure class in the estate.

https://tma-deadman-switch.netlify.app — a tiny site on Netlify's infrastructure, deliberately sharing nothing with the Mac. Source: tools/ops/deadman/.

  • beat — the job guardian POSTs here every pass (~30 min), authenticated by a shared secret (tools/ops/deadman/.secret.local, gitignored; Netlify env DEADMAN_SECRET). The guardian prints deadman ✓ / on every pass.
  • check — runs on Netlify cron, hourly (17 * * * *) and watches TWO independent signals: the heartbeat (stale >3h ⇒ the Mac is gone) and the live cockpit page's own auto-refreshed stamp (stale >30h ⇒ the morning pipeline died even if the Mac is alive). Alerts Slack, re-notifying at most every 6h, and posts a single "recovered" when beats resume.

🔴 Slack, not email, on purpose: every email rail in the estate runs through the Mac's Gmail token, so email cannot be trusted to report the Mac's own death.

🔴 Two Netlify traps, both paid for on 10 Aug 2026: (1) an env var is invisible to a function unless set with an explicit --scope functions runtime — the only symptom is a 403 that looks like a wrong secret; (2) netlify env:set --site X is silently IGNORED when the working directory is linked to a different site — it writes to the linked one. Link the directory first, then set. Also: a scheduled function correctly returns 403 to HTTP — that is proof the schedule is attached, not a fault.


9. Change log

Date Change
2026-08-10 (part 2) THE SECOND HARDENING PASS — closing what the first one left. (1) 🛰️ Off-machine dead-man's switch (§8b) — the last zero-coverage class; proven by forcing both signals stale and watching the Slack alert land, then confirming the 6h rate-limit suppressed the duplicate. (2) Plist lint in the guardian — catches a mis-wired job on the NEXT PASS instead of after 3 days; proven by re-creating the exact /bin/bash-runs-the-python-wrapper bug and watching it fire red. (3) --proof at the wrapper — enforces Aga's own "exit 0 lies when the write is at the end" law in code: a job that exits 0 without refreshing its named artifact is rejected with exit 65; wired into everpaid, emailmetrics, asopull, offerreach. (4) Weekly drill com.tma.jobselftest (Sun 04:10) — re-induces all six failures automatically, because a guard nobody exercises is a guard nobody can trust; a FAILED drill surfaces in the 05:55 email. (5) Slack as the guardian's second alert rail — all alerting rode ONE Gmail token; now a failed send falls through to Slack, with the webhook cached off-T9 (~/.config/tma/slack_alert_webhook, 0600) because the first version read it from .env.local on the drive whose absence is the alert — caught by induced test. (6) Two closers: the 05:45 PM brief now carries the same 24h jobs line (it had zero job health), and the guardian flags any job running without a register row — which found com.tma.socialselflearn unregistered on its first pass.
2026-08-10 THE HARDENING PASS — "these jobs NEVER break" (Aga's directive). Root-caused all 14 failures in ~2,000 recorded runs to 6 causes and closed each class. (1) transcriptcompress had NEVER run — harden_launchd.py reused the job's own interpreter for the wrapper, so bash "ran" a Python file (exit 2 every run, hidden by seed-credit); plist fixed, harden bug fixed, first real run compressed 181 files / 110 MB. (2) Watchdog exit semantics split: findings now exit 0 + dedupe 1/finding/day — was up to 6 duplicate emails/day + false MISSED alarms (the alarm alarming on the alarm). (3) RC3 class (freshness-gated artifact, unscheduled producer) killed: ever_paid_build.py made incremental (50s vs 60min) + atomic + auto-full/14d, scheduled (everpaid 02:10); segment_guard + funnel_stage_export share one self-heal (ever_paid_fresh.py); offerreach (Mon 07:10) + asopull (06:20) scheduled; guardian's token check repointed to the LIVE off-T9 token (false alarm was due 14 Aug). (4) Wrapper: per-attempt timeout (45min default, 7200s on the 3 long jobs) + one 90s transient retry. (5) Guardian: red-only Cc Aga (her ruling — digest + red-only), dedupe-after-delivery, vendored off-T9 Gmail sender, deterministic-failure stop (2 identical failures → 🔴 with log tail, no more kicks), never-ran detection, not-loaded re-bootstrap, guardian_history.jsonl, crash self-report; watchdog check 15 watches the guardian back. (6) Digest: 05:55 email carries a 🤖 Jobs line from 24h history; console band humanized; dead /tmp paths in alerts fixed; 4 unguarded cockpit-refresh steps soft-failed. ytretrofit retired (869/869 done). Everything proven by induced failure, not assertion — deterministic ladder (kick→kick→🟠→🔴+stop), watchdog finding (exit 0, one email, dedupe verified), hung job (killed at timeout, exit 124), flaky job (absorbed, exit 0, retries:1 stamped), heal (backdated 72h → rebuilt 46s → re-read artifact). Final guardian pass: 29 ok · 0 kicked · 0 issues.
2026-07-31 Failed-purchase lane ARMED (com.tma.failedpurchase, 05:55 daily, drafts-only) after Aga's pre-flight: CRO copy review (2 line edits — "cross-border charge", "call your bank"; dual-exit structure kept as load-bearing) → full-family bug audit, 30 findings → documentation. 8 fixed same session, incl. 🔴 C1: nothing was watching replies to dunning/failed-purchase emails — a STOP never reached suppress.csv (fix immediately surfaced a real unread reply from 28 Jul) · C2: upgrade_tag KeyError that would have broken 990 Monthly→Annual Upgrade Engine the day it armed · H2: unpaginated ever_paid could have emailed a paying member · M7: non-atomic shared Gmail token write (would take every hello@ lane dark) · H1: my own malformed plist that also crashed harden_launchd.py. Full register + 12 open items: JOB_AUDIT_FINDINGS_2026-07-31.md. Also corrected §0 (14-hour rule is a third auto-send exception) and §2.5's false reply-pipeline claim.
2026-07-29 §6c — HARDENING SHIPPED (PM session). All 17 jobs rewrapped via tools/ops/harden_launchd.py --apply: universal wrapper (T9 mount-wait · persistent ~/Library/Logs/tma/ logs · success stamps), new 18th job com.tma.jobguardian (30-min + boot safety net: parses live plists, kickstarts missed windows, alerts via notification + hello@ email + status JSON). Missing PATH fixed on cockpitemail + seoselflearn. Verified: simulated §6b miss auto-kicked + self-healed; real cockpitrefresh netlify 403 caught + alerted same night (transient — manual redeploy OK). Plist snapshots: tools/ops/launchd_snapshots/2026-07-29-2059/. Root cause ALSO closed same session: pmset repeat wakeorpoweron MTWRFSU 05:20:00 applied + verified (§6c).
2026-07-29 Registered com.tma.n973to758 (09:40 daily, homebrew python, /tmp logs — §6-compliant; temporary, self-completing) — Aga-approved reroute of the ~8,799 contacts parked in 973 Nurture Sequence 1 NEW COPY FROM CLAUDE (whose emails contain zero offer links) into 758 Nurture Sequence 2, batched 2,000/day. Pilot 5 contacts verified end-to-end (758 record active, 973 record(s) gone, duplicate records cleaned); batch 1 (1,995) launched same session. Unload + delete the §4 row when it prints DONE (~2 Aug). Same session: ambassador/affiliate links stripped from all 32 live emails of 751 Nurture Sequence 1 + 758 Nurture Sequence 2 via PUT /api/3/messages/{id}; originals in marketing/email-sequences/_BACKUPS/751-758-pre-linkfix-2026-07-29/.
2026-07-29 §6b added — the power-off skip. Mac booted 06:39, so the 05:35 + 05:50 windows were lost (runs = 0, /tmp logs absent). Caught up by hand: check_replies 0 new · reply_fulfil 0 new · dunning dry 0 due today (in-lane 20, +1 recovered) · r1_daily full run on Aga's approval → T-30 watcher sent 3 live (mike.goldman@me.com · mail.christophe.martel@gmail.com · fatma.tbee@gmail.com), survey 5,029 rows, queue 111 / $1,568.57, cockpit patched. hello@ drafts before and after: 0.
2026-07-29 One draft added by hand — reply to Goran (goranf@gmail.com, lifetime, abs progression stuck) in his existing thread. Not a lane draft, so send_payment_drafts --auto can never touch it (it hard-filters to the 3 dunning subjects). Awaiting Aga/Leih.
2026-07-24 Registered com.tma.seoselflearn (Mon 08:45, venv python, /tmp logs — §6-compliant from day one) — the SEO fleet redesign's weekly self-learn: pure-Python watch adjudication (GSC per-page 14d post vs pre; REVERT-FLAG never auto-reverts) + weekly CMO/CEO report + human-queue re-rank. Loaded + verified (launchctl list), dry-run + real run both clean (12 armed watches found, 0 flags).
2026-07-24 Extended com.tma.seodailysync — now also renders marketing/seo/SEO_DAILY_BRIEF.md (5 fleet KPIs: organic quiz-starts d7/d28 generate_lead · GSC both domains · AI-referral sessions · link-integrity guard · changelog throughput 24h) + the ≤3/≤3 AGA/NIC human lists from the new tracked queue marketing/seo/SEO_HUMAN_QUEUE.json (§12.7-E contract), mirrored into the cockpit SEO-LIVE block. Also fixed a latent bug: gsc_pull summary --json returns a LIST, but the renderer only read dicts — the cockpit GSC cells had silently rendered "—" since the block was born. Zero LLM tokens throughout.
2026-07-24 Fixed com.tma.socialdash — every run since creation exited 126: launchd ran the .sh via /bin/bash, which has no Full Disk Access to /Volumes/T9 (§6 class). Ported to tools/social-pipeline/refresh_social_dashboard.py run by the finance venv python; plist rewritten + reloaded; verified live (board deployed to tma-social-scoreboard.netlify.app). The .sh stays for manual use.
2026-07-24 Fixed com.tma.seodailysync — never spawned (exit 78, no log files ever created): StandardOutPath/StandardErrorPath pointed at /Volumes/T9 paths launchd cannot create (§6 class — same law, log-path variant). Moved logs to /tmp/tma_seo_sync.out|.err, reloaded. NOTE for new jobs: logs go to /tmp, never onto T9.
2026-07-24 Fixed com.tma.paymentrecovery/usr/bin/python3/opt/homebrew/bin/python3, added PATH + WorkingDirectory to match com.tma.r1daily. plutil OK, re-bootstrapped, dry-run verified (3 candidates found). Backup: com.tma.paymentrecovery.plist.bak-2026-07-24.
2026-07-24 Sent all 5 waiting drafts (4 dunning T2/T3 + 1 R1 reply). hello@ drafts → 0.
2026-07-24 ⏸️ Aga parked the failed-purchase lane — new checkouts incoming will feed richer Stripe data; build against that signal, not today's. R1 + dunning continue unchanged. PI-metadata requirement moved to a build-time ask on the new checkouts.
2026-07-24 Built failed_purchase_lane.py (§2.5) — the third lane. Dry-run clean: 30d window → 14 people, 9 actionable, 5 correctly skipped. Not scheduled, not armed.
2026-07-24 Established that Stripe holds every failed purchase attempt (charge + decline code + email + cardholder name + amount) but carries NO plan/couponmetadata is empty on both charge and PaymentIntent. Plan is inferable from amount only. Nic fix = write plan_slug/coupon/user_id into PI metadata — the same hook already briefed for cart-abandon Path B (NIC-CART-ABANDON-STRIPE-AC-BRIDGE-2026-07-22.md).
2026-07-24 This register created.
2026-07-23 18 of 22 dunning drafts approved + sent.
2026-07-22 com.tma.paymentrecovery first loaded (broken from day one — see §6).
🔍 Job Audit Findings (31 Jul) every known bug and fragility, ranked

hello@ JOB FAMILY — FULL AUDIT FINDINGS · 31 July 2026

Why this exists. Aga's pre-flight rule before arming the failed-purchase lane: "look for any inconsistencies, anything that could break or any bugs for all the jobs, document them all — and then we execute." This is that register.

Scope: all 21 retention/email scripts + the launchd wrapper/guardian + the live plists + live state files, read against AUTOMATION_JOB_REGISTER.md. Read-only audit by an independent agent; every finding below was re-verified by hand before any fix. Status key: ✅ FIXED (this session) · 🔴 OPEN · ⚪ ACCEPTED (known, not worth fixing yet).


0. The headline

30 findings. 8 fixed today (every one that could email the wrong person, plus the two that could take the whole rail down). The remainder are documented, ranked, and none of them block the failed-purchase lane.

The single most valuable find had nothing to do with the new lane: nothing was watching replies to dunning emails. Every dunning and failed-purchase note promises "Reply STOP and I won't email you about it again" — and no scanner watched those subjects, so a STOP never reached suppress.csv. Within one minute of the fix going in, it surfaced a real reply that had sat unread since 28 Jul: Simon replying "I've already cancelled the subscription" to a dunning note. Nobody had ever seen it.


1. FIXED THIS SESSION

# Sev What was wrong Fix
C1 CRITICAL STOP replies to dunning/failed-purchase were never captured. check_replies walks only R1 threads; reply_fulfil.RULES covered only the 986/976 arcs. A member could reply STOP and still get T2 three days later — auto-sent, no human in the loop. The failed-purchase lane's entire conversion mechanic ("hit reply and I'll send you a fresh link") also had no pipeline. reply_fulfil.py now watches all 4 payment subjects (imported, never retyped). STOP → suppress.csv automatically. Live replies are surfaced as 🔴 NEEDS AGA and counted into r1_status.json — deliberately no auto-draft, because an auto-drafted "here's your link" with no link is worse than nothing.
C2 CRITICAL upgrade_tag.py:286 read row['annual_saving']a key that never existed. KeyError on every live tagging, swallowed by a blanket except. AC fields + upgrade-eligible tag were written first, so 990 Monthly→Annual Upgrade Engine would start emailing while the log row was never written → Stage 2/3 could never fire, conversion detection never ran, member re-processed daily. Dry runs never reached the line. row['annual_saving_129']. Latent (gated behind the UPGRADE_LIVE sentinel) — it would have broken the day you armed the upgrade engine.
C3 (part) CRITICAL Non-atomic state writes + write-once-at-end. A crash mid-run lost the whole run's state → next run re-drafted the same notes → two identical drafts, both auto-sendable. failed_purchase_lane: atomic save_state() (tmp+rename) after every draft. Dunning/autosend pair: see 🔴 O1.
M7 MEDIUM→HIGH The shared Gmail token was written non-atomically. Four scheduled lanes + the guardian all refresh through one token.json; two interleaved writes corrupt it and every hello@ lane goes dark until manual re-auth. r1_lib._creds() now writes tmp+os.replace.
H1 HIGH The new lane's plist (written earlier this session) had --auto inside an XML comment — illegal XML. plutil passes but plistlib throws: job never loaded, and harden_launchd.py crashed outright, so no job could be wrapped or enrolled. Self-inflicted, caught by the audit. Comment reworded (no -- sequences) + a warning note in the plist so it can't recur. harden_launchd.py --audit verified working again.
H2 HIGH ever_paid() used unpaginated customers limit:10 + charges limit:100. A serial retrier (one had 21 attempts; Payment-Element checkouts can mint a customer per attempt) could push the successful charge off page 1 → "your payment didn't go through" emailed to a PAYING member. Fully paginated via a new _paged() helper, and fails SAFE: any Stripe error now returns True (treat as paid → don't email).
H3 HIGH "One note per person, ever" was actually one note per charge — state keyed by charge id, so a retrier who failed again next week got a second "one-time" note. Now also skips any email already in state.
M11 MEDIUM Charge filter was status != "succeeded", which swept up pending charges → a payment still processing could be told it failed. status == "failed" only.

Guarded against regression: an assert at import time fails loudly if the failed-purchase subject ever collides with a dunning subject — the invariant that keeps its drafts human-gated.


2. 🔴 OPEN — ranked, none blocking

31 Jul (later): O1 is FIXED (struck through below, kept for the record). O6 remains the gate on arming 976 Cancelled Win-Back — paginate the customer lookup first, or an active paying member can be tagged wb-eligible and offered a win-back discount.

# Sev Finding Why it can wait
~~O1~~ FIXED 31 Jul ~~The dunning ↔ autosend pair still has C3's double-send risk~~ — CLOSED. Aga ruled "fix it" 31 Jul. New tools/retention/state_io.py: atomic_write_json() (temp file in the same dir → fsync → os.replace, so a crash leaves the old file or the new one, never a truncated one) + lane_lock() (shared, non-blocking flock). Both payment_recovery_lane.py and send_payment_drafts.py now take the SAME lock around their whole run and exit 0 if the other holds it — a skipped pass is free, an overlapping pass is the double-send. Both also save state per item immediately after a touch/send, so a crash costs at most one member instead of the run's stamps. read_json() survives an empty/truncated file without the delete-the-file "fix" that re-drips T1. Verified: atomic round-trip + no temp files left · second process correctly excluded · both real scripts skip when the lock is held · live dry run of the lane leaves all 31 records byte-identical.
O2 HIGH send_payment_drafts lists at most 100 drafts, unpaginated; Gmail returns newest-first, so the oldest (ripest to send) fall off first. Approved dunning email silently never sends and nothing reports it. Only bites above 100 simultaneous drafts. Follow nextPageToken.
O3 MEDIUM r1_queue_emails() fails open (except: return set()): if the subscriptions call fails while invoices succeed, the "R1 owns them" skip silently evaporates → two lanes email the same person in one week. Should raise and abort the run instead.
O4 MEDIUM Autosend does no send-time spacing or re-check: after an outage, T2 and T3 for one member can both be >14h and fire in the same pass; it never re-reads suppress.csv or re-checks whether the invoice got paid. One send per recipient per pass + re-check suppress/invoice.
O5 MEDIUM Guardian treats a long-running job as MISSED — compares only last_success, never the last_attempt stamp. com.tma.n973to758 runs ~95 min → burns both kicks and raises a false alert. Cosmetic today (kickstart on a running service is a no-op), but it cries wolf.
O6 MEDIUM saves()/check_saves cap customer lookups at 10 records → a member whose active sub sits on an 11th record is misread as "expired unsaved" → wb_tag marks them wb-eligiblewhen 976 Cancelled Win-Back activates, an active paying member gets a win-back discount. Latent until 976 is armed. Paginate before then.
O7 MEDIUM upgrade_tag._lifetime_paid caps at 100 invoices → undercounts "you've paid $X" precisely for the longest-tenure members the offer targets. Latent behind UPGRADE_LIVE.
O8 MEDIUM migrate_973_to_758.api() retries a POST after an ambiguous timeout → duplicate AC records → contact runs 758 Nurture Sequence 2 twice in parallel. Job self-completes ~2 Aug; check already_in_dst before retrying if it recurs.
O9 MEDIUM Crash-mid-run can duplicate reply drafts (check_replies/reply_fulfil save state only at end). Human-gated (Aga reads before sending). Same fix pattern as C3.
O10 MEDIUM Two unguarded cross-lane pairs: cart-abandon vs failed-purchase (same person, same day, two emails) once the blur-write ships; and send_upgrade_stage doesn't skip current R1 cancel-queue members. Both latent. Add the state-file checks when either ships.
O11 MEDIUM R1 can never re-touch a repeat cancelleralready_sent() is a lifetime set, so someone saved in July is invisible if they cancel again next year. Design gap that grows quietly. Key on (email, subscription) or expire on re-entry.
O12 LOW ×10 draft_body reads only text/plain (HTML-only edited draft → empty body → needs_aga sees subject alone) · sent stamp hits the first matching record when a person has two open invoices · missing internalDate → infinite age → immediate send · tz off-by-one on manual evening runs · watcher send-count scraped from stdout · EMAIL_FIXUPS typo remap not applied in the new lane · reply_fulfil searches in:anywhere (spam included) · retention_cockpit_sync unescaped regex replacement · wb_tag never retries NOT_IN_AC · wrapper keeps a stale last_error. Hygiene. Documented for whoever touches these next.

3. Register corrections applied

The audit checked AUTOMATION_JOB_REGISTER.md against reality and found these drifted:

  • §0's "nothing auto-sends, only two --live exceptions" contradicted §4's own autosend row — the 14-hour rule is a third exception. Now stated in §0.
  • §2.5's claim that failed-purchase replies "are picked up by reply_fulfil.py" was false as coded — true only as of today's C1 fix.
  • §4/§6 still pointed at dead /tmp log paths (§6c moved logs to ~/Library/Logs/tma/ on 29 Jul).
  • send_payment_drafts.py's docstring still calls itself a "one-shot companion"; it is a twice-daily scheduled auto-sender.
  • §2.3's line reference had drifted (:144:177); §8's job count (14) predates the current 18 + guardian.

4. The safety question, answered explicitly

Can send_payment_drafts --auto ever send a failed-purchase draft?

No. Its filter requires BOTH: subject exactly equal to one of the three dunning subjects (imported from payment_recovery_lane.SUBJECTS — list membership, not prefix match) AND the recipient present in payment_recovery_state.json. The failed-purchase subject diverges at character 5 and its recipients live in a different state file. R1 and reply_fulfil drafts all carry Re: prefixes and cannot match either. Unrecognised drafts are skipped and counted "left untouched".

The invariant previously hung on string constants in two files with nothing guarding it — now covered by an import-time assert.


5. Pagination inventory (the failure class that keeps recurring)

A limit=100 scan with no pagination silently truncated a Stripe census on 30 Jul (undercount 4×) and would have emailed a paying member here. Full sweep:

  • Correct: r1_lib.fetch_queue · payment_recovery_lane.failed_renewal_invoices · failed_purchase_lane.failed_purchase_charges · cart_abandon_reconcile._recent_payment_intents · upgrade_tag._active_subs · migrate.enumerate_active_in_src · failed_purchase_lane.ever_paid (fixed today)
  • Still truncating: upgrade_tag._lifetime_paid (O7) · saves/check_saves customers (O6) · send_payment_drafts Gmail drafts (O2)
  • Acceptable: reply_fulfil._search maxResults=50 (self-heals across daily runs)

Standing rule going forward: never use a bare limit=N list for a safety check or a count.


Audit + fixes: 31 Jul 2026. Companion: AUTOMATION_JOB_REGISTER.md (canonical job register) · cockpit ⚙️ Daily Jobs tab (live health).

✉️ hello@ Email Rules the copy law for every 1:1 member email

🔴 HELLO@ EMAIL RULES — the law for every 1:1 email sent from hello@themovementathlete.com

Set by Aga, 31 July 2026. Governs every email the retention rail sends or drafts from hello@themovementathlete.com: R1 cancel-save, the T-30 watcher, dunning/payment-recovery, failed-purchase, reply-fulfilment, concierge, upgrade stages — and any lane added later.

The one sentence that decides every question below:

It has to look like Jesse just typed it.

These emails work because they are indistinguishable from a personal message. Every rule here exists to protect that. When a new idea conflicts with it, the idea loses.


⚠️ First: this is NOT the marketing email estate

Two completely different systems share the word "email". Never apply one's rules to the other.

hello@ 1:1 rail (this document) Marketing estate (ActiveCampaign / Customer.io)
What Personal notes from Jesse to one member about their account Campaigns, sequences, broadcasts
Looks like A person typed it A designed email
Governed by This file CLAUDE.md EMAIL RULE → /email-fleet, locked footer, email_lint.py, white canvas, design guide
Template None. Ever. Canonical template, mandatory
Sent by Gmail API from hello@ AC / CIO

Running these through the marketing fleet would destroy the thing that makes them convert. Running marketing emails under these rules would fail the lint gate. Keep them separate.


THE RULES

1. No styling. None.

No bold. No underline. No italics. No colour, no headings, no dividers, no images, no logo, no footer bar, no background colour, no buttons. A person writing to one other person uses none of these. (Aga, 31 Jul: "remove the bold so it really looks like Jesse just typed it.")

The renderer supports **bold** / _italic_ / __underline__ markers — do not use them in lane copy. They exist only so a future exception can be made deliberately, not by drift.

Note the deliberate difference from the marketing law. The estate rule ("bold the key line, italic the human beats, one underline") is correct for campaigns and wrong here. Same goal — easy reading — opposite means: in a personal email, readability comes from short paragraphs, not from formatting.

2. One idea per paragraph. Short paragraphs.

This is how people actually type, and it is the ONLY readability tool available under rule 1. Never stack the bad news, the reassurance and the instruction into one block. Break them.

3. Links must be clickable — never a bare URL to copy-paste.

(Aga, 31 Jul: "make a link an actual clickable link — instead of a dead link they need to copy and paste.") A URL sitting on its own line becomes a real anchor. - Standard link blue #1155cc — Gmail's own. Not a brand colour: branded links read as a campaign at the exact moment we need trust. - Keep the → arrow — under rule 1 it is the only visual cue the text is clickable. - Built automatically by r1_lib.build_message() / text_to_html(). Never hand-build MIME.

4. Anchor text: descriptive, honest about the destination, CRO-reviewed.

Never "click here" (generic, tests poorly). Never over-promise what the first screen shows. - Dunning → Fix your billing → — task-framing. It must NOT say "Update your card", because the link lands on the Stripe login page (enter email → Stripe sends a sign-in link → then the card form). Promising a card form and delivering a login box creates doubt on a billing page, which costs more than any click-rate gain. - R1 cancel-save → Keep training → — outcome-framing. They chose to leave; administrative language reads as the process they already rejected. The email's real goal is a reply. - Different lanes get different anchors on purpose — the member's psychological state differs. Any new anchor goes through the email-copywriter agent first.

5. multipart/alternative — the plain-text part is ALWAYS kept.

text/plain (markers stripped, bare URL) + text/html (the clickable twin). Non-negotiable: - plain-text clients and forwards must work; - send_payment_drafts.needs_aga() reads the plain part — lose it and the safety gate goes blind (audit finding L1); - a body with no link stays pure plain text — no HTML part at all (e.g. failed-purchase notes, guardian alerts). Don't add HTML for its own sake.

6. The reply is a feature, not a fallback.

Reply-to is always hello@, a human reads it, and the copy says so. Where a lane can convert on a reply instead of a link (failed-purchase: "hit reply and I'll send you a fresh link"), prefer the reply — it has no links to distrust and it starts a conversation. Every lane's subject must be watched by reply_fulfil.py so STOP suppresses and a live reply is surfaced. (This was missing until 31 Jul — audit finding C1.)

7. Two closing beats, always.

  • The human line — "I read these myself", "thanks for training with us, and I mean that".
  • The permission line — an explicit, pressure-free exit: "if the timing turned out to be wrong, that's completely fine — reply and say so." Giving the no-thanks reply equal weight to the yes reply is what stops the email reading as chasing. The copywriter identified this as the single most load-bearing element for reply rate. Never cut it to save space.

8. Signature and footer, verbatim shape.

Jesse
Head Coach, The Movement Athlete

--
You're receiving this because <the specific reason>. This isn't a marketing campaign.
Reply STOP and I won't email you about it again.

Jesse is Head Coach, never "founder". Say why they're getting it, in one honest clause. The STOP promise is real — rule 6 makes it work.

9. Never blame the wrong party; never fabricate.

Copy branches on the actual failure reason (bank block vs card details). No invented urgency, no fake deadlines, no claims we haven't verified. If we caused it, say so.

10. Nothing sends itself.

Every member-facing message is a Gmail draft waiting for Aga. Three explicit exceptions — the R1 T-30 watcher, the upgrade stages (both --live, templated pre-approved copy), and the 14-hour auto-send rule scoped to the dunning lane only. A new lane arms drafts-only.

11. Arming a lane = copy review + audit + docs, then execute.

Aga's pre-flight law: run the copy through the email-copywriter (CRO) seat, audit the whole job family for bugs, document it into the register + cockpit — then arm.


Where this is implemented

Thing File
Renderer (multipart, links, markers) tools/retention/r1_lib.pybuild_message() · text_to_html() · strip_markup()
Dunning copy + anchor tools/retention/payment_recovery_lane.py (BODIES, make_draft)
R1 copy + anchor tools/retention/copy/seg-*.txt · send_r1.py · pre_expiry_watch.py
Failed-purchase copy tools/retention/failed_purchase_lane.py (no links — reply mechanic)
Reply + STOP capture tools/retention/reply_fulfil.py (PAYMENT_SUBJECTS)
Safety gate tools/retention/send_payment_drafts.py (needs_aga)

Canonical companions: docs/company/GOVERNANCE/AUTOMATION_JOB_REGISTER.md (what each lane does) · JOB_AUDIT_FINDINGS_2026-07-31.md (known bugs + open items).

Changing any rule here changes what a real member receives. Update this file in the same session, or it is drift.

Full scheduled-job register (launchd · ~/Library/LaunchAgents/)
JobWhenRunshello@
r1daily05:35 dailyretention/r1_daily.py✉️ drafts + T-30 sends
paymentrecovery05:50 dailyretention/payment_recovery_lane.py --draft✉️ drafts
failedpurchase05:55 dailyretention/failed_purchase_lane.py --draft✉️ drafts
paymentautosend08:00 + 20:00retention/send_payment_drafts.py --auto — the only unattended sender; dunning lane only, 14-hour rule✉️ SENDS
jobguardianevery 30 min + bootops/job_guardian.py — kicks missed windows, alerts hello@✉️ alerts only
n973to75809:40 daily (temporary)retention/migrate_973_to_758.py --batch 2000
cockpitrefresh06:00 dailyfinance/refresh_cockpit_daily.py
emailmetrics06:10 dailyemail-analytics/collect_metrics.py
morningpulls06:15 dailyfinance/morning_pulls.py
cockpitwatchdog06:30 dailyfinance/cockpit_watchdog.py
socialdash06:30 dailysocial-pipeline/refresh_social_dashboard.py
seodailysync06:40 dailyseo/seo_daily_sync.py --deploy
cockpitemail07:00 dailyfinance/daily_cockpit_email.py✉️ to hello@ (internal)
mondaybrief07:00 Monfinance/monday_brief.py✉️ internal
emailselflearn08:12 Monemail-analytics/run_selflearn.py
seoselflearn08:45 Monseo/seo_selflearn.py
ytselflearn08:30 Tueyoutube-analytics/yt_selflearn.py
ytretrofit09:15 dailyyoutube-analytics/apply_retrofit_all.py --apply
growthsyncevery 15 minfinance/growth_repo_sync.py --pull-deploy
com.ghm.* / com.aga.* jobs belong to other projects — not TMA, not listed.
🔴 THE TRAP

Any launchd job that reads /Volumes/T9 MUST use /opt/homebrew/bin/python3 or the finance venv — NEVER /usr/bin/python3. Apple's CommandLineTools python has no Full Disk Access, so it dies with [Errno 1] Operation not permitted before the script runs, leaving an empty log — so it looks idle, not broken. This killed paymentrecovery silently for two days. Health check: launchctl list | grep com.tma (col 2 = last exit status).

Approve & send what's waiting
python3 tools/retention/send_payment_drafts.py          # dry: what's in hello@
python3 tools/retention/send_payment_drafts.py --send   # send dunning drafts only
# R1 reply drafts: open hello@ → Drafts → read → send by hand (the reply IS the save)
Deep detail — every lane, state/log file, runbook, change log — in AUTOMATION_JOB_REGISTER.md · lane state tools/retention/R1_SYSTEM_STATE.md · how to send tools/retention/AGA_RUNBOOK.md.
Rules of this surface: USD only · recurring MRR only (one-time cash separate, never blended) · break-even $15K canonical · every figure carries its time window · no cash/runway/payroll on this surface.
Confidence: MRR, cancels, queue, Meta spend, Stripe revenue = CONFIRMED. Retargeting ROAS, email ~6% = PARTIAL (small n / last-click). Lead→Trial, Cost/Trial, CAC = DARK until Phase 0.
Hierarchy: this cockpit is the daily instrument of TMA-STRATEGY-SOURCE-OF-TRUTH-JUL2026.html — on any contradiction, the SoT wins.