Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit d45e1cc4cdfda5d3ba5008811da95e0f69cd1f41
parent 7b80437cd056f02d6449a9d75631250d9c1ae8b9
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Thu,  1 Oct 2026 16:57:04 -0400

umtool: docs and changelog for the media root and the cache's new place

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Meditor/CHANGELOG.md | 2++
Mumtool/docs/cli.md | 9+++++++--
Mumtool/docs/folders.md | 26++++++++++++++++++++++++++
3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/editor/CHANGELOG.md b/editor/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## [Unreleased] +- **umtool can keep each report's render folder on a media drive.** With `UMTOOL_MEDIA_DIR` set to a directory on that drive, a report project's `out/` (its fetched windows, segments and finished video) is a link to the same path under that directory: a project's first build makes it there, and `umtool storage move-out <project>` (or `--all`) moves an existing one, copying it, checking the copy and only then leaving the link; `--dry-run` says how much would move, and `umtool storage move-back` brings one home. The manifest, its revisions, notes and sources stay where they are, and nothing in umtool reads a project differently. When the drive is not mounted, a build or source check refuses and says so instead of starting a new folder on the main disk; umtool never creates the media directory itself. `umtool storage` lists where each project's `out/` is. With `UMTOOL_MEDIA_DIR` unset nothing changes. +- **umtool's cache moves to `~/.cache/archilyzer/umtool`** (`$XDG_CACHE_HOME/archilyzer/umtool` when that is set, or `UMTOOL_CACHE_DIR`). It was inside the song project's data folder, so it followed that folder onto whatever drive it was on. Run `umtool index` once after updating to rebuild the project index in its new place; umtool works without it, only slower, and the rest of the cache is remade as it is needed. `umtool doctor` now also shows the reports, media and cache folders, and the old cache folder while it is still there; it can be deleted. - **umtool's report videos keep every clip's sound on its picture.** In a crossfaded cut each clip's audio was placed by the audio's own length and its picture by the picture's, and an encoded clip's audio is routinely a few to twenty milliseconds shorter or longer than its video, so the sound drifted further ahead clip by clip: by the end of a seventeen-clip cut it was a third of a second early, and two seconds on one with title and sources cards. Each clip's sound is now padded or trimmed to exactly its picture's length before the crossfade. Every crossfaded report video changes when it is rebuilt, and is in sync; a hard-cut video was not affected. - **umtool's report videos can wear an on-screen deck: one panel under the footage for the whole cut, with a pip timeline, a title per clip, its source and date, and its QR.** A report manifest whose `render` says `"chrome": { "engine": "hyperframes", "layout": "deck" }` scales the footage into a box above a 190 px panel (both sizes are settings) and draws, over the whole cut, one unlabelled pip per clip on a track that fills as the cut plays, the clip's own title from `onscreen.title`, a subtitle naming the recording and its date (the channel too when the cut spans more than one; `onscreen.subtitle` replaces it), and the clip's QR. At each clip change the marker travels to the next pip and the title, subtitle and QR hand over; over a card the panel slides away and comes back after. The citation header, the corner QR and the section footer are not drawn on such a cut, and chapters take the clip's on-screen title. Every setting (sizes, spacing, date format, what the subtitle names, whether cards keep the panel, the motion's timings) is in `render.chrome.deck` and checked when it is saved; an unknown or out-of-range one is refused with a sentence saying why. The panel is rendered once per cut by HyperFrames (pinned to 0.8.24; `HYPERFRAMES_PKG` or `HYPERFRAMES_BIN` override it) and reused until its text or settings change. `build-video.mjs --chrome-only` redraws it over the built segments without rebuilding or fetching anything, `--no-chrome` builds the framed cut without it, and `--chrome-preview <at> <dur>` renders a short window. In umtool, the report page has an **On-screen** section — a switch, the settings, a table of every entry's title and subtitle with the automatic subtitle as its placeholder and a character counter, a live preview with a scrubber, a true still, **Re-render on-screen** and the built video — and the clip bench has on-screen title and subtitle fields with the panel previewed over the clip. The deck changes nothing, byte for byte, in a cut whose manifest has no `render.chrome`. - **A report cut that wears the on-screen deck can show posts — Bluesky or X statements — as cards over the footage.** A report manifest's `posts` list (each with its platform, handle, date, words and link) is drawn near the end of the clip each post belongs with: the clip whose recording most closely precedes it by date, unless the post names one with `attachTo`; `hide` leaves one out. A clip's posts appear four seconds apart and stack down a column at the frame's top right; as the first appears, the footage eases aside (to 86 % of its box, at the far side) to make room, and the clip's last frame is held, in silence, for 2.5 seconds so the last post can be read; then they all leave together in the change to the next clip, which comes in at the normal size. When the column is full the oldest slide up and out. Each card slides in from the edge of the frame and flares in the deck's accent as it lands; it has an accent rail down its edge and shows the post's date, a platform label ("Bluesky" or "X") beside `@handle`, its words in paragraphs up to seven lines with an ellipsis, and a QR of the post's link, in the deck's colours and faces. The hold and the move are made where the cut is joined, not in a clip, so `--chrome-only` changes them without rebuilding one; chapters and the deck's timing count the hold. The timing, the hold (`hold`, 0 turns it off), the move (`shift`: its scale and seconds, or `false`), the column's side, width and inset, the QR size and the line limit are settings under `render.chrome.deck.posts`, and a bad post or setting is refused with a sentence before a build fetches anything. Only the seconds the cards are up are rendered, one short sequence per clip, cached like the deck; `--chrome-only`, `--chrome-preview` and a hard-cut cut lay them as they lay the deck, and `--no-chrome` draws neither — though it still holds and moves the footage, which are part of the cut rather than the chrome. A first post that appears inside the hold still moves the footage, and a hold is a whole number of frames. `posts` changes nothing in a cut that has none, and without the deck it is not drawn at all. diff --git a/umtool/docs/cli.md b/umtool/docs/cli.md @@ -25,7 +25,9 @@ decisions inbox cannot disagree about what is wrong with one. | `build <project> [--preset preview\|fast\|final] [--only ID]` | **prints** the chain | | `index [--rebuild] [--prune] [--since MS] [--json]` | the cache | | `new <slug> [--from <report.md>\|<share URL>\|<channel>/<id>] [--site-origin URL] [--seed chapters]` | scaffold | -| `doctor [--json]` | which tools are on this machine; **exit 1** if the report pipeline is missing one | +| `doctor [--json]` | which tools are on this machine and where the roots are; **exit 1** if the report pipeline is missing one, or `UMTOOL_MEDIA_DIR` is set and not there | +| `storage [<project>] [--json]` | where each project's `out/` lives: dir, link, DANGLING, none | +| `storage move-out\|move-back <project>\|--all [--dry-run] [--json]` | `out/` to the media root (a link left behind) and back — copied, mirrored, verified first; run when nothing is building | | `snapshot <project> [--label L]` | copy the manifest into `revisions/` | | `diff <project> <snapshot>` | added / removed / moved / window / retyped, by entry id | | `export <project> --format toc-bbcode\|toc-markdown\|description\|chapters [--variant V]` | the posting artifacts, from the build's chapter offsets | @@ -36,7 +38,8 @@ projects answering to one name is reported, never resolved by picking one. ## Environment -`REPORTS_DIR`, `SONG_REPORTS_DIR`, `SONG_DIR`, `CHANNELS_DIR`, `UMTOOL_INDEX_DIR` +`REPORTS_DIR`, `SONG_REPORTS_DIR`, `SONG_DIR`, `CHANNELS_DIR`, `UMTOOL_INDEX_DIR`, +`UMTOOL_CACHE_DIR`, `UMTOOL_MEDIA_DIR` — which is how it is tested against the e2e fixture. The path defaults (`lib/paths.mjs`, `song/paths.mjs`): @@ -45,6 +48,8 @@ projects answering to one name is reported, never resolved by picking one. | `SONG_DIR` | `~/.local/share/archilyzer/song`, through its realpath — a symlink there is the supported way to keep the data where it is | | `SONG_REPORTS_DIR` | `~/reports/quartering-uh-song` | | `REPORTS_DIR` | `~/reports` (the parent of `SONG_REPORTS_DIR` when that is set) | +| `UMTOOL_MEDIA_DIR` | unset = `REPORTS_DIR`: `out/` stays in each project. Set, each project's `out` is a link to the same path under it ([folders.md](folders.md)) | +| `UMTOOL_CACHE_DIR` | `$XDG_CACHE_HOME/archilyzer/umtool`, else `~/.cache/archilyzer/umtool` (it was `<SONG_DIR>/.cache/umtool`) | | `CHANNELS_DIR` | `$TRANSCRIPTS_DIR/channels`, else the checkout's `transcripts/channels` (found by walking up from the cwd to `pnpm-workspace.yaml`) | | `VIDEO_ROOT` (`song/spec.mjs`, `song/video-dir.mjs`) | `~/reports/quartering-uh-song/videos` | diff --git a/umtool/docs/folders.md b/umtool/docs/folders.md @@ -9,6 +9,32 @@ environment variable. `SONG_REPORTS` (the um-song deliverables) keeps its exact previous default and is now a *subdirectory* of `REPORTS_ROOT` rather than the widest root there is. +## `MEDIA_ROOT` + +Where a project's render scratch lives (release 17). `UMTOOL_MEDIA_DIR`, else +`REPORTS_ROOT` — and then nothing is different: `out/` is a directory in the +project. Set, a project's `out` is an absolute link to the same project-relative +path under it (`<REPORTS_ROOT>/a/b/out -> <MEDIA_ROOT>/a/b/out`), made by the +first writer (`lib/report/storage.mjs` `ensureOutDir`) or by +`umtool storage move-out`. The manifest, `revisions/`, notes and sources stay put. + +- It must already exist, outside `REPORTS_ROOT`: umtool never creates it, so an + unmounted drive is a loud refusal ("is the media drive mounted?"), never a new + tree on the main disk. A dangling `out` link refuses the same way. +- It is a READ root (a realpath through the link lands under it), never a write root. +- The walk skips `out`, `clips` and `share-*`, so it never stats a link into a + drive that is not there. +- `umtool storage` lists every project's `out` (dir, link, DANGLING, none); + `umtool doctor` names the roots and exits 1 when this one is set and missing. + +## `CACHE_DIR` + +`UMTOOL_CACHE_DIR`, else `$XDG_CACHE_HOME/archilyzer/umtool`, else +`~/.cache/archilyzer/umtool`: the project index, posters, the mix bench's +analyses, sliced audio. Derived, safe to delete. Until release 17 it was +`<SONG_DIR>/.cache/umtool`; `umtool doctor` reports a leftover one, and the first +`umtool index` rebuilds the index in the new place. + ## The walk Two rules do almost all the work.