# HIGH LVL Clipper — agent handoff

Personal AI clipping studio: stdlib-Python server + single-file dashboard, three render
engines (ffmpeg house cuts + luxury/masked grades, Remotion motion comps, HyperFrames),
Inspiration (video → rebuild blueprint), and a locked-down public deployment on the Mac
Mini at **https://clipper.highlvl.ai**. House rules live in `CLAUDE.md` — read both.

---

## Harness (read this first)

State lives in files, not chat history. Route through them every session:

- **`feature_list.json`** — the one source of truth for what exists, its `status`, and `dependencies`. Read it before touching anything.
- **`progress.md`** — running log: Current State, What changed, Next step. Append, don't rewrite.
- **`session-handoff.md`** — Blockers, Files touched, and the Next Session step when you stop.

## Startup Workflow

Before writing code:
1. `./init.sh` — the fail-fast verification gate must be green.
2. Read the top entry of `progress.md` (Current State).
3. Pick the feature from `feature_list.json` (respect `dependencies` and `blocked`).

**One feature at a time.** Never have two features in flight; finish or hand off before
switching. If a bug outside the feature blocks you, log it in `session-handoff.md` instead
of chasing it.

**Definition of Done:** `./init.sh` passes AND the change is exercised for real — a real
render probed with ffprobe AND frames extracted and visually inspected (a green exit code
is not proof a grade looks right). Paste the command + output as Verification Evidence
into `progress.md`, set the feature status, leave the tree clean.
Tests: none yet — **F13 adds pytest**; until it lands, `./init.sh` + the real-render
protocol above is the only gate. Do not claim done without it.

**End of session (before ending):** update `session-handoff.md` — blockers, files touched,
and the Recommended Next Step — and append a progress.md entry if anything changed.

## Model routing (SOP — owner directive)

**Fable 5 orchestrates; Opus/Sonnet execute.** Fable runs point: writes the spec, launches
executor agents, and independently verifies their output from raw artifacts (never trust
executor prose — re-probe files, re-extract frames, re-run gates). Route execution by
complexity: **Sonnet** for mechanical/well-specified work (renames, wiring a defined
endpoint, doc updates); **Opus** for multi-file features, debugging, or anything touching
render pipelines. Executor agents get self-contained briefs (paths, contracts, verify
steps, return-JSON shape) and never git-commit — the orchestrator reviews, verifies, and
commits. Serialize agents that touch the same files (`server.py`/`index.html` are the
usual collision points).

## Scope — stay in scope

**In scope:** everything under `video-studio/` (dashboard, tools, atomizer, compositions,
ops) plus the deployed copy on the Mini (via `ops/deploy-mini.sh` only).
**Out of scope from here:** `content-os/` and the org engine (own harnesses), the vendored
`tools/video-use` and `tools/hyperframes` internals (upstream-syncable — never edit),
anything that LIVE-POSTS to a real account (dry-run is the default; live sends need the
owner's explicit go in the session), and Mini system config beyond the studio LaunchAgents.

## The map

| Piece | Where |
|---|---|
| Server (routes, jobs, STYLES registry) | `dashboard/server.py` |
| Dashboard UI (single file, vanilla JS) | `dashboard/index.html` |
| Luxury + masked grades (LUTs, Vision matte) | `tools/luxury_render.py`, `tools/personmatte.swift`, `tools/luts/` |
| Remotion motion comps | `compositions/motion/src/`, `tools/motion_render.py` |
| HyperFrames engine | `compositions/hyperframes/`, `tools/hyperframes_render.py` |
| Engine router rules | `atomizer/director.py` (`route_engine`) |
| Inspiration pipeline | `dashboard/inspiration.py` |
| Ops (deploy, monitor, sync) | `ops/` |

## Iron rules (learned the hard way — see progress.md history)

1. **Deploy ONLY via `./ops/deploy-mini.sh`** — never raw rsync to the Mini. It versions,
   snapshots, health-gates, and auto-rolls-back.
2. **Never put runtime data under `~/Desktop` or `~/Documents`** — iCloud evicts files
   under disk pressure and dataless reads BLOCK FOREVER. Library lives in `~/Movies/HLC-clips`
   locally, `~/video-studio/library` on the Mini (`STUDIO_OUT`). Detect dataless: `st_blocks == 0`.
3. **Never depend on a single browser API for core UX** — IntersectionObserver callbacks can
   silently never fire. Gallery uses poster thumbs + geometry-eager load + observer + scroll fallback.
4. **The public link runs `SHARED_MODE=1`** — visitors must never be able to post/delete/
   download-to-the-box. Any new POST route: decide its SHARED_MODE stance explicitly.
5. **Two studios, one library** — laptop renders sync to the Mini every 10 min
   (`ops/sync-library.sh`). Don't invent a second sync path.
6. **Verify renders by LOOKING at frames** (extract with ffmpeg, view them), not just exit
   codes — washed-out/broken grades return 0 too.
7. **ffprobe is `FFPROBE`** in luxury_render.py — never `FF.replace("ffmpeg","ffprobe")`
   (it corrupts the ffmpeg-full path; this bug silently forced 24fps for weeks).
8. Renders are subprocesses; the server must stay dumb-fast — nothing blocking on the
   request path (no ffprobe/network in GET handlers).

## Deployed state

- Mini serves the public link via LaunchAgents `com.19keys.clipper-{studio,tunnel}` +
  cloudflared named tunnel `clipper`. Monitor: `com.19keys.clipper-monitor` (5 min,
  self-heals, Telegrams on state change).
- Masked (Vision-matte) grades need `swiftc` — absent on the Mini, so they gracefully
  fall back to `lux2-*` there until Xcode CLT is installed (owner action).
