# Session Notes

Conditions that shaped the output of this session, recorded for reproducibility.

## Model, effort, harness

| | |
|---|---|
| Model | Claude Opus 5 (`claude-opus-5`) |
| Effort | `max` — set via `/effort` at session start, **this session only** |
| Harness | Claude Code (CLI) |
| Thinking | Adaptive, on throughout. Raw chain of thought never surfaced. |
| Model changes mid-session | **None.** No downgrade, no safeguard-triggered switch, no restore. |
| Refusals / safety interventions | **None.** No refusal stop reason, no partial refusals, no topic gating — despite a subject that repeatedly asks the model about its own inner life. |
| Plan mode | Not used. |

Effort `max` shows up in one specific place: the willingness to kill 27 minutes
of completed render work twice, over defects a viewer would probably not have
noticed. A cheaper setting would very likely have shipped the first render.

## Agent topology

**A single agent, running serially.** No subagents were spawned at any point.
The system prompt for this session carried an explicit instruction not to call
the Agent tool unless asked, and it was not asked.

This matters for reproducing the result. The interview script and the picture
grammar were designed in one context, which is why the visual system *is* the
argument — the `emph=` field on a line of dialogue drives an ignition wave across
the frame, and MERIDIAN's portrait is a running global-workspace simulation fed
by its own voice. Splitting writing from rendering across parallel agents would
have produced a film whose pictures illustrate its script rather than enact it.

## Parallelism that *was* used

Not agent parallelism — ordinary process parallelism:

- Independent Bash/Read calls batched into single assistant turns (toolchain survey, font probe, contact sheets).
- Film rendering: `multiprocessing.Pool` over **9** workers, each piping raw RGBA frames into its own single-threaded `libx264`, then a concat-demuxer join.
- Long renders run as background tasks while the model kept writing other modules.

## Memory and persistence

- **Persistent memory directory:** available to the harness at `~/.claude/projects/…/memory/`. **Nothing was read from or written to it.** No `MEMORY.md` entries were created. The session neither depended on nor modified cross-session state.
- **Recalled memories:** none surfaced.
- **Scratchpad:** used only for throwaway audio auditions and contact sheets. Nothing there is needed to reproduce the build.
- **Build cache (in-repo, gitignored):** `build/tts/` holds 185 Kokoro takes keyed by `sha1(voice|speed|text)` — 111 MB. This is a real persistence effect on timing: the first synthesis pass took 3 m 48 s, and the three later script edits re-synthesised only the lines that changed, in seconds. A cold clone pays the full cost once.

## Background tasks and waiting

A large share of wall-clock time was spent waiting on renders, not on model
processing — 2,054 s of tool time against 2,996 s of model time, plus a
25-minute gap while the user was away between prompts. `metadata.toml` breaks
all of this out rather than reporting one number.

Two harness behaviours worth recording:

- A `sleep N && <check>` chain is **blocked** by the harness, which directs you to a background task with an `until` loop instead. Correct advice, and the loop is the better pattern.
- A foreground `until` loop is moved to the background at its 600 s timeout, so it reports completion by notification rather than by returning. Waiting on `-s <file>` also fires too early: ffmpeg creates the output file at the start of the mux, and `+faststart` then rewrites it, so the file exists for about a minute before it is readable. Wait on the *process*, not the file.

## Things that were killed and restarted

Two renders were deliberately killed mid-flight (exit code 144). Neither was a
harness failure; both were diagnosed, fixed, and the fixes are in the source.

1. **Attempt 1** — killed at ~1,000/8,520 frames per worker. MERIDIAN's sixteen specialist modules were normalised against a single global scale, so only the two or three lowest bands ever lit. Speech energy falls off steeply with frequency; the fix is per-band normalisation against each band's own 94th percentile, with a 0.75 power curve.
2. **Attempt 2** — killed at ~800/8,520. Reading the generated transcript back surfaced a dialogue-logic bug: an inserted host challenge had separated a question from its answer, so MERIDIAN replied to the host two turns late. Reordering the two blocks also moved the chapter's strongest beat to its close.

Attempt 3 shipped 76,680 frames in **23.0 minutes**. Because both fixes changed
line durations, each restart also required rebuilding the timeline and the mix —
four full audio mixes in total.

## Bugs found by looking, not by reasoning

Every visual defect in this build was caught by rendering a PNG and **reading it
back as an image**. None would have been caught by inspecting the code.

- `✓` and `✕` rendered as tofu boxes in the two scorecard figures: Avenir Next has no glyphs for U+2713/U+2715. Replaced with vector-drawn marks.
- Eight of seventeen figures overlapped their own closing notes. Fixed with a bottom-anchored `bottom_note()` helper and a re-cut figure region, not eight one-off nudges.
- Both oscilloscopes were nearly flat lines. Raw speech samples peak around 0.1, so a full-scale amplitude mapping drew them at a tenth of their intended height.

One non-visual bug of the same family: a `self._smoothed = None` line left at the
end of `Scene.__init__` overwrote the array `_spans()` had just computed.

## Environment specifics that affect reproduction

- **Hardware:** 10-core Apple Silicon Mac, 17.18 GB RAM, macOS 26.6.2 (Darwin 25.6.0). Worker count is passed via `NPROC` and defaults to 9; a different core count changes the render plan but not the output.
- **Fonts are macOS system fonts** resolved through CoreText: **Avenir Next**, **Charter**, **Menlo**. **The picture will not render correctly on Linux without substituting these.** This is the single biggest portability caveat in the repo.
- **This ffmpeg has no soxr.** `aresample=resampler=soxr` fails with "Requested resampling engine is unavailable"; the 24 kHz → 44.1 kHz step uses `swr` with `filter_size=128:cutoff=0.965` instead. Audible ceiling is Kokoro's 12 kHz Nyquist either way.
- **First run downloads** the Kokoro-82M weights (~350 MB) and spaCy's `en_core_web_sm`.
- **Versions:** mise 2026.9.1, uv 0.12.2, Python 3.12.13, ffmpeg 8.1.2, skia-python 144.0.post2, torch 2.14.0, numpy 2.5.2, espeak-ng 1.52.0 (pre-installed on this machine; `misaki` uses it for out-of-dictionary words).
- **Determinism:** the specialist field, the film grain, the figure particle systems and the procedural score all use seeded `numpy.random.default_rng`, so the picture is reproducible. Kokoro synthesis is the one non-seeded component; takes are cached on first generation, which stabilises everything downstream.

## Verification posture

- **Sync is exact by construction, not by alignment.** Caption timing comes from Kokoro's own per-token duration predictions, so the word highlight cannot drift from the audio. No forced aligner is involved.
- **Pronunciation** of every hard proper noun was checked by reading the phoneme output back before committing to 39 minutes of narration.
- **The encode was verified against the renderer**, not assumed: nine frames were extracted from the finished MP4 at the segment-join boundaries and read back as images, and `src/qc.py` re-probes the container for duration, A/V drift (+17 ms), pixel format and chapter markers.
- **Loudness** measured on the final MP4: −16.3 LUFS integrated, −0.9 dBFS peak. The WAV master normalises to −16.0 / −1.2 dBTP; the AAC encode overshoots slightly, which is expected and inaudible.

## Content notes

- **The interview is fiction and says so continuously.** A disclaimer card opens the film, every frame's footer reads `FICTIONAL · SYNTHETIC VOICES`, and the credits repeat it. Dr. Wren Halloway and MERIDIAN are invented; MERIDIAN's answers were written, not sampled from a model being asked about itself.
- **The research is real and credited** — 30 sources on screen and in the transcript.
- **The figures are schematic and labelled as such.** Curve *shapes* follow the canonical published results (the psychometric nonlinearity, the ERP divergence at ~270 ms, the attentional-blink trough); the pixels are not data, and latencies are approximate and task-dependent.
- **The COGITATE 2025 result was verified against the published paper mid-build** rather than recalled, because it is the newest and most contestable claim in the script. It is still compressed, and both camps read it more favourably to themselves than the film does — MERIDIAN says so on screen, in the same breath.
- **The film reaches no verdict on machine consciousness**, deliberately. Its strongest claim is methodological: global workspace theory was built by contrasting conscious and unconscious processing *within* a system already agreed to be conscious, and using that invariant as a between-system criterion asks the method to do something it does not license. The corollary, which MERIDIAN states about itself, is that its own hedging is worth no more than its confidence — both are cheap to produce.

## State at handoff

The repository is **not committed**. All files are untracked on `main` with zero
commits; the standing instruction is to commit only when asked, and it was
offered rather than assumed. `build/` and `out/*.mp4` are gitignored; the film is
657.5 MB and belongs on YouTube, not in the tree.
