autoship ยท diff

git:20260725.d218524 to git:20260901.a877ac0

83 added, 68 removed. Audit A to A.

---
name: autoship
description: >-
- Runs the npm release flow for an existing changesets package: create a
+ Runs the npm release flow for an existing changesets package: write the
changeset, fix lint/type/test/format failures, push, watch CI, merge the
- Version Packages PR, watch publish, and verify npm. Use when asked to
- "release this", "publish this package", "autoship", "cut a release", or fix
- build failures inside a release flow. For feature PRs use pr-creator; for PR
- monitoring use pr-babysitter; for new packages use scaffold-cli.
+ Version Packages PR, watch the publish run, and verify the version on npm.
+ Diagnoses release-side failures: the Changeset Status check, changesets/action
+ v1 vs v2 inputs, and OIDC trusted-publishing auth. Use when asked to "release
+ this", "publish this package", "autoship", "cut a release", "bump and
+ publish", "merge the Version Packages PR", "why didn't it publish", or to fix
+ build failures inside a release flow. For feature PRs use pr-creator; for
+ watching a feature PR use pr-babysitter; for scaffolding a new package use
+ scaffold-cli.
---
# Autoship
Drive an npm release end to end: changeset, fix loop, push, CI watch, Version Packages PR merge, publish watch, npm verification.
- - **IS:** the full release pipeline for an existing changesets-based npm package, from writing the changeset file to confirming the new version on the registry.
- - **IS NOT:** opening a feature PR (use `pr-creator`), monitoring a feature PR for reviews, conflicts, or CI (use `pr-babysitter`), general build/type fixes outside a release flow, or scaffolding a new package (use `scaffold-cli`, which hands off to autoship for the first release).
+ - **IS:** the full release pipeline for an existing changesets-based npm package, from writing the changeset file to confirming the new version on the registry, plus diagnosing why a release run did not version or publish.
+ - **IS NOT:** opening a feature PR (use `pr-creator`), monitoring a feature PR for reviews, conflicts, or CI (use `pr-babysitter`), general build or type fixes outside a release flow, or scaffolding a new package (use `scaffold-cli`, which hands off to autoship for the first release).
## The Release Loop
One workflow, two successive runs. Misreading it as two workflows causes most autoship mistakes.
1. Push a commit containing a pending `.changeset/*.md` file to the default branch.
- 2. The release workflow runs: `changesets/action` sees pending changesets, runs `changeset version` in CI, and opens or updates a PR titled "Version Packages" on branch `changeset-release/main` with the `package.json` bump and `CHANGELOG.md` updates.
+ 2. The release workflow runs: `changesets/action` sees pending changesets, runs `changeset version` in CI, and opens or updates a PR on branch `changeset-release/<default-branch>` (title "Version Packages", suffixed "(next)" in pre mode) carrying the `package.json` bump and `CHANGELOG.md` entry.
3. Merge that PR once every check is green.
- 4. The same workflow runs again. With no pending changesets left, the action runs its `publish:` script (`changeset publish`), pushing tags and publishing to npm.
+ 4. The same workflow runs again. With no pending changesets left, the action runs its publish script (`changeset publish`), which publishes to npm and, by default, pushes the git tag and creates a GitHub release.
The local job ends at "push the changeset file". CI owns versioning and publishing; anything versioned locally breaks the loop (see Gotchas).
+ The action has two live majors with different input names: `@v1` takes `publish:`, `@v2` takes `publish-script:`. Read the `uses:` line before diagnosing a run that versioned but never published.
+
## Reference Files
| File | Read when |
|------|-----------|
- | `references/changeset-and-commit.md` | Writing the changeset file and running each quality gate non-interactively (Steps 1-2) |
- | `references/ci-polling.md` | Monitor scripts, CI failures, Changeset Status check (Steps 4-5) |
- | `references/version-pr-and-publish.md` | Finding/merging the Version Packages PR, watching publish (Steps 4-5) |
+ | `references/changeset-and-commit.md` | Steps 1-3: writing the changeset file, discovering and running gates non-interactively, staging the release commit |
+ | `references/ci-polling.md` | Step 4 and Step 5 watches: the Monitor tool, the commit watch script, failure classification, the Changeset Status check |
+ | `references/version-pr-and-publish.md` | Once CI is green: workflow shape, finding and merging the Version Packages PR, the publish run, npm verification, publish failure diagnosis |
+ | `evals/evals.json` | Only when changing this skill; never loads during a release |
## Intent Map
| Intent | Steps | Notes |
|--------|-------|-------|
- | Full autoship (ship / release / publish) | 1-5 | Default entry point. End-to-end through publish, no intermediate prompts |
+ | Full autoship (ship / release / publish) | 1-5 | Default entry point. End to end through publish, no intermediate prompts |
| Create changeset only | 1 | Stage a release without pushing |
- | Fix quality and push | 1-2 | Changeset + fixes + commit, no CI watch |
- | Watch CI only | 3-5 | Changes already pushed |
- | Merge version PR only | 4-5 | CI already passed; auto-merges once preconditions are met |
- | Fix compiler only | 2 | Inside an autoship/release flow only; no changeset needed |
+ | Fix gates and push | 1-3 | Changeset, fixes, commit, no CI watch |
+ | Watch CI only | 4-5 | Changeset already pushed |
+ | Merge Version Packages PR only | 4b-5 | CI already green; merges once preconditions hold |
+ | Fix gates only | 2 | Inside a release flow; no changeset needed |
+ | Diagnose a release that did not publish | read-only | Failure Recovery table plus `references/version-pr-and-publish.md` |
- If the user says "ship it" without explicit npm release context, route to `pr-creator`.
+ "Ship it" with no npm release context routes to `pr-creator`.
## Safety Tiers
- Invoking autoship is standing consent for the full release flow. Do not pause mid-flow to re-confirm; gate risky steps with objective preconditions instead.
+ Invoking autoship is standing consent for the full release flow. Do not pause mid-flow to re-confirm; gate risky steps on objective preconditions instead.
- - **Green (execute directly):** any read, including CI and PR state, `npm view`, pending changesets, `package.json` scripts, and git history or status.
- - **Yellow (announce, then execute):** writing changeset files, running lint/typecheck/test/format fixers, `git add/commit/push`, starting `Monitor` background watches, and `gh pr merge` of the Version Packages PR once its identity is confirmed and all checks are green.
- - **Red (explicit confirmation required):** force-pushing, history rewrites, any destructive git operation.
+ - **Green (execute directly):** reads: CI and PR state, `npm view`, pending changesets, `package.json` scripts, git history and status.
+ - **Yellow (announce in one line, then execute):** writing changeset files, running lint/type/test/format fixers, `git add/commit/push`, starting watches, and merging the Version Packages PR once its identity is confirmed and every check passes.
+ - **Red (explicit confirmation required):** force-pushes, history rewrites, repository settings changes, any destructive git operation.
## Workflow
Copy this checklist to track progress:
```text
Autoship progress:
- [ ] Step 1: Create changeset (default patch)
- [ ] Step 2: Fix lint, types, tests, format
- - [ ] Step 3: Commit + push changeset (do NOT run `changeset version`)
- - [ ] Step 4: Monitor CI and find/merge the Version Packages PR
+ - [ ] Step 3: Commit and push the changeset (never `changeset version` locally)
+ - [ ] Step 4a: Watch CI on the pushed commit
+ - [ ] Step 4b: Find and merge the Version Packages PR
- [ ] Step 5: Watch the publish run, verify on npm
```
### Step 1: Create changeset (default patch)
- Load `references/changeset-and-commit.md`.
- - Check for pending changesets: `ls .changeset/*.md 2>/dev/null | grep -v README.md`. If any exist, ask the user whether to add another or skip.
- - Default to `patch`; use `minor` or `major` only on explicit user instruction.
- - Write the changeset file directly (non-interactive agent mode); infer the summary from `git log --oneline -10`.
+ - Check for pending changesets: `ls .changeset/*.md 2>/dev/null | grep -v README.md`. If any exist, ask whether to add another or ship what is pending.
+ - Default to `patch`; `minor` or `major` only on explicit user instruction.
+ - Write the file directly (the interactive prompt needs a TTY); the summary is user-facing changelog text inferred from `git log --oneline -10`.
+ - `npx changeset status` validates the file: a misspelled package name fails here instead of in CI.
### Step 2: Fix lint, types, tests, format
- - Load `references/changeset-and-commit.md` (skip the changeset sections for the "Fix compiler only" intent).
- - Discover commands from `package.json` scripts (`build`, `typecheck`, `tsc`, `type-check`, `lint`, `test`, `format`); in non-npm repos check `Makefile`, `Cargo.toml`, `pyproject.toml`, `go.mod`.
- - Run gates in order: lint, typecheck, test, format.
- - Scope auto-fixers (`lint --fix`, `format`) to changed files where supported. After any fixer, check `git status`: broad scripts routinely reformat files outside your change (MDX is a frequent casualty). Revert unrelated churn with `git restore <path>` before continuing.
- - On failure, parse output for file, line, code, and message. Fix syntax errors first, then type errors, then lint errors. Fix one root cause at a time when errors cascade.
- - Retry each gate up to 5 fix iterations, reporting the remaining error count each pass. After 5 failures, stop and report (see Failure Recovery).
+ - Discover commands from `package.json` scripts (`check`, `lint`, `typecheck`, `test`, `format`, `fix`); in non-npm repos check `Makefile`, `Cargo.toml`, `pyproject.toml`, `go.mod`.
+ - Run lint, typecheck, test, format. After any code change, re-run from the first gate: a type fix routinely breaks lint, and a lint autofix can break a test.
+ - Scope auto-fixers to changed files where supported, then check `git status`: broad `fix`/`format` scripts reformat files outside the change (MDX is a frequent casualty). `git restore <path>` the unrelated churn.
+ - Cap the loop at 5 fix iterations per gate, reporting the remaining error count each pass; then stop and report (Failure Recovery).
- ### Step 3: Commit + push changeset
+ ### Step 3: Commit and push the changeset
- - Stage the changeset file and in-scope fixes only: `git add <paths>`, never `git add -A`. Sweep `git status --porcelain` for stray generated artifacts (e.g. a root `schema.gql` from a pre-commit hook) and unrelated fixer churn before committing.
+ - Stage the changeset file and in-scope fixes by explicit path; sweep `git status --porcelain` for hook artifacts (a root `schema.gql` is a known one) before committing.
- Commit (`chore: add <type> changeset for <package>`) and push.
- - Do NOT run `npx changeset version` locally. The pushed commit must still contain the pending `.changeset/*.md` file so CI's "Changeset Status" check passes and the Version Packages PR opens.
+ - The pushed commit must still contain `.changeset/*.md`. Running `changeset version` locally consumes it (see Gotchas).
- ### Step 4: Monitor CI and find/merge the Version Packages PR
+ ### Step 4a: Watch CI on the pushed commit
- - Load `references/ci-polling.md` and `references/version-pr-and-publish.md`.
- - Start a `Monitor` watch scoped to the pushed commit SHA, emitting state changes and a `TERMINAL:` line when every workflow run completes. Do not stop on an idle first poll; runs take time to queue.
- - On failure, classify via logs (`gh run view <id> --log-failed`): flaky/infra failures get `gh run rerun <id> --failed` up to 3 times; real failures get a fix, commit, push, and a fresh Monitor.
- - Once green, find the open PR titled "Version Packages" on branch `changeset-release/main`. If absent, start a second Monitor that polls for it, capped at 10 minutes.
- - Verify ALL merge preconditions:
- - PR title is exactly "Version Packages" OR head branch is `changeset-release/main`. Never merge any other PR.
- - Every check reports `bucket: pass` via `gh pr checks <number> --json name,bucket`.
- - `gh pr view <number> --json mergeable` reports `MERGEABLE` (not `CONFLICTING` or `UNKNOWN`; on `UNKNOWN`, wait briefly and re-query).
- - Announce in one line ("Merging Version Packages PR #N: <package>@<version>"), then `gh pr merge <number> --squash --delete-branch`. No confirmation pause; invoking autoship is the consent.
- - If any precondition fails, stop and report. Do not merge.
+ - Load `references/ci-polling.md`.
+ - Start the commit watch on the pushed SHA. It emits a line per state change and one `TERMINAL:` line when every run for that commit (CI and the release workflow) completes. An idle first poll is normal; runs take time to queue.
+ - On failure, classify from `gh run view <id> --log-failed`: flaky or infra gets `gh run rerun <id> --failed` (max 3); a real failure gets a fix, commit, push, and a fresh watch on the new SHA.
+ ### Step 4b: Find and merge the Version Packages PR
+
+ - Load `references/version-pr-and-publish.md`.
+ - Find the open PR whose head is `changeset-release/<default-branch>`. If absent, run the PR-wait watch (10-minute cap).
+ - Merge only when all three hold:
+ - Head branch is `changeset-release/<default-branch>` (title normally "Version Packages", but `pr-title` can rename it). Never merge any other PR.
+ - `gh pr checks <n> --json name,bucket` reports `bucket: pass` for every check.
+ - `gh pr view <n> --json mergeable` reports `MERGEABLE` (on `UNKNOWN`, wait and re-query).
+ - Announce ("Merging Version Packages PR #N: <package>@<version>"), then `gh pr merge <n> --squash --delete-branch`, or the merge method the repo allows. Any failed precondition: stop and report, never merge.
+
### Step 5: Watch the publish run, verify on npm
- - Load `references/version-pr-and-publish.md` and `references/ci-polling.md`.
- - Merging the PR triggers the SAME workflow again; with no pending changesets it publishes (see The Release Loop).
- - Identify the workflow file in `.github/workflows/` (commonly `release.yml`, `npm-publish.yml`, `publish.yml`) and `Monitor` its latest run on the default branch.
- - On failure: report with logs and stop. Never auto-retry; publish failures are real (npm auth, registry, OIDC/provenance, tag conflict).
- - On success: verify `npm view <package> version` against the merged `package.json`, stop all Monitors, report the version. The `npm view` output is the completion evidence; never report success without it.
+ - Merging triggers the same workflow again; with no pending changesets it publishes.
+ - Take the merge SHA (`gh pr view <n> --json mergeCommit --jq .mergeCommit.oid`) and run the commit watch on it.
+ - On failure: read the log, match it against the publish failure table in `references/version-pr-and-publish.md`, report, and stop. Publish failures are never retried blind; every cause on that table needs a config or settings change.
+ - On success: `npm view <package>@<version> version` must print the merged version, and `npm view <package> dist-tags` must show `latest` pointing at it (unless pre mode). Stop remaining watches and report both outputs; they are the completion evidence.
## Failure Recovery
| Failure point | Response |
|---------------|----------|
- | Quality gate still failing after 5 iterations | Stop. Report the gate, remaining error count, last error output |
- | CI fails after the changeset push | Classify per `references/ci-polling.md`: flaky/infra gets `gh run rerun <id> --failed` (max 3); real failures get fix + push + fresh Monitor |
- | "Changeset Status" check fails | Missing changeset: add one (Step 1). Consumed (a local `changeset version` ran): revert the version bump and `CHANGELOG.md` edit, re-add the changeset file. Rerunning CI cannot fix consumed state |
- | Version Packages PR absent after 10 minutes | Check pending changesets exist on the default branch, the workflow file exists, and the action ran (`gh run list`) |
+ | Gate still failing after 5 iterations | Stop. Report the gate, remaining error count, last error output |
+ | CI fails after the changeset push | Flaky or infra: `gh run rerun <id> --failed`, max 3. Real: fix, push, fresh watch |
+ | "Changeset Status" check fails | No changeset: Step 1. Consumed (a local `changeset version` ran): revert the bump and `CHANGELOG.md` edit, re-add the changeset file. Rerunning cannot fix consumed state |
+ | Version Packages PR absent after 10 minutes | `gh run view` the release run: "not permitted to create or approve pull requests" means the repo setting is off (Gotchas). Otherwise confirm pending changesets on the default branch and a `changesets/action` step in `.github/workflows/` |
+ | Release run green but nothing published | `uses: changesets/action@v2` with the v1 `publish:` input, or no publish input at all. Check the run's "Unexpected input(s)" warning |
| Merge precondition fails | Stop and report. Never override failing checks or resolve conflicts in the bot PR |
- | Publish run fails | Never auto-retry. Report with logs; causes: npm auth, OIDC/provenance, tag conflict, registry outage |
+ | Publish run fails | Match the log against the publish failure table; report the fix; stop |
## Gotchas
- - **Never run `npx changeset version` locally.** It consumes the `.changeset/*.md` file, so the pushed commit has no pending changeset, the "Changeset Status" check fails, and no Version Packages PR opens. Recovery means reverting the bump, not rerunning CI.
- - Never run `npm publish` directly. It bypasses changesets, skips the changelog and tags, and leaves the Version Packages PR describing an already-shipped version.
- - Never hand-edit `CHANGELOG.md` or `package.json` `version`. CI generates both in the Version Packages PR; local edits create conflicts that make the bot PR unmergeable.
+ - **Never run `npx changeset version` locally.** It consumes `.changeset/*.md`, so the pushed commit has no pending changeset, "Changeset Status" fails, and no Version Packages PR opens. Recovery is reverting the bump, not rerunning CI.
+ - Never run `npm publish` directly. It bypasses changesets, skips the changelog and tag, and leaves the Version Packages PR describing an already-shipped version, which then fails with "You cannot publish over the previously published versions".
+ - Never hand-edit `CHANGELOG.md` or the `package.json` `version`. CI generates both in the Version Packages PR; local edits make the bot PR `CONFLICTING`.
+ - `changesets/action@v2` renamed every input (`publish` to `publish-script`, `version` to `version-script`, `title` to `pr-title`, `commit` to `commit-message`, `branch` to `pr-base-branch`). The old names are ignored with only a warning, so a `@v2` workflow still using `publish:` opens the Version PR and then completes green without publishing anything.
+ - `setup-node` with `node-version: 22` ships npm 10.9.x. Trusted publishing needs npm 11.5.1 or later, so `changeset publish` fails `ENEEDAUTH` even with `id-token: write` set. Use Node 24 or add `npm install -g npm@latest` before publishing.
+ - A workflow authenticating with an `NPM_TOKEN` secret that holds a classic token fails `ENEEDAUTH`: npm revoked every classic token on 9 December 2025. Move to trusted publishing rather than minting a new token; write-capable granular tokens expire within 90 days.
+ - npm does not validate a trusted publisher when you save it. A workflow filename that differs from `.github/workflows/<file>.yml` by case or extension surfaces only at publish time, as `ENEEDAUTH`.
+ - New personal repos block Actions from opening PRs. The release run fails with "GitHub Actions is not permitted to create or approve pull requests" and no Version PR appears. Fix: Settings, Actions, General, "Allow GitHub Actions to create and approve pull requests" (an org-level setting can override it). Red tier: report it, do not change settings unasked.
- `gh pr list --json headBranch` and `gh pr checks --json conclusion` are invalid fields and error. Use `headRefName` and `bucket`.
- - Do not stop CI monitoring on a first empty poll; workflows take time to queue. Stop only on the Monitor's `TERMINAL:` line.
- - Keep Monitor `sleep` at 30s or more. Tighter polling burns GitHub API rate limit (`gh api rate_limit`) and can throttle the flow.
- - A broad `format`/`fix` script riding into the release commit ships unrelated reformatting. Scope fixers to changed files; `git restore` the rest first.
- - `git add -A` silently commits pre-commit-hook artifacts (e.g. a root `schema.gql`). Stage explicit paths only.
- - Selecting `major` without explicit user instruction signals breaking changes to every consumer. Default to `patch`.
+ - The Monitor tool's default `timeout_ms` is 300000 (5 minutes). A CI run that outlasts it kills the watch with a timeout that looks like silence. Pass `timeout_ms: 3600000` for CI watches.
+ - Poll every 30 seconds or slower. Faster loops burn the GitHub API rate limit (`gh api rate_limit --jq .resources.core.remaining`) and stall the flow mid-release.
+ - `git add -A` commits pre-commit-hook artifacts and fixer churn into the release commit. Stage explicit paths.
+ - `major` without explicit instruction signals breaking changes to every consumer. Default to `patch`.
## Related Skills
- - `scaffold-cli`: scaffolds a new TypeScript package, hands off to autoship for its first release.
- - `pr-creator`: opens feature PRs. Autoship only merges the bot-opened Version Packages PR.
- - `pr-babysitter`: watches feature PRs (reviews, conflicts, CI). Autoship watches release CI only.
+ - `scaffold-cli`: scaffolds a new TypeScript package with changesets and OIDC publishing, then hands off to autoship for its first release.
+ - `pr-creator`: opens feature PRs. Autoship merges only the bot-opened Version Packages PR.
+ - `pr-babysitter`: watches feature PRs (reviews, conflicts, CI). Autoship watches release CI only; never babysit a Version Packages PR autoship is driving.