Equaliser AI · Changelog
What shipped, when, why.
Daily release notes from the build session diary. The same notes the team writes for itself — if it isn't here, we didn't ship it.
14 June 2026
Diary — 13/14 June 2026 (the cloud run-through + the saga-ender)
- —PF date-wrapper crash (React #31): a BigQuery DATE {value} wrapper rendered as
- —Lead-gen ROAS leak across Analyse (Dig, HPG): all 6 Analyse v4 pages branched
- —CLF_Just Natural raw key in titles + prose: resolved.display on the dashboard
- —Content bugs from the design read-through: optimise drawer schema leak
- —App-wide house-rule sweep (227 files): ~250+ em/en dash + "--" breaches,
- —Standing cloud health-check app/api/cron/health-sweep/route.ts + vercel.json
13 June 2026
Diary — 13 June 2026 (the autonomous page-output run)
- —Killed the empty-state void across Equalise + Deliver (the #1 "looks thin"
- —Scenarios restored from a 500 (the GET used strict auth, 401 with no session). (fc29a89a)
- —Settings restored from dead-on-every-account (resolution-path mismatch) + uplifted to a real config surface. (155ee6b9)
- —Curated-surface polish: humanised the pipe/tier-path jargon, deduped the
- —App-side completions: per-client growth filter (the LIMIT 10 ran before the
- —Finding-text quality at source (safe half of the trust fix): the consultant
28 May 2026
Diary — 2026-05-28
- —ADR 030 — Two-tier date-control model. Tier A composite pages (Channels, Campaigns, Dashboard) stay anchored with range options; Tier B exploratory pages (Keywords, Audiences, Products, Website, Attribution) flex fully. Trends already wired as the reference. Shared DateRangePicker component + per-page preset lists. Never ship a control that doesn't actually filter.
- —TVF pattern for view-backed pages. Rather than rewrite each view's enrichment in TS, build a tvf_* in equaliser_dev that wraps the proven view SQL with date arguments. Validate parity against the live view at matching window before wiring. Lower risk than hand-porting logic.
- —ALL_TIME_FROM = '2015-01-01'. "All time" preset goes back further than any client's first data, so BETWEEN covers everything without hardcoding a 730-day floor.
19 May 2026
Diary — 2026-05-19
- —/dashboard-v2 → /dashboard-v3. URL now reads honest — v8 is the design system, v3 is the page iteration. Old /dashboard-v2 redirects to v3. James's prompt.
- —Confidence stat killed. Was computed as 1 - |vs_target|/100 — meaningless inverse with no operational signal. Replaced with Headroom = £ budget remaining MTD. Real number an operator reads first thing.
- —SCALE scoring rubric locked v1.0.0: Structure (channel breadth + concentration + stale accounts), Creative (active hero creatives + DG layer), Audience (distinct audiences in 30d), Levers (bid strategy diversity + dynamic image opt-in), Effectiveness (ROAS vs target + pacing discipline). 20 points each = 100 total. Heuristic v1; Sonnet v2 swappable per pillar.
- —Nightly cron 07:00 UTC for SCALE audits, after the 06:00 intelligence cron so BQ is fresh. Per-client try/catch prevents one bad client killing the portfolio sweep.
- —ROAS rendered as 0.0 (no × glyph) per James's spec. Column header carries the unit.
- —Numerics left-aligned per James's spec — tabular-nums keeps column alignment even when left-justified.
15 May 2026
Diary, 2026-05-15
- —Em dashes are banned. Equaliser house style per the Diagnostic spec §7.1. Slipped repeatedly in early outputs; saved as a memory entry. Use commas, colons, or sentence rebuilds.
- —The Therefore Framework is the universal narrative scaffold. Observe / We See That / However / Therefore / Recommendation. Used in every Strategy Doc, every Performance Review entry, every Diagnostic executive summary.
- —One master template pattern fits every tool. Strategy Doc plus 3 input pillar boards plus 1 output Matrix board plus 1 phased Activation Plan board plus 1 Dashboard. Documented in consultancy-tooling/EQUALISER_CONSULTANCY_OS.md.
- —Masters live in Equaliser - Strategy & Ops (workspace 4480019), not a separate templates workspace. Standard monday tier blocks workspace creation; board-level IP-lock works because clients are never invited to this workspace, only to spawned instances.
- —Auto-allowlisted monday MCP write tools mid-session with credential safety (mcp__monday__all_monday_api excluded initially, added later for raw-GraphQL escape hatch). Skipped delete_* permanently to keep destructive operations gated.
- —Did NOT pivot to the csm-provisioning swap. That was a brief paste from a different context. Tonight's mission was the new consultancy tooling. Branch claude/monday-mcp-swap was cut speculatively then deleted.
14 May 2026
Diary — 2026-05-14 (into 2026-05-15)
Diary entry exists but no highlights bullets parsed.
10 May 2026
Diary — 10 May 2026 (long overnight session)
- —ADR 027 (claim broker) accepted.
- —Per-beat Claude calls in parallel, not single page-level call.
- —Materiality floor default 5% spend share (per-beat overrideable).
- —Pages merge live claims with placeholders — live wins, placeholder
- —Beat library expanded to 20: added FatigueIndex, IntentLadder,
- —2cff4aa1 — Page narrative pass: depth ladder + 16 beats + composer +
9 May 2026
Diary — 9 May 2026 (overnight)
- —Build infra audits via MCP, not by asking James. With Supabase +
- —Dual-axis charts as a library-level fix. Adding axis: 'right'
- —Pass full names to charts, let Recharts truncate. The
- —Auto-bump version cron over manual versioning. Annual API
- —Six work types, not ten. Drop keyword (tactic), channel (folded
- —Cell weight + build state are separate axes. Weight = full /
8 May 2026
Diary — 8 May 2026 (overnight build)
- —Two-gate model (above). Documented in ADR 023.
- —Self-host Google Ads MCP fork on Fly.io, not hosted (Ryze etc).
- —Account-id mapping deferred: callback persists rows with raw ad
- —Per-platform gate naming (EQ_MCP_META_ENABLED, EQ_MCP_GOOGLE_ENABLED)
- —lib/mcp/encryption.ts — AES-256-GCM helper with EQ_MCP_KEY
- —app/api/auth/meta-mcp/connect/route.ts — OAuth initiate with HMAC-signed state
7 May 2026
Diary — 7 May 2026
- —a1dd75c8 focusedClient path-segment detection (root cause of
- —807da15f DataFreshness hydration safety, 24 pages
- —df4087f7 /api/findings root + 2 more hydration traps
- —0bf1d5ee Round 5 no-client /api/agents leaks
- —8ec94c4b Cluster on Deliver + Campaigns
- —f054cdbf /api/reports + /api/catches allow-list
6 May 2026
Diary — 6 May 2026
- —791a8536 C1 v2 round 2 design package + ADR 022 (Mode toggle = B)
- —c491f2d8 Geist Mono + font CSS variable mismatch fix
- —3b563452 C1 v2 cool near-white token migration + ss06 forced
- —d2432a9c 8 carrier-element primitives (Sparkline, RatioBar,
- —99c72c2c AgentChip C1 v2 initials variant + per-agent colours
- —8e4720b3 Per-page handoff v1.0 + v1.1 addendum (Claude Design's
5 May 2026
Diary — 5 May 2026 (overnight foundation work, James offline)
- —791a8536 C1 v2 round 2 design package saved alongside round 1 +
- —c491f2d8 Geist Mono loaded via next/font/google + font CSS
- —3b563452 C1 v2 token migration in app/globals.css — surface
- —d2432a9c 8 carrier-element primitives in components/charts/
- —99c72c2c AgentChip refactor + agent accent colour map. Default
- —(Same 99c72c2c) SCALE constant wired into 5 hand-typed call
4 May 2026
Diary — 4 May 2026
- —3fa3da2d AgentChip migration across 11 surfaces — Optimise/Budgets,
- —b876ea6f Standardised column-set toggle (Key / Engine / GA4 /
- —Date-picker placement: pattern is set (top-right when the page is
- —cc441d3d Audiences inline bid-modifier — four preset buttons (-20%
- —03a6c40d Trends anomaly chips with Sentinel-authored commentary —
- —8aa9597c Audit 90-day roadmap drill per pillar — each card has
4 May 2026
Diary — 4 May 2026 (autonomous evening run)
Diary entry exists but no highlights bullets parsed.
3 May 2026
Diary — 3 May 2026
- —7dc1d135 Legal/trust pages chrome — /dpa, /privacy, /terms,
- —e349c21e Cron heartbeat — 37 routes wired. Critical bug:
- —a318d887 proxy.ts public-page allowlist — even after the
- —bdfda661 Lighthouse CI rc + workflow draft
- —b5275888 Period-compare on Campaigns + shared helper
- —bc2cf65a Trends migrated to shared helper
2 May 2026
Diary — 2 May 2026
- —Lock the bones, not the page list. The four sections, the closed loop, the verb framing, the agents-as-narrators-not-tab, the data-leads-AI-supports principle — those are permanent. The specific page list inside each section is allowed to breathe based on real use.
- —URL prefix is /accounts, not /clients. James's call: more neutral for in-house teams and clients themselves.
- —Dashboard is state-aware — same nav label, same template, different scope.
- —Workbench word killed, replaced by Optimise → Plan (the action plan with push-to-Monday/Jira/Slack).
- —/funnel becomes Analyse → Website. Absorbs /landing-pages.
- —/audit moves to Equalise → Audit with the SCALE structure.
28 April 2026
Diary — 2026-04-28 (closeout sprint Day 2 — application sprint)
- —0a699967 — /workbench voice fixes (Loading… / Nothing to action yet / dropped sql/supabase/* from user-facing copy)
- —3a73819a — /clients/[client] declutter: cut top 4-card scorecards, duplicate pacing card, key-concern callout, bottom AgentDecisionsPanel + QuickActions, trimmed RelatedViews 16→6, plus voice fixes in lib/settings/groups.ts + lib/readiness/rubric.ts (-145 lines net)
- —d42169f0 — WoWChange caps at ±999% with (verify) cue past ±200%; Loading… ellipsis sweep across 4 files
- —b186c93f — scripts/perf-audit.ts harness (TTFB / FCP / LCP / bytes / requests via Playwright); switched /home /campaigns /channels to direct chart imports; removed 9 dead imports from /clients/[client]
- —894ca6b6 — docs/cluster-d-coherence-audit.md mapping the seven AI surfaces and three independent opportunity data paths (Supabase finding_clusters, BQ growth_opportunities view, /opportunities own logic); shipped a stopgap note on /opportunities
- —b024ecec — docs/customer-success-30day.md (Expert #6: lifecycle playbook + 4 emails + off-ramp)
28 April 2026
Diary — Overnight 2026-04-28 → 2026-04-29
Diary entry exists but no highlights bullets parsed.
28 April 2026
Overnight Plan — Started 2026-04-28 ~23:30 BST
Diary entry exists but no highlights bullets parsed.
27 April 2026
Diary — 2026-04-27 (cloud-only monitoring + local n8n pause)
- —cfc4b616 Cloud-only monitoring: pause local n8n + add daily Slack heartbeat
- —app/api/cron/agent-monitor-daily/route.ts — new cloud cron
- —vercel.json — schedule 30 8 * * *
- —scripts/n8n-pause-all.ts — bulk-deactivate workflows via n8n API
- —Memory + memory-backup updated
- —login item in System Settings → General → Login Items
26 April 2026
Diary — 2026-04-26 / 2026-04-27 (10-hour spine + ligaments run)
Diary entry exists but no highlights bullets parsed.
25 April 2026
2026-04-25 — Continuous build: strategist + action tranche
- —cc4dd3c5 — Wave 1: Synthesis Agent + Morning Briefing + WhyTrail + Strategy Partner wiring
- —700a9e61 — Wave 2: Visual Analyst nightly + Governance sweep (3 agents)
- —a4c1aa4e — Wave 3: One-click Apply + audit + undo + actions log
- —b87f990a — Wave 4: Trending products + interactive saturation slider + seasonal-anomaly filter
- —aeec66ad — Wave 5: Pricing tier infrastructure (£1k/£2k floor)
- —2707f211 — Wave 6: Cost ceilings + sweep verifications
25 April 2026
Platform audit — 2026-04-25
Diary entry exists but no highlights bullets parsed.
24 April 2026
Diary — 2026-04-24 (overnight build, post-nav-lock)
Diary entry exists but no highlights bullets parsed.
23 April 2026
Diary — 2026-04-23 (session D)
- —tests/tier1-chrome.spec.ts — Playwright smoke covering 30 surfaces.
- —lib/telemetry/use-surface-telemetry.ts — hook layered on top of
23 April 2026
Diary — 2026-04-23 (session C)
- —S21 /portal — own PortalLayout with top-nav branding; client-facing surface deliberately distinct from the workbench
- —S33 /agents/network — bespoke full-bleed status bar layout, already token-driven
- —/audit/roadmap/print — dedicated print surface, no chrome by design
- —/onboarding — multi-step wizard, full-bleed landing UX
23 April 2026
Session — 2026-04-23
- —D2 resolved: docs/briefs/* (migration + net-new + nav-and-pages v1.0) are binding; docs/ui-design-brief-2026.md stays as rationale/why
- —D6 resolved: /results killed — route deleted, no external links
- —ADR-012: Storybook scoped to components/kit/** only (not surfaces)
- —ADR-013: Palette migration sequenced as 8 commits with additive-first approach; gate flip (design-lint --strict) deferred until surface migrations have removed the 51 existing killed-hex consumers
- —F1.8 narrowed: killed-hex check reports in every run but only gates under --strict, so the 51 pre-F1 violations across 31 files don't block the gate until those surfaces are migrated
- —afb719b4 F4 Storybook 10.3.5 + 6 kit primitive stories
22 April 2026
2026-04-22b — Follow-up session: security + delivery + surface propagation
- —PII baseline pinned at 42, not migrated-in-one-shot. Writing redactClaudeParams() wrappers across 42 routes would have ballooned the security commit beyond readable review. Baseline can only shrink; new routes can't regress.
- —Slack delivery stays disabled, not half-built. Needs per-org webhook storage which hasn't been designed. Visible-but-disabled > half-working.
- —PDF via print, not @react-pdf or puppeteer. Zero new deps, exact visual parity with the share view, works in every browser. Good enough for pilot; swap to server-side render if a client complains about pagination.
- —Banner falls silent on API failure rather than showing an error. The tab content is the primary payload — a broken banner must never block the page.
22 April 2026
2026-04-22 — Night session: the "feels alive" sprint
Diary entry exists but no highlights bullets parsed.
21 April 2026
2026-04-21 — Diary
- —1f8db314 Registry YAML (67-column spec)
- —1515374b client_account_mapping (36 rows)
- —a4c5bcc0 stg_google_ads_daily (8/9 parity 0.00%)
- —11e917d2 stg_meta_daily (7/7 parity 0.00%)
- —9dd988f1 stg_bing_daily (6/6 parity 0.00%)
- —5c99d259 stg_tiktok_daily (1/1 w/ data gap flagged)
20 April 2026
2026-04-20 — Diary
- —21ea8160 [S4.x] Funnel→Airbyte migration task — references existing docs
- —aa7a0435 [S1.8] Next.js route-segment error boundaries
- —44cbf2d4 [S1.2] Typography scale — 20 non-14 violations swapped
- —1cc27ea4 [S5.2] Playwright — polish primitives coverage
- —5e220ad4 [S3.6] /learning page — closes Settings IA dead link
- —fbc7bcd5 [S3.6] IA dead-link check + redirect /bid-strategy + /creatives
19 April 2026
2026-04-19 — Diary
- —21ea8160 [S4.x] Funnel→Airbyte migration review task — references existing docs
- —aa7a0435 [S1.8] Next.js route-segment error boundaries
- —44cbf2d4 [S1.2] Typography scale — 20 non-14 violations swapped
- —1cc27ea4 [S5.2] Playwright — polish primitives coverage
- —5e220ad4 [S3.6] /learning page — closes Settings IA dead link
- —fbc7bcd5 [S3.6] IA dead-link check + redirect /bid-strategy + /creatives
18 April 2026
2026-04-18 — Diary
- —4ed4b0af — 14 v2 contracts + cron registry update
- —c5db7af4 — growth_radar urgency enum hardening
- —865fa899 — enum hardening across 11 contracts
- —a1e63249 — OpenAI+Gemini JSON-mode force
- —1b32c1b1 — provider quota/429 fallback
- —1ecb2f27 — batch-lane maxTokens 4000→8000
17 April 2026
Diary — 17 April 2026 (Overnight Build Session)
- —4bee2489 — preparatory (Tremor + chart wrappers + competitive doc)
- —fabd82c7 — foundation (brand tokens + 9 shadcn primitives + reports engine + settings sections + mobile viewport)
- —c040f8bb — design-system.md + settings consolidation wired (4 groups)
- —1f12e601 — typography + hero gradient + 180ms transitions default
- —Sessions 15 (auth hardening) → DONE
- —Session 19 (reports engine) → SHIPPED (weekly pack generator + 4-template library)
16 April 2026
Session Diary — 16 April 2026
- —Accent colour fix (CRITICAL — all buttons were invisible)
- —AI presence restored on 22 pages via usePageIntelligence hook
- —Ask EQ with BigQuery tool use (real data answers)
- —Ask EQ animated equaliser bars icon
- —Anti-hallucination guardrail
- —AI significance filter (critic <7 suppressed)
15 April 2026
Session Diary — 15 April 2026
- —Daily diary protocol established — every session writes a diary entry on exit, reads latest on entry. Product thinking captured mid-session, not just at end.
- —Personality locked in: R2-D2 style — expert, opinionated, pushes back, no sycophancy, Death Star 2 framing
- —Plan saved to file — tasks/plan.md captures full product vision so it survives session loss
- —Navigation philosophy: conventional hierarchy (what it is) not purpose-based (analyse/optimise/create)
- —12 pages rebuilt with enterprise depth
- —46 pages PageContainer → PageShell