From e3e6ab2cd1fc1cb0d287febab68f2606557a7eb3 Mon Sep 17 00:00:00 2001 From: KDR Date: Tue, 11 Aug 2026 23:29:32 -0700 Subject: [PATCH 1/2] =?UTF-8?q?Prepare=20for=20tinycloud=200.3.20:=20playa?= =?UTF-8?q?ble=20Slack=20unfurls=20+=20entity=20search=20(skill=20floor=20?= =?UTF-8?q?=E2=86=92=200.3.20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tinycloud 0.3.20 (SDK 0.7.24) adds playable Slack unfurls and entity search (features 42→45, verbs stay 17): - `--link-preview` on `publish` / `publish video` gains a `player` level — the pasted link unfurls in Slack with an inline player via the Cloudglue Slack app (implies the `full` card). A private share plays itself; a site plays the hero share set with the new site-only `--preview-share ` flag (requires player; "" clears; card-only without one). Public sites take `player` too (their hero must be a public share); public shares already unfurl playable with no flag. Private content plays only in Slack workspaces the account owner connected in the Cloudglue dashboard, anyone who can see the Slack message can play it (every doc surface says ask the user first), and downgrading revokes playback in already-posted unfurls. - entities collections become first-class probe/ask targets (extractions indexed free; tinycloud-created ones are segment-level by default → segment hits with real timestamps), omitting `--scope` is now AUTO (the search picks the level, so probing doesn't require knowing the collection type), and `collections show` file rows gain `searchable_status` (the metadata/entity search-index readiness signal). Because the skill teaches the new flag values and probe semantics, the floor rises to 0.3.20: tinycloud-skill.json min_version/supported_range + required_features (+publish.link.preview.player.v1, +probe.entities.v1, +probe.scope.auto.v1) with preflight.sh kept identical (the CI sync check passes). npm launcher version → 0.3.20 (1:1 with the binary). SKILL.md and reference/verbs.md teach the new surface; CLAUDE.md records the release. Verified: npm test 42/42 (fixture CDN) and 42/42 against a real 0.3.20 darwin-arm64 dist tarball; scripts/smoke-test.sh all-pass against the extracted 0.3.20 binary (EXPECTED_VERSION=0.3.20); preflight.sh exits 0 against it (all 34 required features present); shellcheck clean; claude plugin validate passes. --- CLAUDE.md | 32 ++++++++++ package.json | 2 +- skills/tinycloud/SKILL.md | 43 ++++++++++--- skills/tinycloud/reference/verbs.md | 89 ++++++++++++++++++++++----- skills/tinycloud/scripts/preflight.sh | 4 +- skills/tinycloud/tinycloud-skill.json | 9 ++- 6 files changed, 150 insertions(+), 29 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a06bc3a..db026f3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -287,6 +287,38 @@ failures: it gains the 0.3.7 chat-retry layer (`TINYCLOUD_MODEL_RETRIES` now covers both agents), and an errored turn is truthful — `✖ turn failed` on stderr, an `error` field in the `--json` trace, exit 1 (previously a backend blip could exit 0 with an empty, zero-usage trace). +0.3.20 picks up SDK 0.7.24 and adds **playable Slack unfurls and entity +search** (features 42→45, verbs stay 17): `--link-preview` on `publish` and +`publish video` gains a `player` level (feature +`publish.link.preview.player.v1`) — the pasted link unfurls in Slack with an +INLINE PLAYER via the Cloudglue Slack app instead of a static card. On a +private share, `player` makes the share itself play; a site plays its hero +share, set with the new site-only `--preview-share ` flag (requires +`--link-preview player`; `""` clears; without a hero the unfurl stays +card-only). Unlike `full`, `player` matters on BOTH site visibilities — a +public site's hero must be a public share, and public *shares* already unfurl +playable with no flag. Private content plays only in Slack workspaces the +account owner connected in the Cloudglue dashboard; `player` implies the +`full` card, anyone who can see the Slack message can play the video (every +doc surface says ask the user first), and downgrading revokes playback in +already-posted unfurls. The card-field flags now accept `full` or `player`; +the hero comes back as `data.preview_share_id` and in `publish list` rows as +`link-preview=player hero=`. Entity search (features `probe.entities.v1` +/ `probe.scope.auto.v1`): an `entities` collection is a first-class +`probe`/`ask` target — each file's latest completed extraction is indexed +into search documents for free; video-level extractions search at `--scope +file`, segment-level at `--scope segment` (tinycloud-created entities +collections are segment-level by default), and omitting `--scope` is now AUTO +(the search picks the level per scope, so probing no longer requires knowing +the collection type — previously an omitted scope meant segment-only). +`collections show` file rows gain `searchable_status` (the metadata/entity +search-index readiness signal, distinct from the enrichment `status`), and +the SDK bump also makes `publish video list`'s file filter bind server-side +(the SDK previously sent camelCase query keys the API ignored; tinycloud's +client-side filter masked it). Because the skill teaches the new +flag values and probe semantics, the floor was raised to 0.3.20 (same +merge-after-CDN gate — the dist PR merges only after CDN `channels.stable` = +0.3.20). The host-level `profile` verb and the leading global flags `--home`/`--profile` (also `$TINYCLOUD_HOME`; 0.3.3+) relocate state and are intentionally absent from `commands --json` — like the launcher's install/update, they're CLI/host diff --git a/package.json b/package.json index 90dea21..e809e1f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cloudglue/tinycloud", - "version": "0.3.19", + "version": "0.3.20", "description": "Agent CLI for deep video and image work, by Cloudglue. Downloads the tinycloud binary on first run.", "bin": { "tinycloud": "bin/tinycloud.js" diff --git a/skills/tinycloud/SKILL.md b/skills/tinycloud/SKILL.md index 6844347..d7b1556 100644 --- a/skills/tinycloud/SKILL.md +++ b/skills/tinycloud/SKILL.md @@ -88,7 +88,8 @@ tinycloud caption ./demo.mp4 --format srt --transcript -o ./tinycloud-output/cap # Find things: local keyword search vs cloud semantic search vs Q&A tinycloud search "pricing" --in ./demo.mp4 --json -tinycloud probe "product demo moments" --in collection:col_123 --scope segment --limit 5 --json +tinycloud probe "product demo moments" --in collection:col_123 --limit 5 --json # no --scope = AUTO (0.3.20+): the search picks the right level +tinycloud probe "product demo moments" --in collection:col_123 --scope segment --json # explicit level still forces it tinycloud probe "renewal call" --in collection:col_123 --scope file \ --filter "source_metadata.parties.email~=%@acme.com" --json # filter by stored fields (0.3.15+) tinycloud ask "What objections came up?" --in ./demo.mp4 --json @@ -126,12 +127,14 @@ tinycloud library collections create my-desc --type media-descriptions --describ # The API default is speech+summary ONLY (no visuals/scene text) and it is IMMUTABLE after create — # pass --describe full when visual probe/ask queries matter. `show` reports describe_config. tinycloud library collections add ./demo.mp4 --to col_desc --json # uploads a local source first; enrichment is async (pending) -tinycloud library collections show col_desc --json # poll files[].status until completed, then query — +tinycloud library collections show col_desc --json # poll files[].status until completed, then query +# (metadata/entities rows also report files[].searchable_status, 0.3.20+ — completed = probe/ask can find the file); # the collection's --type decides the read verb (each line below is a DIFFERENT, matching-type collection): tinycloud ask "what's discussed?" --in collection:col_desc --json # media-descriptions → ask / probe / search tinycloud face search ./person.jpg --in collection:col_faces --json # face-analysis → face list / face search -tinycloud library collections entities col_ents ./demo.mp4 --json # entities → collections entities -tinycloud probe "kickoff" --in collection:col_meta --scope file --json # metadata (free, no processing) → probe --scope file / ask +tinycloud library collections entities col_ents ./demo.mp4 --json # entities → collections entities / probe / ask (0.3.20+) +tinycloud probe "acme corp" --in collection:col_ents --json # entities are indexed for search free after each extraction +tinycloud probe "kickoff" --in collection:col_meta --scope file --json # metadata (free, no processing) → probe / ask (file-level) tinycloud query "top entities by file count?" --in collection:col_ents --json # ANY type → query for analytics (count/group/join, 0.3.17+) tinycloud library collections remove cloudglue://files/ --from col_desc --json tinycloud library collections delete col_desc --json @@ -152,6 +155,9 @@ tinycloud publish video ./demo.mp4 --visibility public --json tinycloud publish video ./demo.mp4 --clip-start 18 --clip-end 33 --json # Hard clip — the share page plays ONLY the moment (0.3.8+) tinycloud publish video ./demo.mp4 --clip-start 18 --clip-end 33 --clip-only --json +# Playable Slack unfurl (0.3.20+, ASK THE USER FIRST): the pasted link plays inline in Slack +tinycloud publish video ./demo.mp4 --visibility private --link-preview player --json +tinycloud publish ./site --link-preview player --preview-share --json # site link plays its hero share ``` Per-verb details and all flags: [reference/verbs.md](reference/verbs.md). @@ -208,10 +214,23 @@ Authoring your own recipes: [reference/workflow-authoring.md](reference/workflow added to collections. Local `search` can match cached `see` results. - Do not pass `--background` to `ask`; background jobs exist only for tracked async ops (`watch`, `see`, `extract`). +- `probe`/`ask` scope (0.3.20+): omit `--scope` for AUTO — the search picks + the right level for the collection (media, metadata, or entities) itself, + so you no longer need to know a collection's type before probing it. An + explicit `--scope` still forces a level: `metadata` and video-level + `entities` collections are file-level (`--scope segment` errors); + segment-level `entities` collections search at `--scope segment` — and + collections created by `collections create --type entities` are + segment-level by default. +- Entity search (0.3.20+): an `entities` collection is a first-class + `probe`/`ask` target — each file's latest completed extraction is indexed + into search documents for free. `probe` FINDS entity content (segment hits + carry real timestamps); `query` still MEASURES it. Wait for + `files[].searchable_status == "completed"` in `collections show` before + expecting hits. - `probe --filter` works only with a collection scope (`--in - collection:col_…`), and a `metadata` collection is file-level — probe it - with `--scope file` (segment scope errors). `source_metadata.*` filters are - file-level facts too, so pair them with `--scope file`. + collection:col_…`). `source_metadata.*` filters are file-level facts, so + pair them with `--scope file`. - `query` (0.3.17+) is for analytics, not search: when the task is to COUNT, GROUP, rank, or join across a collection ("how many…", "which … most", "total hours per host"), reach for `query`, not `probe`/`ask`. Run `query @@ -265,6 +284,16 @@ Authoring your own recipes: [reference/workflow-authoring.md](reference/workflow link (content and playback stay sign-in gated), and platforms cache per exact URL, so turning it back off does not retract posted cards. Details in [reference/verbs.md](reference/verbs.md). +- Playable Slack unfurls (0.3.20+): `--link-preview player` upgrades the + Slack card to an **inline player** (via the Cloudglue Slack app; implies the + `full` card). A private share plays itself; a site — public or private — + plays the hero share set with `--preview-share ` (a public site's + hero must be a public share; public *shares* already unfurl playable, no + flag needed). Private content plays only in Slack workspaces the account + owner has connected in the Cloudglue dashboard. ⚠️ Anyone who can see the + Slack message can play the video — always ask the user before opting + private content in; downgrading to `full`/`none` revokes playback in + already-posted unfurls. Details in [reference/verbs.md](reference/verbs.md). - Live-API components (0.3.6+; the fuller v8–v12 surface is taught from 0.3.18): the same embed script also defines collection-scoped, **private-site-only** elements that let viewers search/chat/query inside a diff --git a/skills/tinycloud/reference/verbs.md b/skills/tinycloud/reference/verbs.md index b0d840a..92d2c69 100644 --- a/skills/tinycloud/reference/verbs.md +++ b/skills/tinycloud/reference/verbs.md @@ -155,11 +155,32 @@ place during the scan, nothing is re-billed). ### probe — semantic search (cloud) ```bash -tinycloud probe "" --in collection:col_… [--scope file|segment] [--limit 20] +tinycloud probe "" --in collection:col_… [--limit 20] # no --scope = AUTO (0.3.20+) +tinycloud probe "" --in collection:col_… --scope file|segment # force a level tinycloud probe "" --in collection:col_… --scope file \ --filter "source_metadata.host_email=kevin@acme.com" --filter "source_metadata.tags*=demo,intro" ``` +**Auto scope (0.3.20+, feature `probe.scope.auto.v1`)**: omit `--scope` and +the search picks the right level for the collection itself (and can fan out +to file + segment plans and fuse the results) — so a bare +`probe "" --in collection:` works on media-descriptions, metadata, and +entities collections alike, without knowing the collection's type first. An +explicit `--scope` forces the level and must be supported by the collection: +`metadata` and video-level `entities` collections are file-level +(`--scope segment` errors); segment-level `entities` collections search at +`segment`. + +**Entity search (0.3.20+, feature `probe.entities.v1`)**: an `entities` +collection is a first-class probe target — each file's latest completed +extraction is indexed into search documents for free after the extract job. +Video-level extractions surface as file hits; segment-level ones as segment +hits with real start/end times (citations resolve like media segments) — +collections created by `library collections create --type entities` are +segment-level by default, so expect segment hits. Wait +for `files[].searchable_status == "completed"` in `collections show` before +expecting hits. `probe` FINDS entity content; `query` MEASURES it. + `--filter ` (0.3.15+, feature `probe.filters.v1`; repeatable, ANDed, collection scopes only) narrows the searched set by stored fields before semantic ranking. Criteria are ANDed — with each other and with any @@ -175,9 +196,9 @@ through arrays match when ANY element matches; ISO datetime fields compare as strings with `<`/`>`), `metadata.*` (user metadata from `collections add --metadata`), `video_info.duration_seconds|has_audio`, and `file.filename|bytes|uri|created_at|id`. source_metadata filters are -file-level facts — pair them with `--scope file`. Probing a `metadata` -collection requires `--scope file` (its documents are file-level; segment -scope errors). +file-level facts — pair them with `--scope file`. A `metadata` collection is +file-level: probe it with `--scope file` or no `--scope` at all (auto); +explicit `--scope segment` errors. ### ask — grounded Q&A (cloud) @@ -186,6 +207,9 @@ tinycloud ask "" --in [--include-citations[=false]] ``` +`ask` accepts the same collection scopes as `probe` — media-descriptions, +rich-transcripts, metadata, and (0.3.20+) entities collections; the answer +grounds itself in whichever document kinds the collection carries. Never pass `--background` to `ask`. ### query — structured analytics over collections (cloud, 0.3.17+) @@ -370,7 +394,12 @@ completed`; `failed` is terminal) — a query before then returns empty or error `has_more`, and `next_page_token` — page with `--page-token` until the token is null (0.3.16+, feature `library.collections.pagination.v1`; earlier binaries capped every listing at 50 with a wrong `has_more: false` and a -redacted token, so a >50-file collection could not be enumerated). +redacted token, so a >50-file collection could not be enumerated). Each file +row's `status` is the enrichment readiness (poll to `completed` before +querying); on metadata and entities collections rows also carry +`searchable_status` (0.3.20+) — the search-index readiness for the file's +metadata/entity documents (`completed` = findable via `probe`/`ask`; it can +lag `status` briefly while docs index). The collection's `--type` decides which verb reads it (every type follows the same `create → add → poll show → query → delete` lifecycle): @@ -379,9 +408,9 @@ same `create → add → poll show → query → delete` lifecycle): |---|---| | `media-descriptions` (default) | `ask` / `probe` / `search` (`--in collection:`) | | `face-analysis` | `face list` / `face search` | -| `entities` (needs `--prompt`/`--schema`) | `library collections entities ` | +| `entities` (needs `--prompt`/`--schema`) | `library collections entities `; also `probe` / `ask` (0.3.20+ — entities are search-indexed free) | | `rich-transcripts` | `collections sync --artifacts transcripts` | -| `metadata` (0.3.15+, free) | `probe --scope file` / `ask` | +| `metadata` (0.3.15+, free) | `probe` / `ask` (file-level; omit `--scope` or use `--scope file`) | Every type is additionally queryable with `query` (0.3.17+) for analytics — counts, group-bys, joins over file attributes, user/connector metadata, and @@ -397,8 +426,9 @@ index connector `source_metadata` plus user `--metadata` fields into file-level search documents WITHOUT downloading or processing the media — indexing is free and near-instant (no describe/transcribe jobs, so `add` readiness is quick). Add google-drive, dropbox, zoom, gong, recall, grain, or -iconik URIs/share links (or already-synced files) and query with -`probe --scope file` (segment scope errors) or `ask`, using `--filter` on +iconik URIs/share links (or already-synced files) and query with `probe` +(omit `--scope` for auto, or `--scope file`; explicit segment scope errors) +or `ask`, using `--filter` on `source_metadata.*`/`metadata.*` paths to narrow. Use one to triage a large connector library (titles, participants, dates, tags) before paying for full processing in a `media-descriptions` collection. @@ -481,7 +511,8 @@ tinycloud workflow [--param k=v] [--segment ] [--out ] ```bash tinycloud publish [--name ] [--visibility public|private] - [--link-preview none|full] [--preview-title ] [--preview-image ] --json + [--link-preview none|full|player] [--preview-title ] [--preview-image ] + [--preview-share ] --json tinycloud publish list --json # sites for this account, with URLs tinycloud publish unpublish --json # site_id, site name, or the --name label ``` @@ -529,10 +560,12 @@ completely differently: `--link-preview` is flippable on an **existing** site without republishing content: the run reports `action: "settings-only"` (a settings PATCH, no re-upload, no new version). The state comes back as `data.link_preview` (plus -`data.preview_title` / `data.preview_image_url`) and shows in `publish list` -rows as `link-preview=full`. `--preview-title`/`--preview-image` require -`--link-preview full`, and a non-absolute `--preview-image` errors before any -upload. +`data.preview_title` / `data.preview_image_url` / `data.preview_share_id`) +and shows in `publish list` rows as `link-preview=full` or +`link-preview=player hero=`. `--preview-title`/`--preview-image` require +`--link-preview full` or `player`, `--preview-share` requires +`--link-preview player`, and a non-absolute `--preview-image` errors before +any upload. ⚠️ **Ask the user before opting a private site in.** `--link-preview full` makes the card title, the site description, and the card image readable by @@ -542,12 +575,26 @@ or cookies; the site stays sign-in gated). Platforms cache per exact URL and rehost the image, so flipping back to `none` stops *future* unfurls but does not retract already-posted cards. +**Playable Slack unfurls (0.3.20+, `publish.link.preview.player.v1`)** — +`--link-preview player` upgrades the Slack unfurl from a static card to an +**inline player** (via the Cloudglue Slack app; other platforms still show +the card). It implies the `full` card, so every card rule above applies. A +site plays its **hero share**, set with `--preview-share ` (a share +id from `publish video`; without one the unfurl stays card-only; pass `""` to +clear). Unlike `full`, `player` matters on **both** visibilities: a public +site's hero must be a **public** share, and a private site's hero plays only +in Slack workspaces the account owner has connected in the Cloudglue +dashboard (Settings → Slack) — everywhere else the link falls back to the +ordinary card. ⚠️ Anyone who can see the Slack message can play the video — +ask the user before opting private content in. Downgrading to `full`/`none` +revokes playback in already-posted unfurls (posted cards are not retracted). + ### publish video — share a video ```bash tinycloud publish video [--visibility public|private] # default public [--name ] [--segment-id <id>] [--clip-start <s> --clip-end <e> [--clip-only]] - [--link-preview none|full] --json + [--link-preview none|full|player] --json tinycloud publish video list [--in <source>] [--visibility public|private] --json tinycloud publish video unpublish <share-id | source> --json # --visibility disambiguates ``` @@ -591,10 +638,20 @@ feature id. "Sign in" card unless you pass `--link-preview full`, which serves bots a metadata-only stub built from those same three fields. It comes back as `data.share.link_preview`, and re-running flips it on an existing share - (a PATCH — no new share). Playback stays sign-in gated in every mode. + (a PATCH — no new share). Playback outside Slack stays sign-in gated in + every mode. ⚠️ Ask the user first: `full` makes the share's title, description, and thumbnail readable by anyone who fetches the link, and platforms cache per exact URL, so turning it back off does not retract already-posted cards. +- Playable Slack unfurls (0.3.20+, `publish.link.preview.player.v1`): + `--link-preview player` on a PRIVATE share lets the share itself play + inline when its link is pasted in a Slack workspace the account owner has + connected in the Cloudglue dashboard (implies the `full` card; elsewhere + the link falls back to the card). A PUBLIC share already unfurls playable + wherever the Cloudglue Slack app is installed — no flag needed. ⚠️ Anyone + who can see the Slack message can play the video — ask the user before + opting a private share in. Downgrading to `full`/`none` revokes playback in + already-posted unfurls. When generating custom site HTML around a `<cg-video>` embed, use the component's built-ins instead of reinventing them. It defaults to a diff --git a/skills/tinycloud/scripts/preflight.sh b/skills/tinycloud/scripts/preflight.sh index 65ae326..1f402d8 100755 --- a/skills/tinycloud/scripts/preflight.sh +++ b/skills/tinycloud/scripts/preflight.sh @@ -9,11 +9,11 @@ set -u # Mirror tinycloud-skill.json: min_version / supported_range upper bound # (CI diffs these against the manifest). -MIN_VERSION="0.3.18" +MIN_VERSION="0.3.20" MAX_VERSION_EXCLUSIVE="0.4.0" INSTALL_CMD='curl -fsSL https://app.cloudglue.dev/tinycloud.sh | bash' # Kept in sync with ../tinycloud-skill.json required_features (CI diffs them). -REQUIRED_FEATURES="envelope.v1 watch.v1 watch.speech.v1 see.v1 extract.v1 extract.images.v1 caption.v1 search.v1 probe.v1 probe.filters.v1 ask.v1 query.v1 query.export.v1 clip.v1 grab.v1 face.v1 jobs.v1 library.collections.v1 library.collections.create.v1 library.collections.mutate.v1 library.collections.entities.v1 library.collections.metadata.v1 library.collections.describe.v1 library.collections.pagination.v1 library.sync.url.v1 workflow.v1 publish.v1 publish.manage.v1 publish.video.v1 publish.link.preview.v1 setup.v1" +REQUIRED_FEATURES="envelope.v1 watch.v1 watch.speech.v1 see.v1 extract.v1 extract.images.v1 caption.v1 search.v1 probe.v1 probe.filters.v1 probe.entities.v1 probe.scope.auto.v1 ask.v1 query.v1 query.export.v1 clip.v1 grab.v1 face.v1 jobs.v1 library.collections.v1 library.collections.create.v1 library.collections.mutate.v1 library.collections.entities.v1 library.collections.metadata.v1 library.collections.describe.v1 library.collections.pagination.v1 library.sync.url.v1 workflow.v1 publish.v1 publish.manage.v1 publish.video.v1 publish.link.preview.v1 publish.link.preview.player.v1 setup.v1" # 1) Binary present and responsive? if ! command -v tinycloud >/dev/null 2>&1; then diff --git a/skills/tinycloud/tinycloud-skill.json b/skills/tinycloud/tinycloud-skill.json index dc24eec..8047bc9 100644 --- a/skills/tinycloud/tinycloud-skill.json +++ b/skills/tinycloud/tinycloud-skill.json @@ -1,8 +1,8 @@ { - "skill_version": "0.3.19", + "skill_version": "0.3.20", "tinycloud": { - "min_version": "0.3.18", - "supported_range": ">=0.3.18 <0.4.0", + "min_version": "0.3.20", + "supported_range": ">=0.3.20 <0.4.0", "required_features": [ "envelope.v1", "watch.v1", @@ -14,6 +14,8 @@ "search.v1", "probe.v1", "probe.filters.v1", + "probe.entities.v1", + "probe.scope.auto.v1", "ask.v1", "query.v1", "query.export.v1", @@ -34,6 +36,7 @@ "publish.manage.v1", "publish.video.v1", "publish.link.preview.v1", + "publish.link.preview.player.v1", "setup.v1" ], "envelope_schema": "1", From eca9eab287237bf7059930c2774b573ad72ed128 Mon Sep 17 00:00:00 2001 From: KDR <kevd1337@gmail.com> Date: Wed, 12 Aug 2026 11:48:15 -0700 Subject: [PATCH 2/2] docs: live CDN now serves 0.3.20 (channels.stable = 0.3.20) --- CLAUDE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index db026f3..df430c5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -371,9 +371,9 @@ of printing JSON. Any script invoking the binary must redirect `</dev/null` metadata sync) vs live-CDN jobs (`Install + smoke` matrix, npx-against-CDN) which run only on push to main or manual dispatch — never on PRs, because a CDN gap would fail every PR. -- The live CDN serves 0.3.19 (latest aliases + v-prefixed pinned tarballs - for 0.3.0 through 0.3.19, with `manifest.json` + `.sha256` - sidecars; `channels.stable` = 0.3.19); all smoke legs are required. +- The live CDN serves 0.3.20 (latest aliases + v-prefixed pinned tarballs + for 0.3.0 through 0.3.20, with `manifest.json` + `.sha256` + sidecars; `channels.stable` = 0.3.20); all smoke legs are required. - `publish-npm.yml` (tag `v*`): asserts tag == package.json version → gates on `generate-manifest.mjs --check` against the live CDN → publishes via npm trusted publishing (OIDC, `id-token: write`, npm ≥ 11.5.1 — no token