# `window.zeq` — embed the ZeqVM physics engine in any web software

The ZeqVM browser extension exposes a small global, **`window.zeq`**, on any site
the user grants. Your web app's own JavaScript calls it to run real,
dimensionally-checked physics against the user's ZeqVM machine — no API key in
your code, the user's machine is the authority, and the extension's service
worker holds the token (your page never sees it).

This is how you put the engine *inside other software*: a logistics dashboard, a
trading tool, a lab notebook, a game — anything running in the browser.

---

## Turning it on

1. The user installs the ZeqVM extension and signs in.
2. On your site, the user opens the extension side panel and clicks **⚛ Compute**
   (or you ship a button that asks them to). The extension injects `window.zeq`
   and a visible compute box after a one-time per-site permission grant.
3. Your code waits for it:

```js
function whenZeqReady(cb) {
  if (window.zeq && window.zeq.__zeqvm) return cb(window.zeq);
  window.addEventListener("zeq:ready", () => cb(window.zeq), { once: true });
}
```

`window.zeq.__zeqvm` is the version string (`"1.287"`). A `zeq:ready` event
fires once the API is live.

---

## The API

Every method returns a Promise.

| Method | Call | Returns |
|---|---|---|
| **compute** | `zeq.compute(operators, inputs)` | `{ value, unit, equation, zeqProof, verify_claim, … }` |
| **solve** | `zeq.solve({ prompt, mass, tMax, dt, … })` | master-equation result `{ energy, errorPct, registerDump, … }` |
| **multibody** | `zeq.multibody({ prompt, bodies:[{mass}], tMax, dt })` | `{ bodies, interactions, totalEnergy }` |
| **verify** | `zeq.verify(proof, claim)` or `zeq.verify(claimObj)` | `{ valid, … }` |
| **pulse** | `zeq.pulse()` | `{ pulseHz, zeqond, phase, … }` (free) |
| **operators** | `zeq.operators({ search, domain, limit })` | `{ operators:[…], total }` (free) |
| **prove** | `zeq.prove({ … })` | public proof receipt (free) |
| **lattice** | `zeq.lattice({ nodes:[…] })` | multi-node compute |
| **shift** | `zeq.shift({ … })` | KO42 metric re-alignment |
| **modulate** | `zeq.modulate(value)` | `{ value, equation }` — KO42, local, no network |

### Examples

```js
whenZeqReady(async (zeq) => {
  // Force from F = ma — operators are picked from the 1,500+ catalogue.
  const f = await zeq.compute(["KO42"], { mass: 2, acceleration: 3 });
  console.log(f.value, f.unit);            // 6 "N"
  console.log(f.zeqProof);                 // signed 64-hex receipt

  // Verify the receipt round-trips (proves the value, not just bookkeeping).
  const v = await zeq.verify(f.zeqProof, f.verify_claim);
  console.log(v.valid);                    // true

  // Live 1.287 Hz clock — free, no key.
  const p = await zeq.pulse();
  console.log(p.pulseHz, p.zeqond, p.phase);

  // Two-body simulation.
  const sim = await zeq.multibody({
    prompt: "two gravitating bodies",
    bodies: [{ mass: 1 }, { mass: 2 }], tMax: 2, dt: 0.25,
  });
  console.log(sim.totalEnergy);
});
```

---

## The dimensional compiler (errors are a feature)

`compute`/`solve`/`multibody` are **dimensionally checked**. If your inputs don't
engage the solver, the call rejects with `err.status === 400` and `err.data`
carrying the 7-step protocol trace and an **"accepted inputs"** hint:

```js
try {
  await zeq.compute(["KO42"], { value: 1 });   // dimensionless — won't compile
} catch (err) {
  console.log(err.status);                     // 400
  console.log(err.data.error.message);         // "...Accepted inputs: m [M], a [L·T⁻²], v [L·T⁻¹], r [L]…"
}
```

Treat this like a type error: surface the hint, fix the inputs.

---

## What's metered vs free

- **Metered** (uses the user's machine key, may return `402` if balance is short):
  `compute`, `solve`, `multibody`, `lattice`, `shift`.
- **Free / public**: `pulse`, `operators`, `prove`, `verify`, `modulate`.

A `402` surfaces as a rejected Promise with `err.status === 402` — prompt the
user to top up rather than retrying.

---

## Security model

- `window.zeq` is only defined on sites the user **explicitly granted** (a Chrome
  permission prompt the first time).
- The API is `Object.freeze`d; calls are `postMessage`d to an isolated relay that
  forwards to the extension's service worker. **The page never receives the auth
  token or machine key** — only the computed result.
- Results are sanitized; the relay only accepts the known method names.

---

## Not the browser? Use the SDK family

The extension is the *browser* member of the ZeqVM client family — all hit the
same `/api/zeq/*` routes:

- **TypeScript / Python SDK** — server + CLI (`app/packages/sdk`).
- **MCP server** — agent integration (`Bearer zeq_ak_…`).
- **`window.zeq`** — this — in-browser, user-authorized.

Same engine, same proofs, three doors in.
