# StillMade assistant connections

StillMade's optional MCP adapter exposes the same creation-draft service used by Create, plus saved project context and run inspection. It does not run inside the editor or control an open StillMade tab. The in-app assistant is separate and project-scoped.

## Recover a submitted result in the app

An open Block workspace exposes `submittedRecovery` when this account/device has
a pending hosted request. Its inspection contains the request/run identity,
recovery kind and availability, without quotes, settings, credentials or media.
When the user asks to recover that output, native chat can offer
`recover_submitted_result` with the exact inspected `requestId`.

This is a project edit through the existing review and task authorization path.
It reads the submitted request, verifies its result and saves it through the
shared host. It does not dispatch generation or approve spending. The returned
saved receipt distinguishes `applied`, `retained-for-review` and `already-saved`.
Batch and connected outputs remain for review; changed single-run inputs also
prevent automatic application. A failed lookup or save is not a completion.
Saved-project MCP can retrieve a completed capability request with
`recover_project_capability_request`; retaining or selecting it remains this
separate native action.

The local **stdio MCP adapter** is the currently verified connection path for clients that can run a local process. The separately gated remote OAuth code path has not been exercised with a real ChatGPT or Codex host. The adapter can connect to a deployed StillMade backend over HTTPS once the backend has been explicitly configured and deployed.

### Development HTTP MCP transport

The server also provides `/api/agent/mcp` as a Streamable HTTP transport for
development clients that can privately supply a StillMade connection bearer
token. It is disabled unless `STILLMADE_AGENT_ENABLED=true` and
`STILLMADE_REMOTE_MCP_ENABLED=true`. Set `STILLMADE_REMOTE_MCP_ORIGIN` to the
exact HTTPS application origin or a loopback HTTP origin. The route rejects a
different Host or browser Origin and resolves the connection on every request.
Tools still use the same capability registry, account/project scopes, revisions
and receipts as stdio. Manually issued `sm_agent_` tokens remain the development
transport; they are separate from OAuth grants.

### Gated remote OAuth path

The server has protected-resource and authorization-server discovery at
`/.well-known/oauth-protected-resource` and
`/.well-known/oauth-authorization-server`. The authorization code flow uses
StillMade sign-in and approval, S256 PKCE, one-use five-minute codes, and
hashed seven-day `sm_oauth_` bearer tokens. Each token is bound to the exact
`/api/agent/mcp` resource and a pre-registered client ID. Supported scopes are
`catalog:read`, `creations:read`, `creations:write`, `projects:read`, and
`runs:read`. Draft writes save private Create drafts only. Project edits,
publication, Block execution, and spending remain unavailable on this OAuth
grant. The user chooses up to 25 currently accessible projects for read access;
none is selected by default. Access to a shared project is checked again on
each read, so losing the underlying share also ends the connection's access.
The HTTP transport now offers the same `stillmade://agent/guide` and
`stillmade://sdk/block-authoring` resources and Block-authoring/debug prompts
as the local stdio adapter. These are guidance only; tool permissions still
come from the authenticated, scoped capability registry.

To stage a real client test, configure `STILLMADE_AGENT_ENABLED=true`,
`STILLMADE_REMOTE_MCP_ENABLED=true`, `STILLMADE_AGENT_OAUTH_ENABLED=true`,
the exact HTTPS `STILLMADE_REMOTE_MCP_ORIGIN` ending in `/`, and
`STILLMADE_AGENT_OAUTH_CLIENTS` as a JSON array of registered `clientId` and
`redirectUris` values. Use the exact callback supplied by the host. The
`0300_agent_oauth_grants.sql` migration was applied and checked in the connected
Supabase project on 30 September UTC. The feature flags and client registration
have **not** been enabled; no live host acceptance has been performed. Do not
add the remote endpoint to the portable plugin package until that test passes.
The consent page returns to the same request after a StillMade Google sign-in;
email sign-in stays on that page.
For a credential-free local integration check, run
`node scripts/local-auth-acceptance/verify-agent-oauth.mjs` from the checkout.
It starts disposable Auth/PostgreSQL, applies the numbered migrations, and
checks the OAuth/MCP tool, resource, prompt and revocation paths without contacting a paid
provider. It does not establish ChatGPT host compatibility.

## Enable the backend

An operator must have the `agent_connections` schema and set `STILLMADE_AGENT_ENABLED=true`. That table was observed in the connected Supabase project on 30 September UTC. Existing project, Block and account storage must already be configured.

Optionally set `STILLMADE_AGENT_DIAGNOSTICS=true` for a bounded request-failure feed. It holds up to 200 metadata records in each server process and disappears on restart. No request bodies, headers, raw paths, query strings, provider messages or stacks are collected. On serverless deployments, results cover only the responding instance.

Ordinary creation does not depend on agent tables or the MCP adapter. Disabling agent access rejects agent requests; it does not change Create. The connection settings load only when opened, and there is no editor polling. MCP uses separate IP/account rate counters and a process-local limit of two active tool calls per account/four overall, without consuming creation concurrency slots. It still shares database/storage resources; performance and cross-instance capacity have not been measured.

## Connect a local MCP client

1. Open Settings → Assistant connections.
2. Name a connection, choose permissions and expiry (1–30 days), and create it. Only catalog browsing is checked initially. Project/run access defaults to no projects; select projects explicitly or enter project IDs. Draft permissions apply to your accessible creation library, separately from project restrictions.
3. Copy the token immediately. It is shown once, never saved to browser storage, and the server stores only its hash. Revoke it from Settings at any time.
4. In a local checkout, install the isolated adapter dependencies with `npm ci --prefix packages/stillmade-mcp --ignore-scripts`. Node 20 or newer is required.
5. Configure your MCP client using its supported environment/secret settings:

```json
{
  "mcpServers": {
    "stillmade": {
      "command": "node",
      "args": ["/absolute/path/to/AAA/packages/stillmade-mcp/server.mjs"],
      "env": {
        "STILLMADE_URL": "https://your-stillmade-host.example",
        "STILLMADE_AGENT_TOKEN": "YOUR_CONNECTION_TOKEN"
      }
    }
  }
}
```

Use the backend origin, without a path. HTTP is accepted only for localhost. Redirects are rejected. Never put your connection token in a committed config file, prompt, URL, or Block source. The adapter does not need your password, Supabase session, provider keys or database credentials.

## Available user actions

- `list_catalog`, `search_marketplace`, `find_existing_blocks`
- `search_github_candidates`, `inspect_github_repository`, `read_github_source`, `inspect_github_sdk_package`
- `get_block_authoring_guide`, `search_documentation`, `validate_block_source`, `test_block_source`
- `list_creations`, `get_creation`, `save_creation`, `begin_block_remix`
- `list_projects`, `get_project_context`
- `get_run`, `list_recent_runs`
- With `analytics:read`: `get_creator_analytics`, `get_creator_retention`, `get_creator_dotplot`, `get_my_listing_reviews`

`analytics:read` returns only the connection owner's own creator reports. No tool accepts another creator or account ID, and project-limited connections are rejected. Dot-plot rows are creator-scoped pseudonyms, not account IDs. See `docs/ANALYTICS.md`.

Live-tab inspection and control are no longer exposed in the app connection UI.
External MCP clients continue to use the saved catalog, creation, project-context,
and run-inspection tools listed above.

## Reuse first

Before authoring, the client calls `find_existing_blocks` with the goal and, when
known, the inputs it starts from and the results it must produce. It searches
reviewed Marketplace listings, tested Community Blocks, built-ins and the
person's own Blocks by function and name, with no model, provider or credit
cost, and returns one outcome:

- `use` or `use-own`: an existing Block already does it; offer it instead of building.
- `remix`: a close Block allows an attributed remix. `begin_block_remix` creates a
  private draft from that exact version, with its license, notices and creator
  credit; retrying the same `requestId` returns the same draft.
- `compose` or `build-gap`: existing Blocks chain together; build only the missing step.
- `build`: nothing close exists, or the person wants their own version.

`validate_block_source` and `save_creation` also list up to three similar existing
Blocks (`similarExisting`). Publishing an exact copy of another creator's public
Block without remix lineage is refused.

## Block authoring uses the connected model

When a user asks Claude, GPT, or another MCP client to create or refine a Block,
the connected client model writes the complete SDK package itself. The default
sequence is `find_existing_blocks`, `get_block_authoring_guide`, targeted `search_documentation` calls,
local source composition by that model, `validate_block_source`, repair of every
reported failure, optional offline `test_block_source` for an eligible package,
and `save_creation` with `kind: "block"` and the observed
revision. The adapter also exposes `stillmade://sdk/block-authoring` and the
`create_stillmade_block` prompt so clients receive this policy before authoring.

`validate_block_source` performs the current schema, static source, interface,
collaboration, appearance, export, permission, and remix-readiness admission
checks. It does not execute fixtures or previews. A Block save is rejected unless
that static admission passes. The response records `execution: "not-run"`, zero
StillMade credits, and zero StillMade provider calls instead of implying runtime
verification.

`test_block_source` needs a connection with `creations:write`. It runs up to
five declared JavaScript or recipe fixtures after static admission. JavaScript
uses the existing isolated SDK worker; recipe execution is deterministic. The
tool provides no provider, network, or desktop executor. Capability, ComfyUI,
and native desktop packages require their separate reviewed host path. A
fixture pass does not approve visual quality, a customer result, or publication.

This path never calls the in-app AI Block Builder, a hosted provider, or a paid
research action. Asking to create a Block is not permission to spend. External
MCP connections do not receive app-control or paid-dispatch capabilities.
Declaring a capability or ComfyUI runtime only
describes later review-required execution and does not dispatch it while authoring.

For a public repository that already contains a StillMade SDK package,
`inspect_github_sdk_package` reuses the existing GitHub importer at one exact
commit. It returns verified source pins, package identity, and static admission.
Only a complete, unredacted package of at most 40 KB is returned to the host;
larger or redacted packages are classified for a smaller source selection.
This inspection does not save, run, install, or publish anything. It does not
declare the repository's redistribution rights on the user's behalf.

Draft saves use the existing Create service, protected namespaces, team permissions, checkpoints, immutable object storage and optimistic revision checks. Supply revision `0` for a new draft, or the actual current revision for an edit. Returned source may be redacted or truncated: never blindly save a partial document. If a save times out or conflicts, inspect the draft first. The adapter does not automatically retry writes.

Saved context uses the existing project context contract and storage reader. Inspection does not open an editor, reset a project's inactivity clock, dispatch a provider, poll/verify retained media, settle a charge or retry a run. Project reads cover owned and currently shared projects within the connection's selected project scope.

The server validates scopes, project restrictions, expiration, revocation and account suspension on every call. Tool invocation records contain tool name, actor, timestamps and outcome, with no inputs/results. A crash may leave `started`, meaning the result is unknown. Tokens cannot be used as ordinary application session tokens.

## Internal debugging

Internal tokens are separate from user tokens. Issue one using `POST /api/agent/internal/connections` with a normal administrator session from an allowed admin IP after the existing MFA step. Example body:

```json
{"name":"Developer diagnostics","projectIds":null,"expiresInDays":1}
```

The internal endpoint replaces requested scopes with `debug:read` and `analytics:admin`; the public endpoint never grants either, and a user token that somehow holds them has them removed when it is resolved. Configure a separate MCP instance with `STILLMADE_MCP_AUDIENCE=internal`. Existing admin IP restrictions, fresh administrator/suspension checks and recent MFA apply again on **every** tool discovery and invocation. MFA expiry can require re-verifying in the admin UI even before token expiry. Revoke internal tokens through the same Settings connection list.

Internal tools: `get_project_debug_state`, `get_failed_requests`, `get_recent_errors`, `get_credit_job`, `get_agent_activity`, `get_runtime_info`. Cross-account tools require an explicit account ID; project restrictions still apply. Global/account-wide tools are unavailable on project-limited connections. Credit inspection returns recorded job accounting, not proof of complete provider settlement.

Whole-app analytics tools (`analytics:admin`): `get_analytics_definitions`, `get_analytics_overview`, `get_analytics_retention`, `get_analytics_dotplot`, `get_analytics_funnel`, `get_analytics_signals`, `get_analytics_production`, `get_analytics_marketplace`, `get_analytics_acquisition`, `get_analytics_experiments`, `get_analytics_economics`, `get_analytics_health`, `get_analytics_timeline`. They return the same report envelope as the admin Analytics tab (definition, period, coverage, population, `measurement_status`) and use the same strict parameters; raw SQL, HogQL or unknown fields are rejected. Create the internal connection with `"projectIds":null`, because whole-app analytics are unavailable on project-limited connections. Analytics tool calls never count as customer activity.

The `debug_stillmade` MCP prompt starts an inspection workflow. Begin with a reported symptom and project/run/request IDs; correlate saved structure, error codes and uncertain dispatch states. Record hypotheses separately from observations. Tests and reproduction actions still require the authorization specified in the project's instructions.

## Assistant boundaries and remaining work

The in-app Gemini conversation uses the trusted project assistant path and is
limited to the current project. It does not use the external MCP connection or
expose the former live-tab control bridge. The remote MCP adapter remains available
for the catalog, creation, saved-project, and run-inspection tools listed above,
but it cannot control an open StillMade tab.

Supported saved-project workflow edits: `begin_project_block_remix` starts a private Create draft from the exact pinned Block source. After `get_creation` / `save_creation` edits, `preview_project_workflow_edit` and `apply_project_workflow_edit` add, replace, move or remove a Block in the Project Type. Add/replace require a complete saved Block creation draft and `creations:read`; the Block passes static SDK admission and a remix must identify the exact current parent. Apply requires `projects:read`, `projects:write`, the three preview digests and a unique request ID. It commits the Type and Canvas together, pins the exact package, and archives affected results. The call does not run a Block. `prepare_project_type_draft` copies the current exact project workflow and embedded Block code to Create for listing review; only the project owner can do this, with `projects:read` and `creations:write`. It returns whether the project stayed current during the handoff. It does not publish.

Local verification on September 27, 2026: focused PGlite workflow mutation and MCP capability tests covered exact Block draft replacement, move replay, remix ancestry, and listing draft source/version handoff; project workflow and Create-draft tests passed; the client production build completed. These checks do not establish a live account or production deployment acceptance.

Not implemented: hosted Streamable HTTP/OAuth onboarding, arbitrary headless project edits outside the reviewed workflow/input paths, paid run approvals/dispatch, exporting/publishing, persistent cross-instance logs, PostHog/Sentry/deployment integrations, browser session diagnostics, and automatic reproduction/testing. Future paid actions must use the existing trusted integration, exact approval, whole-workflow budget and settlement boundaries; read access grants no spending authority.

At the initial adapter installation, no automated tests, browser QA, protocol smoke tests, builds or migrations had been run. The isolated adapter dependency installation was performed with lifecycle scripts disabled. The later focused local verification above covers the new workflow tools; connection, revocation and live deployment compatibility still need acceptance with a real account.

Protocol implementation follows the [official MCP TypeScript SDK](https://ts.sdk.modelcontextprotocol.io/server). The SDK is isolated in the adapter package; it adds no dependency to web/desktop creation bundles.

## Saved project task controls

With `projects:read`, `inspect_project_tasks` reads shared task status without an open tab or navigation. Pass `projectId` and optionally an exact `taskId`; list results accept `offset`/`limit` (maximum 50) and return `nextOffset`. Each page observes current state, so re-inspect a selected task before controlling it. Reads do not promote tasks or pause work when rollout is disabled.

Separately select `projects:control` **and** `projects:read` when creating a connection to allow `control_project_task`. Existing grants never gain this permission automatically. It controls only an existing authorized shared task through the coordinator; it is not a project-edit, generation, spending or approval grant. The current requester/editor/owner rules apply. Viewers cannot intervene in another person's task; only its authorized requester or the owner can resume. Takeover changes the lead, preserving the original requester and payer.

Supply `projectId`, `taskId`, `action` (`pause`, `takeover`, `cancel`, `resume`), a new UUID `requestId`, and the exact observed `requesterId`, `taskRevision`, `instructionRevision`, `controlEpoch`. Optional `reason` is at most 300 characters. A changed task requires fresh inspection. Reuse the identical request ID and payload only to retrieve the original acknowledgment; replay never applies the effect again. `receipt` describes that original action while `task` reflects current state. Current connection grants, project access and task authority are rechecked even on replay.

Pause/cancel fence later effects but cannot guarantee already accepted provider work stops or avoids its existing cost. Resume queues revalidation of current state; normal source, plan, review and budget requirements still apply. Native and external task controls use the same coordinator and require the complete observed fence. Older clients that omit it receive `PROJECT_AI_REFRESH_REQUIRED` and must refresh; their request makes no task change. Saved task records and receipts are retained. Arbitrary review-mode changes and hosted dispatch are not exposed.

The backend additionally requires `0193_project_ai_control_receipts.sql` after existing coordination and permission migrations. Local verification and configured database application are recorded separately from deployment and ordinary-account acceptance.

## Retrieve a submitted capability result

`recover_project_capability_request` is a delivery-only read, separate from the app's reviewed `recover_submitted_result` edit. The existing actor-owned `get_run`/`list_recent_runs` metadata includes `request_id` for discovery. Supply an exact saved `projectId` and that original UUID `requestId` under both `projects:read` and `runs:read`. The request must belong to the connection actor and that project; the existing capability lookup also requires current project edit access. It verifies the retained source and stored media through the same service used by native delivery recovery, then rechecks the unchanged ledger and current access. Optional `expectedRevision` rejects a changed repeat read.

A completed request returns its redacted retained outputs with `recoveryState:retrieved`, `validatedFor:delivery-only`, `applied:false` and `selectionChanged:false`. This retrieves data only: it does not attach output to a placement, retain a project candidate, select a result, poll a provider, execute, settle credits or grant approval. The normal output envelope remains bounded; `truncated:true` means only an excerpt was returned. Media addresses, storage keys and credentials remain redacted. Pending, failed or uncertain work is not reported as retrieved and returns no partial output. A missing or invalid original is unavailable, never a reason to rerun automatically.

No live tab is needed for this read. Project retention/selection still uses the existing reviewed recovery UI; canceled or stale task intent cannot be overridden by retrieving earlier data. Async provider reconciliation and full external execution/recovery parity remain separate work.

### Retained result inspection

Retained unselected results have a separate read-only inventory. The Result tab
shows eight candidates at a time. Use native `list_retained_results` or external
`list_project_flow_retained_results` with `{placementId, revision:
unusedResultsRevision, offset, limit}` (plus `projectId` externally); list pages
contain at most eight candidates. Only records still retained for the current
Block package are included: unused single results, unselected connected results,
and batch records explicitly marked unused after a source change. The ordinary
batch picker is separate. `historyComplete:false` means evicted history is not
recoverable through this inventory, even at its final page.

Each candidate has an exact `candidateId`, `outputDigest`, run/item/attempt
metadata, and captured-input/output counts and cursors. Native
`inspect_retained_result` and external `inspect_project_flow_retained_result`
accept `{placementId, revision: unusedResultsRevision, candidateId, section,
offset, limit}`. Sections `inputs` and `outputs` page at most 16 identities or
previews. Sections `text` and `collection` also require `outputKey` and the exact
preview `path`; text requires its returned `identity` and permits at most 4,000
characters, collections at most 16 members. Reuse the exact candidate and list
revision on every page. Changes anywhere in retained records, package or preview
restrictions invalidate that revision. Inspect fresh state after a conflict.
Current project read access is rechecked after saved reads; native/UI caches
reset when the authorized reader changes. External/native results redact media
addresses. Sensitivity and prior preview restrictions still apply; a restricted
candidate cannot become inspectable through a later page. Captured inputs remain
bounded metadata and may be incomplete; nested structured previews disclose
omitted fields rather than claiming a complete document. These reads never
select a candidate, restore media, dispatch work, or substitute current output
for a retained value.

### Native output observations and original context

Mapped native Canvas outputs use the installed exact-version host port adapter. Flow can show a saved image, video or text value as `ready` with `observation.kind: "native-canvas-output"` and `runReceiptAvailable:false`. The Inspector labels that value **Available**; it does not invent a completed run, receipt or result pin. The exact selected asset/version is preserved in Result and Using. Missing values, mismatched host identities and navigation-only workspace ports remain unavailable. `ProjectFlowNativeObservation` describes this read-only origin; normal output/source paging retains its identity. Native production-workspace connections also use the exact installed host manifest and declared port handles; a newer catalog release cannot redefine an older pin. Original standalone nodes without placement/version metadata retain their historical 1.0.0 contract. Unknown, mismatched and non-host pins cannot impersonate a production workspace.

Whole-project Script retains its original narration source. Transcript uses the selected Voiceover take’s recorded transcript and word timings, independently of the editable narration draft. Older takes without stored transcript text derive it from their own timed words. A new Transcript-only run protects the original Voiceover document; changing an unrelated narration draft does not invalidate it. Original legacy receipts that also include Script remain valid with their stricter source checks. An older proposal cannot replace original reads with current documents, and a legacy result lacking derived proof must be rerun before guarded adoption. Other derived fields and arbitrary dynamic reads require separate attribution. Scoped narration and supported shot/scene collections capture their original Blueprint, Shot Plan, Animation, Panels and Board contributors, including empty originals whose later additions could change the result. They do not substitute the whole-project Script. Native asset inventories, generation records, scoped version histories and character/location/style collections can now retain their original contributor and membership proof when canonical reconstruction exactly matches the consumed value. A bounded v2 Canvas projection excludes only the exact host-dispatched producing placements while retaining their IDs/types, so saving their own output does not invalidate native collection membership. Current saved executable asset/generation members can retain their original selected-output, state and native-source evidence when exact canonical reconstruction matches the consumed collection. A producing placement’s own consumed previous output is captured separately when provable. Ambiguous, legacy, archived, private or unsupported collection members, local-only media, whole-project version metadata and noncanonical source documents remain unproven. v1 source reads stay compatible; new v2 captures require explicit server support. Media-dependent narration and arbitrary dynamic reads still require separate attribution.

Stateful host runs retain the exact starting-memory identity and resulting-state digest alongside original input/output evidence. Original native reads carry through subsequent memory transitions, connected batches, loops and checkpoint recovery. Declared initial/reset memory is distinct from legacy saved memory even when its bytes match; old receipts cannot gain proof from current documents or by removing a warning. Missing or changed state proof blocks protected workspace adoption. This is host-maintained provenance, not cryptographic attestation against rewriting an entire saved receipt. Older retained plans/checkpoints may require their existing recovery/reset path when the new memory evidence changes the plan identity.

Task-authored final Canvas adoption can bind the original native read union to the same transaction as the current task and Canvas execution checks. The host's `taskSourceReadSet` is retained in the exact save/recovery receipt, with explicit `assistantSourceReadSetVersions` capability negotiation. A lost response is recovered by reading the original commit; it does not resubmit an old proposal over newer work. Stale completed results may still be retained for review. Manual selection in saved Canvas projects now uses an acknowledged source save with the original native read union and `sourceCanvasPrecondition`, negotiated with `sourceCanvasPreconditionVersion:1`. Source roots and current execution content are checked under the same ordered transaction locks; layout-only changes are preserved. Exact request recovery distinguishes applied, not-applied and unresolved saves, including no-op selection, without replaying old work over newer selections. Servers without the capability refuse selection. Local drafts and unused-result retention remain separate. Legacy results do not gain missing original-source proof. Remaining native/background producers require separate coverage.

The saved-project inspector and compact handoff can open the exact source Block workspace through existing draft-save navigation guards. Account, project, read access, placement and matching package source are checked after drafts finish saving. The existing Editor opening suppresses automatic narration import/export for this navigation request. Previews without workspace navigation say **Inspect source Block**. Compact handoffs show required inputs needing attention even when the primary value is ready; **Using** targets the first such input.

Large Flow connection lists page 40 placements and offer **Find a Block** with direct keyboard access. Exact input links remain available after search. The map keeps its own bounded pages and selected neighborhood. Unchanged bounded scalar activity reports reuse the shared projection; new captured evidence, source changes and revoked access invalidate the relevant view.

External controllers can review one complete retained local connected run with `preview_project_flow_completed_results`, then select it using `use_project_flow_completed_results`. Apply requires the exact returned Flow, Canvas and candidate digests, a new request ID and the current task fence. Every selected row must have its original sealed v2 source receipt. The server validates the existing plan and original source roots, rechecks project/connection/task authority, and saves through shared Canvas operations. An acknowledged retry returns its original receipt without selecting the result again, even if the current selection has changed.

This external path supports complete recipe/JavaScript connected runs with current inputs, asset-descriptor batches with non-media outputs, and shared complete local loop receipts. All-assets, scene and selected-shots batches require the original complete inventory receipt captured and acknowledged before dispatch; it binds the original scope, ordered targets, exact plan and eight contributing workspace roots. Preview and apply check those original roots again, including workspaces that were empty when the batch started. JavaScript memory transitions require exact initial, reset or retained starting identity and resulting state with original sealed proof. Preview exposes digest-only `stateChanges`; apply saves the original outputs and memory without executing them again. Legacy/unproven or changed memory is unavailable. Hosted execution, decoded/generated media, incomplete runs and failure-recovery results still use their existing workspace review. Broad batches without original inventory proof remain unavailable; current inventory cannot be substituted for missing historical evidence. Inventory membership and each consumed item’s output or memory lineage are separate requirements. A local preview does not establish shared source proof. Preview and apply never dispatch a Block, load media, request model analysis or spend credits. A source/authority conflict keeps the retained result available for review; it does not silently rerun the workflow.

Completed local loops can retain their exact whole receipt in shared Canvas history without selecting outputs or advancing memory. A failed shared save preserves the original device checkpoint. Shared `retainedLoopRuns` summaries expose bounded run identities, pass counts and current selection for review; they do not claim revalidation. Retention is limited to four envelopes, 512 KiB per envelope and 1 MiB total per starting placement; exceeding a bound keeps device recovery and reports the limit rather than evicting old history. External selection validates the original whole loop and every consecutive pass against current sources, memory, task and authority, then uses the existing adoption path without dispatch. In the native workspace, another editor can explicitly choose a shared run without its original device checkpoint. Review validates the original complete receipt; Use rechecks its shared identity and the reviewed Canvas execution state before acknowledged selection. A newer selection or changed source requires fresh review.

Shared loop pass inspection uses the existing `list_project_flow_retained_results` and `inspect_project_flow_retained_result` operations. Initial discovery exposes bounded historical identities; explicit inspection verifies the original whole envelope before returning captured input identities and paged output/text/collection previews. It validates original evidence without requiring today's inputs to match, and does not select or execute the pass. Changed original history or revoked read access invalidates the response. Native Result review uses the same verified reader through **Inspect saved pass**.

Existing-media and host-action selections carry explicit selection metadata. Flow separates them from worker execution receipts and attempt history; a media selection identity is not a run ID. Saved selection still checks current authority and the reviewed Canvas/source state.

External connections must explicitly opt into `projects:write` alongside `projects:read` for reviewed Flow input, pin, result/memory changes and saved-media restoration. Defaults and existing connections do not gain permissions. Shared Flow reads recheck current connection authority after asynchronous work; all four Flow mutations recheck it in their write transaction, including replay. Media restoration rechecks through its existing before-write guard. Revocation, expiry, project/scope changes and suspension invalidate stale authority.
