// Home / Introduction page
function Home() {
  const shell = useShell();
  const tocItems = [
    { id: 'what', label: 'What is MemGC?' },
    { id: 'who', label: 'Who is it for?' },
    { id: 'how', label: 'How it works' },
    { id: 'decay', label: 'Calibrated decay', level: 3 },
    { id: 'hybrid', label: 'Recall', level: 3 },
    { id: 'audit-link', label: 'Audit & lineage', level: 3 },
    { id: 'injection', label: 'Injection safety', level: 3 },
    { id: 'storage', label: 'Storage backends', level: 3 },
    { id: 'different', label: 'What makes it different?' },
    { id: 'start', label: 'Where to start' },
    { id: 'principles', label: 'Design principles' },
  ];

  return (
    <div className="app">
      <Topbar section="docs" theme={shell.theme} setTheme={shell.setTheme} onSearch={() => shell.setSearchOpen(true)} onMenuToggle={() => shell.setMobileMenuOpen(true)} />
      <div className="main">
        <Sidebar activeId="introduction" mobileOpen={shell.mobileMenuOpen} onMobileClose={() => shell.setMobileMenuOpen(false)} />
        <article className="content">
          <div className="crumbs">
            <a href="index.html">Docs</a>
            <span className="sep">/</span>
            <span>Introduction</span>
          </div>

          <div className="eyebrow">Documentation · v0.0.2</div>
          <h1 className="h1">Self-hostable AI memory for <em>production agents.</em></h1>
          <p className="lede">
            Your agents remember things. Over time they remember too much, get confused, and cost a fortune.
            MemGC throws away the old stuff intelligently — so your agents stay sharp, fast, and cheap.
            Runs on your own server.
          </p>

          <div style={{display:'flex', gap:10, marginBottom:36, flexWrap:'wrap'}}>
            <a href="quickstart.html" className="btn-primary">
              <Icon name="rocket" size={13} stroke={2}/> Start in 2 minutes
            </a>
            <a href="api.html" className="btn-ghost" style={{border:'1px solid var(--line)'}}>
              <Icon name="code" size={13} stroke={2} style={{marginRight:6}}/> Read the API reference
            </a>
            <span className="tag-pill">
              <span style={{width:6,height:6,borderRadius:'50%',background:'oklch(0.62 0.12 150)'}}/>
              v0.0.2 live on PyPI
            </span>
          </div>

          <h2 id="what" className="h2">What is MemGC?</h2>
          <p>
            MemGC is a memory layer for AI agents that takes <em>forgetting</em> seriously. Most memory
            systems focus on what to remember — MemGC focuses on what to <strong>throw away</strong>,
            mathematically and predictably, so your agent's context never bloats into hallucination
            territory or runaway token bills.
          </p>
          <p>
            It's a Rust core with Python bindings, ships as a 4.8 MB wheel, and runs entirely on your
            own server. Your data never touches our infrastructure — there isn't any.
          </p>

          <h3 style={{marginTop:40, marginBottom:16, fontSize:15, fontWeight:600, color:'var(--ink-2)'}}>How a turn flows through the four core operations</h3>
          <figure style={{margin:'0 0 36px', padding:'32px 24px', background:'var(--bg-elev)', border:'1px solid var(--line)', borderRadius:12}}>
            <div style={{display:'grid', gridTemplateColumns:'1fr auto 1fr auto 1fr auto 1fr', gap:8, alignItems:'center', fontFamily:'var(--font-mono)', fontSize:11.5}}>
              <div style={{padding:'18px 12px', border:'1px solid var(--line)', borderRadius:8, background:'var(--bg)', textAlign:'center'}}>
                <div style={{fontSize:18, marginBottom:6}}>📥</div>
                <strong>extract()</strong>
                <div style={{marginTop:6, color:'var(--ink-3)', fontSize:10.5}}>turn → atomic Memory</div>
              </div>
              <div style={{color:'var(--ink-4)', fontSize:16, textAlign:'center'}}>→</div>
              <div style={{padding:'18px 12px', border:'1px solid var(--line)', borderRadius:8, background:'var(--bg)', textAlign:'center'}}>
                <div style={{fontSize:18, marginBottom:6}}>🔍</div>
                <strong>retrieve()</strong>
                <div style={{marginTop:6, color:'var(--ink-3)', fontSize:10.5}}>vector + BM25 hybrid</div>
              </div>
              <div style={{color:'var(--ink-4)', fontSize:16, textAlign:'center'}}>→</div>
              <div style={{padding:'18px 12px', border:'1px solid var(--accent)', borderRadius:8, background:'var(--accent-soft)', color:'var(--accent-ink)', textAlign:'center'}}>
                <div style={{fontSize:18, marginBottom:6}}>📜</div>
                <strong>consolidate()</strong>
                <div style={{marginTop:6, color:'var(--ink-3)', fontSize:10.5}}>8k log → 140-tok YAML</div>
              </div>
              <div style={{color:'var(--ink-4)', fontSize:16, textAlign:'center'}}>→</div>
              <div style={{padding:'18px 12px', border:'1px solid var(--line)', borderRadius:8, background:'var(--bg)', textAlign:'center'}}>
                <div style={{fontSize:18, marginBottom:6}}>🗑️</div>
                <strong>sweep()</strong>
                <div style={{marginTop:6, color:'var(--ink-3)', fontSize:10.5}}>score-based GC</div>
              </div>
            </div>
            <figcaption style={{textAlign:'center', marginTop:20, fontSize:12.5, color:'var(--ink-3)', fontStyle:'italic', fontFamily:'var(--font-serif)'}}>
              Extract distills, retrieve finds, consolidate compresses, sweep forgets — together they keep memory bounded.
            </figcaption>
          </figure>

          <h2 id="who" className="h2">Who is it for?</h2>
          <p>
            Engineering teams running AI agents in production. Anyone whose agent's context window
            keeps growing, whose token bill keeps climbing, or whose compliance review asks the
            question "show me what your agent knew on Tuesday at 3pm." If you've ever been told
            <em style={{color:'var(--ink-3)', fontStyle:'italic'}}> "just summarize the history"</em> and
            felt that's not a real answer — MemGC is for you.
          </p>

          <h2 id="how" className="h2">How it works</h2>
          <p>
            Five capabilities make MemGC different from a generic memory store:
          </p>

          <h3 id="decay" className="h3">Calibrated decay</h3>
          <p>
            Every memory has a six-component score that determines its survival on the next sweep:
            <strong> frequency</strong> (recall count), <strong>relevance</strong> (importance),{' '}
            <strong>diversity</strong> (distinct query contexts), <strong>recency</strong>{' '}
            (half-life decay), <strong>consolidation</strong> (spaced-repetition days), and{' '}
            <strong>conceptual</strong> (tag coverage). Weights sum to 1.0 by default; rows whose
            weighted score falls below the survival threshold get deleted on the next sweep. Math
            decides what stays — not an LLM judge.
          </p>

          <h3 id="hybrid" className="h3">Recall</h3>
          <p>
            <code>recall()</code> is the single retrieval entry point. The bound LLM rewrites the
            query into 2-3 angles, then for each rewrite memgc fans out vector cosine + BM25
            lexical concurrently via <code>tokio::join!</code>. The per-query result lists are
            fused via N-list RRF, blended with raw cosine for a final re-rank, and (optionally)
            spliced with the consolidated profile at rank 1. A row hit by either channel still
            ranks; an exact-keyword match rescues a semantic miss, and vice versa. Borrowed in
            spirit from Mem0's <code>utils/scoring.py</code>.
          </p>

          <h3 id="audit-link" className="h3">Audit & lineage</h3>
          <p>
            Every <code>Memory</code> row carries a <code>(status, version, lineage_id)</code>{' '}
            triple. Updates produce a new row with <code>version + 1</code> and the prior row flipped
            to <code>archived</code>; <code>history(lineage_id)</code> returns the full chain. Plus
            an opt-in persistent SQL operations log:{' '}
            <code>with_persistent_audit_log()</code> records every <code>extract</code> /{' '}
            <code>retrieve</code> / <code>consolidate</code> / <code>sweep</code> to the{' '}
            <code>memgc_audit_log</code> table. SOC 2 / GDPR friendly.{' '}
            <a className="inline" href="audit.html">Read more →</a>
          </p>

          <h3 id="injection" className="h3">Injection safety</h3>
          <p>
            Six prompt-injection defenses no other memory library ships:
          </p>
          <ul>
            <li><strong>Six-pattern reject list on <code>extract()</code></strong> — blocks the openclaw paper's known injection shapes before storage.</li>
            <li><strong><code>&lt;relevant-memories&gt;</code> wrap on <code>consolidate()</code></strong> with closing-tag escape, so retrieved content can't break out into the system prompt.</li>
            <li><strong>Query sanitizer on <code>retrieve()</code></strong> — strips prepended system-prompt noise from over-long queries (a 200-char cap that recovered 89% R@10 on mempalace's audit).</li>
            <li><strong>SHA-1 verbatim dedup</strong> via <code>find_by_hash</code> + a partial unique index — race-safe under concurrent writers.</li>
            <li><strong>Middle-truncation pre-pass</strong> on consolidation payloads above 50k tokens, with UTF-8 codepoint awareness for CJK and emoji.</li>
            <li><strong>Audit-by-default lineage</strong> — every change is recoverable.</li>
          </ul>

          <h3 id="storage" className="h3">Storage backends</h3>
          <p>
            Three first-class adapters share one trait:
          </p>
          <ul>
            <li><strong><code>SqliteStorage</code></strong> — local file or in-memory; auto-migrates; the production-ready zero-deps default.</li>
            <li><strong><code>PostgresStorage</code></strong> — pgvector with native cosine distance, ivfflat index (lists=100 default, hnsw on the migration path), runtime-templated <code>vector(N)</code> column for the caller's embedder.</li>
            <li><strong><code>InMemoryStorage</code></strong> — for tests and quick demos; supports brute-force cosine vector search so the LongMemEval harness doesn't need a Postgres container.</li>
          </ul>
          <p>
            All three pass the same ~70 contract tests, byte-identical. Swap by changing one line.
          </p>

          <h2 id="different" className="h2">What makes it different?</h2>
          <ul>
            <li>
              <strong>The only Rust-core memory library.</strong> Mem0, MemPalace, Letta, MemOS — all Python.
              Rust gets you a 50× faster cold start, a single-binary deploy, and pgvector at
              production scale without re-architecture.
            </li>
            <li>
              <strong>Calibrated decay you can tune.</strong> The 6-component score is documented,
              the half-life is documented, the weights are caller-tunable. No LLM-as-judge for "is
              this still relevant" — you get math.
            </li>
            <li>
              <strong>Audit-trail-by-default.</strong> Every row has a version chain.
              <code>history(lineage_id)</code> answers "what did the agent know at any past
              moment." Add the persistent SQL audit log if you need a tamper-resistant operations
              record.
            </li>
            <li>
              <strong>Six injection defenses</strong> — none of Mem0 / MemPalace / Letta / MemOS
              ship these.
            </li>
            <li>
              <strong>BYO everything</strong> — storage, LLM, embedder. Three of each ship
              in-tree (Anthropic / OpenAI / Azure for LLM; OpenAI / Azure / Voyage for embedder),
              but the trait is open and the bring-your-own path is documented.
            </li>
            <li>
              <strong>LongMemEval R@5 = 0.984</strong> on the 450-question held-out split. Pure
              retrieval, no LLM rerank, single locked-config run, full disclosure.{' '}
              <a className="inline" href="longmemeval.html">See the methodology →</a>
            </li>
          </ul>

          <h2 id="start" className="h2">Where to start</h2>
          <p>Pick the path that matches how you learn.</p>

          <div className="card-grid">
            <a className="card" href="quickstart.html">
              <div className="card-ico"><Icon name="rocket" size={16}/></div>
              <h3>Quickstart</h3>
              <p><code>uv add memgc</code>, open a handle, extract your first memory, run hybrid retrieval. ~5 minutes.</p>
              <span className="arr"><Icon name="arrowR" size={14} stroke={2}/></span>
            </a>
            <a className="card" href="api.html">
              <div className="card-ico"><Icon name="code" size={16}/></div>
              <h3>API reference</h3>
              <p>The <code>MemGC</code> handle, the <code>Memory</code> row, the <code>Storage</code> + <code>Embedder</code> traits — every public type.</p>
              <span className="arr"><Icon name="arrowR" size={14} stroke={2}/></span>
            </a>
            <a className="card" href="longmemeval.html">
              <div className="card-ico"><Icon name="sparkle" size={16}/></div>
              <h3>LongMemEval R@5 = 0.984</h3>
              <p>The benchmark numbers, what was tuned, what was measured, full reproduction recipe.</p>
              <span className="arr"><Icon name="arrowR" size={14} stroke={2}/></span>
            </a>
            <a className="card" href="audit.html">
              <div className="card-ico"><Icon name="shield" size={16}/></div>
              <h3>Audit & lineage</h3>
              <p>Per-row version chains plus the opt-in operations log. SOC 2 / GDPR / forensic-ready.</p>
              <span className="arr"><Icon name="arrowR" size={14} stroke={2}/></span>
            </a>
            <a className="card" href="https://github.com/carrickcheah/memgc" target="_blank" rel="noreferrer">
              <div className="card-ico"><Icon name="ext" size={16}/></div>
              <h3>GitHub</h3>
              <p>Read the source, file an issue, send a PR. Apache 2.0 across the workspace.</p>
              <span className="arr"><Icon name="arrowR" size={14} stroke={2}/></span>
            </a>
            <a className="card" href="https://pypi.org/project/memgc/" target="_blank" rel="noreferrer">
              <div className="card-ico"><Icon name="ext" size={16}/></div>
              <h3>PyPI</h3>
              <p>v0.0.2 live now. <code>uv add memgc</code> works on macOS / Linux / Windows.</p>
              <span className="arr"><Icon name="arrowR" size={14} stroke={2}/></span>
            </a>
          </div>

          <h2 id="principles" className="h2">Design principles</h2>
          <p>
            Three ideas shape every product decision. When something in the API feels unusual,
            <em style={{color:'var(--ink-3)', fontStyle:'italic'}}> "why did they do it like that?"</em> — these are the answer.
          </p>

          <h3 className="h3">Math, not vibes</h3>
          <p>
            Forgetting is a math problem, not a judgment problem. MemGC computes a deterministic
            6-component score for every row and deletes whatever falls below threshold. No LLM
            judge says "is this still relevant" — judges hallucinate, drift, and cost money. A
            documented formula doesn't.
          </p>

          <Callout type="note" title="Why this matters">
            Auditors, regulators, and your own future debugging self will thank you for a
            forgetting policy that runs identically every time. <code>(weights, half_life)</code>{' '}
            in, deleted set out.
          </Callout>

          <h3 className="h3">Stateless by construction</h3>
          <p>
            MemGC stores nothing of its own. Your data lives in <em>your</em> SQLite file or{' '}
            <em>your</em> Postgres database. MemGC manages a single table inside it
            (<code>memgc_memories</code>) and never touches the rest. Drop the database, the
            entire MemGC state is gone — there's no separate cache, no daemon, no remote
            endpoint phoning home.
          </p>

          <h3 className="h3">BYO, three of each</h3>
          <p>
            Three storage backends (<code>SqliteStorage</code>, <code>PostgresStorage</code>,{' '}
            <code>InMemoryStorage</code>), three LLM clients (<code>AnthropicClient</code>,{' '}
            <code>OpenAIClient</code>, <code>AzureOpenAIClient</code>), three embedders
            (<code>OpenAIEmbedder</code>, <code>AzureOpenAIEmbedder</code>, <code>VoyageEmbedder</code>).
            Plus a mock for each. Custom backends implement the trait directly — no per-vendor
            integration glue lives in core.
          </p>

          <Feedback />
          <PageFoot next={{ label: 'Quickstart', href: 'quickstart.html' }} />
        </article>
        <TOC items={tocItems} />
      </div>
      <SearchOverlay open={shell.searchOpen} onClose={() => shell.setSearchOpen(false)} />
      <TweaksPanel visible={shell.tweaksVisible} theme={shell.theme} setTheme={shell.setTheme} />
    </div>
  );
}
ReactDOM.createRoot(document.getElementById('root')).render(<Home />);
