Skip to content

FE-1592: Add a repo skill for recording Petrinaut demo videos - #9541

Draft
kube wants to merge 4 commits into
mainfrom
claude/fe-1592-demo-recording-skill
Draft

FE-1592: Add a repo skill for recording Petrinaut demo videos#9541
kube wants to merge 4 commits into
mainfrom
claude/fe-1592-demo-recording-skill

Conversation

@kube

@kube kube commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Before this PR, recording a demo of a Petrinaut flow needed one person's local tooling. The capture harness, the encoder, the pointer overlay and the canvas framing helpers all lived in a home directory, so nobody else could produce a comparable video, and a before/after pair could not be split between two people.

Vendors that tooling into .agents/skills/recording-petrinaut-demos, where anyone working in the repository picks it up. Everything resolves from the repository root, so it runs from any checkout, and the publish step is a script that posts a finished file to GitHub's user-attachments store and prints a URL that plays inline for anyone who can read the repository.

Links

Changes

Procedure

  • SKILL.md carries the fixed output format and the storyboard budget

    18s, 16:10, 1300 CSS px captured at retina density, encoded to 1600x1000 H.264, so two recordings can be compared frame for frame.
    The three acts and the per-beat holds come from takes that read badly and were redone.

  • SKILL.md carries the before/after recipe and its trap

    Both takes run one scenario against two builds. Restoring the branch after the revert leaves a file that main has and the branch deleted staged, because git cannot remove from the working tree what HEAD does not contain.

  • references/petrinaut-setup.md carries what the editor itself needs

    The two localStorage keys, the settings that make the house look, canvas framing, and the traps that swallow a click aimed at a node.

Tooling

  • scripts/record-demo.mjs captures through CDP rather than Playwright's recorder

    recordVideo cannot capture retina: a larger size pads the frame with grey and deviceScaleFactor never reaches the video.

  • scripts/demo-hud.mjs draws the pointer and the keystrokes over the app

    Playwright renders no cursor into a screencast. The shape follows the app's own computed cursor, so a resize handle shows the system's double arrow.

  • scripts/upload-attachment.sh turns a file into a link

    Takes a plain gh auth token, so no browser drag-and-drop. Fetching the printed URL yourself answers 404 — the redirect is signed for a session — so the script says how to confirm it instead.

  • scripts/probe-cursor.mjs screenshots the overlay in a few seconds

    Judging the pointer by recording a whole take costs a minute each time.

Test coverage

  • Manual, end to end from this checkout:

    Recorded the example scenario against the website dev server (606 frames, no console or page errors), encoded it (1600x1000, yuv420p, 540 frames, 1.39 MB), and ran the cursor probe.

  • None automated:

    Every script drives a browser against a served app; a test that mocked that would assert the mock.

How to test

  • yarn workspace @apps/petrinaut-website dev
  • npx turbo run build --filter @hashintel/petrinaut
  • node .agents/skills/recording-petrinaut-demos/scripts/record-demo.mjs .agents/skills/recording-petrinaut-demos/references/example.scenario.mjs --out ./demo

    Expect a printed beat timeline and errors: 0

  • .agents/skills/recording-petrinaut-demos/scripts/make-demo.sh ./demo/recording.json ./demo/out.mp4

    Expect h264,1600,1000,yuv420p,30/1,540 and four check frames beside the output

  • Open the four check frames

    Expect the toolbar centred, then folded, then revealed under the pointer

The capture harness, the encoder, the pointer overlay and the canvas helpers
lived in one person's home directory, so nobody else could produce a
comparable video and a before/after pair could not be split between two
people. They now sit in .agents/skills and resolve from the repository root.

The publish step is a script that posts a finished file to GitHub's
user-attachments store and prints the asset URL, which plays inline for anyone
who can read the repository.
@kube kube self-assigned this Sep 4, 2026
@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
petrinaut Ready Ready Preview Sep 4, 2026 11:02pm UTC
3 Skipped Deployments
Project Deployment Actions Updated
hash Ignored Ignored Preview Sep 4, 2026 11:02pm UTC
hashdotdesign-tokens Ignored Ignored Preview Sep 4, 2026 11:02pm UTC
petrinaut-docs Ignored Ignored Preview Sep 4, 2026 11:02pm UTC

Request Review

@github-actions github-actions Bot added the area/infra Relates to version control, CI, CD or IaC (area) label Sep 4, 2026
Comment thread .agents/skills/recording-petrinaut-demos/scripts/record-demo.mjs Fixed
`.claude/skills/skill-rules.json` is generated from the skill frontmatter by
`yarn agents:skill-management generate-skill-rules`, and CI regenerates it to
check nothing in .agents/skills is missing from it.
Semgrep reads the first `console.log` argument as a format string, so a
computed value there is a forgeable one. The elapsed time moves into an
argument.
Both takes have to run the same scenario against two builds, and the revert
that gets you the second one has a trap: restoring the branch leaves a file
that main has and the branch deleted staged, because git cannot remove from
the working tree what HEAD does not contain.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/infra Relates to version control, CI, CD or IaC (area)

Development

Successfully merging this pull request may close these issues.

2 participants