# Run State Contract

This file owns persistent single-video run state after intake. It does not own
template promotion, editorial media detail, batch queues or npm publication.

## State Location And Scope

Every production project stores one machine-readable state document:

`videos/<project-name>/run-state.json`

Read this file first when continuing an existing project. Once intake is
recorded, do not ask completed intake questions again unless the user changes
the recorded values.

The file stores metadata and artifact paths, not full script, storyboard or
source prose. Long creative content remains in its dedicated project files.

## Required State Data

- Schema version, project identity, created/updated timestamps.
- Resolved intake: channel profile, output language, template strategy and
  template set when required.
- Selected approved template metadata: set id, tier, domain and concise
  selection rationale.
- Mode flags: `auto-run` or `review-first`, plus reporting level.
- Ordered checkpoint records for `source`, `script`, `voice`, `composition`,
  `render` and `qa` (displayed as `QA`).
- Compact events for initialization, completion, invalidation, retries,
  blocked fallback proposals and approvals.

## Stage Lifecycle

Each stage has one status:

`pending`, `in_progress`, `complete`, `invalid`, `blocked`, `failed`

A stage becomes `complete` only with its required artifact metadata and
fingerprints of direct dependencies. `qa` requires a passing check result and
a dependency fingerprint for the current render or composition.

## Resume And Invalidation

`resume-check` validates completed artifact paths and dependency fingerprints.
If an artifact is missing, unreadable or no longer matches its fingerprint, it
records an event and invalidates from the earliest affected stage.

Locked dependency cascades:

| Change | Invalidate from |
| --- | --- |
| Primary source or factual claim | `source` |
| Script content | `script` |
| Narration text or voice profile/provider | `voice` |
| Template set, scene plan or layout | `composition` |

Downstream stages are invalidated with the affected stage; earlier valid
stages remain complete.

## Retry And Fallback

Only same-output technical failures can be retried automatically. One initial
attempt plus two retries is the maximum; after three failed attempts the stage
is `failed`.

Any proposed fallback that changes voice/provider, language, source proof,
template or output quality sets the affected stage to `blocked`. Record the
original choice, proposed fallback, reason and impact. `approve-fallback`
records a decision event scoped to that run and reopens only the needed work;
it never changes global channel or template defaults.

## Helper Commands

Use `scripts/run_state.py` rather than editing state JSON manually:

- `init`
- `inspect`
- `complete-stage`
- `invalidate`
- `select-template`
- `record-retry`
- `block-fallback`
- `approve-fallback`
- `resume-check`

Commands emit JSON for workflow decisions. `inspect --human` is available for
brief human review.

Use `select-template --registry <templates/registry.json> --template-id <id>
--rationale <reason>` after recommendation. It rejects candidate-only records.
If an already recorded selected set changes, the command invalidates
`composition`, `render` and `qa` while preserving earlier completed stages.
