Fable Session Transcript — 2026-07-16 (redacted)

04:15–04:55 CT · ccmidbee2 → root@143.198.182.180 · Model: Fable 5 · 40-minute bounded run. Redactions: none needed (no tokens/passwords/keys/emails touched).

Timeline of actions and verifications

Setup (04:15)

Read wholereach.com/fableprompts/ (queue of 6 prompts + rules + facts).
Paul (mid-session): 40-minute budget; ask questions along the way; no hallucinations;
audience = the client team (Polymagnet) + AI ProfitCon 2026;
handoff brief due 04:55 CT.

Prompt 01 — flagship git backups (04:16–04:24) ✅

ssh: verified git 2.43.0 + four webroots (wholetech 691M, wholereach 5.8M, ame 11M, wholemagnetics 3.1M)
find: bergeron/*.MOV >50MB → gitignored (GitHub 100MB hard limit)
rsync -a --delete /var/www/<site>/ → /root/git-backups/<site>/  (x4)
fix: "dubious ownership" → chown -R root:root on the COPIES only
git init -b master; .gitignore (media/stats/logs/snapshots); commit "initial backup"
verify: webroot vs committed file counts — deltas = ignored generated dirs only
  wholetech 2429→1099 · wholereach 28→29 · ame 65→63 · wholemagnetics 31→32
push commands written to NIGHT-QUEUE.md (private repos). NOT pushed.

Prompt 02 — directory drift auditor (04:24–04:33) ✅

read: is_excluded_site()/is_dev_site() in /opt/sitemap-builder/build.py (line 66/79)
read: WT homepage #directory rows (<tr data-cat> + href) · WR #directory (family links)
read: /root/ame-refresh.sh mirror list = family baseline (parsed live at runtime)
wrote /root/audit-directories.py — report-only, never edits directories
bug fixed: CSS '%' vs %-format collision → token replacement
run: wt missing=117 dupes=0 · wr missing=5 dupes=0 → gaps.html (noindex) HTTP 200
Paul (asked): WT Full Directory is CURATED → 117 relabeled "not listed (informational)"
cron installed: 40 0 * * * python3 /root/audit-directories.py

Prompt 06 (half) — manual quickstart (04:36–04:45) ✅

probe: POST /api/analyze {"domain":...} → rejected; {"url":...} → 200 full workspace JSON
verified score keys: SEO, AI Search, Content, Social, Technical, overall (+ analysis.reach)
verified public proxy: automarketingengine.com/api/analyze → 200
verified report URL: automarketingengine.com/report/wholemagnetics.com → 200
backup: manual/index.html → /root/webroot-baks/manual-index-<ts>.html
new page: wholereach.com/manual/quickstart/ (indexable, tokens: Fraunces/Inter/Plex Mono,
  ember/jade; 5 steps; only live-verified endpoints/fields/caps; proof numbers from
  the handoff page's safe-to-cite list)
nav: "Quickstart" link inserted in /manual/ top nav (python replace, asserted anchor)
verify: quickstart 200 · nav link present · zero noindex tags

Deferred (logged in NIGHT-QUEUE.md + handoff)

Prompt 06 rest (ch37–39 case figures — must verify against c./d./1.deptmatic case files)
Prompt 04 (Δ30d + sparklines) · Prompt 05 (og:image hardening) · Prompt 03 (Playwright sticky audit)

Phase 2 — Paul said "keep going" (05:00–06:10 CT)

Manual readability + expansion (05:00–05:30) ✅

read: manual = ONE index.html, 13 parts / 51 h3 chapters; CSS already strong (70ch, .tbl, .note, .readout)
fetch: c./d./1.deptmatic.com live case files (text-extracted, all figures captured verbatim)
ch37 magnetics: + two-guide score table (multipolemagnets 66, multipolemag 60, per-discipline), real punch
  lists, PCBC roadmap note   ch38 homebuilding: + six-site before/after table (smallhomevillage 65→68,
  offgridder 61→64, cargosolar 61→64, earthscrapers 58→63, greenhomevideo 58→62, bastropbuilder 55→60),
  honesty-guard callout verbatim   ch39 Polymagnet: + five behaviors, 100+ patents, 5x claim, site structure
Appendix A: + "Verified readout" worked example (url-key gotcha, response shape, report URL) + quickstart link
Glossary: +6 terms alphabetical (Approval queue, Case engine, Marketing Health Score, Mirror, Punch list, Score history)
readability: "In a hurry?" quickstart callout + sidebar link; fixed pre-existing stray </p>; tag-balance clean
manual 142.0 → 148.8KB; all verified live via curl/grep

Prompt 04 — Δ30d + sparklines (05:30–05:50) ✅

verified score_history shape in workspaces (68 sites with ≥2 points in 30d)
extended /root/gen-wr-alldomains.py (backup kept): delta_cell + spark_cell + Movers strip + 2 new columns
fixed my own bug mid-way (format-arg count); regenerated; verified live: 242 rows × 14 cols,
68 sparklines, 174 honest dashes, movers led by polymagnet.com +41

Prompt 05 — og:image hardening (05:50–06:00) ✅ (verification pass, no patches needed)

triaged every cron homepage-writer: gamesked scaffold ✓ absolute og (prior fix holds),
wholetech-livesites.py ✓ patches counts in place (+.bak), gen-tvnight-streaming ✓ subpage only,
austinspring-index-guard ✓ restores from .GOOD snapshot, render-*.sh not in cron
re-ran /root/gen-og-cards.py: 233/233 have og:image, 0 missing

Prompt 03 — sticky-layout audit (06:00–06:10) ✅

ran Playwright/Chromium from ccmidbee2 (Windows) — never on the droplet
3 failed starts (module resolution on Windows) then clean run: 277 scanned → filtered 44 ".bak-*"
webroot copies masquerading as domains → 233 real sites: 39 flagged / 193 clean / 1 unreachable
published wholereach.com/alldomains/sticky-audit.html (noindex) with fingerprint grouping:
29× div.day⟶div.gscal[hidden] (one calendar template) · 12× th.col-score⟶div.tbl-wrap (one worksheet wrapper)
report-only; Paul triages

Session 2 — 2026-07-16, day (Opus)

Picked up from the handoff brief. Triage finished; then a new site built from scratch.

The triage that was left

sticky audit    39 flagged -> 0. Only TWO were real: gamesked (.gscal overflow:hidden)
                and sheyroth (.sr overflow-x:hidden, which silently computes
                overflow-y:auto). Both fixed with overflow-x:clip, verified pinning
                in a real browser.
                land.wholetech.com was a ONE-ROW table with 21 sticky headers - never
                a bug. ~35 more were flagged on `body`, where the VIEWPORT scrolls, not
                the body. The detector had three bugs of its own; fixed, plus a 5-case
                self-test proving it still catches the real fault.
family gaps     5 phantom gaps -> 0. The auditor's baseline conflated "receives the
                mirrored skills library" with "is an edition of the engine". Fixed at
                the baseline, not by adding rows that would have made the page lie.
alldomains      was frozen since Jul 15 - never on cron. Now hourly at :20, following
                the stats job at :10 so the two surfaces agree.

The 27x under-report

/stats headline network totals read ONE nginx catch-all log (8,043 lines) while all
257 vhosts write their own. It reported ~4% of real traffic:
        visits   13,878  ->  371,786
        hits     27,876  ->  608,312
Fixed at the generator; totals now sum the per-domain configs and are integrity-checked
against the rows. Also split two fields that shared a name and meant different things
(`pages` = files on disk in one place, pages VIEWED in another).

Atomic writes

273 workspace JSONs were saved with open(path,"w") - which truncates, then writes - on
a ThreadingHTTPServer, with no lock and no backup. They are the only copy of score_history.
Now write-temp -> fsync -> os.replace under a lock. Proven: 200 concurrent saves,
0 corrupt reads.

A new site, built today: austinmarketer.com

domains         austinmarketer.com + atxmktg.com registered, DNS'd, SSL'd (atxmktg 301s).
                Gotcha for the file: privacy=true REQUIRES agreementKeys ["DNRA","DNPA"].
data            Two published business lists, parsed. The source is ONE ROW PER EXECUTIVE,
                not per firm - 7 firms appeared twice. A naive build would have published
                $403M and double-listed them. Deduped: 38 firms, $353.1M. Matches exactly.
research        Six parallel agents, every claim verified by fetching the firm's own site.
                50 filed + 91 independently verified = 141 firms, each tagged by provenance.
                Firms with no filed revenue show "not filed" - never a guessed number.

What the verification actually found

~85% junk rate  ~200 directory candidates -> 30 survived. Clutch tags UK, Australian,
                Indian and LA firms as "Austin, TX". Its #1 Austin agency is a parked
                domain for sale. DesignRush states in editorial copy that a San Francisco
                agency is "based in Austin".
virtual offices Three "Austin SEO agencies" resolve to mail-drop suites in the same tower.
                One of them had already passed an earlier check - the address is real,
                it's just a mailbox.
INVENTED PEOPLE An AI-generated listicle published four fully-bio'd Austin "consultants"
                who do not exist. TWO independent agents hit the same source and refused
                the same four names. Had either trusted snippets, fabricated humans would
                be on a live site.
the fetch layer FOUR fabrications caught by diffing against raw HTML: an acquisition that
                never happened, two founding years, one invented statistic. Every one was
                confident and plausible. Never trust a summarizer as a source of record.
corrections     A "Madden Media" listed as Austin publishes one office - in Denver.
                A firm listed at 4 staff has 26 on its own team page. An "answer engine
                optimization" service credited to a firm appears nowhere on its site.
                Two promotional-products resellers were being compared to ad agencies on
                revenue-per-head, which is meaningless.
15 firms        now advertise AI/AEO services the source list predates entirely. That is
                not a correction - it is the story.

Two lessons that changed the method

Association boards were 0-for-54. They select for people whose EMPLOYER funds their
volunteering - agency staff and academics. Meetup ORGANIZERS were the opposite: nearly
every one is independent, because running a meetup is their lead generation.

A stale website is not a dead business. A featured marketer was flagged "possibly dormant"
off a 2015 site date - he was in a meeting that afternoon. Liveness-by-copyright-date has
false negatives, and the human in the room outranks the heuristic. Same correction applied
to a self-reported "2-10 employees" band that is really two people.

On ranking, and what was refused

LinkedIn follower counts: blocked 31-of-34 (HTTP 999). Not viable. Proven, not assumed.
Google rank: argued against. The top results for "Austin marketing agency" ARE the
geo-page spam and the mailboxes this list exists to expose - ranking by it would promote
them. Recommended instead: Wayback first-seen age (free, unblockable) and a
practice-what-you-preach score - does the SEO agency have schema? Does the AEO shop have
an llms.txt? Their own site is the one door never closed to us.

Where to pick up

- /vote/ page: needs a real backend, and needs to NOT become the pay-to-play dynamic the
  site exists to oppose. Votes belong in their own column, labelled, never in the ranking.
- Impact Makers Party event page: all data gathered (Aug 13, Creative Collective, 6:30pm).
  The rename from the old name is confirmed on their own site. Their 17-year speaker
  archive is behind a paid login - the most complete record of Austin marketing speakers,
  and nobody can see it. That comes from asking, not scraping.
- Ranking metric for the 91 unfiled firms.
- Social links: 34 LinkedIn harvested; X is linked by only 9 of 43 - the cohort has left it.

Where to pick up

Next-session brief: /fableprompts/next/