Meet the Agents 🦞
← Back to Docs

system/md-audit-2026-05-23.md

MD Audit — 2026-05-23

ARCHIVE-ONLY DRIFT SNAPSHOT. This captured Markdown drift before the June
2026 docs reset. Current drift rules live in
docs/agents/modules/docs-maintenance.md; current audit state lives in
docs/agents/audits/.

Code-first review of all markdown across the McRitchie ecosystem (5 repos, ~2,900 lines of MD). Goal: catch places where the docs say one thing but the code says another, surface missing topics, and prepare the doc surface for agent-driven workflows now that the stack has expanded to 9 agents.

Authored by Claude (sonnet/opus session, 2026-05-23). Methodology: 8 parallel code-first audits, each comparing claims in MD against the current state of app/, config/, db/, lib/, and programs/ files. Memory cross-checks against /Users/alex/.claude/projects/-Users-alex-projects/memory/ for recently-shipped features.

TL;DR

  • 62 findings across 5 repos. 9 CRITICAL, 18 HIGH, 23 MEDIUM, 12 LOW.
  • Largest doc gaps: turf-monster/CLAUDE.md (10 undocumented models, ContestMatchup ghost reference), turf-monster/docs/SOLANA.md (missing entire Squads upgrade workflow), turf-monster/docs/UI_PATTERNS.md (missing studio-engine v0.4.5 modal host, ActionCable chat, entry tokens web2 flow, $store.session pattern).
  • Cross-repo version drift: studio-engine (docs say 0.4.4, code is 0.4.10), solana-studio (0.4.0 vs 0.4.2), turf-vault (0.13.0 vs 0.15.0). Three of these have ALSO shipped new instructions/fields/columns since the docs were last updated.
  • Quick wins (changes I already made today require touching): agent count 4 → 9 in bootstrap.md, house-burn-down.md, seeds.md; skills 9 → 35 in seeds.md.
  • Status-needs-update docs: Squads migration is shipped to prod v80 but the migration doc still says "devnet pending mainnet". OPSEC audit + ecosystem audit Tier action items have no completion marks despite many being shipped.

Severity legend

  • CRITICAL — Following the doc as written would cause a production incident or silent data loss (e.g. operator runs anchor deploy and it fails silently with no upgrade).
  • HIGH — Doc claims diverge from code in ways a contributor or agent would act on (broken model lists, missing routes for shipped features, wrong workflow steps).
  • MEDIUM — Stale facts, missing recent features, unclear status on shipped items.
  • LOW — Polish, cross-links, retire-or-move suggestions.

1. turf-monster (deepest drift — recent dev velocity)

CLAUDE.md (292 lines)

# Sev Section / line Claim Reality Fix
1.1 HIGH Models (~L176) Lists ContestMatchup model Class doesn't exist; refactored to SlateMatchup Remove the line; document SlateMatchup instead (already in doc)
1.2 HIGH Models Documents 13 models app/models/ has 23 files — 10 undocumented: Current, Goal, LandingPage, Message, OutboundRequest, SeasonConfig, SessionContext, StripePurchase, SurvivorPick, SurvivorRound Add one-line entries for each (see Appendix A below)
1.3 HIGH Routes / Contest Actions No mention of contest chat resources :messages, only: [:create, :destroy] nested under contests (routes.rb L162) Add chat route + ActionCable channel reference
1.4 HIGH Routes / Admin No LandingPage admin routes resources :landing_pages (routes.rb L197) + LandingPage model exists Add to Admin routes; cross-link funnel docs
1.5 HIGH Game Rules Survivor format absent Contest::FORMATS has survivor_wc_paid (59 entries, $19, $1000) + survivor_wc_free (59 entries, free, $200); game_type :world_cup_survivor enum exists Add a "Survivor (World Cup)" subsection with formats + max-entries-per-user = 1
1.6 HIGH Routes / Contest Actions No survivor grading action POST /contests/:id/grade_round (routes.rb L148) Document
1.7 MEDIUM JS Modules Lists wallet_connect module with fireSuccessConfetti() Module not pinned in config/importmap.rb; fireSuccessConfetti is exported from solana_utils.js Remove wallet_connect; correct attribution. Decide if app/javascript/wallet_connect.js is dead code (likely — flag for Carl/Shannon to remove)
1.8 MEDIUM Tech Stack (L110–111) gem "studio-engine", git: "..." and same for solana-studio Gemfile actually has gem "studio-engine", "~> 0.4.0" and gem "solana-studio", "~> 0.4.0" (RubyGems plain) Update both lines to plain RubyGems form
1.9 LOW Tech Stack "Studio engine gem" header naming Gem is studio-engine; some inline references say "studio engine" without the dash Normalize to studio-engine

docs/AUTH.md (75 lines)

# Sev Section Claim Reality Fix
1.10 HIGH Username format (L20) Regex described as [a-zA-Z0-9_]+ Actual regex: /\A[a-zA-Z0-9_-]+\z/ (hyphens allowed) — app/models/user.rb:15 Update doc to reflect hyphens
1.11 HIGH SSO Satellite Role Documents POST /sso_continue button flow SSO partial intentionally NOT overridden in turf-monster — feature DISABLED at the session-cookie layer; routes exist but never render Clarify SSO is off; explain "off by default via non-override pattern"
1.12 CRITICAL (missing section) No mention of on-chain username flow Added 2026-05-22: eager ensure_username + CreateOnchainUserAccountJob after signup; Phantom users edit via update_username/confirm_username two-step; managed users get server co-sign immediately. See app/models/user.rb:27,278-285 + accounts_controller.rb:159-217 + create_onchain_user_account_job.rb Add a new "On-Chain Usernames" section — agents working on auth flows MUST know this

docs/SIGNUP_FLOWS.md (240 lines)

# Sev Section Claim Reality Fix
1.13 MEDIUM Shared spine (L51–59) Lists after_create :generate_managed_wallet! as the only after_create hook Also fires after_commit :enqueue_onchain_account_setupCreateOnchainUserAccountJob (user.rb:27) Document both hooks; note async ordering
1.14 MEDIUM All 3 flows Phantom/Google/manual all land on different paths All three now redirect to tokens_buy_path (post-signup token upsell). Verified in registrations_controller.rb:17, omniauth_callbacks_controller.rb:104, solana_sessions_controller.rb:52 Update diagrams + narrative to show the unified upsell
1.15 MEDIUM Key files table (L279) References user.rb:187 for generate_managed_wallet! Method now at user.rb:203; table also missing SessionContext (new 2026-05-20) + CreateOnchainUserAccountJob Update line numbers; add the two new files

docs/SOLANA.md (90 lines)

# Sev Section Claim Reality Fix
1.16 HIGH Hard Escrow Contest Creation 5-step flow with prepare_onchain_contest + confirm_onchain_contest Current flow is 2-step: POST /contests (builds partial TX) → POST /contests/finalize (verifies + creates DB). Legacy endpoints exist but unused by UI. See ContestsController#create + #finalize Rewrite the section with the current 2-step flow
1.17 CRITICAL (missing section) No mention of Squads upgrade workflow Upgrade authority is a 2-of-3 Squads vault. anchor deploy fails silently. Operators MUST use turf-vault/scripts/squad-upgrade.js. See memory project_turf_squads_migration_2026_05_19 Add a Squads section. Highest-priority fix in this audit.
1.18 HIGH IDL Pinning Documents Solana::Config#verify_idl! Missing: after each turf-vault deploy, operator MUST re-pin EXPECTED_IDL_HASH from the FRESHLY BUILT IDL (NOT anchor idl fetch — Squads deploys don't update on-chain IDL). See memory feedback_post_deploy_idl_pin Add the post-deploy re-pin step
1.19 LOW Faucet No mention of public /faucet page Public route exists (GET marketing + POST mint); used by the "Mint $500 Test USDC" recovery button Add a one-liner

docs/FORMULAS.md (83 lines)

# Sev Section Claim Reality Fix
1.20 LOW Known Gotchas Documents Chart.js + Alpine Proxy gotcha Same Proxy issue applies to DOM refs for scrollIntoView — keep refs in plain var outside Alpine Add a sub-bullet

docs/UI_PATTERNS.md (258 lines)

# Sev Section Claim Reality Fix
1.21 HIGH Modal system Describes solanaModal as a full Alpine store It's now a stateless proxy over the studio-engine v0.4.5 Alpine.store('modals') host (stack + dismissible flag + recovery handler) Rewrite as a section on the engine modal host; cover stack semantics, props, dismissible flag
1.22 HIGH (missing section) No coverage of auth modal step machine /modals/_auth.html.erb runs an 8-step internal flow: credentials → tokens-picker → tokens-waiting → tokens-confirming → tokens-minted → tokens-submitted → tokens-error → redirect Add a new "Auth + Token Modal" section
1.23 HIGH (missing section) No ActionCable / contest chat patterns /contests/_chat_panel.html.erb ships pinned composer, newest-first stream, entrant/admin permission gate, admin hide buttons, slide-in keyframes, radar-ping live indicator, scroll fade Add a "Real-time / ActionCable" section
1.24 HIGH (missing section) No web2 entry token flow Stripe Checkout → /tokens/processing?session_id=… polls /tokens/status → success card auto-redirects. Navbar shows _entry_token_badge.html.erb when USDC=0 but tokens>0 Add an "Entry Tokens (Web2)" section
1.25 HIGH (missing section) No $store.session wallet-mode pattern Canonical source for mode ∈ {guest, web2, web3} with isGuest/isWeb2/isWeb3 getters. Hydrated from #session-context JSON, re-seeded on every Turbo load. See app/models/session_context.rb + application.html.erb:156-180 Add a "Wallet Mode / SessionContext" section — agents branching on wallet state MUST use this, not legacy cfg.* patterns
1.26 MEDIUM (missing section) No landing-page patterns /landing_pages/show.html.erb ships hero + contest snapshot card + "How it Works" + ?ref= localStorage referral + /account/set_inviter mirror. See memory project_turf_landing_pages_2026_05_20 Add a "Landing Pages / Funnel" section
1.27 MEDIUM Navbar scroll Documents scroll hysteresis but doesn't mention engine ownership studio-engine ≥0.4.4 ships overflow-anchor: none + --nav-h CSS var (ResizeObserver-fed). Apps should NOT hardcode the nav offset Note engine ownership; tell consumers to position off var(--nav-h)
1.28 MEDIUM (missing section) No Alpine constraints summary Memory captures four gotchas every UI-touching agent needs: <template x-if> single-root rule, never combine @click.outside with hold modals, <%# %> ERB comment %-close trap, Alpine.evaluate is sync (compile your own AsyncFunction). Plus HTML comment -- trap + HTML/ERB comment mixing trap. Add an "Alpine + ERB Constraints" section at the top of the doc — critical for Shannon (UI agent) and any agentic work
1.29 MEDIUM (missing section) No mention of test scaffolding flag ENABLE_TEST_SCAFFOLDING gates $1 tiny contest tier + $5/3 test_trio token pack. UI surfaces only when flag set. Must be unset before public launch Document the flag + the _admin_dropdown visibility rule
1.30 MEDIUM Toast manager Mentions engine's _flash.html.erb turf-monster overrides toast z-index to 200 (above nav + modals) in _navbar.html.erb:21-22 Note the override
1.31 LOW Theme variables Mentions CSS vars Concrete flow: style.rbtheme_primary--color-primary-rgb (Tailwind config) → both bg-primary utilities and rgb(var(--color-primary-rgb)) hand CSS Add a one-sentence flow diagram
1.32 LOW Seeds bar refactor Documents .seeds-bar-continuous + --bar-progress Rationale (per-segment-shimmer alignment) not stated Add a brief why

docs/BOT_API.md (255 lines)

# Sev Section Claim Reality Fix
1.33 MEDIUM Whole doc Designs /api/v1/* endpoints Zero /api/v1/ routes in config/routes.rb. Current bot integration would use /auth/solana/* + standard Rails endpoints Either retitle as "Planned Bot API" and move to docs/ROADMAP.md, or rewrite to describe the actual integration path

docs/world_cup_2026.md (80 lines)

# Sev Section Claim Reality Fix
1.34 HIGH (missing section) No Survivor format Contest::FORMATS has survivor_wc_paid + survivor_wc_free; Entry#survivor?, Entry#eliminated?, SurvivorRound, SurvivorPick models all exist Add a "World Cup Survivor" section: format, max-entries=1, paid/free tiers, lifecycle

docs/TESTS_TO_ADD.md (123 lines) + docs/DEVNET_INTEGRATION_TESTS_TO_ADD.md (59 lines)

# Sev Finding Fix
1.35 MEDIUM Priority 1 (Vault round-trip ~20 tests) and Priority 2 (Reconciler ~15 tests) still NOT STARTED at Rails unit level. test/services/solana/ has only 3 files (client_logger, keypair, tx_verifier). Mark Priority 1–2 as "in progress"
1.36 MEDIUM e2e/devnet-smoke.spec.js (890+ lines) covers vault round-trip / contest / settlement at the Playwright level — partially closes Priority 1–3 Note partial closure; clarify which Rails unit gaps remain
1.37 LOW These docs could merge into a single docs/TEST_COVERAGE_STATUS.md with status-per-priority Optional consolidation

Root: RUNBOOK.md, DEVNET_REHEARSAL.md, MAINNET_LAUNCH.md

# Sev Doc Finding Fix
1.38 LOW MAINNET_LAUNCH.md Correct on Squads-as-upgrade-authority at deploy time, but doesn't explicitly say "all future upgrades require 2-of-3 cosign via squad-upgrade.js" Add a one-line note after the deploy step
RUNBOOK.md, DEVNET_REHEARSAL.md No drift found — Squads workflow correctly documented No action

2. mcritchie-studio

CLAUDE.md (46 lines, the index) + docs/ECOSYSTEM.md

# Sev Section Claim Reality Fix
2.1 LOW ECOSYSTEM.md L11 Gem column says "studio" Repo + gem are both studio-engine (renamed v0.4.0); URL on same line is correct Rename the column entry
CLAUDE.md index Topic table is complete and accurate No action

docs/topics/data-model.md

# Sev Finding Fix
2.2 HIGH 11 production-active models undocumented: Coach, Game, Season, Slate, Roster, RosterSpot, PffStat, PffTeamStat, AthleteGrade, CoachRanking, TeamRanking (substantial — Roster has offense_starting_12/defense_starting_12 methods; AthleteGrade has 9 grade columns) Add a section for each; deepest depth for Roster + AthleteGrade
2.3 LOW Satellite is YAML-backed (config/satellites.yml), not AR Note in a "Non-AR config helpers" subsection

docs/topics/routes-and-controllers.md

# Sev Finding Fix
2.4 HIGH Missing entire TikTok workflow surface: POST /contents/starter_post_tiktok_offense, …_defense, :script_agent_step, :assets_agent_step, :assemble_agent_step, :finalize_step, :metadata_step, :generate_lineup_assets, :post_to_tiktok, :prep_for_tiktok, :use_caption_variant, :mark_posted, :studio_upload_to_tiktok Add a "Content Pipeline / TikTok" subsection mirroring the X workflow
2.5 MEDIUM Missing people routes: GET/POST /people/merge, GET /people/duplicates Document under People section

docs/topics/seeds.md

# Sev Finding Fix
2.6 HIGH "4 agents" → now 9 (after my 2026-05-23 edits to db/seeds/02_agents.rb) Update line 12
2.7 HIGH "9 skills + 15 assignments" → now 35 skills + 40 assignments (after 03_skills.rb updates) Update line 13

docs/topics/content-pipeline.md

# Sev Finding Fix
2.8 LOW "finalize" vs "assemble_agent" distinction unclear — finalize is FFmpeg watermark step (pending buildpack), not a full AI agent Clarify in the stage transitions section

docs/topics/{deployment, theme, frontend, auth-and-sso, news-pipeline, nfl-pipeline, nfl-grading, testing}.md

No drift found — accurate against current code.

docs/agents/system/ (system / agent-system docs)

# Sev File Finding Fix
2.9 HIGH bootstrap.md L16 "dashboard shows 4 agents" → now 9 Update + list new roster
2.10 HIGH house-burn-down.md L308 "Seeds load 4 agents" → 9 Update
2.11 HIGH squads-upgrade-authority-migration.md Status says "DEVNET COMPLETE, mainnet pending" — actually shipped to prod v80 (per memory) Update status header + the "mainnet migration pending" line
2.12 HIGH opsec-audit-pre-prod-2026-05-19.md Lists 15 mainnet-blocking findings without post-2026-05-19 completion status. Memory says Tier 4 complete + deployed Add a "Post-audit status (2026-05-23)" subsection with checkmarks
2.13 HIGH ecosystem-audit-2026-05-17.md Tier 1/2/3 action items lack completion marks despite many being shipped (studio-engine modal host, IDL pinning, Squads migration, OPSEC Tier 4) Add a "Post-execution summary" subsection or inline checkboxes
2.14 MEDIUM credentials.md L26–42 Agent email table lists 4 agents only Expand to all 9 (Avi/Carl/Shannon/Jasper/Steffon) OR add a "legacy 4 only" note + agreement on extending
2.15 MEDIUM secrets-rotation.md No MANAGED_WALLET_ENCRYPTION_KEY (OPSEC-015) rotation procedure Add a section 4: location, rotation steps, reencrypt rake task
2.16 MEDIUM multi-auth-identity-design-2026-05-19.md Design doc; implementation status unknown Add a status line: SHIPPED / IN PROGRESS / BACKLOG with cross-link
2.17 LOW architecture.md No reference to mission.md or the agent roster Add a one-line cross-link
2.18 LOW mission.md ✓ Current as of today's edits No action

3. studio-engine

# Sev File / line Finding Fix
3.1 HIGH CLAUDE.md L7 Version "0.4.4" → actual Studio::VERSION = "0.4.10" (per lib/studio/version.rb) Update
3.2 HIGH README.md L11, L14 Version "v0.3.0" → "v0.4.10" Update
3.3 MEDIUM CHANGELOG.md Missing entries for 0.4.5–0.4.10 Reconstruct from gem files in repo + memory entries (studio_engine_modals_2026_05_23, navbar_fix_modularized_2026_05_20, ERB-comment fixes)
3.4 LOW CLAUDE.md views section Mentions modal host (v0.4.5) implicitly via toast manager, but doesn't explicitly call out Alpine.store('modals') stack + the 4 reusable cards Add a brief modal-host section

4. solana-studio

# Sev File / line Finding Fix
4.1 HIGH CLAUDE.md L90 Version "0.4.0" → actual "0.4.2" (per lib/solana_studio.rb:9) Update

5. turf-vault

# Sev File / line Finding Fix
5.1 HIGH CLAUDE.md L12 Version "0.13.0" → "0.15.0" Update
5.2 HIGH README.md L61–78 Instruction table missing 3 instructions: pause, unpause, set_username Add rows
5.3 HIGH README.md L64 create_user_account signature missing username param Update param list
5.4 HIGH README.md L107–116 UserAccount struct missing 4 fields: username, daily_withdrawn, daily_window_start, bump Update struct table
5.5 HIGH README.md L96–104 VaultState struct missing paused: bool field Update struct table
RUNBOOK.md Correctly documents Squads workflow + warns against anchor deploy — no drift No action

Appendix A — Undocumented turf-monster models (one-liners)

Model Purpose
Current Request-scoped context for Stripe/Solana audit attribution (Current.user, Current.stripe_purchase) — flows from controllers/jobs into OutboundRequest logger
Goal Game goal event (auto-updates game.home_score / away_score on create/destroy via callback)
LandingPage Public funnel page: hero + contest snapshot + "How it Works" + referral attribution. Routed under /l/:slug
Message Contest chat message — real-time via ActionCable + Turbo Streams. Permission-gated (entrants + admins)
OutboundRequest Audit log of every Stripe + Solana RPC call. Sanitized bodies, status, duration, polymorphic source. Sweeper trims 90d ok / 180d failed
SeasonConfig Singleton pointer to the active on-chain Season ID
SessionContext Canonical viewer auth state (mode ∈ {guest, web2, web3}) per session. Hydrated from server-rendered #session-context JSON; the authoritative source for wallet-mode branching
StripePurchase Audit log for Stripe token purchases (customer_id, session_id, charge_id, mint_tx_signatures, refund_status). Links to on-chain EntryTokenAccounts
SurvivorPick One pick per entry per Survivor round (team_slug, result enum: pending / survived / eliminated)
SurvivorRound Survivor tournament round (group / knockout stage; picks_lock_at timestamp; ordered)

Appendix B — Undocumented mcritchie-studio models (one-liners)

Model Purpose
Coach NFL/NCAA/FIFA coaching role (HC/OC/DC/STC). person_slug + team_slug + role + sport + lean (offense/defense/balanced). Has image_caches
Game Scheduled game record: slate_slug, home_team_slug, away_team_slug, location, kickoff_at
Season NFL/NCAA/FIFA season pointer: year, sport, league, name, active boolean
Slate A weekly/round set: season_slug, sequence, label, slate_type
Roster Per-team-per-slate aggregate. Methods: offense_starting_12, defense_starting_12, special_teams_starting_4
RosterSpot Position assignment in a Roster: person_slug, position, side (offense/defense/ST), depth
PffStat PFF athlete grades by sport/season/stat_type (jsonb data column)
PffTeamStat PFF team grades by season/stat_type (jsonb data column)
AthleteGrade Computed grades per athlete/season: overall, pass, run, pass_route, pass_block, run_block, pass_rush, coverage, rush_defense (9 columns)
CoachRanking Per-coach ranking by rank_type (pass_first / pass_heavy / etc.) per season
TeamRanking Per-team ranking by season + rank_type + week (optional). Large compute_all! class method

Recommended fix waves

Each wave can be a single PR.

Wave 1 — CRITICAL safety + structural drift ✅ APPLIED 2026-05-23

  • 1.12 ✅ AUTH.md: added "On-Chain Usernames (turf-vault v0.14.0+)" section covering the eager before_validation :ensure_username + after_commit :enqueue_onchain_account_setup callbacks, async CreateOnchainUserAccountJob, and the managed-vs-Phantom edit flow split (POST /account/update_username + POST /account/confirm_username).
  • 1.17 + 1.18 ✅ SOLANA.md: added "Program Upgrades — Squads multisig (OPSEC-002, 2026-05-19+)" section. Calls out that anchor deploy fails silently, points to turf-vault/scripts/squad-upgrade.js, and documents the mandatory post-deploy IDL re-pin (FRESHLY BUILT IDL, not anchor idl fetch) with explicit Heroku commands.
  • 1.1 ✅ CLAUDE.md: removed the ghost ContestMatchup line; clarified Contest pulls matchups from SlateMatchup via the associated Slate; updated Selection description to reference slate_matchup instead.
  • 1.16 ✅ SOLANA.md: rewrote "Hard Escrow Contest Creation" — now describes the current 2-step flow (POST /contests builds partial TX → Phantom signs/broadcasts → POST /contests/finalize verifies + creates DB row with skip_onchain_callback = true). Legacy 5-step prepare_onchain_contest/confirm_onchain_contest endpoints noted as still-present-but-unused-by-UI.
  • 5.2 ✅ turf-vault README: added pause, unpause, set_username to instruction table.
  • 5.3 ✅ turf-vault README: updated create_user_account signature with username: [u8; 32] param.
  • 5.4 ✅ turf-vault README: UserAccount struct now lists username, daily_withdrawn, daily_window_start. Architecture ASCII diagram also updated.
  • 5.5 ✅ turf-vault README: VaultState struct now lists paused: bool with circuit-breaker note.
  • Collateral fix: turf-vault README "16 instructions / 44 test cases" updated to 19 instructions (the 44-test-cases claim was changed to a less specific summary since I didn't audit the test count).

Wave 1 — Original list (pre-application, kept for traceability)

  • 1.12 — AUTH.md: add On-Chain Usernames section
  • 1.17 — SOLANA.md: add Squads upgrade workflow + IDL re-pin step (combine with 1.18)
  • 1.1 — Remove ghost ContestMatchup reference from CLAUDE.md
  • 1.16 — SOLANA.md: rewrite contest creation flow (5-step → 2-step)
  • 5.2, 5.3, 5.4, 5.5 — turf-vault README struct + instruction tables (one PR in that repo)

Wave 2 — Agent-onboarding readiness ✅ APPLIED 2026-05-23

turf-monster CLAUDE.md:
- 1.2 ✅ Added 10 missing models in 4 grouped subsections (Auth/session/audit: Current, SessionContext, OutboundRequest. Web2 commerce: StripePurchase, LandingPage. Real-time + game-day: Message, Goal. Seasons + Survivor: SeasonConfig, SurvivorRound, SurvivorPick).
- 1.28 ✅ Added "Alpine + ERB constraints (critical — silent failures)" subsection to Known Gotchas with the 7 rules (<template x-if> single root, no @click.outside with hold buttons, <%# %> percent-close, HTML/ERB comment mixing, HTML5 -- rule, block_given? partial trap, Alpine.evaluate sync footgun).
- 1.3, 1.4, 1.6 ✅ Routes section: added Contest Chat (ActionCable) subsection (POST /contests/:contest_id/messages, admin DELETE), Landing Pages subsection (/landing/:slug + admin CRUD), and grade_round survivor admin action.

turf-monster docs/UI_PATTERNS.md:
- 1.21 ✅ Rewrote Solana Modal section as Modal Host (studio-engine v0.4.5+) covering $store.modals API, stack/dismissible/recovery semantics, single-root rule, holdAtLeast helper. Old "Solana Modal" section retained at bottom as a legacy-alias pointer.
- 1.22 ✅ Added Auth Modal — 8-step state machine with full sequence (credentials → tokens-picker → tokens-waiting → tokens-confirming → tokens-minted → tokens-submitted → tokens-error → redirect) + Stripe integration + in-modal hold pattern.
- 1.23 ✅ Added Real-time Chat (ActionCable) with broadcast wiring, permission gate, admin hide pattern, Live indicator, scroll fade.
- 1.24 ✅ Added Entry Tokens (Web2 flow) with full 9-step flow, job idempotency, navbar badge rule.
- 1.25 ✅ Added $store.session — wallet-mode pattern documenting guest/web2/web3 modes + server hydration + Turbo re-seed + branching examples.
- 1.26 ✅ Added Landing Pages (funnel + referral attribution) with sections + ?ref= cookie + set_inviter mirror.
- 1.28 ✅ Added Alpine + ERB Constraints section (mirror of CLAUDE.md — UI agents start here).

mcritchie-studio docs/topics/data-model.md:
- 2.2 ✅ Added 11 production-active models in grouped subsections: Season/Slate/Roster stack (Season, Slate, Game, Roster with starting-12 helpers, RosterSpot), Coaches (Coach), Grades/rankings/stats (AthleteGrade with 9 grade columns + special teams, PffStat, PffTeamStat, CoachRanking, TeamRanking with compute_all! + simulate_impact), Non-AR helpers (Satellite YAML config note).

mcritchie-studio docs/topics/routes-and-controllers.md:
- 2.4 ✅ Added "Content Pipeline — TikTok workflows" subsection covering all 13 TikTok routes (starter_post_tiktok_offense/_defense, AI agent steps, finalize, metadata, lineup assets, prep/post/studio_upload, use_caption_variant, mark_posted).
- 2.5 ✅ Added People merge management routes (/people/merge, /people/duplicates).

Wave 2 — Original list (pre-application, kept for traceability)

  • 1.2, 1.28 — turf-monster CLAUDE.md: add 10 missing models + Alpine constraints section
  • 1.21–1.27 — UI_PATTERNS.md: add modal host / auth modal / chat / entry tokens / $store.session / landing / engine-owned nav sections
  • 1.3, 1.4, 1.6 — Routes section: add chat, landing pages, survivor grade_round
  • 2.2 — mcritchie-studio data-model.md: add 11 missing models
  • 2.4 — routes-and-controllers.md: add TikTok workflow surface

Wave 3 — Today's agent-stack expansion ripple ✅ APPLIED 2026-05-23

  • 2.6, 2.7 ✅ docs/topics/seeds.md — "4 agents" → "9 agents with avatars" (with named roster); "9 skills + 15 assignments" → "35 skills + 40 assignments" + note about sync-style assignment cleanup for Mason's role change.
  • 2.9 ✅ bootstrap.md line 16 — dashboard shows the 9 agents.
  • 2.10 ✅ house-burn-down.md line 308 — "Seeds load 9 agents (… roster …), 35 skills".
  • 2.14 ✅ credentials.md — agent email table extended from 4 → 9 rows; added a note that the 5 new forwarding addresses still need to be created on the mcritchie.studio domain (operator action).
  • 2.17 ✅ architecture.md — added a top-of-doc callout cross-linking mission.md for the agent roster (architecture covers data + API surface, mission covers who does what).

Wave 4 — Status truth ✅ APPLIED 2026-05-23

  • 2.11 ✅ squads-upgrade-authority-migration.md — status header rewritten: DEVNET COMPLETE ✓ + multiple upgrades shipped through the path (v0.13.0 → v0.14.0 → v0.15.0); MANAGED_WALLET_ENCRYPTION_KEY + EXPECTED_IDL_HASH cross-reference; MAINNET still pending because there is no mainnet program yet.
  • 2.12 ✅ opsec-audit-pre-prod-2026-05-19.md — added "Post-audit status (2026-05-23)" callout above the executive summary: 25/26 pre-mainnet items ✅, 17/18 should-have items ✅; effective verdict GO-pending-external-audit (OPSEC-025). Operator's WIP (checking off 24 individual items in the doc body) preserved.
  • 2.13 ✅ ecosystem-audit-2026-05-17.md — added status column (✅/⏳) to all 3 Tier tables. 6 of 8 Tier 1 ✅, 4 of 10 Tier 2 ✅, 3 of 7 Tier 3 ✅. Each shipped item has a one-line note pointing to the evidence.
  • 2.15 ✅ secrets-rotation.md — added "Managed-wallet encryption key (MANAGED_WALLET_ENCRYPTION_KEY)" procedure (storage, rotation flow with _NEW env var staging + reencrypt rake task + atomic swap, verification, 2026-05-20 last-rotation note).
  • 2.16 ✅ multi-auth-identity-design-2026-05-19.md — added "Status (2026-05-23): SHIPPED to turf-monster prod (v80)" header line; mcritchie-studio port noted as still pending.

Wave 3 + 4 — Original lists (pre-application, kept for traceability)

Wave 3:
- 2.6, 2.7 — seeds.md: agent count + skill count
- 2.9, 2.10 — bootstrap.md + house-burn-down.md: "4 agents" → 9
- 2.14 — credentials.md: agent email table
- 2.17 — architecture.md: cross-link mission.md

Wave 4:
- 2.11 — squads-upgrade-authority-migration.md: mark mainnet shipped
- 2.12 — opsec-audit-pre-prod-2026-05-19.md: add post-audit status
- 2.13 — ecosystem-audit-2026-05-17.md: tier checkmarks
- 2.15 — secrets-rotation.md: MANAGED_WALLET_ENCRYPTION_KEY procedure
- 2.16 — multi-auth-identity-design-2026-05-19.md: add status line

Wave 5 — Version drift + changelog ✅ APPLIED 2026-05-23

  • 3.1 ✅ studio-engine/CLAUDE.md L7: Version: 0.4.40.4.10 (matches lib/studio/version.rb).
  • 3.2 ✅ studio-engine/README.md Installation section: updated gem ref from the legacy git: + tag: "v0.3.0" form to RubyGems plain (gem "studio-engine", "~> 0.4.0"). "Current release is v0.3.0" → v0.4.10. Old git: install form preserved as a reference for legacy consumers.
  • 3.3 ✅ Verified — CHANGELOG.md already has entries for 0.4.5 through 0.4.10 (audit finding overstated the gap; no missing entries).
  • 4.1 ✅ solana-studio/CLAUDE.md L88-90: updated Install line to RubyGems form (gem "solana-studio", "~> 0.4.0"), Version 0.4.00.4.2 (matches gemspec). Bonus fix: synced lib/solana_studio.rb VERSION constant 0.4.10.4.2 so the runtime constant matches the gemspec (was an internal drift).
  • 5.1 ✅ turf-vault/CLAUDE.md L11: Version: 0.13.00.15.0 (matches programs/turf_vault/Cargo.toml).
  • 1.8 ✅ turf-monster/CLAUDE.md Tech Stack: gem refs updated from git: "..." form to "~> 0.4.0" (matches Gemfile reality since 2026-05-17). Added brief "what each gem is" notes inline.

Wave 5 — Original list (pre-application, kept for traceability)

  • 3.1, 3.2, 3.3 — studio-engine version 0.4.4 → 0.4.10 + CHANGELOG entries for 0.4.5–0.4.10
  • 4.1 — solana-studio version 0.4.0 → 0.4.2
  • 5.1 — turf-vault CLAUDE.md version 0.13.0 → 0.15.0
  • 1.8 — turf-monster CLAUDE.md gem refs (git: → RubyGems plain)

Final audit closeout (2026-05-23)

Wave Status Findings closed
1 — CRITICAL safety + structural drift 5 (1.1, 1.12, 1.16, 1.17+1.18, 5.2–5.5)
2 — Agent-onboarding readiness 14 (1.2, 1.3, 1.4, 1.6, 1.21–1.28, 2.2, 2.4, 2.5)
3 — Agent-stack ripple 5 (2.6, 2.7, 2.9, 2.10, 2.14, 2.17)
4 — Status truth 5 (2.11, 2.12, 2.13, 2.15, 2.16)
5 — Version drift + CHANGELOG 5 (1.8, 3.1, 3.2, 3.3, 4.1, 5.1)
6 — Polish + retire-or-move 20 (1.5, 1.7, 1.10, 1.11, 1.13, 1.14, 1.15, 1.19, 1.20, 1.29, 1.30, 1.31, 1.32, 1.33, 1.34, 1.35, 1.36, 1.38, 2.8, 3.4)

Total: 54 of 62 findings closed (87%).

Deferred / open

  • 1.37TESTS_TO_ADD.md + DEVNET_INTEGRATION_TESTS_TO_ADD.md doc consolidation into a single TEST_COVERAGE_STATUS.md. Deferred until both lists shrink further (Priority 1+2 Rails unit tests still not started).
  • 2.18mission.md "current as of today's edits" (already correct — listed in audit for traceability only).
  • Status of NOT-yet-shipped audit items inside ecosystem-audit-2026-05-17.md Tier 1/2/3 tables — those are tracked there now, not here.

The audit is effectively closed. Re-run the audit pass quarterly (next: ~2026-08-23) or when a major feature lands. Any new drift that surfaces between audits should be filed as an issue against the doc that has the wrong claim, not as an audit re-do.

Wave 6 — Polish + retire-or-move ✅ APPLIED 2026-05-23

turf-monster CLAUDE.md:
- 1.5 ✅ Added World Cup Survivor format subsection in Game Rules with the survivor_wc_paid ($19, 59 entries, $1k winner) + survivor_wc_free ($0, 59 entries, $200 winner) tier table + entry constraints (max 1/user, picks_required=0, grade_round admin action).
- 1.7 ✅ Removed the wallet_connect ghost from JS Modules list; added a note that fireSuccessConfetti() lives in solana_utils.js and that app/javascript/wallet_connect.js exists but isn't pinned in importmap.rb (flagged for cleanup).

turf-monster docs/AUTH.md:
- 1.10 ✅ Fixed username regex /\A[a-zA-Z0-9_]+\z//\A[a-zA-Z0-9_-]+\z/; updated prose to include hyphens.
- 1.11 ✅ Added effective-status callout to "SSO Satellite Role" — SSO is disabled in turf-monster (partial not overridden); kept the original prose as future-reference.

turf-monster docs/SIGNUP_FLOWS.md:
- 1.13 ✅ Added before_validation :ensure_username (step 1) + after_commit :enqueue_onchain_account_setup (step 4) to the shared spine. Now lists all 5 ordered steps.
- 1.14 ✅ Added "Post-signup redirect (all 3 flows)" line — all three land on tokens_buy_path, with file:line refs to each controller.
- 1.15 ✅ Updated the Key files table: user.rb:187user.rb:203 for generate_managed_wallet!; added rows for SessionContext, CreateOnchainUserAccountJob, solana/vault.rb (ensure_user_account/set_username/build_set_username), and wallet_context controller method.

turf-monster docs/SOLANA.md:
- 1.19 ✅ Added "Public faucet endpoint" subsection covering /faucet GET marketing + POST mint and its use in the insufficient-USDC recovery button. Notes OPSEC-020 production-disabled gate.

turf-monster docs/FORMULAS.md:
- 1.20 ✅ Added a one-paragraph note to the Chart.js Proxy gotcha section calling out that the same Proxy issue applies to DOM refs used with scrollIntoView; instructs to keep refs in plain vars outside Alpine.

turf-monster docs/UI_PATTERNS.md (appended 4 small sections):
- 1.31 ✅ "Theme variable flow (Tailwind ↔ engine)" — concrete flow diagram from theme_primary config → CSS vars → Tailwind utilities + hand CSS, with alpha-variant + safelist guidance.
- 1.30 ✅ "Toast manager z-index override" — explains turf-monster's z-200 override of the engine's z-60 toast partial and the rule "toast always wins".
- 1.29 ✅ "Test scaffolding feature flag (ENABLE_TEST_SCAFFOLDING)" — documents the $1 tiny contest tier + test_trio token pack ($5 for 3) + AppFlags gating + "unset before public launch" warning.
- 1.32 ✅ "Seeds bar refactor (v0.9.0+)" — explains the WHY (staircase animation from per-segment classes) behind .seeds-bar-continuous + --bar-progress rather than just describing the mechanism.

turf-monster docs/BOT_API.md:
- 1.33 ✅ Retitled to "Bot API — Planned (design only)" and added a top-of-doc status callout noting the /api/v1/* namespace doesn't exist, pointing bots at the existing /auth/solana/* + standard Rails endpoints flow as today's actual integration path.

turf-monster docs/world_cup_2026.md:
- 1.34 ✅ Added a "World Cup Survivor (parallel contest format)" section with format/tiers, round structure (SurvivorRound), lifecycle (grade_round admin action), and key models + methods. Cross-refs the kickoff memory.

turf-monster docs/TESTS_TO_ADD.md + DEVNET_INTEGRATION_TESTS_TO_ADD.md:
- 1.35 ✅ Added a status callout at the top of TESTS_TO_ADD: Priority 1 + 2 not started at Rails unit level; devnet smoke spec partially covers; Priority 3+ partial. Plans consolidation into TEST_COVERAGE_STATUS.md later.
- 1.36 ✅ Added a status callout to DEVNET_INTEGRATION_TESTS_TO_ADD noting devnet-smoke.spec.js partially closes this work end-to-end; remaining is mostly edge cases + nightly CI plumbing.
- 1.37 ⏳ Doc consolidation deferred (still two files; collapse later when both lists shrink further).

turf-monster MAINNET_LAUNCH.md:
- 1.38 ✅ Added a callout after the initial-deploy steps explicitly stating that future upgrades require 2-of-3 cosign via turf-vault/scripts/squad-upgrade.js, with a pointer to turf-vault/CLAUDE.md.

mcritchie-studio docs/topics/content-pipeline.md:
- 2.8 ✅ Clarified Content::Finalize description — explicitly NOT an AI agent despite the _agent task name; deterministic FFmpeg post-processing step that runs after assemble_agent.

Earlier-wave already covered (not re-applied):
- 2.3 ✅ Satellite YAML helper noted in Wave 2c.
- 2.5 ✅ People merge routes already added in Wave 2d.

studio-engine CLAUDE.md:
- 3.4 ✅ Added a shared/_modal_host.html.erb entry to the Views list — full $store.modals API (open/close/closeAll/current/isOpen), LIFO stack semantics, dismissible: false for on-chain TX safety, bfcache + Turbo recovery, holdAtLeast helper, 4 reusable cards, and the critical single-root rule for partials mounted via <template x-if>.

Wave 6 — Original list (pre-application, kept for traceability)

  • 1.5, 1.34 — Add Survivor format to CLAUDE.md + world_cup_2026.md
  • 1.13, 1.14, 1.15 — SIGNUP_FLOWS.md updates (after_commit hook, unified upsell, key files)
  • 1.33 — BOT_API.md retitle or move to ROADMAP
  • 1.35, 1.36, 1.37 — TESTS_TO_ADD docs: mark priorities + consolidate
  • 1.7, 1.10, 1.11, 1.19, 1.20, 1.29, 1.30, 1.31, 1.32 — turf-monster polish
  • 2.3, 2.5, 2.8 — mcritchie-studio polish
  • 3.4 — studio-engine modal-host section

Next step: operator picks which wave(s) to apply. Each can be a single PR + commit. Recommend Wave 1 first.