# Fresh — AI-First Architecture (v0.1)

We are rebuilding Fresh as an **AI-first, intent-driven** site. There is no
fixed page. The site is the *rawest possible bones* (content + capabilities)
behind a standardized **outlet**. When a visitor arrives, an AI **plug**
connects to the outlet, mines the visitor's intent, and composes the experience
in real time. The chatbot is gone entirely — the **emergency
exit**.

```
  BONES ──▶ OUTLET ──▶ PLUG ──▶ MORPHIC COMPONENTS ──▶ (saved morph)
  data      socket     brain     hooks & listeners       persistence
```

## The pieces

| Layer | File | Responsibility |
|-------|------|----------------|
| **Bones** | `data/bones.js` | Raw content nodes + capability actions, tagged by topic. No layout, no order. The source of truth for the manifest. |
| **Outlet** | `js/outlet.js` | The socket (`window.FreshOutlet`). Exposes a machine-readable manifest, an event bus, a signal firehose, action dispatch, and morph persistence. Dumb about meaning. |
| **Plug** | `js/plug-default.js` | The brain. Mines intent from signals and emits a composition. Heuristic + client-side today; swappable for any LLM agent. |
| **Morphic components** | `js/morphic.js` | `<morphic-root>` + `<morphic-section>`: pure listeners on the outlet that render from bones and self-adjust emphasis. |
| **Chrome** | — | Removed. Morph save/share/reset live on as outlet APIs with no floating UI; an emergency action dials the practice (`js/outlet.js`). |

## The plug contract

A plug is any object that implements:

```js
const plug = {
  id: 'my-agent',
  onConnect(outlet) { /* subscribe, mine, outlet.setComposition(...) */ },
  onDisconnect() { /* cleanup */ }
};
window.FreshOutlet.connect(plug);
```

The outlet hands the plug this surface: `manifest()`, `getNode()`,
`getAction()`, `on()/off()`, `signal()`, `setComposition()`, and `bones`.

A composition the plug ships back:

```js
outlet.setComposition({
  intent: { focus: ['cosmetic', 'cost'], urgency: 'normal' },
  hero: 'cosmetic',                       // which hero variant to frame with
  order: [                                // ordered + emphasized nodes
    { nodeId: 'hero',     emphasis: 'featured' },
    { nodeId: 'services', emphasis: 'featured' },
    { nodeId: 'cost-info', emphasis: 'normal' },
    { nodeId: 'why-us',   emphasis: 'muted' },
    { nodeId: 'about',    emphasis: 'hidden' }
  ]
});
```

`emphasis` ∈ `hidden | muted | normal | featured`.

## Bring your own agent (BYO)

The whole point of "the user brings their own plug." Two ways in:

1. **Before load** — set `window.FRESH_BYO_PLUG = yourPlug` and the default
   plug stands down.
2. **At runtime** — call `window.FreshOutlet.connect(yourPlug)` (e.g. from an
   extension, an injected agent, or an MCP bridge). It replaces the current plug.

Read `window.FreshOutlet.manifest()` to discover everything the site can show
and do without scraping the DOM.

## Intent signals

Components emit raw behavior the plug subscribes to via `outlet.on('signal')`:
`view`, `dwell`, `click`, `query`, `scroll`. The default plug also seeds intent
from `?intent=`, `?for=`, `?q=`, and the referrer. Try `index.html?intent=cosmetic`
or `?intent=emergency`.

## WebMCP — the standardized plug socket (`js/webmcp-adapter.js`)

We comply with **WebMCP** (`navigator.modelContext`), so a visitor's own
browser agent can drive the site through a W3C-standard API instead of our
bespoke plug contract:

- Each `bones.actions[]` is exposed as a WebMCP tool (`fresh_<action>`), whose
  handler calls `outlet.dispatch()`.
- `set_intent({ topic })` lets an agent declare intent; it's routed through the
  signal bus so the connected plug recomposes the page.
- `describe_site()` returns the manifest — agents introspect, never scrape.
- On every `composition:changed` we call `provideContext({ tools })` to replace
  the toolset, so what's exposed always matches the currently relevant intent.

Feature-detected on `navigator.modelContext`; with no agent present it emits a
silent, inspectable `console.debug` preview and changes nothing else.

## AG-UI event stream (`js/agui-bridge.js`)

We expose an **AG-UI v3.0**-compatible event view via
`window.FreshAGUI.subscribe(cb)`. Outlet events map to AG-UI events:

| Outlet event | AG-UI event | Notes |
|--------------|-------------|-------|
| first composition | `STATE_SNAPSHOT` | full normalized state |
| `composition:changed` | `STATE_DELTA` | RFC-6902 JSON-Patch diff (not a resend) |
| `signal` | `CUSTOM` (`name:signal`) | behavior / trace |
| `action` (dispatch) | `TOOL_CALL_START` + `TOOL_CALL_END` | frontend tool call |
| `emergency` | `CUSTOM` (`name:interrupt`) | human-in-the-loop |

Normalized state is `{ hero, focus[], nodes:{ id:{ emphasis, index } } }`, so a
consumer can reconstruct the page purely from the snapshot + deltas.

## Status

- ✅ F0: **home page** morphs to intent, end to end (bones → outlet → plug →
  morphic render → save).
- ✅ F1: **WebMCP adapter** — capabilities exposed as `navigator.modelContext`
  tools; toolset re-published on every recomposition.
- ✅ F2: **AG-UI bridge** — outlet events surfaced as an AG-UI v3.0 event stream
  (snapshot + JSON-Patch deltas + tool-call + interrupt).
- ✅ F3: **llms.txt + schema.org** — discoverability generated from bones.
- ✅ F4: **all pages on the morphic layer** — about/services/contact are bones;
  the booking form is the `submit-appointment` capability's input surface.
- ✅ F5: **LLM plug** — endpoint-driven intent/composition with safe fallback
  (client-side complete; live endpoint is the documented seam).
- ✅ F6: **MCP Apps UI resource** — sandboxed-iframe resource + JSON-RPC contract
  (client artifact complete; a live MCP server is the seam). See `mcp-app/`.
- ✅ F7: **portable component tree** — `fresh.ui/v1` adapter so external GenUI
  engines can drive `<morphic-root>` (`js/portable-tree.js`).
- ✅ F8: **shareable / named morphs** — `?morph=` URL links + saved personal
  default (`outlet.shareUrl()` / `applyUrlMorph()`).
- ✅ Phase 0 (redesign): **knowledge base** — canonical-markdown articles
  (`kb/*.md` + the `data/kb.js` catalog) on a stable reading surface that
  keeps the capability layer live, plus an intent-aware `article-grid`
  teaser node on the home page.
- ✅ Phase 0 (redesign): **LLM pages** — generated markdown twins of every
  page, a KB-aware `llms.txt`, the `ai.html`/`ai.md` agent guide, robots.txt.
- ✅ Phase 0 (redesign): bones grid items can carry `image`/`imageAlt`
  (restores Dr. Sloengaard's photo through the morphic and MCP-app renderers).
- ✅ Phase 0 (redesign): **Open Data API** — curated public dental datasets
  as static JSON under `/api/` (generated by `tools/gen-datasets.js`), plus
  `mcp/fresh-datasets.js`, a zero-dependency stdio MCP wrapper so partners
  get the datasets as tools with no infrastructure.

The `ralph/` backlog (F0–F8) is complete. The successor program is
**`docs/REDESIGN.md`** — the AG-UI × A2UI *native* redesign: a live MCP
server + MCP app as the first-class surface (Phase 1), a real AG-UI client
run loop replacing this read-only bridge and the legacy chatbot channel
(Phase 2), and Google A2UI replacing `fresh.ui/v1` as the portable tree
(Phase 3).
