Skip to content

Fix the README architecture diagram and rebuild the demo video with narration - #1

Merged
yablokolabs merged 5 commits into
mainfrom
fix-arch-diagram-and-demo-video
Oct 7, 2026
Merged

yablokolabs merged 5 commits into
mainfrom
fix-arch-diagram-and-demo-video

Conversation

@yablokolabs

@yablokolabs yablokolabs commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Architecture diagram. The README image was cropped on the right and had labels outside their boxes. It is redrawn from a tracked source (assets/arch-diagram.svg, rendered by make diagram). Each pipeline stage has its partner at the same height, so every connector is one straight line. Six layout tests measure each label with rsvg-convert, the renderer that makes the PNG.
  • Demo video. demo/mender-demo.mp4 showed Segment error: intro — el is not defined for its whole length and had no audio. The nine scenes are rebuilt (demo/videos/), use a Mender style made from the logo colours, and show values from the 2026-10-06 eval run of low-memory-limit. The video now has a British English narration (ElevenLabs, voice Lily) and is 93.9 s long.
  • Repeatable build. videowright 0.1.1 does not publish two modules that its own entry files import, so a clean install could not render; a postinstall script writes them. generate.sh and scripts/sync_audio.py rebuild the narration and the scene timing. Browser tests drive the real player, because videowright render exits 0 even when a scene throws.

Root causes

Defect Cause
Diagram cropped, labels overflow Label widths were estimated for fonts that are not installed; the renderer fell back to a wider font. No SVG source was tracked, so nothing could be measured.
Video is an error screen Every segment used el inside play(), where it does not exist. The render reports success anyway.
Reveals would not show One timing entry for 3 to 6 beats, and CSS transitions, which the render clock does not drive.
Video cannot be rebuilt A hand patch in node_modules that was not tracked.

Notes for the reviewer

  • Listen to the narration. It was checked by duration, loudness (-16 LUFS) and the words that the provider reports, not by ear.
  • The voice is a built-in ElevenLabs voice. A library voice needs a paid plan; then VOICE_ID=... generate.sh, python3 scripts/sync_audio.py, npm test and a new render are enough.
  • The "25 s" in the video is the pipeline time of that run (triage to prepared PR). It does not include fault injection, the settle wait or evidence collection.
  • CI now installs librsvg2-bin and fonts-liberation for the diagram tests. The browser tests of the video run locally (npm test in demo/videos), not in CI.
  • The OnMe style is removed from demo/videos/styles/; nothing used it.

Test Plan

  • make test: ruff, ruff format, mypy, pytest (84 tests, 6 of them for the diagram)
  • demo/videos: npx tsc --noEmit, npx biome check, npm test (11 browser tests)
  • npm ci from an empty node_modules, then a render: works with 0 npm audit findings
  • Frames of the final MP4 checked by eye at ten narration cues
  • A person listens to the narration once
  • A person looks at the diagram in the rendered README

… tests

The PNG in the README was cropped on the right and several labels ran out of
their boxes. The label widths had been estimated for fonts that are not
installed, so the renderer fell back to a wider font, and no SVG source was
tracked to measure.

assets/arch-diagram.svg is now the source and pins Liberation Sans. The six
pipeline stages go top to bottom, and each partner (cluster, Tavily, sandbox,
model tiers, GitHub) is at the height of the stage that uses it, so every
connector is one straight line. The accent colour is the green of the logo.

tests/test_arch_diagram.py measures every label with rsvg-convert and fails
when a label leaves its box, two labels overlap, two boxes partly overlap, a
connector crosses a box or a label, or anything is outside the canvas.
make diagram renders the PNG. CI installs librsvg2-bin and fonts-liberation so
that the test runs there.
…narration

The committed video showed "Segment error: intro - el is not defined" for its
whole length and had no audio. Every segment used `el` inside play(), where it
does not exist, declared one timing entry for three to six beats, animated with
CSS transitions that the render clock does not drive, and loaded the logo from
a URL that returns 404.

The nine segments are rewritten in demo/videos/segments (the documented place;
the symlink is gone). They keep the host element in a module variable, reveal
beats with element.animate(), and show data from the committed eval results for
the low-memory-limit case in place of the invented values. A new `mender` style
uses the logo colours and locally served fonts, and replaces the OnMe style.

The narration is one ElevenLabs file (voice Lily, British English). Timing in
audio/tracks/v1/track.ts is computed from its word timestamps and snapped to
60 fps frames; each segment carries the same values.

videowright 0.1.1 does not publish two modules that its own entry files import,
so a clean install could not render. scripts/apply-videowright-fix.mjs writes
them after each install.

tests/video.spec.ts drives the real player in a browser, because the render
exits 0 even when a segment throws. The rendered MP4 is not part of this commit;
the test that checks it fails until the 1080p render is committed.
demo/mender-demo.mp4 replaces the file that showed a segment error for its whole
length and had no audio stream. It is the 60 fps, 1920x1080 render of
demo/videos/videos/demo with audio track v1 (voice Lily, normalised to
-16 LUFS), 96.4 seconds long. All 11 browser tests pass against it, and frames
from the file were checked by eye at ten narration cues.

PLAN.md now names the mender style and the narration, points to the generated
script, and has a log entry for this rebuild. voiceover_script/script.md is
generated from the segments by `videowright script --write`.
Layout only: Biome is the formatter that the videowright project template
installs, and its default layout differs from the hand-written one in eleven
files. No behaviour changes; the type check and the 11 browser tests pass.
…, render again

An independent review compared each value in the video with the eval run and
found four claims that said more than the run shows. They are corrected:

- "25 s from a broken service" was the pipeline time (triage to prepared PR),
  which does not include fault injection, the settle wait or evidence
  collection. The outro and the narration now say "from evidence".
- "15 sources" were 15 search results, 14 of them distinct.
- The sandbox command now marks the flags that it leaves out.
- The nano prompt of 11,020 tokens is labelled as the prompt, and the triage
  scene shows the four signals and three suspects that the run returned.

The narration is generated again with three corrected lines (93.5 s), and
demo/mender-demo.mp4 is the new render (93.9 s).

scripts/sync_audio.py now builds the audio track and writes the scene timing to
the track and the segments, so a new voice needs no hand-copied numbers.
generate.sh writes to temporary files first, so a refused or empty API response
cannot replace the audio of the last good run.

The nine segments share one defineScene() helper in place of nine copies of the
same mount, play and unmount code.

Diagram: the ledger label says "cost per model tier" (Tavily has no cost). The
layout tests also check that the PNG has the shape of the SVG canvas, fail in
place of a skip when CI has no renderer, and read connectors only from <line>
elements. The README says where the video source is and how to render it.
@yablokolabs
yablokolabs merged commit d6d280d into main Oct 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant