# Read project context

Request scoped snapshots of scenes, shots, visual references, media and version history.

A Step can bind an input to an explicit project context field:

```json
{
  "inputs": {
    "shots": {"type":"shot[]", "context":"shots"}
  },
  "permissions": {"project":["context.shots.read"]}
}
```

Supported fields and exact types:

| Context field | Input type | Contents |
| --- | --- | --- |
| `script` | `script` | `{schemaVersion:1,text}`; selected-shot narration for a narrow selection |
| `scenes` | `scene[]` | Existing scene IDs, descriptions, and scoped `shotIds` |
| `shots` | `shot[]` | Existing shot/panel IDs, scene ownership, descriptions, dialogue and timing |
| `characters` | `character[]` | Canvas-selected visual references with blueprint descriptions |
| `locations` | `location[]` | Canvas-selected location references with blueprint descriptions |
| `styles` | `style[]` | Saved Canvas, blueprint, panel and board styles and references |
| `assets` | `asset[]` | Current media with `assetId`, `versionId`, `kind`, `url`, source and explicit ownership |
| `generations` | `metadata[]` | Retained generated-media records with `asset`, `active`, `status`, and saved generation metadata |
| `versions` | `metadata[]` | Retained media versions and project-level shot-plan/timeline version metadata |
| `timeline` | `timeline` | Current editor document; filtered collections in a scene/shot/asset selection |
| `metadata` | `metadata` | Project ID/name and host-selected `scope` |

Every binding requires its own `context.<field>.read` permission. These are exact
permissions: `context.assets.read` does not authorize `context.versions.read`.
The Step workspace, preview, and future-media worker derive this index from the
project's current source documents. No duplicate production state is saved.

Canvas remains authoritative for its existing asset IDs, approved/current version,
and selected character/location/style reference galleries. Legacy reference
images remain available without reselecting deliberately deselected images.
Panels and White Board Motion supply their existing scenes, panels, collage
media, transitions and voiceover. The editor supplies media-bin items, clips,
audio, saved score takes and retained timeline media. An editor item explicitly
linked by Canvas node/version or panel ID reuses that source identity; a stale
editor copy cannot promote a different Canvas version. URL-only panel histories
use deterministic version identifiers that survive history trimming. Different
assets sharing a URL remain distinct. Legacy global `assets`/`library` caches are
excluded because they can contain other projects' data.

Media history entries contain `{schemaVersion:1, id, assetId, versionId, asset,
source, active}` and only saved metadata such as timestamp, model or duration.
Generation entries additionally have `status:"completed"`. Missing model/provider
metadata is omitted, never guessed from a model currently selected in a control.
Document history entries contain `documentType`, `versionId`, `active` and a saved
label/name; they have no `asset`. These metadata entries do not contain old script
bodies. A URL is a reference, not permission for guest code to fetch it.

The host narrows context to the Step's selected scene, shots, or assets before
binding inputs. Only explicit scene/shot ownership and source associations count;
unowned media is excluded from narrow selections. Scene documents contain only
selected `shotIds`, script contains only selected narration, and a narrow timeline
omits unrelated collections, transcript and timeline histories. Unrelated
character/location references are excluded. `metadata.scope` describes the
selection. Guest inputs cannot widen it. Project-wide execution receives the
project-wide snapshot only for the exact requested fields.

`resolveContextInputs(manifest, explicitInputs, projectSnapshot)` copies only
requested fields into input bindings. Context bindings take precedence over manual
values. Guests have no live project handle, write-through access, credentials or
ambient filesystem/network access. Fixture inputs must include concrete context
values; offline execution does not invent a project. Context delivery is implemented
in the Step workspace, preview and automatic-processing worker, not the advanced
Canvas block runner.

For example, a history-aware Block can declare:

```json
{
  "inputs": {"history": {"type": "metadata[]", "context": "versions"}},
  "permissions": {"project": ["context.versions.read"]}
}
```

Its code reads `input.history` and checks for `record.asset` when processing media
records. It must not assume every version describes a file.

## Complete shot-plan context
Use `{ "type": "shot-plan", "context": "shotPlan", "required": false }`
with `permissions.project: ["context.shotPlan.read"]` to receive the complete
saved shot-plan document. This preserves scene grouping, narration, timing and
other saved planning fields instead of rebuilding a document from flattened
`shots`. Array-based saved plans are normalized to `{schemaVersion: 1, shots: [...]}`;
object plans retain their fields with `schemaVersion: 1`.

This binding is available only for whole-project context. It is omitted for
scene, shot and asset selections, and when no plan exists. The host copies the
value; editing it does not save changes. Use the existing scoped `shots` binding
for selected-shot processing. Media URLs inside documents grant no media-read
permission; downloading still requires selected typed asset references and
`asset.read`. Exporters can also read the saved score from `timeline.audioScore`
under their existing `context.timeline.read` grant.

## Standalone timeline export
[Download Export timeline 2.0.0](/block-sdk/examples/export-timeline.stillmade-block).
This independently versioned JavaScript Block owns serialization and uses generated
SDK controls plus the shared Download result UI. Add it to a project with a timeline,
choose XML or XML + media, run it, then download. Its timeline, media, Blueprint,
shot-plan and project-name inputs bind automatically to authorized project context.

The canonical archive includes source, typed ports, UI schema, permissions,
MIT notices, original-source evidence, lineage and three executable fixtures.
Validate, test and remix it with the public CLI. No dependencies require manual
installation. The exact package is also available through the first-party catalog.

XML retains media links. ZIP bundles selected timeline media and fails if a
requested transfer is unavailable. Auxiliary project documents are retained as
metadata; their unrelated external media is not a full project backup. Device-local
media and bundled sounds depend on supported host transfers. Normal sandbox and
download limits apply. This is the existing StillMade XML serializer; compatibility
with every external editing application has not been established.

## Timed captions and caption styling
[Download Captions 2.0.0](/block-sdk/examples/captions.stillmade-block). This
standalone, remixable Block converts a transcript into editable timeline captions.
It owns phrase grouping, word timing and caption appearance, runs in the JavaScript
sandbox, and returns ordinary `timeline-edit` proposals for review and Apply.
It does not transcribe audio or spend execution credits.

The optional context binding `{ "type": "transcript", "context": "transcript",
"required": false }` requires `context.transcript.read`. At whole-project scope
it supplies a copied `{schemaVersion:1, words:[{text,start,end}], text, audioUrl?}`
from the saved voiceover when word timings exist. It is omitted when absent and
for scene, shot or asset selections. URL metadata grants no media access.
Explicitly connected transcript inputs remain separate from this fallback.

Captions uses a connected transcript first, then entered text, then the project's
saved transcript. Text without word timings uses estimated timing, identified in
the proposal title. Start offsets word times into the timeline. Duration zero
keeps transcript timing; a positive duration clips the result to that interval.
A proposal supports at most 100 lines and rejects longer results without silently
truncating them. Existing captions stay intact and locked tracks reject Apply.

`caption.add` retains its required `{id,trackId,text,start,end}` values and also
accepts these optional fields. Unknown fields and values outside these limits
are rejected by the same SDK validator and host apply path:

| Field | Accepted values |
| --- | --- |
| `words` | Up to 1,000 `{text,start,end}` entries, ordered by start, contained in the caption interval; nonempty text up to 5,000 characters, end at or after start |
| `font` | `Hanken Grotesk` |
| `size` | 8–200 |
| `color`, `highlightColor` | Three- or six-digit hex color |
| `background` | `none` or three- or six-digit hex color |
| `backgroundOpacity`, `backgroundPadding`, `backgroundRadius` | 0–100 |
| `position` | `top`, `middle`, or `bottom` followed by `left`, `center`, or `right`, separated by one space |
| `animation` | `none` or `fade` |

The host fills omitted appearance values with its existing defaults, preserves
provided styling and clones word timings before saving through ordinary edit
history. Caption updates retain their existing `{text,start,end}` contract.
Package source, MIT notices, lineage and three fixtures are retained in the
canonical archive; validate, test and remix it using the public CLI.
