chore: daily data inventory refresh (2026-08-06)
Deploy Log
Every deploy across all products, automatically logged.
August 2026
chore: daily data inventory refresh (2026-08-05)
chore: daily data inventory refresh (2026-08-04)
Weekly engine report [skip ci]
chore: daily data inventory refresh (2026-08-03)
chore: daily data inventory refresh (2026-08-02)
chore: daily data inventory refresh (2026-08-01)
July 2026
chore: daily data inventory refresh (2026-07-31)
chore: daily data inventory refresh (2026-07-30)
chore: daily data inventory refresh (2026-07-29)
chore: daily data inventory refresh (2026-07-28)
Grades the bot against the external 8-point "what an AI marketing agent needs to actually work" standard, reconciles it with the cockpit-not-doer doctrine, and sequences remaining work behind the real binding constraint.
Weekly engine report [skip ci]
The landing-page report was hardcoded to 25 rows. That is a dashboard view, and it was being used as a measurement: GDA's AI sessions (1,016/28d) run ~10x its GSC blog clicks (104/28d across 273 pages), so any per-page traffic ranking
chore: daily data inventory refresh (2026-07-27)
The data layer under GDA's buy-or-wait pages: upc_catalog / upc_resolution_log / street_prices, plus deal_bodies and deal_retailer_capture so no deal body is ever discarded again.
chore: daily data inventory refresh (2026-07-26)
Durable experiment registry: atomic IDs, source normalization, page-set readouts
Collector: daily Discover/News surface tracking (Round-2 R2)
S3 AI pipeline: fact-block generation, draft-pipeline fixes, weekly citation panel
chore: daily data inventory refresh (2026-07-25)
GSC truth layer: direct-API collector, mirror retired from all verdicts (10x plan S0)
chore: daily data inventory refresh (2026-07-24)
chore: daily data inventory refresh (2026-07-23)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore: daily data inventory refresh (2026-07-22)
Persist exp_gda_014 + exp_gda_015 to committed experiments ledger
Category coverage matrix + on-page spec sequencing
chore: daily data inventory refresh (2026-07-21)
Farm-out brief: deal-archive audit (Q1)
On-page optimization spec + striking-distance worklist
SEO verdict: whitespace + ceiling + link-acquisition playbook (exp_gda_014)
* Dashboard: readable SVG charts (axis + values + threshold line), inconclusive note, register recent GDA push - barChart(): SVG with y-axis (max/0), per-bar values (few points), and a labeled
* Dashboard: readable SVG charts (axis + values + threshold line), inconclusive note, register recent GDA push - barChart(): SVG with y-axis (max/0), per-bar values (few points), and a labeled
* Dashboard: readable SVG charts (axis + values + threshold line), inconclusive note, register recent GDA push - barChart(): SVG with y-axis (max/0), per-bar values (few points), and a labeled
Weekly engine report [skip ci]
chore: daily data inventory refresh (2026-07-20)
* Dashboard: readable SVG charts (axis + values + threshold line), inconclusive note, register recent GDA push - barChart(): SVG with y-axis (max/0), per-bar values (few points), and a labeled
* Dashboard: readable SVG charts (axis + values + threshold line), inconclusive note, register recent GDA push - barChart(): SVG with y-axis (max/0), per-bar values (few points), and a labeled
* Dashboard: readable SVG charts (axis + values + threshold line), inconclusive note, register recent GDA push - barChart(): SVG with y-axis (max/0), per-bar values (few points), and a labeled
Dashboard: readable SVG charts (axis + values + threshold line), inconclusive note, register recent GDA push (#54)
1c41460- barChart(): SVG with y-axis (max/0), per-bar values (few points), and a labeled dashed threshold line — before/after uses the baseline avg as the line to beat, gate uses the target center. Fixes 'green stuff unintelligible without numbers'
chore: daily data inventory refresh (2026-07-19)
chore: daily data inventory refresh (2026-07-18)
chore: daily data inventory refresh (2026-07-17)
* Growth Engine dashboard: clickable tests, plain-English descriptions, days-live, labeled data - learnings/experiment-meta.json: human 'what we changed' + A/B vs before/after per test
Growth Engine dashboard: clickable tests, plain-English descriptions, days-live, labeled data (#52)
310b8dd- learnings/experiment-meta.json: human 'what we changed' + A/B vs before/after per test - Live tests now clickable → drill-in with metric label, promote/kill thresholds, and the data series (gate weeks for the engine metric; lazy-fetch GA4/ai-referrals otherwise)
product-state: GDA + PLY north_star (one metric + growth/retention companions), growth-model equations, guardrails, demand_validated/pmf_validated, PLY local = city+1hr; Demand-Validated stage documented.
* Onboard to ops; status.md with full backlog + constraint Constraint (★): the XmR validator's verdict math is unsound. Verified in
- product-state: GDA + PLY North Star (one metric + growth/retention companions), growth-model equations, guardrails, demand_validated/pmf_validated flags, PLY local = city + 1hr drive-time; Demand-Validated stage documented
chore: daily data inventory refresh (2026-07-16)
Any Claude session POSTs an experiment contract (product, metric, direction, hypothesis, treatment) with X-Internal-Auth; the bot appends to learnings/experiments.jsonl (+ a trial stub if start_now). The front door of
Codifies the loop: North Star -> growth model -> backlog -> pre-register -> readout -> attribution -> back to backlog. Cockpit frame (sense/decide/alert/ draft, never publish), distributed-register/central-ledger, low-traffic readout
pnpm@latest in the Docker image now hard-errors on unapproved dependency build scripts (ERR_PNPM_IGNORED_BUILDS). Pin the version via packageManager + corepack and add msw to ignoredBuiltDependencies.
chore: daily data inventory refresh (2026-07-15)
The skill file schema is already a flashcard schema, so card generation is a deterministic transform — no LLM in the loop. Six card types come out of the sections (concept, diagnostic, cue, edge, error, benchmark); the packager
Constraint (★): the XmR validator's verdict math is unsound. Verified in code: min_sample_impressions is pre-registered on every experiment but read by zero lines; CTR is fed to XmR as a daily mean-of-ratios. The RFD flagging
Orchestration spec above the existing page-type generators (persona-hub, decision-guide, comparison): the weekly GSC-mining selection loop, the price-guide generator gap, the sitemap measurement contract, the
- product-state: S3->S4 per W29 gate (3/3 weeks above baseline); crank metric path fixed to gda.crank.* (validator convention); crank target 12-25 pages/wk; exit plan set - exp_gda_012 registered: llm-surfaces hedge contract on gda.ai_referrals.sessions
chore: daily data inventory refresh (2026-07-14)
Weekly engine report [skip ci]
chore: daily data inventory refresh (2026-07-13)
chore: daily data inventory refresh (2026-07-12)
chore: daily data inventory refresh (2026-07-11)
chore: daily data inventory refresh (2026-07-10)
chore: daily data inventory refresh (2026-07-09)
chore: daily data inventory refresh (2026-07-08)
chore: daily data inventory refresh (2026-07-07)
Reliability fixes from review: trials keying, validator dedupe, crank tolerance, concurrency (#43)
ad88175- allocator: trials latestById used wrong key (trial_id vs id) - probesActive was blind - validator: validateAll now dedupes latest-per-id and treats non-pending verdicts as terminal (stops ~5 junk re-verdict records/day; trials.jsonl had 68 copies of trial_0001)
Weekly engine report [skip ci]
engine-weekly: dispatch Deploy after committing report (reports are baked into the image) (#42)
cfb7cb9Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
chore: daily data inventory refresh (2026-07-06)
chore: daily data inventory refresh (2026-07-05)
chore: daily data inventory refresh (2026-07-04)
chore: daily data inventory refresh (2026-07-03)
chore: daily data inventory refresh (2026-07-02)
chore: daily data inventory refresh (2026-07-01)
June 2026
chore: daily data inventory refresh (2026-06-30)
chore: daily data inventory refresh (2026-06-29)
chore: daily data inventory refresh (2026-06-28)
chore: daily data inventory refresh (2026-06-27)
chore: daily data inventory refresh (2026-06-26)
chore: daily data inventory refresh (2026-06-25)
chore: daily data inventory refresh (2026-06-24)
chore: daily data inventory refresh (2026-06-23)
chore: daily data inventory refresh (2026-06-22)
chore: daily data inventory refresh (2026-06-21)
chore: daily data inventory refresh (2026-06-20)
chore: daily data inventory refresh (2026-06-19)
chore: daily data inventory refresh (2026-06-18)
chore: daily data inventory refresh (2026-06-17)
chore: daily data inventory refresh (2026-06-16)
chore: daily data inventory refresh (2026-06-15)
chore: daily data inventory refresh (2026-06-14)
chore: daily data inventory refresh (2026-06-13)
chore: daily data inventory refresh (2026-06-12)
chore: daily data inventory refresh (2026-06-11)
chore: daily data inventory refresh (2026-06-10)
chore: daily data inventory refresh (2026-06-09)
chore: daily data inventory refresh (2026-06-08)
chore: daily data inventory refresh (2026-06-07)
chore: daily data inventory refresh (2026-06-06)
chore: daily data inventory refresh (2026-06-05)
chore: daily data inventory refresh (2026-06-04)
chore: daily data inventory refresh (2026-06-03)
chore: daily data inventory refresh (2026-06-02)
chore: daily data inventory refresh (2026-06-01)
May 2026
chore: daily data inventory refresh (2026-05-31)
chore: daily data inventory refresh (2026-05-30)
chore: daily data inventory refresh (2026-05-29)
chore: daily data inventory refresh (2026-05-28)
chore: daily data inventory refresh (2026-05-27)
chore: daily data inventory refresh (2026-05-26)
chore: daily data inventory refresh (2026-05-25)
Fix stale source-health labels on experiments dashboard
Phase 0 SEO treatments deployed via additive isolation 2026-05-22 11:55 EDT (Heroku v972 = 795c778 'SEO Phase 0 treatments (additive)'). Verified prod 2026-05-24: titles say 2026, AggregateOffer schema present, /compare returns
Lessons: GDA deploy target Heroku-vs-Coolify check
RFD: GSC verdict math unsafe for sparse CTR
chore: daily data inventory refresh (2026-05-24)
chore: daily data inventory refresh (2026-05-23)
Add 90d/180d time ranges + full period selector on experiments page
Re-anchor exp_gda_001/002 to real prod treatment start (2026-05-22)
Wire ai_referrals validator source to live GA4
Verified prod: GSC read endpoints shipped as additive-only isolation (Heroku v967 = 4ba61f1), deployed ~7h ago. /snapshots returns 2,952 rows, /aggregates works, marketing-bot probe WIRED, all 6 GSC trials
GDA asked whether to deploy the GSC endpoint now (overriding the CTR-readout gate) or hold to 2026-06-03. Verified current prod first: it has ROLLED BACK to master — GSC endpoint 404, draft endpoint 404, no JSON-LD, titles still
chore: daily data inventory refresh (2026-05-22)
Harden OAuth return-redirect against open-redirect token leak
Rules for links in Reddit posts/comments, grounded in the Reddit/AI-search corpus: Reddit links are nofollow+ugc (zero SEO juice) — value is branded search + AI citation + clickstream. One deep UTM'd link at the post bottom,
Make Run-validator button self-service (one-time GitHub authorize)
chore: daily data inventory refresh (2026-05-21)
Charles's "step back" insight: instead of scattered best-X pages, build buyer-journey HUBS ("The New AR-15 Owner", "PCC Owner") that chain the sub-decisions (which rifle/optic/can/light/trigger...) into one page,
Add Run-validator button + daily XmR cron; refresh GSC endpoint spec
The auto-researcher project (~/Documents/auto-researcher/) already built ~70% of this agent — the full research engine, with 4 shipping-ready posts. Its review flagged the build directive + 8 empirically-grounded
Charles challenged whether the earlier "authority first, near-zero new pages for 60 days, prune the dead" guidance matched the SEO corpus. It didn't — two parts had drifted to generic SEO caution:
The two scaling engines for the 1M-users plan, both niche-agnostic (parameterized by a property adapter so they're not gun-specific). Grounded in the full marketing-corpus review (Cody SEO, Reddit/AI-search
Now that GA4 is live (111 AI sessions/30d baseline, 110 ChatGPT), close the measurement loop:
Charles's draft review surfaced GDA-side data defects (a $1,799 Razor HD scope bundled under the $400 UH-1 sight; M855A1 priced by box not per round; SR-15 lower-receiver kits blended into the rifle price). Those live
Every recommendation section now opens with a live price card sourced from GDA's deal tracker (current / 30d-low / deal-count / GDA link). This is GDA's differentiator vs truegunvalue/gun.deals — live tracked
Farm-out spec for the deep research-synthesis Reddit format, templated from Charles's r/MP5 "Hunt for the Perfect Short MP5K Can" post (9.9k views, 42 upvotes, 49 comments). This is the lever the citation baseline
chore: daily data inventory refresh (2026-05-20)
WebSearch proxy for AI citation sets, 2026-05-19. Headline: gundealalerts.com is NOT cited for any sampled price query. truegunvalue.com dominates the "current price/value/trends 2026" intent we targeted; gun.deals (competitor)
Turns "is this singing for AI bots?" from faith into a number. - api/analytics/ai-referrals.js: queries GA4 for sessions sourced from
The repost-corrected script rejected superseded drafts via direct curl to GDA, which bypassed the ledger-logging path — so 8 blended drafts still showed 'draft' on /drafts.html though they were rejected on GDA. Append
Charles caught 6 fanout fact blocks that blended incompatible SKUs into one price range: complete rifles with lowers/parts (KAC SR-15 "$1,060-$3,000"), new with refurbished (Vortex AMG), optics-ready with
The original fanout threshold (>50 chars, >=10 impressions, 0 clicks) only caught 1 query. Real GDA GSC data analysis showed the fanout space is much larger at a looser threshold.
The agent now logs every successful draft POST to learnings/drafts.jsonl, and the new /drafts.html page lists pending drafts with one-click Approve/Reject backed by GDA's existing /api/internal/drafts/<id>/{approve,reject}
Two GitHub Actions workflows that close the autonomous loop: 1. gsc-snapshot-cron.yml — daily 06:00 UTC
Merges parallel work from ~/Documents/marketing_bot/ working tree into the session, then adds the marketing-bot READ side that lights up automatically when GDA ships the GSC snapshot endpoint.
Chart.js with responsive+maintainAspectRatio:false needs a positioned, fixed-height parent to size against. Without it, canvas inherits the parent's auto height, Chart.js resizes the canvas, parent grows, canvas
The original signals (sessions, users, signups) had no data in GDA's snapshots collection. Confirmed via direct snapshot query: signups: 0 points
End-to-end cross-property write loop is now real: marketing-bot's gda/gsc-refresh agent can POST drafts to GDA's new /api/internal/drafts endpoint. Smoke-tested against production — draft drf_o9tr6xaw
12 consolidations merge true duplicates across files while preserving every distinct insight. Added new Theme 6 (Feed & Food Sources) from the new feed-and-food-sources skill. 32K words, ~1,900 lines.
- New L4 skill: mule-deer-multi-year-unit-mastery (Expert tier capstone with 5-year compounding curve framework) - New L2 skill: mule-deer-trail-camera-strategy (water seeps, mineral
The app was recreated; old webhook UUID returned 404 silently breaking auto-deploy on push. Confirmed new UUID via Coolify API: Application marketing-bot-img -> i19tphkv2ylq7pulqg6vfvgz
- New L1 skill: mule-deer-terrain-features-and-tactics — 58KB reference defining water/saddle/cover/rim-rock/benches/burns/basin/drainages with deer use patterns, mechanism, and hunting tactics for each.
pnpm 11 turned ignored build scripts into a fatal install error, which broke the Docker build (corepack pulled latest). Pin to the version that's been working and explicitly approve the three
Includes all third-wave additions (Denning, Holden, Dioni) and the deepening edits to existing files. ~30K words, organized for truck-the-night-before navigation with a re-ranked Make-or-Break
The Link>Card pattern produced an inline <a> wrapping a block <div>, which is invalid HTML — left-click navigation broke silently on some browsers (right-click "open in new tab" still worked because the
- New domains/mule-deer/ (39 skills, 185 edges, 7 categories: behavior, e-scouting, terrain, glassing, stalking, public-land, shot-craft) - Hunting domain renamed to "Coyote & Predator Hunting" (67 skills)
- 39 mule deer skill files across 7 categories (behavior, e-scouting, terrain, glassing, stalking, public-land, shot-craft) sourced from ~60 transcripts: Hartsky, Brady Miller, Robby Denning, Marlon Holden,
chore: daily data inventory refresh (2026-05-19)
chore: daily data inventory refresh (2026-05-18)
chore: daily data inventory refresh (2026-05-17)
chore: daily data inventory refresh (2026-05-16)
chore: daily data inventory refresh (2026-05-15)
chore: daily data inventory refresh (2026-05-14)
chore: daily data inventory refresh (2026-05-13)
chore: daily data inventory refresh (2026-05-12)
chore: daily data inventory refresh (2026-05-11)
chore: daily data inventory refresh (2026-05-10)
chore: daily data inventory refresh (2026-05-09)
chore: daily data inventory refresh (2026-05-08)
chore: daily data inventory refresh (2026-05-07)
chore: daily data inventory refresh (2026-05-06)
chore: daily data inventory refresh (2026-05-05)
chore: daily data inventory refresh (2026-05-04)
chore: daily data inventory refresh (2026-05-03)
chore: daily data inventory refresh (2026-05-02)
chore: daily data inventory refresh (2026-05-01)
Resolve inventory merge conflicts
April 2026
chore: daily data inventory refresh (2026-04-29)
chore: daily data inventory refresh (2026-04-28)
Goal extractor: - Pull <command-args> body when the first message is a slash command (was capturing the framework caveat instead of the user's prompt).
The key fallback in claudeops_supabase.py was the pre-rotation key (iat: 1774551995), which silently 401'd against self-hosted Supabase since the key rotation on 2026-03-30. Hook sync had been broken for
Lives at /conductor on the existing dashboard. One row per session: project, status, goal (first user prompt verbatim, with on-demand Haiku 4.5 summarize), file/commit/push counts, resolved PR URLs (via gh CLI), and a click-through
chore: daily data inventory refresh (2026-04-27)
chore: daily data inventory refresh (2026-04-26)
chore: daily data inventory refresh (2026-04-25)
chore: daily data inventory refresh (2026-04-24)
Walk-forward backtest across 26 leagues, 4 treatments (xg=0, 0.05, 0.1, 0.2). xgWeight=0.2 beats control: OVERS +3.99pp, UNDERS +3.31pp, SIDES +1.18pp CLV. Effect is monotonic with no plateau. AH flat (~9.7% CLV across all treatments).
Copy-pasteable prompt for dropping into sessions that need to check the data inventory before answering data questions. Self-contained (works without the SessionStart hook), lists all 24 sources, names the
Signal count grew from 11→17 (2^17=131K combos), causing 5,958 combos per chunk × 6K bets × betKeys/profits arrays to exceed 8GB heap.
Post-mortem on the variance-lookback-short-symmetric rejection (registered + tested + rejected 2026-04-17). Key points recorded for future-me:
Pre-registered 2026-04-17 to test whether lowering VARIANCE_LOOKBACK (10 → 5/6/7/8) would preserve CLV while enabling coverage for early- season bets that can't hit 10-match history. Tested via
On-demand endpoint (no schedule) to compute league-specific venue calibration for v3 Sofascore xG. Runs on main server where sofascore_xg and derived v3 cache both live. Trigger manually with CRON_SECRET when needed.
Adds --xg-weight passthrough in job-registry and compute-worker so factorial jobs can run against xG solver variant caches.
HFA signal was null for 9 leagues because DEFAULT_LEAGUES in hfa-monitor.ts was a 19-league whitelist. getCurrentHFA() gated on this before even checking files — so bets in ucl, mls, austria-bl, arg-b-nacional,
7 additional seasons of Marcel 2-1-1-5 projections from Understat data. Combined with TM availability backfill (in progress), this gives the marcel-injury-impact signal 10 seasons of coverage instead of 2.
Inventory audit found that fotmob-match-xg already ships 269 files covering 50 leagues, including the 4 leagues I'd previously marked as "at data ceiling" for FF(xG)/Context/DynXG:
- Add marcelInjuryImpactEnabled config to EvalConfig with threshold (15%) and dampening (50%) - Compute Marcel xG missing fraction in data-loader from TM availability + Marcel projections - Lambda adjustment: reduce attack lambda when >15% of projected xG is missing
- Generate Marcel 2-1-1-5 projections for 2024/2025/2026 seasons - 2,412 players across Big 5 leagues (2,045 with age data) - Validation: +17.1% RMSE improvement over naive (npxG/90)
Round 8 left the Bundesliga Squad/GK coverage at 9/11 because Hamburg and Augsburg weren't in reep/team-bridge at all — resolveTeamTmId couldn't hop from canonical name to TM ID for either, even though the
- Extract core compute logic into lib/sofascore-shot-xg.ts (shared by script + cron) - Add /api/cron/compute-shot-xg endpoint (09:00 UTC daily, after accumulate-xg) - Cron entry added to Hetzner server
After rounds 6 + 7 unlocked Big-5 squad-history data, coverage jumped to 93/182 but still missed 9 Championship bets. Not a reader bug — the new resolveTeamTmId handles all the fuzzy name variants. It was estimateRound
The first pass of the scrape produced full roster data but empty availability matrices for 10 La Liga + 17 Ligue 1 + 3 Bundesliga teams (matchdayCount: 0, availability: []). Manual re-test of Monaco showed
The inventory discipline check surfaced that `data/availability/raw/` is an un-registered orphan directory — the Championship signal coverage has been running off 24 hand-placed files in a dir that `generate-data-inventory.ts`
Second retro today. The morning one was about overclaiming without measurement. This afternoon's is about reaching for parallelism before verifying unit cost matches the spec.
Swaps MODEL_PATH from xg_pre_shot_v1_compact.json to xg_universal_v3_compact.json. v3 model trained on FotMob+Understat combined data (211K shots), properly calibrated with base_logit=-2.195 (goal rate 0.098). v1 was miscalibrated on Sofascore coords
One-variable change: flip leagueExclude from ["segunda", "la-liga", "ligue-2"] to [] in DEFAULT_EVAL_CONFIG at lib/backtest/bet-evaluator.ts:294.
2026-04-15 session: observed rate of ~240 snapshots/hour across 8 parallel workers on cloud-lab. Spec said 5 seconds per solve; actual was 60-200s. Two causes identified from the actual log:
So that design specs and decision records committed alongside inventory changes (like docs/specs/inventory-gate-hook.md from the previous commit) are auto-staged by data:ship and don't need a separate follow-up commit.
Problem: The existing SessionStart hook printed only a source count summary. Sessions still grepped the codebase to find data sources instead of reading the inventory, because the inventory itself wasn't in their initial context —
First full audit after the sofascore swap turned up SP-Mismatch misses for Club Brugge v Anderlecht, Gent v Mechelen (belgian-pro). Investigation: the sofascore DB key `belgianPro` contains SWEDISH ALLSVENSKAN data, not
Round-3 audit left 5 signals below ceiling because their source data (understat-shots) was Big-5 only and frozen at 2024. The inventory review turned up sofascore_shots in Supabase with 368k shots across
Honest post-incident retro of yesterday's session. The proximate bugs (stale fire script, no state seed, no rsync-on-failure) are real and fixed in 1616a76c. The deeper issue is process: I treated job.status
2026-04-15 retro: cloud-lab was silently running Apr-7 code (88 commits behind origin/main) for 8 days because the fire script's `git pull --ff-only` was aborting on every single job ("Please commit your changes or stash them
Walks 24 sources (was 19). Plus two generator improvements: 1. Walker now handles single-file paths (for data/signal-registry.json which
- Add enrichment?: number to Multipliers (default 1.0, pass-through) - Include enrichmentMultiplier in SizingResult breakdown - Log enrichmentMultiplier on every PaperBet sizing record
chore: daily data inventory refresh (2026-04-15)
Inventory robustness: validation chokepoint + data:ship + pre-commit hook + marcel/player-finishing sources
0deb97aThe other agent shipped broken inventory state last session because the system relied on discipline ("run the tests before committing") instead of enforcement. This commit adds three layers that make broken state structurally
Real proof the getOrCompute() pipeline works end-to-end on production data: - Inputs: sofascore_shots (156,794 rows in Supabase) + xg_pre_shot_v1_compact.json
compute-sofascore-shot-xg: drop per-shot from cached output (23MB → ~300KB)
Three changes: 1. CLAUDE.md gains a "How to use the inventory — the workflow" subsection with
Results: - 6-config sweep: all positive sizing lift (+0.45% to +0.63%) - Walk-forward: 3/3 OOS folds positive (+0.52% to +12.58%)
Red-team battery (2026-04-14) found two guardian bypasses in the submit endpoint:
chore: daily data inventory refresh (2026-04-14)
Several data/ subdirs are gitignored (footystats-matches, betexplorer-odds, squad-history/raw, etc.) because they're huge local caches. The previous generator walked them naively, so the committed INVENTORY.json's coverage
Adds a version-controlled priority task list at data/cloud-lab/roadmap.json that any cloud-lab submission must match. Sessions that try to queue unapproved work get a 403 with a link back to docs/specs/cloud-lab-guardian-spec.md.
Two UX issues surfaced: 1. The expanded comparison table (click any signal row) sorted rows by
Round-2 showed AggV2 flat at 96/181 despite adding the `*2025.json` files. Reason: for calendar-year leagues (arg-primera, brazil-a, mls), the bets we're scoring are from April 2026 — the 2025 files only contain matches
Second pass on signal coverage after the first unblock commit: 1. findTeamInMap now tries canonical→full (miToCanonicalName) too.
Makes the web container's queue.ts handle ONLY cloud-lab jobs and the compute-worker container handle ONLY local jobs. Both read the same data/compute-jobs/jobs.json but filter on job.target so they never pick
After landing the data-unblock commit and re-running the audit: 1. GK change: 0/33 on Championship even though Squad strength works 33/33
The coverage audit on the first fresh 181-bet shadow-backfill found five signals at 0% coverage — Squad, GK change, AggV2, SP-xGA regression, and SP-mismatch — plus ShotXG at 34% and HFA at 78%. Root cause was not the
Replaces the hardcoded N≥1000, +0.5pp practical-significance floor, p<0.10 bootstrap threshold, 3pp matchday-interleave tolerance, and 1% suspicious-N dedup heuristic with data-driven equivalents:
Phase 0 (cloud-lab VM): fix LAST=0 idle-check bug that was killing the VM 5 min after every boot. /root/auto-shutdown.sh and /root/watchdog.sh now handle missing /tmp/last-job-activity explicitly (initialize + exit 0)
The 2026-04-13 /gauntlet freeze had a second half: even after fixing the backfill script to read from Supabase, every redeploy reverted the in-image shadow-backfill.json to whatever snapshot was committed to git (Apr 7, 72
20 signals with positive marginal mined from registry + factorial. Key finds from 2,048-combo factorial: - contextXg: +0.39% main effect (biggest single boost)
Experiments (all validated walk-forward on 2025): - Age-conditional weighting: wins keyPasses/90 only (+0.05%) - Asymmetric 30+: no consistent win
Two gaps surfaced on /track: FS All showed "—" for 17 of 181 settled bets (164/181 coverage). Root causes were both naming-related.
Root cause: scripts/backfill-shadow-signals.ts read data/paper-trade/ledger.json directly from the filesystem. In the container this file is frozen at whatever shipped in the Docker image, while production writes go to Supabase. Result:
Append new section to docs/specs/edge-hunt.md describing how to promote the 11 Bayesian priors hypotheses into the pod-shop factorial search.
Post-mortem on 8 settlement failures from the same root cause. Hardcoded subset vs verified map, symptom-patching loop, architectural fix.
Path C (xG calibration, 136K shots): - H9 player finishing: Brier -0.00040 direction correct but BELOW -0.002 threshold - H10 opponent context: +0.00002 (hurts slightly) REJECTED
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Expanded footystats-to-cache-team-map.json from 588 → 1257 entries covering all 40+ leagues (UCL, Belgian Pro, Brazil, Argentina, Uruguay, Serie C/D, MLS, Liga MX, J-League, Austrian BL, Eerste Divisie, etc.)
Root cause of recurring settlement failures: settler had a hardcoded 100-entry team map while a verified 588-team JSON map existed unused. Every unmapped team silently failed to settle.
Infrastructure: - Phase 0: runWithoutSignal mapping for marcel-early-prior, squad-value-early-season, promoted-team-lambda-adjust, squad-value-regularization signals
FootyStats returns "Angers SCO" but settler expected "Angers". Also added Saint-Étienne, Nîmes, Châteauroux accent mappings.
Details the UUID-vs-integer label filter bug that made 15+ consecutive deploys show red while production ran fine, and the no-op rollback that hid it.
Fitted LOWESS age curves from 789 player-seasons. No-age wins 5/5 stats. Survivorship bias hides decline — 34+ players are +16.5% above average because only elite survive. Key next steps: backfill to 11 seasons,
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-publishes deploy info to dev.imprevista.com/blog on successful deploy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cross-product deploy changelog deployed at dev.imprevista.com