Share

Every release

The release loop: one editable take becomes the demo, the listing and the social cuts, and the next version re-renders it.

A release needs media: the demo, the store listing, a card for the feed, a what's-new clip. vosso treats that set as one editable document rendered to many destinations, so shipping the media becomes part of shipping the release, and the next version is mostly a re-render.

The loop, once per release:

  1. 1

    Keep the script in the repo

    actions.json is the recording script: the click path through your product, written once and committed next to the code it demonstrates. It is the next release's script too.

  2. 2

    Re-record, keep the cut

    Shell
    vos record --actions actions.json --out take --strict
    vos plan take --reuse

    Record the same script into the same take directory: the footage is replaced and the cut survives (doc.prev.json). --reuse then re-times that cut onto the new recording. The recorder wrote down when every step ran, so a zoom you placed on the checkout button follows the checkout button, even when a new banner shifted everything down; the look copies over; the automatic camera re-plans. Whatever could not follow, a moved step or a control that left the UI, is named in the report rather than guessed at, and you fix just those.

  3. 3

    Cut it, deliver it

    Cut by exception over what the planner proposed, then render the whole destination set in one pass:

    Shell
    vos deliver take-v2 --to cws,producthunt,linkedin,og --release "v2.1"

    The verb renders and verifies, and composes nothing: the still moments come from the script's steps (the end of a gesture, or of the wait after a click that navigates), the cards render from the poster documents beside the take (poster/<class>/doc.json, one per aspect class, each a plain take whose card sits where the poster wants it and ends on a freeze whose start is the still), and the cuts play what vos plan proposed into the document in one animation vocabulary: the card's enter, the templates the recipe names (an end card from your shelf, or the official End card template from vos.so when the recipe leaves endCard on: the house one as clips after the footage), a caption per step, a music bed and click sounds where the channel plays sound. A poster is made with vos plan <poster take> --style <a poster on your shelf> --headline "…", which copies the layout and types the words in, then pushed like any take. Every asset is verified against its channel's spec and kit.json records the set; vos validate kit/kit.json --picture then reads what each asset looks like (a blank moment, a crop where a card was asked for, a headline cut at the edge, white words on a paper ground) and says it with a code and a fix. See Store listings for the store half in detail.

  4. 4

    Push it, labelled for the release

    Shell
    vos push take-v2 --label "v2.1 launch" --note "what shipped, one line"

    The push creates a version named for the release, and the watch page always plays the latest one, so a shared link never goes stale. The take, the script and the kit are the release's media source, kept.

The repo is the home

Keep the release's media source next to the code it demonstrates:

Text
media/
  actions.json   the recording script (steps carry ids and captions)
  doc.json       the signed-off cut of the last release
  BRAND.md       the brand kit: colours, faces, the look (vos brand writes it)
  LAUNCH.md      per-channel house rules and the release's words (headline, kicker, music)
  kit.json       what the last release shipped, verified

The platform mirrors it: vos push versions the take on your shelf, vos pull brings studio edits back, and media/vos.json tracks which vos the pushes land on. After a release, commit the updated doc.json so the next re-record has the cut to carry.

Run it on every pull request

The whole loop is headless, so CI can produce the release's media, and a pull request can carry it the way a preview deployment carries a site: one comment with the watch page and the kit, updated in place on every push, so reviewers, QA and marketing sign off on a link. The vosjs/action action does the loop:

Text
name: release media
on:
  pull_request:
  push:
    tags: ['v*']
permissions:
  contents: read
  pull-requests: write
jobs:
  media:
    runs-on: ubuntu-latest # ships Google Chrome, which mp4 renders need
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - uses: vosjs/action@v1
        with:
          key: ${{ secrets.VOS_API_KEY }} # mint a content key at /app/api

It records media/actions.json, carries media/doc.json onto the new footage, renders cws,og,github by default (channels: widens it; the cards render from the poster/ documents committed beside the script), re-measures the kit with vos validate, pushes the take labelled for the release, attaches the kit to the run, and keeps the comment. Without the key nothing is pushed and the comment says so. The same run on a tag is the release.

Or write the workflow by hand

The steps the action runs, if you would rather own them (the same VOS_API_KEY secret):

Text
name: release media
on:
  push:
    tags: ['v*']
jobs:
  media:
    runs-on: ubuntu-latest # ships Google Chrome, which mp4 renders need
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm i -D @vosjs/cli
      - name: record the shipped product
        run: npx vos record --actions media/actions.json --out /tmp/take --strict --json
      - name: carry the committed cut onto the new footage
        run: npx vos plan /tmp/take --reuse --from media/doc.json --json
      - name: render the destination set
        run: npx vos deliver /tmp/take --to cws,og --release "${{ github.ref_name }}" --json
      - name: push the take, labelled for the release
        env:
          VOS_API_KEY: ${{ secrets.VOS_API_KEY }}
        run: |
          cp media/vos.json /tmp/take/vos.json || true
          npx vos push /tmp/take --label "${{ github.ref_name }} launch" --note "CI release media" --yes --json
      - uses: actions/upload-artifact@v4
        with: { name: release-kit, path: /tmp/take/kit }

--strict fails the job on a broken selector instead of shipping around it, and a push against a stale base fails with the changelog of what changed on the shelf, so a human race never resolves silently. The flagged list from --reuse prints in the job log; anything named there is the release's real to-do.

Hand it to your agent

The whole loop is agent-shaped. npx skills add vosjs/skills installs the launch-kit skill, and a message like "we're shipping v2.1 on Friday, make the demo and the Chrome Web Store listing" is enough: the agent records, cuts, delivers and pushes, and you fine-tune the result in the studio.