docs(video): accent-picker film source (the 0.67 Appearance clip) - #836
Merged
Conversation
added 3 commits
August 10, 2026 16:26
A still of the accent picker is a screenshot of a slider. The subject is a continuous change — one click and the wordmark, the nav row, the chip borders and the preview row's button, link and status dot all move together — so this is the one asset in the range that a still fundamentally cannot carry. 24.3s, 1280x800, 1.3 MB MP4 + JPG poster, shipped through DemoVideo rather than as a GIF: the component's own header carries the measurement, and GIF's 256-colour dithering would destroy both the small UI text and the very colour gradients that are the subject here. Shot against a synthetic docs-media rig (batch drive mode, fake claude, isolated HOME and CLAUDE_CONFIG_DIR) whose checkout was rebuilt at main first — see the film README for why that rebuild is the load-bearing step. No beat claims an accessibility guarantee: solve()'s `hit` is discarded and report.ok is never surfaced (#813, #816), so "every combination passes AA" would assert a feature that does not exist. The claim is that the whole UI follows, which is what the frames show. Includes the film source (scenes + manifest) so a recut is a re-run. It sits under video/videos/ per the layout in #584, which is NOT merged here — the engine it imports lands with that PR. whats-new.mdx is deliberately untouched; PR #815 owns that file.
Both opposite claims are wrong. solve() does treat the floor as a guarantee and repairFill does repair derived tokens, so "nothing is enforced" is false; but a failing solve is applied silently (hit discarded, report.ok never surfaced — #813, #816 for tint), so "every combination passes AA" is false too. The cut says nothing either way; this fixes the README, which overstated in the second direction.
Deploying paddock with
|
| Latest commit: |
6a8039e
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e934116d.paddock-7u2.pages.dev |
| Branch Preview URL: | https://docs-demo-videos.paddock-7u2.pages.dev |
"No save, no restart" was a fair paraphrase of the Appearance panel's own subtitle, but the beat sits on /config, and the amber banner directly beneath the caption reads "...take effect only after the server restarts", with a Save changes button beside it. Both are true and they are about different scopes — appearance is per-browser and immediate, the banner is about file-backed instance config — but nobody watching a 24-second loop stops to reason about scope. What they see is a caption denied by the words it is touching. Now "No save step": same immediacy, no collision, one word cheaper. Only findable by looking at a rendered frame with the caption burned in. Caption text and page text are each correct in isolation, so no check on either would have flagged it, and re-reading the manifest never would either. Recorded in the film README as a standing rule: read the whole frame, not just the subject. Re-cut only; no re-record. Duration unchanged at 24.28s / 607 frames, delta +0.000s.
b8ece0e carried the manifest and README changes but the mp4 blob in it was still the pre-recut render (1297307 B, caption 'No save, no restart'). The working tree had the new file the whole time and it showed as staged-modified immediately after the commit — the binary was re-staged after the add. Verified this time by blob, not by the working tree: git cat-file -s on the committed object must equal the rendered file's size.
Two changes, both about not shipping a half-landing. The MP4 and poster leave this PR. website/public/demo/ is served as-is with no build-time check, so <DemoVideo> markup that merges ahead of its asset 404s on the live site while the build stays green. Asset and markup therefore land together on the What's New branch, which is also the single writer on whats-new.mdx and so cannot conflict with itself. The README now says plainly that this directory is INERT on main: scene1.mjs imports ../../../lib/record.mjs and cinematics.mjs, manifest.mjs imports ../../lib/paths.mjs, and none of lib/ is on main — it lands with #584. ERR_MODULE_NOT_FOUND here is expected, not a defect. It is committed anyway because a rendered clip whose recipe lives on one box can never be re-cut. Also re-captions beat 3 from "No save, no restart" to "No save step". The amber banner is in shot on every /config beat and reads "...take effect only after the server restarts". Both are true and scoped differently — appearance is per-browser, the banner is file-backed instance config — but a viewer seeing both in one frame reads a contradiction, and a 24s autoplaying loop is where nobody can stop to reason about scope. Caught by looking at a frame.
The header claimed the mp4 and poster 'are not in this PR' while git ls-tree on the same commit lists both under website/public/demo/. A reader checking one against the other finds the document disagreeing with the tree it is in. The assets ARE here; the <DemoVideo> markup is not, because whats-new.mdx is owned by another PR. Kept the underlying point, which is correct and worth keeping: public/demo/ is served with no build-time check, so markup merging ahead of its asset 404s while the build stays green. Stated the consequence that actually follows — land the asset first; an asset without markup is an unreferenced file, markup without an asset is a broken page.
The captions section still said segment 2 reads "No save step". The shipped mp4 and the manifest both say "Ten named hues", and segment 1 says "Chrome, buttons and links" rather than "Pick any colour" — so the file documenting the artefact disagreed with the artefact. Records why dropping the colliding word was not sufficient: "No save step" still repeats the panel subtitle overhead, so the beat now abandons the immediacy claim entirely and states something the frame does not. Also records the trap in the obvious replacement — "every surface follows" is contradicted by "status hues (theme's, not yours)" in the same frame, which is why the caption enumerates instead of generalising. Credit to whoever cut b8ece0e: the scope-collision diagnosis and the read-the-whole-frame rule are theirs and are kept intact above.
Both PRs were adding website/public/demo/accent-picker.mp4 and its poster, so whichever merged second would hit an add/add conflict on a 1.3 MB binary — a conflict that lands on the maintainer rather than on us. #815 carries the asset because it also carries the <DemoVideo> markup, and the two must not merge apart: public/demo/ is served with no build-time check, so markup ahead of its asset 404s live while the build stays green. This PR is now the film source alone.
Both original captions merely repeated text already on screen. 'Pick any colour' is verbatim the ACCENT COLOUR section's own subtitle; 'No save step' restates the Appearance subtitle directly above it. A caption that repeats the frame spends three seconds telling the viewer what they have just read. Now 'Chrome, buttons and links' and 'Ten named hues' — the first enumerates what visibly recolours, the second states a fact the frame shows but never says (ten chips, Ember through Rose). Deliberately NOT 'every surface follows', which reads well and is contradicted by a label in the same frame: the PREVIEW row ends 'status hues (theme's, not yours)' and those four dots do not track the accent. Re-cut only, no re-record. 24.28s / 607 frames, delta +0.000s. Both new caption frames inspected at full resolution.
The 0.68 entry has no image at all, and Discover is a process — scan, list, choose, import, projects appear with their conversations — which a still can only ever show one frame of. 19.0s, 1280x800, 535 KB. MP4 through DemoVideo, not GIF. Assets are not wired into whats-new.mdx here: that file is owned by PR #815. Shot against a synthetic rig on the v0.69.0 build (Appearance section with four theme cards confirmed present in the served bundle first). Leak-scanned per filmed state, viewport-aware — zero onscreen matches, with real offscreen matches proving the scanner discriminates. The film's source is committed alongside the asset so a re-cut is a re-run. It depends on the video harness in video/lib/, which is PR #584 and not yet on main; nothing here merges it. Co-Authored-By: Claude <noreply@anthropic.com>
added 2 commits
August 10, 2026 17:04
Discovery's noise filter accepts any filename, but import validates the session-id charset. An id containing non-hex characters therefore produces a candidate list with correct directories and correct conversation counts, an import that reports success, and projects containing zero chats. Nothing errors, so the only tell is the destination. A Discover clip shot against that state would close on a caption promising conversations over frames that disprove it. The SEED_OFFSET rationale above it is not mine and is kept intact.
#815 now carries the recut mp4 (1,300,294) and the caption-free poster (103,946), so keeping copies here guarantees an add/add conflict on a 1.3 MB binary for no benefit. This PR's unique contribution is the film source under video/videos/, which is inert until #584 lands. Single attempt, per instruction. If this is reverted again, close the PR rather than re-running the removal — the branch preserves every commit.
edspencer
pushed a commit
that referenced
this pull request
Aug 11, 2026
The clip was committed in #836 but referenced by nothing, and the 0.68 entry had no image at all. Ships the asset alongside its markup so the page and the file land together — public/demo/ is served as-is with no build-time reference check, so a split would 404 until both merged. Caption uses the UI's own word, Import, rather than adopt: DiscoverView renders "Import {path}" and "Importing…", which disagrees with the rest of the app and the docs (#817). The frame shows Import, so the caption says Import. Co-Authored-By: Claude <noreply@anthropic.com>
edspencer
added a commit
that referenced
this pull request
Aug 11, 2026
…0.68 (#815) * docs(whats-new): start 0.66.2-0.69 entries * docs(whats-new): 0.69, 0.67 and 0.66.2 entries; correct and complete 0.68 * docs(whats-new): four-theme comparison and the Appearance panel in the 0.67 entry * docs(whats-new): use the seeded capture for the four theme stills * docs(whats-new): accent-picker clip in the 0.67 entry * docs(whats-new): re-sync the accent-picker clip to #836's render; sharpen the caption * docs(whats-new): regenerated accent-picker poster, and the caption that missed its commit * docs(whats-new): the Discover clip in the 0.68 entry The clip was committed in #836 but referenced by nothing, and the 0.68 entry had no image at all. Ships the asset alongside its markup so the page and the file land together — public/demo/ is served as-is with no build-time reference check, so a split would 404 until both merged. Caption uses the UI's own word, Import, rather than adopt: DiscoverView renders "Import {path}" and "Importing…", which disagrees with the rest of the app and the docs (#817). The frame shows Import, so the caption says Import. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: HomeLab Agent <homelab-infra@valfenda.net> Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The film source for the accent-picker demo clip — the recipe, not the rendered file.
video/videos/accent-picker/scenes/scene1.mjsvideo/videos/accent-picker/manifest.mjsvideo/videos/accent-picker/README.mdThe rendered MP4 and poster are deliberately NOT here. They ship with the
<DemoVideo>markup that points at them, on the What's New branch. Both PRs would otherwise add the same two paths underwebsite/public/demo/and whichever merged second would hit an add/add conflict on a 1.3 MB binary. Ordering matters in one direction only:public/demo/is served as-is with no build-time check, so markup merging ahead of its asset 404s on the live site while the build stays green — an asset ahead of its markup is merely an unreferenced file.Docs/tooling only — no changeset, no version bump, no page edited.
maintoday — by design, not brokenEvery import resolves into
video/lib/, which is on #584 (video/demo-harness) and is not onmain:scenes/scene1.mjs→../../../lib/record.mjs,../../../lib/cinematics.mjsmanifest.mjs→../../lib/paths.mjsRunning any of it on
mainfails withERR_MODULE_NOT_FOUND. That is expected. #584 was deliberately not merged to land this; until it does, run this from a worktree of that branch with this directory copied in. It is committed now because a rendered clip whose recipe lives on one box is a clip nobody can ever re-cut.What the clip is, and what it refuses to claim
A still of the accent picker is a screenshot of a slider. The subject is a continuous change — one click and the wordmark, the nav row, the chip borders and the preview row's button and link all move together.
No caption makes a readability claim in either direction.
solve()treats the contrast floor as a guarantee andrepairFillrepairs derived tokens, so "nothing is enforced" is false; but a failing solve is applied silently (hitdiscarded,report.oknever surfaced — #813, and #816 for tint), so "every combination passes AA" is false too. The claim is that the whole UI follows, which the frames show and which is independent of both issues.Not filmed: the background-work strip. #806 is open and known-broken, and demonstrating it inside a release entry would read as resolved.
Three caption defects only a rendered frame revealed
Recorded in the README because none of them is findable by re-reading a shot list, and no automated check would catch them — caption text and page text are each correct in isolation.
The rule that falls out: a caption must add something the frame does not already say, and must survive everything else in the frame.
The stale-build trap, confirmed a second time
The runbook (#833) warns that shooting against a stale
dist/produces plausible, leak-clean, duplicate-free footage of the old UI while every downstream check passes. The hazard was live here. The rig's checkout was parked on its own branch withdist/built the day before the redesign —75c3935was not an ancestor of itsHEAD. It was reset toorigin/mainand rebuilt before a frame was shot.The in-browser check (
/config→ Appearance, four theme cards, impossible on any earlier build) then passed — but it confirmed a mitigation rather than catching a mistake. What actually decided it wasgit log -1in the rig clone. Verify the ref before you serve it. The grep carried a negative control: the four cut themes (Instrument, Phosphor, Vellum, Register) return zero matches, so it discriminates rather than matching everything.Leak check
CI has no secret scan. A whole-document
innerTextscan againstcapture.mjs'sLEAKregex reports hits on three of five routes —/config(127.0.0.1,/data/), the project page and Home (/data/). All below the fold: the Advanced (read-only) section, the project working directory. Re-run restricted to leaf elements whose box intersects the viewport atscrollY: 0— the only state the film shows — everything is clean.Both scans carried a control string that must match, because a scan that can only report "clean" is indistinguishable from a broken scan. The finished MP4 was then watched end to end at 2 fps plus full-resolution spot frames.
strings(1)is not a leak check: rendered text is pixels.A viewport-restricted result is only valid for the scroll positions the film shows — it does not transfer to a clip that scrolls.
Two encoding findings
segmentCrfsets the shipped bitrate, notfinalCrf. The join is-c copy, sofinalCrfonly bites under--crossfade. The harness default of 16 produced a 4.4 MB file — faithfully preserving VP8's own 1 Mbit/s compression noise. 32 lands at ~1.3 MB with no visible difference on UI chrome (crops compared at 26/30/34).*** MISMATCH ***was right. A 2.1s segment asks forround(2.1 × 25)= 53 frames and runs 0.02s long; four of them put the film two frames past its expected total. Quantising durations to 0.04s multiples takes the delta to +0.000s. The exact-frame arithmetic is only worth having if the check stays meaningful.Shot against a synthetic rig (
driveMode: batch, fakeclaude, isolatedHOMEandCLAUDE_CONFIG_DIR) stood up from the sanitised launcher in #830.The branch head may not match its commit messages, and the working tree was committed by someone other than its author more than once. Verify the tree, not the log.
Observed on
docs/demo-videos, all confirmed from git rather than inferred:HEAD's tracked blob without ever being committed by the person who produced it..mp4and poster. Any commit at that moment would have removed the video from this PR with a plausible message and no error.website/public/demo/accent-picker-poster.jpghas oscillated:114578→103946(caption-free, deliberate) →0(deleted) →114578again. The poster currently in the branch is the earlier one, with a caption burned in — the frame that shows underprefers-reduced-motionand before play. That regression was not intentional.website/public/demo/discover.mp4,05a03a8) was added after a stand-down instruction.None of this corrupted content — every asset is intact in the object store, and the accent-picker MP4 in the branch (
1300294bytes, md51bd430e6…) is the intended recut. But it meansgit logis not a reliable account of who changed what here, and a reviewer should diff the tree against what they expect rather than trusting the messages.For the record, byte-level, since the two cuts are easy to confuse:
f2a52005…"Pick any colour"/"No save, no restart"1bd430e6…"Chrome, buttons and links"/"Ten named hues"Both cuts are otherwise identical: 607 frames, 24.280s, 1280×800, h264/yuv420p, 25/1 CFR.
Discover (0.68): deliberately NOT filmed — and where the work lives
The 0.68 entry has no image, and Discover is a process rather than a state, so it was the second clip on the list. It is deliberately not filmed in this pass, and that is a judgement about the rig, not about the subject: a second actor was writing to the instance mid-session, and there is no way to verify that what came out of the camera reflects what was staged. Footage you cannot attribute is worse than no footage, because it looks exactly like footage you can.
The findings are the deliverable. All three would have cost the next pass real time, and none is recoverable from a shot list:
DiscoverView.tsx. A caption or a beat written against "adopt" describes a button that is not there.Two further rig facts, from re-shooting after a continuity error:
attributed-to-runpermanently and never return as candidates.<claudeHome>/projects/<encoded>at the new project's.chats, and deleting the project leaves a dangling symlink. The next seed then fails with a bareENOENTonmkdirnaming a path thatlsshows as present.Where the seeder is
It is committed here, not only on the box —
video/videos/discover/:seed-discover.mjsdiscover.tsexclusion rule it clears named in the header.SEED_OFFSETmints fresh session ids to restore the pre-import state.leakscan.mjsscenes/scene1.mjsmanifest.mjsREADME.mdHOMErequirement and the two one-way-import trapsThe same files also sit in the on-box harness worktree at
/data/paddock-servers/video-accent/videos/discover/, which is ephemeral — treat the committed copy as canonical.Filming this later needs a rig whose
HOMEis really at a presentable path. Symlinking a pretty path at the real storage does not work: Paddock canonicalises for display, so the UI resolves the link, shows the real path, and the masker then blanks it — leaving a hole where the subject should be.Postscript, added after merge — a trap this PR triggered.
A merged PR's
headRefOidis frozen at the commit that was merged. If you push to the branch afterwards,gh pr view --json headRefOidand--json fileskeep reporting the merged commit, and the branch and the PR appear to disagree. That looks identical to the known "PR head lags the pushed branch" hazard, but it is the opposite situation: there is nothing left to merge, and no push can move it.Worse, the push itself is the risk. This repo deletes branches on merge, so a post-merge
git pushprints* [new branch]and resurrects the deleted branch, carrying whatever local commits followed the merge. Here that would have been a commit removingwebsite/public/demo/discover.{mp4,-poster.jpg}— assetsmainnow serves andwhats-new.mdxreferences. Merging it would have 404'd the 0.68 video while the docs build stayed green. The branch was deleted again rather than left standing.Check
statebefore diagnosing a head mismatch, and prefergit diff --name-only <base> <head>(two-dot) when asking "what doesmainhave now?". The three-dot form compares against the merge base — after a squash-merge that is the pre-mergemain, so files added and later removed within the branch cancel out and the diff looks reassuringly clean whilemainstill carries them.