# umtool docs umtool judges and drives the things this repo makes videos out of. There are two kinds of work in it today and the tool treats them the same way: as **projects** in a folder tree, each with a state, a set of open decisions, and a build. These sheets live in the repo because they describe code and have to move with it. Notes about *one particular video* belong beside that video, in its own `README.md` — which the project page now renders at the top, with any other `*.md` beside it under **Notes**. `/` is the [dashboard](dashboard.md): what is running, what is waiting on you, where every project stands, which sources nobody has checked, what is built, and whether this machine can build. The song piles are one nav entry, `song ▸`. ## You have been asked for an umtool video Work out which kind you are making first — the rest follows from it. | What you were handed | Kind | Start here | |---|---|---| | A cited sweep report (`*sweep-report.md`) and "make this a video" | `report-video` | [report-video.md](report-video.md), then [authoring.md](authoring.md) | | One archived recording and "make a video from this" | `report-video` | `umtool new --from / [--seed chapters]`, or the editor's "Open in umtool" | | A song's clips and "judge these" | `song` (template `um-song`) | `~/reports/quartering-uh-song/specs/` | | A report with no manifest yet | `sweep-report` | [authoring.md](authoring.md) | The short path from a cited report to a built video: ```sh # 0. scaffold it (writes an EMPTY timeline and a citation checklist), from a # report, a viewer share URL, or a bare /. `--seed chapters` # writes one clip per digest chapter -- the digest's boundaries, not guesses. umtool new --from umtool new --from the-quartering/MpZuPjnF_O8 --site-origin https://jeralyzer.pages.dev --seed chapters umtool doctor # can this machine build at all? # 1. write the timeline (authoring.md — this is the work, and nothing automates it) # 2. is every source still fetchable, and is every citation wired up? umtool check # 3. widen windows to whole sentences (dry first, then apply) node umtool/report-to-video/resolve-windows.mjs ~/reports//video.manifest.json node umtool/report-to-video/resolve-windows.mjs ~/reports//video.manifest.json --write # 4. bench any clip whose edges you are unsure of # /browse//clip/ # 4b. if the manifest has a ledger, rule on every claim in it. `umtool check` # BLOCKS until it is empty, because both totals lie on an unadjudicated one. # /browse//claim/ # 5. build: a fast pass to watch, then the real one. # The BUTTON on the project page runs it -- cancellation, the per-step # timeouts and the process-group kill live in the server's job runner. # `umtool build` prints the same chain if you would rather paste it. umtool build --preset fast # 6. before revising: keep the manifest that made the deliverable umtool snapshot --label v1 # …edit… umtool diff revisions/-v1.manifest.json # 7. post it: the TOC / description / chapters, derived from the build's offsets umtool export --format toc-bbcode ``` **A manifest may describe more than one cut.** `build-video.mjs --variant sourced|full` selects between them; `sourced` is the default and still writes `out/.mp4`, so the button and `umtool build` are unchanged. The working files moved under `out//` while `clips-raw` and `availability.json` stayed at the root. See [report-video.md](report-video.md#one-manifest-two-cuts). **Run step 2 before step 5, always.** It is a few seconds and it catches the two defects that have already shipped in real videos: a manifest with no `siteOrigin` (19 QR codes encoding `undefined/?v=…`) and one pointing at `http://localhost:3000` (QR codes that resolve to nothing on anybody's phone). ## The sheets | Sheet | What it covers | |---|---| | [dashboard.md](dashboard.md) | The front door: what each panel reads, `/api/jobs`, `umtool doctor` | | [projects.md](projects.md) | Kinds vs templates, marker files, ids, how to add a kind | | [folders.md](folders.md) | The walk, `REPORTS_ROOT`, read roots vs write roots | | [browse.md](browse.md) | The project index, the four filters, cards per kind | | [report-video.md](report-video.md) | The manifest as an EDL, the three-stage window model, `lock` | | [clip-bench.md](clip-bench.md) | Editing a clip's window against the waveform and the cues | | [claim-bench.md](claim-bench.md) | Ruling on a `ledger[]` claim against ±90 s of context | | [build.md](build.md) | The four-step chain, presets, cancellation, overwrite | | [decisions.md](decisions.md) | What earns a severity, and how a kind contributes | | [mix-from-a-project.md](mix-from-a-project.md) | Deep-linking a clip into `/mix` | | [index.md](index.md) | The LMDB index, and why the filesystem stays the model | | [cli.md](cli.md) | `umtool ls / show / check / build / window / …` | | [notes.md](notes.md) | Operator notes on articles and videos; `umtool notes`, the agent loop | | [sites.md](sites.md) | `/sites`: every site's articles, their media, workspaces and notes | | [authoring.md](authoring.md) | Writing a manifest from a sweep report | | [e2e.md](e2e.md) | The fixture, the stubs, the global queue | | [quirks.md](quirks.md) | Everything that cost time to find out | ## The rules that outrank convenience 1. **The filesystem is the model.** An index may cache what the tree says; if a value exists *only* in the index, that is a bug. See [index.md](index.md). 2. **The index must not shell out.** Listing projects never probes, never runs ffprobe, never runs yt-dlp. Measuring is what a project page and a job do. 3. **Judgements travel with the tree.** `verdicts.json`, `notes.json` and `video.manifest.json` live *inside* the project directory, so copying the directory copies the decisions. 4. **Never guess at something you cannot read.** A directory whose name does not route, a project two kinds match, a citation with no cue file — each is *reported*, never silently dropped or resolved by picking one.