Ruinan - #133
Merged
Merged
Ruinan#133
Conversation
The MP4 now closes the story the terminal starts. After the result card, the run types its real serve command and output line, then a browser window cross-fades in and scrolls a full-page screenshot of the report's overview — a guided tour of what the run produced. Discrete UI shots (the M1-M5 stage evidence pages) follow in the same browser chrome, cross-faded, so the viewer clicks through the pipeline's stages. - timeline.build(): optional serve segment (typed command + output + hold) appended after the card; the SVG renderer passes nothing, so the README's inline animation is byte-for-byte unchanged - render_mp4.py: browser-window chrome (same frame/lights as the terminal, URL field instead of a heading), eased full-page scroll with adaptive duration, cross-fades between acts, card fade-out when the serve prompt needs its rows back on long logs - shoot_ui: capture the report UI with the playwright-core the web build already carries plus a system Chrome — overview full-page, any stage's evidence page (--stage M1..M5), viewport or fullPage, theme pinned to dark - README: the new pipeline and flags Nothing simulated: the serve command and its output are the real CLI's, and every screenshot is this run's own report.
shoot_ui gains --full: with --view evidence --stage CODE, after the stage-list click it also clicks the .depth-switch "Full record" tab, so the screenshot is what the reader sees after pressing "See everything this step recorded" — the structured artifact behind each stage's summary brief. Used by the MP4 to render every page of the report UI in sequence.
The MP4 now treats the report UI as pages the viewer reads in turn,
not as a strip of still shots. The terminal still closes on the same
serve hand-off, but after the overview scroll the video opens each
stage's Summary, scrolls it to the bottom (the "See everything this
step recorded" CTA is right there), cross-fades into the Full record
page, scrolls it the same way, and repeats for M1 through M5. Cases
and the agent audit log follow.
The sticky stage-list would scroll away inside a full-page capture, so
shoot_ui gains --scrollset: it records the page's full height, the
sidebar's natural document offset, and a viewport screenshot taken
once sticking has engaged; the renderer reads that sidecar and
overlays the pinned sidebar from the moment the scroll reaches it.
The result looks like a real browser scrolling, not a scrollbar
guessing where the chrome is.
The two-act summary→full pattern also kills the "duplicate-looking
page" problem the previous version had: the Summary and Full record
shots shared the same viewport, so ten samey frames read as repetition.
With each page scrolled, every act shows something distinct.
- shoot_ui: --scrollset writes {name}.png + {name}-pin.png + {name}.json
- render_mp4.py: --ui-scroll FILE (repeatable, ordered) for chained
scroll acts; _scroll_pin reads the sidecar; _browser_act overlays
- theme.py: SCROLL_MIN 3.5 → 2.2s — with twelve scroll acts the
previous floor made the per-page motion feel sluggish
- README: --ui-scroll in the render example, --scrollset in the
capture example
The UI tour now reads as someone clicking through it. Between every
scroll act — the overview, each stage's summary, the deepen page, the
case studio — the renderer points a cursor at the button that opens the
next act. It glides in (ease-out over 0.45s), settles, then clicks: the
tip nudges into a press and a ring pulses out. The next act's xfade
takes over from there, and during the blend the cursor dissolves into
the new page.
The shots themselves stay the same full-page captures — the cursor is
purely a render-time overlay. shoot_ui --scrollset now also measures
every click target's viewport position and the capture viewport size
and writes them into the sidecar JSON, so the renderer can rebase
bottom-anchored targets (CTA, footer index buttons) to the video's
browser viewport. _click_target infers from consecutive sidecars what
the click should be: same stage with full=true → the CTA; next stage →
its sidebar button; next view → the matching footer index.
The shipped video deepens only M2 and M5 — the two stages whose Full
records carry the story. The other stages' Summary scrolls land on the
CTA at the bottom, but no click follows; the act just holds and the
next sidebar click carries on. That keeps the loop tight while the
viewer still gets to see each stage's findings as a scroll.
- shoot_ui: scrollset sidecar adds {view, stage, full, viewport,
stage_buttons, cta, buttons}
- render_mp4.py: _ease_out_cubic, _cursor_layer (RGBA pointer + click
ring), _click_frames (glide + press as a mini-act), _scroll_meta,
_click_target (a,b), sidebar click in pinned coords + bottom-anchored
rebase; main() sequences acts and inserts clicks; _browser_act gained
a hold override
- README: --ui-scroll example kept summaries for M1-M5, deepened only
M2 and M5; the CTA click is described
jiaq-liu
approved these changes
Sep 13, 2026
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.
Summary
Type of change
Checklist
ruff check .passesmypy evalrxpassespytest -m "not gpu"passes (all fast unit tests green)FakeModelCHANGELOG.mdupdated under[Unreleased]