diff --git a/components.lock.json b/components.lock.json index 80c14a72..6685e99c 100644 --- a/components.lock.json +++ b/components.lock.json @@ -3,10 +3,10 @@ "state": "resolved", "cli": { "repository": "screenrig/cli", - "commit": "e21fcc552442e4dbd08d81cdd85abaccf76b0fbf", + "commit": "880abf4fbf53af93e30ed59553ba1320db649e9f", "artifact": { "file": "screenrig-cli.tgz", - "sha256": "cfea694d7c14a0008e521174e46376fb767283a54032137fe95d46676b21caaa" + "sha256": "19c4d7843edce94b35f73fc262ab4e52e6b84fb4266bd32b14e1f287def07c83" } } } diff --git a/plugins/screenrig/cli/README.md b/plugins/screenrig/cli/README.md index 92629ae1..83778504 100644 --- a/plugins/screenrig/cli/README.md +++ b/plugins/screenrig/cli/README.md @@ -156,3 +156,63 @@ Development profiles are described in [CONTRIBUTING.md](https://github.com/scree See [`RELEASING.md`](https://github.com/screenrig/cli/blob/main/RELEASING.md) for CalVer stamping and npm publication. Report suspected vulnerabilities through the [security policy](SECURITY.md). + +## Prepare, publish, and edit playlists + +For ready images and videos, prepare a full-screen playlist in playback order: + +```sh +screenrig playlist init med_POSTER med_VIDEO --name "Lobby loop" --screen scr_LOBBY --output lobby.json +screenrig playlist preview lobby.json --output preview --contact-sheet +screenrig screen publish scr_LOBBY lobby.json --expect-rev 7 +``` + +Inspect the preview before publishing. `playlist init` reads media metadata and +screen observations but makes no remote writes. It creates one page per media ID, +with `contain` fit, a black background, and a 200 ms crossfade. Images last 8000 ms; +videos are muted, do not loop, and advance on completion. Use `--duration-ms` for +image duration and `--fit contain|cover|fill` for content fit. Override the canvas +with both `--target-width` and `--target-height`; these also work without `--screen`. +Unknown or multiple reported surfaces require explicit dimensions. Output files +must not already exist. + +`screen publish ` creates a new playlist, assigns it using the +expected **screen** revision, and reads back the assignment. It does not update an +existing playlist by name. A name collision requires a different name or an +explicit `playlist update`. Its JSON result reports `playlist_id`, +`playlist_revision`, `screen_id`, `screen_revision`, `assignment_verified`, and +`playback_verified`. Assignment verification does not prove playback; request and +inspect a screenshot and relevant playback evidence separately. + +Publishing saves a private local journal automatically. After an ambiguous failure, +repeat the identical command and input with the same config to resume. If playlist +creation succeeded before assignment failed, the error identifies the created +playlist. Do not delete it or start another create to recover. A revision conflict +requires inspecting the screen and reconciling the intended assignment; an already +created playlist can be assigned explicitly with `screen assign`. Publishing never +silently refreshes the expected revision. Unfinished recovery stops after the +24-hour server idempotency window; inspect and reconcile before making more writes. + +To edit an existing playlist: + +```sh +screenrig playlist show pl_EXISTING --output lobby.json +screenrig playlist update pl_EXISTING lobby.json --expect-rev 4 +``` + +`playlist show --output` writes the editable `{name, pages}` document and returns +its path, `playlist_id`, and source `revision` on stdout. Use that returned revision +for the update. It preserves dynamic selectors, schedules, motion, and pinned +application releases, removing server-derived media and timing fields. Comments +remain separate. Plain `playlist show` is an inspection response; `--editable` +without `--output` returns `data.document`, `data.playlist_id`, and `data.revision`. +Updating a playlist affects every screen assigned to it. + +Playlist validate, create, update, preview, and screen publish accept `-` as their +input file to read stdin. JSON envelopes are never written into authored files. +`--expect-rev` is the preferred revision spelling; `--if-match` remains a compatible +alias. Supply only one. The HTTP revision contract is unchanged. + +Generation accepts either `--prompt TEXT` or `--prompt-file FILE`, including +`--prompt-file -` for stdin. The file is the complete prompt, with no trimming; +the existing 4000-character limit applies. Prompts are excluded from diagnostics. diff --git a/plugins/screenrig/skills/screenrig/SKILL.md b/plugins/screenrig/skills/screenrig/SKILL.md index c41356e7..2f6d8429 100644 --- a/plugins/screenrig/skills/screenrig/SKILL.md +++ b/plugins/screenrig/skills/screenrig/SKILL.md @@ -95,13 +95,15 @@ shapes belong in prepared content, not additional native playlist primitives. 1. Prepare and inspect the content at the intended size. Generation stores its returned media ID directly; do not upload it again. -2. Write or update the authored playlist file. Read [playlists](references/playlists.md) - before editing its shape, motion or schedule. Keep at least one page always eligible. -3. Create or update the playlist, then assign it to the resolved screen. Use the - current revision with `--if-match` when changing an existing resource. -4. Read back the assignment, request a screenshot, and inspect relevant playback - and events. Report what was observed and any remaining uncertainty. A command - succeeding alone does not prove physical display. +2. For full-screen images or videos, use `playlist init` to prepare the authored + file from media IDs and screen dimensions. For other layouts, author the file + using [playlists](references/playlists.md). Preview and inspect it. +3. Publish a new playlist with `screen publish SCREEN_ID FILE --expect-rev REV`. + To edit an existing playlist, obtain its file with `playlist show ID --output + FILE`, then use `playlist update` with the returned revision. Updates affect + all assigned screens. See the playlist reference for partial-failure recovery. +4. Request a screenshot and inspect relevant playback and events. Assignment + readback alone does not prove physical display. Report the observed evidence. For screen controls, screenshots, comments, events and feedback, use [operations](references/operations.md). For app uploads, page completion and K/V, diff --git a/plugins/screenrig/skills/screenrig/references/applications.md b/plugins/screenrig/skills/screenrig/references/applications.md index 19cd9f97..1b084c4d 100644 --- a/plugins/screenrig/skills/screenrig/references/applications.md +++ b/plugins/screenrig/skills/screenrig/references/applications.md @@ -36,7 +36,7 @@ revision with `app show`, then publish a new release: ```bash screenrig app show app_EXAMPLE -screenrig app update app_EXAMPLE ./lobby-board --if-match 3 +screenrig app update app_EXAMPLE ./lobby-board --expect-rev 3 ``` `app update` preserves application identity, name, and application K/V. It uses @@ -117,11 +117,11 @@ must carry `controller: true`. Do not set `controller` on a `duration` or ```bash screenrig playlist create ./lobby-board.json screenrig screen list -screenrig screen assign scr_EXAMPLE --playlist-id pl_EXAMPLE --if-match 3 +screenrig screen assign scr_EXAMPLE --playlist-id pl_EXAMPLE --expect-rev 3 ``` Take `--playlist-id` from `data.id` of the `playlist create` result. Take -`--if-match` from the screen's current `revision`, which both `screen list` and +`--expect-rev` from the screen's current `revision`, which both `screen list` and `screen show` return. `revision_conflict` means refetch and retry. Do not invent the revision. @@ -145,7 +145,7 @@ Application K/V is binary-safe. Use exactly one value mode. screenrig kv set --application-id app_EXAMPLE lobby --json-value '{"open":true}' screenrig kv get --application-id app_EXAMPLE lobby screenrig kv list --application-id app_EXAMPLE -screenrig kv delete --application-id app_EXAMPLE lobby --if-match REVISION +screenrig kv delete --application-id app_EXAMPLE lobby --expect-rev REVISION ``` `kv get` returns the stored bytes only as `data.value_base64`, including when diff --git a/plugins/screenrig/skills/screenrig/references/commands.md b/plugins/screenrig/skills/screenrig/references/commands.md index e35a0b50..aa47b37a 100644 --- a/plugins/screenrig/skills/screenrig/references/commands.md +++ b/plugins/screenrig/skills/screenrig/references/commands.md @@ -13,10 +13,10 @@ agent disconnect --yes [--allow-lockout] dashboard [--print-url] app pack [--output FILE] app upload [--name NAME] [--no-wait] [--poll-ms MS] -app update --if-match REVISION [--no-wait] [--poll-ms MS] +app update --expect-rev REVISION [--no-wait] [--poll-ms MS] app list app show -media generate --prompt TEXT [--aspect-ratio RATIO] [--quality low|medium|high] [--tag TAG] +media generate (--prompt TEXT | --prompt-file FILE) [--aspect-ratio RATIO] [--quality low|medium|high] [--tag TAG] [--no-progress] media upload [--content-type TYPE] [--tag TAG] [--no-wait] [--poll-ms MS] [--no-transcode] [--codec h264|hevc] [--max-fps N] @@ -27,38 +27,41 @@ media upload-batch --state FILE [--concurrency N] media show media download [--output FILE] media list [--tag TAG] [--primitive image|video] -media update (--tag TAG | --clear-tag) --if-match REVISION -media delete --if-match REVISION +media update (--tag TAG | --clear-tag) --expect-rev REVISION +media delete --expect-rev REVISION compose catalog compose render [--output DIRECTORY] [--combined] [--target-width PX --target-height PX] [--safe-area] [--open] [--lint-only] compose batch --output DIRECTORY [--only ID] [--target-width PX --target-height PX] [--safe-area] [--lint-only] +playlist init --name NAME --output FILE [--screen ID] + [--target-width PX --target-height PX] [--duration-ms MS] [--fit contain|cover|fill] playlist validate playlist create -playlist update --if-match REVISION +playlist update --expect-rev REVISION playlist export --output DIRECTORY -playlist import [--name NAME] [--update ID --if-match REVISION] -playlist show +playlist import [--name NAME] [--update ID --expect-rev REVISION] +playlist show [--output FILE | --editable] playlist list -playlist delete --if-match REVISION +playlist delete --expect-rev REVISION screen update [--name NAME] [--playlist-id ID] [--timezone ZONE] - --if-match REVISION + --expect-rev REVISION screen list [--state archived] screen show -screen assign --playlist-id ID --if-match REVISION -screen set-timezone --timezone ZONE --if-match REVISION -screen archive --if-match REVISION -screen unarchive --if-match REVISION -screen delete --if-match REVISION -screen rotate-public-id --if-match REVISION +screen publish --expect-rev REVISION +screen assign --playlist-id ID --expect-rev REVISION +screen set-timezone --timezone ZONE --expect-rev REVISION +screen archive --expect-rev REVISION +screen unarchive --expect-rev REVISION +screen delete --expect-rev REVISION +screen rotate-public-id --expect-rev REVISION screen toast --text TEXT [--level info] [--duration-ms MS] screen screenshot [--output FILE] [--timeout MS] [--poll-ms MS] kv get --application-id ID -kv set --application-id ID --json-value JSON [--if-match REVISION] -kv set --application-id ID --file FILE --content-type TYPE [--if-match REVISION] -kv set --application-id ID --value-base64 BASE64 --content-type TYPE [--if-match REVISION] -kv delete --application-id ID --if-match REVISION +kv set --application-id ID --json-value JSON [--expect-rev REVISION] +kv set --application-id ID --file FILE --content-type TYPE [--expect-rev REVISION] +kv set --application-id ID --value-base64 BASE64 --content-type TYPE [--expect-rev REVISION] +kv delete --application-id ID --expect-rev REVISION kv list --application-id ID comment show screen comment show playlist [--page PAGE_ID] @@ -92,3 +95,5 @@ Global flags include `--json`, `--human`, `--api-url URL`, `--config PATH`, On `revision_conflict`, fetch the resource, reapply the intended change, and retry with the returned revision. On an ambiguous transport failure, reuse the same idempotency key. + +`--if-match` remains an alias for `--expect-rev`; do not supply both. diff --git a/plugins/screenrig/skills/screenrig/references/compose.md b/plugins/screenrig/skills/screenrig/references/compose.md index 9e209f13..3b3ceae1 100644 --- a/plugins/screenrig/skills/screenrig/references/compose.md +++ b/plugins/screenrig/skills/screenrig/references/compose.md @@ -329,3 +329,5 @@ cropping. Eight-digit hex is how the page stays transparent and the plate keeps alpha. Layered region PNGs can sit as image primitives at their manifest rects. Inspect with `--combined`; default agent output stays layered. A presentable poster is one generated `image` primitive, not photo plus overlay. + +After uploading finished slide images, pass their media IDs in playback order to `playlist init`, inspect the preview, then use `screen publish`. See [playlists](playlists.md). diff --git a/plugins/screenrig/skills/screenrig/references/media.md b/plugins/screenrig/skills/screenrig/references/media.md index a8af6bfb..0a726d3c 100644 --- a/plugins/screenrig/skills/screenrig/references/media.md +++ b/plugins/screenrig/skills/screenrig/references/media.md @@ -164,7 +164,7 @@ On a build that converts: object. Hyphens are rejected; `ExecIntro2026` is valid and `exec-intro` is not. `media list --tag TAG [--primitive image|video]` filters by that tag and is the reliable filename → id map after upload. - `media update (--tag TAG | --clear-tag) --if-match REVISION` changes + `media update (--tag TAG | --clear-tag) --expect-rev REVISION` changes or clears it. Untagged objects are omitted when `--tag` is present on `media list`. - The conversion runs `ffmpeg` and `ffprobe`. They must be on `PATH`, or their @@ -250,3 +250,5 @@ problem code and status. Run `doctor` for local diagnostics. Use `doctor --repair-config` only to repair an existing credential file whose permissions are too broad. + +For long or exact-copy prompts, use `media generate --prompt-file FILE` (or `-` for stdin) instead of `--prompt`. For full-screen playback of ready media IDs, use `playlist init` and `screen publish`; see [playlists](playlists.md). diff --git a/plugins/screenrig/skills/screenrig/references/operations.md b/plugins/screenrig/skills/screenrig/references/operations.md index b1dff90e..5dcb0e67 100644 --- a/plugins/screenrig/skills/screenrig/references/operations.md +++ b/plugins/screenrig/skills/screenrig/references/operations.md @@ -5,11 +5,11 @@ ```bash screenrig screen list screenrig screen show scr_EXAMPLE -screenrig screen update scr_EXAMPLE --name "Lobby" --playlist-id pl_EXAMPLE --if-match REVISION -screenrig screen assign scr_EXAMPLE --playlist-id pl_EXAMPLE --if-match REVISION -screenrig screen set-timezone scr_EXAMPLE --timezone America/Los_Angeles --if-match REVISION -screenrig screen archive scr_EXAMPLE --if-match REVISION -screenrig screen unarchive scr_EXAMPLE --if-match REVISION +screenrig screen update scr_EXAMPLE --name "Lobby" --playlist-id pl_EXAMPLE --expect-rev REVISION +screenrig screen assign scr_EXAMPLE --playlist-id pl_EXAMPLE --expect-rev REVISION +screenrig screen set-timezone scr_EXAMPLE --timezone America/Los_Angeles --expect-rev REVISION +screenrig screen archive scr_EXAMPLE --expect-rev REVISION +screenrig screen unarchive scr_EXAMPLE --expect-rev REVISION screenrig screen toast scr_EXAMPLE --text "Updated lobby loop" --level info screenrig screen screenshot scr_EXAMPLE --output ./lobby.webp ``` @@ -59,7 +59,7 @@ screenrig comment delete screen scr_EXAMPLE ``` `--json-value` is a JSON object. `--file` reads a JSON object from disk. -Exactly one of those on set. Last write wins; do not send `--if-match`. +Exactly one of those on set. Last write wins; do not send `--expect-rev`. Unset show is `{ "comments": null }`. ## Events diff --git a/plugins/screenrig/skills/screenrig/references/playlists.md b/plugins/screenrig/skills/screenrig/references/playlists.md index 57e9056c..3217086d 100644 --- a/plugins/screenrig/skills/screenrig/references/playlists.md +++ b/plugins/screenrig/skills/screenrig/references/playlists.md @@ -1,5 +1,65 @@ # Playlists, motion, schedules and bundles +## Prepare, publish, and edit playlists + +For ready images and videos, prepare a full-screen playlist in playback order: + +```sh +screenrig playlist init med_POSTER med_VIDEO --name "Lobby loop" --screen scr_LOBBY --output lobby.json +screenrig playlist preview lobby.json --output preview --contact-sheet +screenrig screen publish scr_LOBBY lobby.json --expect-rev 7 +``` + +Inspect the preview before publishing. `playlist init` reads media metadata and +screen observations but makes no remote writes. It creates one page per media ID, +with `contain` fit, a black background, and a 200 ms crossfade. Images last 8000 ms; +videos are muted, do not loop, and advance on completion. Use `--duration-ms` for +image duration and `--fit contain|cover|fill` for content fit. Override the canvas +with both `--target-width` and `--target-height`; these also work without `--screen`. +Unknown or multiple reported surfaces require explicit dimensions. Output files +must not already exist. + +`screen publish ` creates a new playlist, assigns it using the +expected **screen** revision, and reads back the assignment. It does not update an +existing playlist by name. A name collision requires a different name or an +explicit `playlist update`. Its JSON result reports `playlist_id`, +`playlist_revision`, `screen_id`, `screen_revision`, `assignment_verified`, and +`playback_verified`. Assignment verification does not prove playback; request and +inspect a screenshot and relevant playback evidence separately. + +Publishing saves a private local journal automatically. After an ambiguous failure, +repeat the identical command and input with the same config to resume. If playlist +creation succeeded before assignment failed, the error identifies the created +playlist. Do not delete it or start another create to recover. A revision conflict +requires inspecting the screen and reconciling the intended assignment; an already +created playlist can be assigned explicitly with `screen assign`. Publishing never +silently refreshes the expected revision. Unfinished recovery stops after the +24-hour server idempotency window; inspect and reconcile before making more writes. + +To edit an existing playlist: + +```sh +screenrig playlist show pl_EXISTING --output lobby.json +screenrig playlist update pl_EXISTING lobby.json --expect-rev 4 +``` + +`playlist show --output` writes the editable `{name, pages}` document and returns +its path, `playlist_id`, and source `revision` on stdout. Use that returned revision +for the update. It preserves dynamic selectors, schedules, motion, and pinned +application releases, removing server-derived media and timing fields. Comments +remain separate. Plain `playlist show` is an inspection response; `--editable` +without `--output` returns `data.document`, `data.playlist_id`, and `data.revision`. +Updating a playlist affects every screen assigned to it. + +Playlist validate, create, update, preview, and screen publish accept `-` as their +input file to read stdin. JSON envelopes are never written into authored files. +`--expect-rev` is the preferred revision spelling; `--if-match` remains a compatible +alias. Supply only one. The HTTP revision contract is unchanged. + +Generation accepts either `--prompt TEXT` or `--prompt-file FILE`, including +`--prompt-file -` for stdin. The file is the complete prompt, with no trimming; +the existing 4000-character limit applies. Prompts are excluded from diagnostics. + ## Playlist writes Four wire primitives exist: `image`, `video`, `iframe`, and `application`. @@ -18,11 +78,10 @@ and `primitives`. A primitive is flat: `id`, a `primitive` field naming one of the four, that primitive's own fields, then `rect`, `layer`, `content_fit`, optional `enter`, and optional `motion`. There is no nested content object. -Keep the authored playlist JSON as the source of truth. `playlist show` is an -inspection payload, not a guaranteed write document: the server may add -resolved/defaulted fields such as `advance.max_ms` and -`selector.one_at_a_time`. Do not feed a show payload directly to `playlist -create` or `playlist update`; edit and submit the authored file instead. +Keep the authored playlist JSON as the source of truth. To obtain one from an +existing playlist, use `playlist show ID --output FILE`; the returned envelope +includes the source revision. Ordinary `playlist show` remains an inspection +response and must not be submitted as a write document. Image and video primitives require a `selector`. `iframe` and `application` do not take one. Do not put `media_id` on the primitive itself; it belongs @@ -301,7 +360,7 @@ owns it. `{"days": ["fri"], "start": "22:00", "end": "02:00"}` runs Friday 22:00 through Saturday 02:00. ```bash -screenrig screen set-timezone scr_EXAMPLE --timezone America/Los_Angeles --if-match 3 +screenrig screen set-timezone scr_EXAMPLE --timezone America/Los_Angeles --expect-rev 3 ``` `--timezone` is an IANA identifier such as `America/Los_Angeles` or @@ -316,7 +375,7 @@ referenced image or video rendition together. ```bash screenrig playlist export pl_EXAMPLE --output ./lobby-bundle screenrig playlist import ./lobby-bundle -screenrig playlist import ./lobby-bundle --update pl_TARGET --if-match REVISION +screenrig playlist import ./lobby-bundle --update pl_TARGET --expect-rev REVISION ``` The export destination must not exist. The bundle contains @@ -328,8 +387,8 @@ names are unique per account, so importing an account's own export unchanged is refused with 409 `resource_conflict` ("playlist name is already in use"); that problem's `error.next` names the two ways forward. `--name NAME` (1 to 120 characters) imports the bundle as a new playlist under that name; -`--update ID --if-match REVISION` replaces the existing playlist instead. -Updating requires both `--update` and the current `--if-match` revision. +`--update ID --expect-rev REVISION` replaces the existing playlist instead. +Updating requires both `--update` and the current `--expect-rev` revision. ```bash screenrig playlist import ./lobby-bundle --name "Lobby loop (copy)" diff --git a/scripts/validate-plugin.py b/scripts/validate-plugin.py index e006b60b..c3c1bea1 100755 --- a/scripts/validate-plugin.py +++ b/scripts/validate-plugin.py @@ -371,7 +371,7 @@ def check_no_alternate_surfaces(cli_source: Path | None) -> None: required_marketplace = { "README.md": ["https://screenrig.ai/docs/start/", "SECURITY.md", "Node.js 20.11"], "skills/screenrig/SKILL.md": ["screenrig version", "screenrig-plugin-freshness --json", - "screenrig doctor", "not_enrolled", "agent enroll", "--if-match", + "screenrig doctor", "not_enrolled", "agent enroll", "--expect-rev", "payment_required", "idempotency", "references/commands.md"], } for relative, facts in required_marketplace.items(): diff --git a/skills/screenrig/SKILL.md b/skills/screenrig/SKILL.md index c41356e7..2f6d8429 100644 --- a/skills/screenrig/SKILL.md +++ b/skills/screenrig/SKILL.md @@ -95,13 +95,15 @@ shapes belong in prepared content, not additional native playlist primitives. 1. Prepare and inspect the content at the intended size. Generation stores its returned media ID directly; do not upload it again. -2. Write or update the authored playlist file. Read [playlists](references/playlists.md) - before editing its shape, motion or schedule. Keep at least one page always eligible. -3. Create or update the playlist, then assign it to the resolved screen. Use the - current revision with `--if-match` when changing an existing resource. -4. Read back the assignment, request a screenshot, and inspect relevant playback - and events. Report what was observed and any remaining uncertainty. A command - succeeding alone does not prove physical display. +2. For full-screen images or videos, use `playlist init` to prepare the authored + file from media IDs and screen dimensions. For other layouts, author the file + using [playlists](references/playlists.md). Preview and inspect it. +3. Publish a new playlist with `screen publish SCREEN_ID FILE --expect-rev REV`. + To edit an existing playlist, obtain its file with `playlist show ID --output + FILE`, then use `playlist update` with the returned revision. Updates affect + all assigned screens. See the playlist reference for partial-failure recovery. +4. Request a screenshot and inspect relevant playback and events. Assignment + readback alone does not prove physical display. Report the observed evidence. For screen controls, screenshots, comments, events and feedback, use [operations](references/operations.md). For app uploads, page completion and K/V, diff --git a/skills/screenrig/references/applications.md b/skills/screenrig/references/applications.md index 19cd9f97..1b084c4d 100644 --- a/skills/screenrig/references/applications.md +++ b/skills/screenrig/references/applications.md @@ -36,7 +36,7 @@ revision with `app show`, then publish a new release: ```bash screenrig app show app_EXAMPLE -screenrig app update app_EXAMPLE ./lobby-board --if-match 3 +screenrig app update app_EXAMPLE ./lobby-board --expect-rev 3 ``` `app update` preserves application identity, name, and application K/V. It uses @@ -117,11 +117,11 @@ must carry `controller: true`. Do not set `controller` on a `duration` or ```bash screenrig playlist create ./lobby-board.json screenrig screen list -screenrig screen assign scr_EXAMPLE --playlist-id pl_EXAMPLE --if-match 3 +screenrig screen assign scr_EXAMPLE --playlist-id pl_EXAMPLE --expect-rev 3 ``` Take `--playlist-id` from `data.id` of the `playlist create` result. Take -`--if-match` from the screen's current `revision`, which both `screen list` and +`--expect-rev` from the screen's current `revision`, which both `screen list` and `screen show` return. `revision_conflict` means refetch and retry. Do not invent the revision. @@ -145,7 +145,7 @@ Application K/V is binary-safe. Use exactly one value mode. screenrig kv set --application-id app_EXAMPLE lobby --json-value '{"open":true}' screenrig kv get --application-id app_EXAMPLE lobby screenrig kv list --application-id app_EXAMPLE -screenrig kv delete --application-id app_EXAMPLE lobby --if-match REVISION +screenrig kv delete --application-id app_EXAMPLE lobby --expect-rev REVISION ``` `kv get` returns the stored bytes only as `data.value_base64`, including when diff --git a/skills/screenrig/references/commands.md b/skills/screenrig/references/commands.md index e35a0b50..aa47b37a 100644 --- a/skills/screenrig/references/commands.md +++ b/skills/screenrig/references/commands.md @@ -13,10 +13,10 @@ agent disconnect --yes [--allow-lockout] dashboard [--print-url] app pack [--output FILE] app upload [--name NAME] [--no-wait] [--poll-ms MS] -app update --if-match REVISION [--no-wait] [--poll-ms MS] +app update --expect-rev REVISION [--no-wait] [--poll-ms MS] app list app show -media generate --prompt TEXT [--aspect-ratio RATIO] [--quality low|medium|high] [--tag TAG] +media generate (--prompt TEXT | --prompt-file FILE) [--aspect-ratio RATIO] [--quality low|medium|high] [--tag TAG] [--no-progress] media upload [--content-type TYPE] [--tag TAG] [--no-wait] [--poll-ms MS] [--no-transcode] [--codec h264|hevc] [--max-fps N] @@ -27,38 +27,41 @@ media upload-batch --state FILE [--concurrency N] media show media download [--output FILE] media list [--tag TAG] [--primitive image|video] -media update (--tag TAG | --clear-tag) --if-match REVISION -media delete --if-match REVISION +media update (--tag TAG | --clear-tag) --expect-rev REVISION +media delete --expect-rev REVISION compose catalog compose render [--output DIRECTORY] [--combined] [--target-width PX --target-height PX] [--safe-area] [--open] [--lint-only] compose batch --output DIRECTORY [--only ID] [--target-width PX --target-height PX] [--safe-area] [--lint-only] +playlist init --name NAME --output FILE [--screen ID] + [--target-width PX --target-height PX] [--duration-ms MS] [--fit contain|cover|fill] playlist validate playlist create -playlist update --if-match REVISION +playlist update --expect-rev REVISION playlist export --output DIRECTORY -playlist import [--name NAME] [--update ID --if-match REVISION] -playlist show +playlist import [--name NAME] [--update ID --expect-rev REVISION] +playlist show [--output FILE | --editable] playlist list -playlist delete --if-match REVISION +playlist delete --expect-rev REVISION screen update [--name NAME] [--playlist-id ID] [--timezone ZONE] - --if-match REVISION + --expect-rev REVISION screen list [--state archived] screen show -screen assign --playlist-id ID --if-match REVISION -screen set-timezone --timezone ZONE --if-match REVISION -screen archive --if-match REVISION -screen unarchive --if-match REVISION -screen delete --if-match REVISION -screen rotate-public-id --if-match REVISION +screen publish --expect-rev REVISION +screen assign --playlist-id ID --expect-rev REVISION +screen set-timezone --timezone ZONE --expect-rev REVISION +screen archive --expect-rev REVISION +screen unarchive --expect-rev REVISION +screen delete --expect-rev REVISION +screen rotate-public-id --expect-rev REVISION screen toast --text TEXT [--level info] [--duration-ms MS] screen screenshot [--output FILE] [--timeout MS] [--poll-ms MS] kv get --application-id ID -kv set --application-id ID --json-value JSON [--if-match REVISION] -kv set --application-id ID --file FILE --content-type TYPE [--if-match REVISION] -kv set --application-id ID --value-base64 BASE64 --content-type TYPE [--if-match REVISION] -kv delete --application-id ID --if-match REVISION +kv set --application-id ID --json-value JSON [--expect-rev REVISION] +kv set --application-id ID --file FILE --content-type TYPE [--expect-rev REVISION] +kv set --application-id ID --value-base64 BASE64 --content-type TYPE [--expect-rev REVISION] +kv delete --application-id ID --expect-rev REVISION kv list --application-id ID comment show screen comment show playlist [--page PAGE_ID] @@ -92,3 +95,5 @@ Global flags include `--json`, `--human`, `--api-url URL`, `--config PATH`, On `revision_conflict`, fetch the resource, reapply the intended change, and retry with the returned revision. On an ambiguous transport failure, reuse the same idempotency key. + +`--if-match` remains an alias for `--expect-rev`; do not supply both. diff --git a/skills/screenrig/references/compose.md b/skills/screenrig/references/compose.md index 9e209f13..3b3ceae1 100644 --- a/skills/screenrig/references/compose.md +++ b/skills/screenrig/references/compose.md @@ -329,3 +329,5 @@ cropping. Eight-digit hex is how the page stays transparent and the plate keeps alpha. Layered region PNGs can sit as image primitives at their manifest rects. Inspect with `--combined`; default agent output stays layered. A presentable poster is one generated `image` primitive, not photo plus overlay. + +After uploading finished slide images, pass their media IDs in playback order to `playlist init`, inspect the preview, then use `screen publish`. See [playlists](playlists.md). diff --git a/skills/screenrig/references/media.md b/skills/screenrig/references/media.md index a8af6bfb..0a726d3c 100644 --- a/skills/screenrig/references/media.md +++ b/skills/screenrig/references/media.md @@ -164,7 +164,7 @@ On a build that converts: object. Hyphens are rejected; `ExecIntro2026` is valid and `exec-intro` is not. `media list --tag TAG [--primitive image|video]` filters by that tag and is the reliable filename → id map after upload. - `media update (--tag TAG | --clear-tag) --if-match REVISION` changes + `media update (--tag TAG | --clear-tag) --expect-rev REVISION` changes or clears it. Untagged objects are omitted when `--tag` is present on `media list`. - The conversion runs `ffmpeg` and `ffprobe`. They must be on `PATH`, or their @@ -250,3 +250,5 @@ problem code and status. Run `doctor` for local diagnostics. Use `doctor --repair-config` only to repair an existing credential file whose permissions are too broad. + +For long or exact-copy prompts, use `media generate --prompt-file FILE` (or `-` for stdin) instead of `--prompt`. For full-screen playback of ready media IDs, use `playlist init` and `screen publish`; see [playlists](playlists.md). diff --git a/skills/screenrig/references/operations.md b/skills/screenrig/references/operations.md index b1dff90e..5dcb0e67 100644 --- a/skills/screenrig/references/operations.md +++ b/skills/screenrig/references/operations.md @@ -5,11 +5,11 @@ ```bash screenrig screen list screenrig screen show scr_EXAMPLE -screenrig screen update scr_EXAMPLE --name "Lobby" --playlist-id pl_EXAMPLE --if-match REVISION -screenrig screen assign scr_EXAMPLE --playlist-id pl_EXAMPLE --if-match REVISION -screenrig screen set-timezone scr_EXAMPLE --timezone America/Los_Angeles --if-match REVISION -screenrig screen archive scr_EXAMPLE --if-match REVISION -screenrig screen unarchive scr_EXAMPLE --if-match REVISION +screenrig screen update scr_EXAMPLE --name "Lobby" --playlist-id pl_EXAMPLE --expect-rev REVISION +screenrig screen assign scr_EXAMPLE --playlist-id pl_EXAMPLE --expect-rev REVISION +screenrig screen set-timezone scr_EXAMPLE --timezone America/Los_Angeles --expect-rev REVISION +screenrig screen archive scr_EXAMPLE --expect-rev REVISION +screenrig screen unarchive scr_EXAMPLE --expect-rev REVISION screenrig screen toast scr_EXAMPLE --text "Updated lobby loop" --level info screenrig screen screenshot scr_EXAMPLE --output ./lobby.webp ``` @@ -59,7 +59,7 @@ screenrig comment delete screen scr_EXAMPLE ``` `--json-value` is a JSON object. `--file` reads a JSON object from disk. -Exactly one of those on set. Last write wins; do not send `--if-match`. +Exactly one of those on set. Last write wins; do not send `--expect-rev`. Unset show is `{ "comments": null }`. ## Events diff --git a/skills/screenrig/references/playlists.md b/skills/screenrig/references/playlists.md index 57e9056c..3217086d 100644 --- a/skills/screenrig/references/playlists.md +++ b/skills/screenrig/references/playlists.md @@ -1,5 +1,65 @@ # Playlists, motion, schedules and bundles +## Prepare, publish, and edit playlists + +For ready images and videos, prepare a full-screen playlist in playback order: + +```sh +screenrig playlist init med_POSTER med_VIDEO --name "Lobby loop" --screen scr_LOBBY --output lobby.json +screenrig playlist preview lobby.json --output preview --contact-sheet +screenrig screen publish scr_LOBBY lobby.json --expect-rev 7 +``` + +Inspect the preview before publishing. `playlist init` reads media metadata and +screen observations but makes no remote writes. It creates one page per media ID, +with `contain` fit, a black background, and a 200 ms crossfade. Images last 8000 ms; +videos are muted, do not loop, and advance on completion. Use `--duration-ms` for +image duration and `--fit contain|cover|fill` for content fit. Override the canvas +with both `--target-width` and `--target-height`; these also work without `--screen`. +Unknown or multiple reported surfaces require explicit dimensions. Output files +must not already exist. + +`screen publish ` creates a new playlist, assigns it using the +expected **screen** revision, and reads back the assignment. It does not update an +existing playlist by name. A name collision requires a different name or an +explicit `playlist update`. Its JSON result reports `playlist_id`, +`playlist_revision`, `screen_id`, `screen_revision`, `assignment_verified`, and +`playback_verified`. Assignment verification does not prove playback; request and +inspect a screenshot and relevant playback evidence separately. + +Publishing saves a private local journal automatically. After an ambiguous failure, +repeat the identical command and input with the same config to resume. If playlist +creation succeeded before assignment failed, the error identifies the created +playlist. Do not delete it or start another create to recover. A revision conflict +requires inspecting the screen and reconciling the intended assignment; an already +created playlist can be assigned explicitly with `screen assign`. Publishing never +silently refreshes the expected revision. Unfinished recovery stops after the +24-hour server idempotency window; inspect and reconcile before making more writes. + +To edit an existing playlist: + +```sh +screenrig playlist show pl_EXISTING --output lobby.json +screenrig playlist update pl_EXISTING lobby.json --expect-rev 4 +``` + +`playlist show --output` writes the editable `{name, pages}` document and returns +its path, `playlist_id`, and source `revision` on stdout. Use that returned revision +for the update. It preserves dynamic selectors, schedules, motion, and pinned +application releases, removing server-derived media and timing fields. Comments +remain separate. Plain `playlist show` is an inspection response; `--editable` +without `--output` returns `data.document`, `data.playlist_id`, and `data.revision`. +Updating a playlist affects every screen assigned to it. + +Playlist validate, create, update, preview, and screen publish accept `-` as their +input file to read stdin. JSON envelopes are never written into authored files. +`--expect-rev` is the preferred revision spelling; `--if-match` remains a compatible +alias. Supply only one. The HTTP revision contract is unchanged. + +Generation accepts either `--prompt TEXT` or `--prompt-file FILE`, including +`--prompt-file -` for stdin. The file is the complete prompt, with no trimming; +the existing 4000-character limit applies. Prompts are excluded from diagnostics. + ## Playlist writes Four wire primitives exist: `image`, `video`, `iframe`, and `application`. @@ -18,11 +78,10 @@ and `primitives`. A primitive is flat: `id`, a `primitive` field naming one of the four, that primitive's own fields, then `rect`, `layer`, `content_fit`, optional `enter`, and optional `motion`. There is no nested content object. -Keep the authored playlist JSON as the source of truth. `playlist show` is an -inspection payload, not a guaranteed write document: the server may add -resolved/defaulted fields such as `advance.max_ms` and -`selector.one_at_a_time`. Do not feed a show payload directly to `playlist -create` or `playlist update`; edit and submit the authored file instead. +Keep the authored playlist JSON as the source of truth. To obtain one from an +existing playlist, use `playlist show ID --output FILE`; the returned envelope +includes the source revision. Ordinary `playlist show` remains an inspection +response and must not be submitted as a write document. Image and video primitives require a `selector`. `iframe` and `application` do not take one. Do not put `media_id` on the primitive itself; it belongs @@ -301,7 +360,7 @@ owns it. `{"days": ["fri"], "start": "22:00", "end": "02:00"}` runs Friday 22:00 through Saturday 02:00. ```bash -screenrig screen set-timezone scr_EXAMPLE --timezone America/Los_Angeles --if-match 3 +screenrig screen set-timezone scr_EXAMPLE --timezone America/Los_Angeles --expect-rev 3 ``` `--timezone` is an IANA identifier such as `America/Los_Angeles` or @@ -316,7 +375,7 @@ referenced image or video rendition together. ```bash screenrig playlist export pl_EXAMPLE --output ./lobby-bundle screenrig playlist import ./lobby-bundle -screenrig playlist import ./lobby-bundle --update pl_TARGET --if-match REVISION +screenrig playlist import ./lobby-bundle --update pl_TARGET --expect-rev REVISION ``` The export destination must not exist. The bundle contains @@ -328,8 +387,8 @@ names are unique per account, so importing an account's own export unchanged is refused with 409 `resource_conflict` ("playlist name is already in use"); that problem's `error.next` names the two ways forward. `--name NAME` (1 to 120 characters) imports the bundle as a new playlist under that name; -`--update ID --if-match REVISION` replaces the existing playlist instead. -Updating requires both `--update` and the current `--if-match` revision. +`--update ID --expect-rev REVISION` replaces the existing playlist instead. +Updating requires both `--update` and the current `--expect-rev` revision. ```bash screenrig playlist import ./lobby-bundle --name "Lobby loop (copy)"