function ChangelogPage() {
  const entries = [
    { d: '2026-04-22', t: 'Architecture critique + truthfulness automation', tag: 'Platform', body: 'Internal review landed a 30-day plan: CI checks for doc-to-code drift, a compliance sprint (MFA + legal acceptance capture + retention policy skeleton), pricing config lifted out of code paths, and per-tool trust defaults for every Medium/High-stakes action.' },
    { d: '2026-04-21', t: 'Background agents — Phase 1.0 plan approved', tag: 'Agent Workforce', body: 'Scheduled read-only agents move from design to executable plan. Seven commits, 1.5–2 weeks focused work. Schema + aggregates + message-bus guard landing first; first user-facing template (weekly project digest) in Phase 1.1. Default 2,500 cr/mo cap, enforced, per tenant.' },
    { d: '2026-04-20', t: 'Trust layer v1 shipped', tag: 'Agent Workforce · 4a', body: 'Three filters — PII scrub · two-tier prompt-injection detector · pluggable toxicity. Sanitize-first, rarely-block. Wired into AgentRuntime (inbound + outbound) and MCP (inbound + outbound). Audit split: TrustLayerSummary + TrustLayerEvent.' },
    { d: '2026-04-18', t: 'RFIs external-reviewer spike green-lit', tag: 'RFIs', body: 'Magic-link flow for architects + engineers answering RFIs without a login. Scoped, one-time-use tokens with short TTL; token scrubbed from access logs; posts back to the originating tenant as the canonical record.' },
    { d: '2026-04-17', t: 'Photos Phase 2 — vision auto-tagging', tag: 'Photos', body: 'Thirteen stage commits. Vision runs via VisionClientInterface (Anthropic · OpenAI · NullVisionClient). Async-metered through MeteringRecorder; priced via RateCard::forVision(). Tag sources: ai_suggested · human_confirmed · human_added.' },
    { d: '2026-04-14', t: 'Sub-budgets + itemized invoices', tag: 'Agent Workforce · 3b', body: 'Per-user sub-budgets ENFORCED; per-module observation-only. Invoice CSV — one row per ledger transaction, 15 columns. Current-usage endpoint exposes real-time totals + forecast + per-user/per-module breakdowns.' },
    { d: '2026-04-10', t: 'Budgets + alerts + forecast', tag: 'Agent Workforce · 3a', body: 'TenantBudget aggregate · observe/enforce mode · thresholds at 50/80/100%. Linear forecast. HTTP 402 on enforce. BudgetAlertNotifier emails workspace admins once per threshold per month.' },
    { d: '2026-04-06', t: 'Stripe credit top-ups', tag: 'Agent Workforce · 2b', body: 'CreditPack catalog (Starter 10k / Growth 50k / Scale 250k). BillingProviderInterface::createTopUpCheckoutSession. Idempotent on session id — webhook replays never double-credit.' },
    { d: '2026-04-02', t: 'Credit ledger + rate card + pricer', tag: 'Agent Workforce · 2a', body: 'Append-only ledger with balance_after snapshot. Stateless pricer (20 + 10/1k + 10/1k, ceil-rounded). MeteringRecorder::finish() debits atomically in the same DB transaction.' },
    { d: '2026-03-27', t: 'Daily Logs module', tag: 'Modules', body: 'Second first-party module. Two aggregates. Six tools. Medium-stakes preview before save. Finalisation one-way; inputs immutable; drafts reversible.' },
    { d: '2026-03-19', t: 'Agent Workforce metering', tag: 'Agent Workforce · 1', body: 'AgentInvocation + AgentAction aggregates. Wired into AgentRuntime + MCP. Feature-flag gated. Tiles, top-tools, recent-invocations in React dashboard.' },
    { d: '2026-03-10', t: 'shadcn migration complete', tag: 'Frontend', body: 'Every page on Card / Button / Input / Dialog / Select / Popover + Command primitives. Real forms on RHF + zod. Dark mode live. Toasts via Sonner.' },
  ];
  return (
    <>
      <section className="section-tight pt-16">
        <Container>
          <Eyebrow>Changelog</Eyebrow>
          <h1 className="m-display mt-3 max-w-3xl">What shipped. In order. With receipts.</h1>
          <p className="m-lede mt-5 max-w-2xl">We mark everything shipped in `CLAUDE.md` with ✅, stubbed with 🟡, deferred in `DEFERRED.md` with a trigger. This page is the customer-facing mirror of that ledger.</p>
        </Container>
      </section>

      <section className="pb-20">
        <Container>
          <div className="card p-0 overflow-hidden">
            <ul className="divide-y-hairline">
              {entries.map((e, i) => (
                <li key={i} className="p-6 flex gap-6">
                  <div className="w-28 shrink-0">
                    <div className="text-[12px] font-mono" style={{ color: 'var(--fg2)' }}>{e.d}</div>
                    <div className="mt-1"><Badge>{e.tag}</Badge></div>
                  </div>
                  <div className="flex-1">
                    <div className="text-[15px] font-semibold">{e.t}</div>
                    <p className="text-[13.5px] mt-1.5" style={{ color: 'var(--fg2)' }}>{e.body}</p>
                  </div>
                </li>
              ))}
            </ul>
          </div>
        </Container>
      </section>
      <CTABand />
    </>
  );
}
Object.assign(window, { ChangelogPage });
