# Outline page turn r02 — editable dual-tool study

One existing treatment: `study-outline-page-turn`, with two original-content
variants. This revision changes one lower-corner join mechanism in `default`.
The adaptation and shared renderer are unchanged. Read `REVISION.md` for the
bounded change and regression measurements; this is not a fidelity approval.

**Status:** mechanically reproducible candidate; source review remains
changes-required. No native DaVinci Resolve execution or blind-review win is
claimed. The builder inspected static states, not perceived continuous motion.
Read `SOURCE.md`, `CONTENT_CONTRACT.md`, `RESOLVE.md` and `VERIFICATION.md`.

## What is editable

- `src/`: retained shared Remotion core, unchanged.
- `recipes/study-outline-page-turn.json`: retained 38-frame choreography; only
  the default's 32 lower-corner path commands change from r01.
- `adapters/typography.ts`: retained factory with the bounded join repair and
  unchanged `BookDesign` API. The module also contains an unused wordmark helper;
  no second recipe or mechanism is added here.
- `examples/study-outline-page-turn/{default,adaptation}.json`: 113-field Content
  records; adaptation is byte-preserved. Both use `#080808` on white. Their curves
  differ: `rounded-book` versus `field-notebook`.
- `assets/VARIANT/`: 38 full-pose SVGs, 111 separately filled leaf SVGs,
  frame/path CSVs and exact controls JSON for each delivered variant.
- The separate off-volume evidence delivery holds each real silent Remotion
  MP4, its 38 lossless render frames and binding, plus the prepared 38-image
  opaque PNG sequence and four 38-image transparent ordered-layer sequences.
  These generated movies/images are **not inside this source kit or its ZIP**.

No source footage, screenshots, source identity artwork, remote imagery or demo
data is an implementation input. Every leaf is original parameterized code/SVG.
The unchanged shared core loads the permitted Geist font even though this
treatment has no text; `public/fonts/OFL.txt` travels with the font.

## Reproduce without installing or copying dependencies

The tested preparation platform is Linux with Bash, `flock`, Python 3.10+, Node
22.18+ (tested 24.13.1), FFmpeg/FFprobe, full Chrome for Testing and the exact
already-installed versions in `package-lock.json`. There is no install step.
Do not link or copy `node_modules`. The supplied external resolver and webpack
override read the existing dependency directory directly.

From this kit directory, set these variables to your existing resources:

```bash
export CARET_SHARED_NODE_MODULES="${EXISTING_NODE_MODULES:?existing absolute dependency directory}"
export REMOTION_BROWSER_EXECUTABLE="${FULL_CHROME_BINARY:?actual executable, not a launcher}"
export TMPDIR="${SCRATCH_DIR:?existing scratch directory}"
export FIELDNOTES_ENCODER_LOCK="${ENCODER_LOCK:?shared encoder lock file}"
export FIELDNOTES_STORAGE_ROOTS="$PWD:$TMPDIR"
export FIELDNOTES_STORAGE_CAP=100000000
: "${OUTPUT_DIR:?set an absolute external off-volume output directory}"
node scripts/typecheck.mjs
node --experimental-loader ./scripts/shared-dependencies.mjs --experimental-strip-types --test tests/*.test.mjs
python3 -B tests/test_delivery_verifier.py
bash scripts/run.sh render --variant default --out "$OUTPUT_DIR/default/render"
bash scripts/run.sh render --variant adaptation --out "$OUTPUT_DIR/adaptation/render"
bash scripts/run.sh prepare --variant default --out "$OUTPUT_DIR/default/prepare"
bash scripts/run.sh prepare --variant adaptation --out "$OUTPUT_DIR/adaptation/prepare"
: "${DELIVERED_EVIDENCE_DIR:?supplied immutable r02 evidence root, separate from this new run}"
python3 -B scripts/verify-delivery.py --evidence "$DELIVERED_EVIDENCE_DIR" --browser-binary "$REMOTION_BROWSER_EXECUTABLE"
```

The scripts refuse existing output directories. Choose fresh names on another
run; do not delete or rebind previous evidence. `OUTPUT_DIR` must be an absolute
directory on the approved off-volume filesystem, outside the repository and
this kit. Add its existing parent to `FIELDNOTES_STORAGE_ROOTS`, without nesting
roots or counting the same directory twice. Keep scratch outside the kit and
count every owned output in the storage roots. On the original bounded host,
the coordinator additionally runs its unchanged global storage guard before
each command. That private guard and machine paths are not part of this kit.

The last command checks the **delivered immutable pair**, not the fresh outputs
just generated. New runs record their own storage/runtime observations, so their
manifest bytes need not equal the frozen receipt even when image/movie bytes
match. Keep new manifests with those outputs and compare every decoded frame,
clock, content and asset hash before issuing a new receipt. Never rewrite the
delivered receipt merely to make a newly generated directory pass.

`toolchain.json` pins the full Chrome binary SHA-256, not a shell wrapper or
package version alone. Chrome runs headlessly using `chrome-for-testing`; Chrome
Headless Shell is rejected by the binary check. If a compatible full browser is
absent, stop; these commands never download one. A userspace Chrome runtime may
also need its pre-existing dynamic-library search path in `LD_LIBRARY_PATH`.

`scripts/common.mjs` uses a process-local loopback server configuration inherited
from the retained render harness. Its loopback address is not a private service
dependency. No external source media is requested.

## New original content

The receipt-bound delivery verifier checks the frozen pair's manifest bytes,
browser/toolchain/font provenance, exact unique on-disk inventories, every file
hash, all PNG dimensions, and all 76 decoded movie frames and clocks. It rejects
duplicate JSON keys before they can collapse into a dictionary. Legitimately
identical held frames are allowed only at their exact receipt-bound positions.
The ten verifier regression tests include forged browser/font records and
duplicated, missing or substituted PNG inventory entries.

`scripts/verify.py` (also exposed by the inherited `npm run verify` alias) is
only the earlier low-level movie/binding helper. Its success alone is **not** a
complete provenance or inventory check; use `verify-delivery.py` for this pair.
The receipt is unsigned: obtain the ZIP checksum through a trusted handoff.
Replacing the entire kit/receipt is outside its proof, and historical browser
execution is not cryptographically attested.

Write an `inputs/new-book.json` using the exact contract; for example:

```json
{"family":"field-notebook","turningLeafWidth":0.97,"pageCurvature":1.07,"ink":"#123040"}
```

Then run the same renderer and preparation path without replacing either example:

```bash
bash scripts/run.sh render --design inputs/new-book.json --out "$OUTPUT_DIR/new-book/render"
bash scripts/run.sh prepare --design inputs/new-book.json --out "$OUTPUT_DIR/new-book/prepare"
```

This is a new content substitution needing its own visual review, not a third
verified output in the delivered evidence. The executable input gate rejects
unknown controls, external paths and arbitrary pose data. Save the new design,
generated Content in the manifest, output hashes and review together.

## Delivery boundaries

`SHA256SUMS` binds the public kit. The separately delivered ZIP contains original
code/SVG/control data, guides and the permitted font only: no generated MP4/PNG,
source evidence or dependencies. All generated binary evidence and the brief
attributed source clip live in the separate off-volume handoff, never as an
asset dependency. This revision generated all movies/images off-volume from
the outset. r01 source files, outputs and frozen review packets remain untouched.
There is no publication action, site/registry update, synthesized narration,
OBS pairing, final all-hands approval or new distinct-mechanism credit here.
