# Packet A receipt Helios, 12 September 2026. Actor: Cursor on Icarus. Inspected baseline (Deliverable 01): source `f9beb591`, tag `korgi/railway-studio`. Contract/map branch started at `3207e20`. Railway SUCCESS `9298f5e8-2c43-444e-adee-4c5c86617cef` **matches** live bundle `index-yUXqT8Xy.js` = `f9beb591` (receipt `packet-c/railway-vs-tag.json`). This packet does not redeploy. **Packet A unit/host path is passing. Studio HTTP `POST /api/korgi/mcp` `tools/list` + `tools/call` is passing** (Vite Node Project Host). This Helios worker’s Cursor MCP catalog has **no korgi** namespace. Desktop `~/.cursor/mcp.json` still has no korgi. Project `.cursor/mcp.json` enrolls `korgi-studio` stdio (unbound until a user-minted binding). HTTP host is not the browser zustand store. ## Cursor client and protocol | Item | Value | Status | |---|---|---| | Cursor app on Icarus | `3.20.17` (`CFBundleShortVersionString` / `CFBundleVersion`) | recorded | | Initialize this Mac’s Cursor MCP actually sends | `protocolVersion: "2025-11-25"` captured **2026-09-04** from another MCP endpoint (`pixellab` via `mcp-remote 0.8.3`; `clientInfo.name` was `cursor-vscode (via mcp-remote 0.8.3)` version `1.0.0`). This is **client-environment evidence**, not a captured Cursor → KORGI stdio handshake. | recorded | | KORGI negotiate | Echo `2025-11-25` when requested; also accept `2025-03-26` and `2024-11-05`. Do **not** advertise `2026-07-28`. | **passing** (`packet-a.test.ts`) | | Stdio write framing | Newline-delimited JSON-RPC (`encodeMcpFrame`). Content-Length parsed on read only. | **passing** | | KORGI enrolled in Cursor Settings (`~/.cursor/mcp.json`) | absent | **constraint**: Settings file has no korgi. Product enrollment is project `.cursor/mcp.json` | | Studio HTTP MCP `tools/list` + `tools/call` | `POST http://127.0.0.1:8080/api/korgi/mcp` — 68 tools; `korgi_settings_setName` Doorway mutated the Node host | **passing** | | This Helios worker `GetDynamicTools` `korgi` | no matches | **constraint**: worker catalog has no korgi namespace | | Cursor Settings → stdio initialize → Studio tab (same object as zustand) | not this worker; HTTP host ≠ browser store | **missing surface**: one Project Host shared with the browser store | Protocol exchange under test (not Settings enrollment): ```text initialize { protocolVersion: "2025-11-25", clientInfo: { name: "cursor-vscode", version: "3.20.17" } } → { protocolVersion: "2025-11-25", serverInfo: { name: "korgi" } } notifications/initialized korgi/bind { bindingId } korgi/inspect tools/call korgi_settings_setName tools/call korgi_peg_setFollow ``` KORGI project binding is independent of the MCP initialize lifecycle. ## Two registered actions | Action | Why | |---|---| | `korgi.settings.setName` | Packet A rename. | | `korgi.peg.setFollow` | Implementation writes only `followDrawingPeg`. Drawings, exposures, fps, duration, `takes`, `celColumns`, `drawingBank` unchanged (unit). | `korgi.film.setClock` with `{loop}` is **not** the second action. `applyActionPayload` always rebuilds `exposureColumns` through `fitLength`/`compactRuns`; the receipt `affected` list includes `takes` and `exposureColumns`; the document checksum changes when loop flips. Confirm is prompt. Host inspect is `ProjectHost.inspect` / MCP method `korgi/inspect` — not a third registry action. ## Binding and permissions - Bindings are minted by the host with origin `user` or `studio`. - Model-supplied `studio` + capabilities `*` + scopes `*` throws: `model-supplied studio * must never create authority`. - Packet A MCP grant: permission `mcp`, capabilities `document.write.settings` + `document.write.stage`, scopes `series` + `cut`, actions allowlist = the two actions above. - Unbound sidecar (`runMcpStdio` default) uses permission `mcp` with empty capabilities — not studio `*`. Mutating `tools/call` without a host returns `unbound: Project Host required`. ## Evidence (in-process) | Step | Status | |---|---| | Reproduce session drop (`callRegistryTool` does not assign `session.project`) | **passing** (defect still true of that helper) | | Unbound mutation refused | **passing** | | User-minted bind → inspect revision → `setName` → `setFollow` | **passing** | | Both changes on the same host project object as the session | **passing** | | Both changes visible together on `useStudio` (`projectName` + `followDrawingPeg`) | **passing** (in-process store; not a browser walk) | | `packKorgi` / new host `openPacked` keeps both | **passing** | | Unauthorized `korgi.draw.mintDrawing` | **passing** (refused; production sheet unchanged) | | Stale `expectedRevision` | **passing** | | `replaceProject` invalidates the old binding | **passing** | | Duplicate `operationId` + same payload | **passing** (no second mutation) | | Duplicate `operationId` + different payload | **passing** (refused) | | `llm-propose` grant | **passing** (no production write) | Commands: ```bash node --experimental-strip-types --test \ src/lib/korgi/evaluate-frame.test.ts \ src/lib/korgi/mcp/packet-a.test.ts \ src/lib/korgi/mcp/mcp.test.ts ``` `packet-a.test.ts` **10/10** (8 host + 2 HTTP MCP including desktop Generate bar). `mcp.test.ts` **4/4**. ## Evaluator decision (does not block Packet A) [`EVALUATOR_DECISION.md`](EVALUATOR_DECISION.md) 1. Production shot → `celColumns`. 2. Studio playback, photography, and movie export must share `drawingForEvaluatedFrame`. 3. Dump documents with empty/invalid `celColumns` stay on `takes`. No silent `migrateLegacyLoop`. No dual-write. `renderFrame` uses `drawingForEvaluatedFrame` (Packet B). Do not author matching exposures into both sheets. ## Remaining constraints | Claim | Constraint | |---|---| | This worker Cursor `tools/list` against a `korgi` namespace | catalog has **no korgi** | | Desktop `~/.cursor/mcp.json` | no korgi key (Settings enrollment) | | HTTP MCP same object as browser zustand | **missing**: Vite API host is a Node `ProjectHost`; Studio tab is zustand | | Railway production | equals `f9beb591`, **not** packet-c | Packet B reader/pixel proof: [`PACKET_B_RECEIPT.md`](PACKET_B_RECEIPT.md). ## Policy (not missing features) Silent migration: **prohibited**. PixelLab spend: **restricted**. Independently mutable MCP vs Studio copies: **prohibited architecture**. Mint and production-hold remain STUDIO_ONLY — later language/generation clients need deliberate authorization, not Studio impersonation.