* Require a 10–20 record sample and explicit approval before enrolling a full batch
`batch create` / `action execute-batch` fan out across every record in their
data source, so a config mistake and the full bill arrive together. Every
surface that can launch one now requires the same three steps: count the pool
for free, sample 10–20 records through the exact workflow and config, then ask
the user to approve the full enrollment with both the record count and the
credit estimate in the question.
The canonical gate lives in cargo-orchestration ("The sample gate"), with the
sampling mechanics per data kind — `kind: "filter"` + `limit`, `recordIds`, a
sliced `records` array, a truncated CSV — and the note that `kind: "segment"`
and `kind: "change"` take no limit, so they can't be sampled directly.
The GTM cost gate was a 1–3 row pilot, which can't produce a hit-rate, and
hit-rate is what drives the estimate. Split it: 1–3 rows proves one action's
config shape, 10–20 records before any batch. The approval message now states
how many records the full run enrolls alongside what they cost, and approval of
the sample is explicitly not approval of the full run.
Propagated to the router recap, gotchas, and interaction conventions (the gate
holds even when a batch arrives through cargo-orchestration or cargo-cdk with
no GTM framing), and to cargo-cdk (a deployed play's first batch, and the
per-run re-bill of a scheduled one). Aligned the downstream copy that quoted
the old 1–3 row pilot: the execution-planner agent, build-tam, and save-as-play
(whose play pilot was a single record).
Verified against the live CLI: `batch create --help` for where `limit` is
accepted, `segment list` for `recordsCount`/`filter`, and `file upload --file`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Bump plugin versions to 1.16.0 and regenerate skill-metadata.json files
Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Auree Aubert <aureeaubert@users.noreply.github.com>
* feat: native subagents + opt-in statusline
Rebased onto main (post #55): cargo-execution-planner and cargo-list-builder
ship as Claude Code plugin subagents (haiku tier; canonical role specs in
cargo-gtm/agents/ for every channel), plus hooks/cargo-statusline.mjs — an
opt-in statusline (workspace, credits, CLI pin state) whose render path is
cache-only with a detached refresh. README documents the settings.json wiring
and the plugin's subagent benefit. cargo -> 1.14.0 (manifests lockstep),
cargo-gtm -> 1.5.0 (list-builder + §2 fan-out routing). Metadata regenerated
over main's tree.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(statusline): exact semver pin match; single-flight refresh lock
- The pin check used a substring test, so 21.0.29 / 1.0.290 / 10.0.29 all
satisfied pin 1.0.29 and rendered as pinned. Extract the semver from
--version output and require exact equality.
- render() spawned a detached --refresh child on every call while the cache
was missing/stale, with no in-flight guard — frequent statusline updates
stacked overlapping cargo-ai processes until the first refresh landed. A
lock file created atomically (flag "wx", stale after 60s for crashed
children) makes refresh single-flight; the child releases it after writing
the cache, and a failed spawn frees it immediately.
Verified: 6 parallel cold renders spawn exactly 1 refresh child; lock releases
after the cache write; warm render never spawns; all tricky version shapes
(21.0.29, 1.0.290, 10.0.29, "Loading..." prefix) compare correctly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(statusline): refresh preserves the previous cache across failures
refresh() rebuilt the cache from scratch, so one transient CLI failure
blanked fields that were still valid (workspace, credits, pin state) and a
fresh `at` was stamped even when nothing was fetched — pushing the retry a
full TTL away. It now starts from the previous cache, overwrites a field only
on a successful fetch, and advances `at` only when at least one fetch
succeeded; a fully failed refresh leaves the file byte-identical so the next
render retries immediately (rate-limited by the refresh lock).
Verified with a stub cargo-ai (bypassing volta's PATH re-injection): total
failure leaves the cache byte-identical; partial failure (--version only)
keeps workspace/credits, updates the pin segment, advances the clock.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>