Today nothing reaches npm between two release-please releases, so trying a merged but unreleased change means building from source. This adds a continuously published preview channel. Every CI-green push to `main` that is not a release merge publishes `<package.json version, patch bumped>-preview.N` under the `preview` dist-tag, tags the commit `v<version>`, and dispatches the same agent registry update a stable release does. With `main` at 0.73.0 that gives `0.73.1-preview.1`, `0.73.1-preview.2`, and so on; `N` restarts at 1 whenever a release moves the base. `latest` is untouched. ## Approach - **Added to `publish.yml` rather than a new workflow.** npm binds a trusted publisher to one repo + workflow filename, and a package gets only one. A separate file would fail OIDC and cost the stable path its publisher. - **Gated on the `CI` workflow succeeding** (`workflow_run`), so a red commit is never published. release-please's release merge is excluded by the head commit's author and subject — its `releases_created` output is not reachable from a different workflow run. - **`N` is the max of the npm registry and local git tags.** npm reserves versions forever, even after `unpublish`, so a reused `N` is a hard failure; but the registry is CDN-served and lags, which the tags cover. A registry read failure aborts rather than guessing. - **Base is patch+1, not release-please's prediction**, which moves mid-flight and would reset `N` under already-published previews. - **The version is applied to the CI working tree only**, never committed — `package.json` and the release-please manifest stay release-please's to own. - **`--tag preview` is mandatory:** `npm publish` defaults to `latest` even for a semver prerelease. - **Three jobs.** `publish-npm-preview` mirrors `publish-npm` and only publishes (no repo write access); `publish-tag-preview` only tags, so a failed tag is retryable with _Re-run failed jobs_ without re-publishing an immutable version; `trigger-registry-update` is shared with the stable path. Both downstream jobs gate on a `published` output the publish step sets, not on job status — the tag push happens after the publish, so a red job can still mean npm has the version. ## Next step The publish is `npm publish --dry-run` for now. The `workflow_run` trigger and the `release` environment's protected-branch policy mean this job cannot run off the default branch at all, so merging this is the only way to exercise the trigger, the gate and the version calculation — and with `published` unset, the rehearsal neither tags nor touches the registry. Once one run looks right, a follow-up drops `--dry-run` and adds `echo "published=true" >> "$GITHUB_OUTPUT"` to that step. Nothing else changes.
1.7 KiB
Agent guide
An ACP-compatible coding agent powered by the Claude Agent SDK. Source in src/,
TypeScript, ESM, Node >= 22.
Commands
npm run build # tsc
npm run test:run # vitest, single pass
npm run check # eslint + prettier --check
npm run lint:fix # eslint --fix
npm run format # prettier --write
CI runs format:check, lint, build and test:run. Run npm run check before
opening a PR.
Pull requests
Squash merges use the PR title as the commit subject, and release-please parses it
to compute the next version. Titles must be conventional commits using one of:
feat, fix, perf, revert, docs, style, chore, refactor, test,
build, ci. conventional-prs.yml rejects anything else.
The title also decides the release: feat: bumps the minor, fix:/perf: the
patch, and chore:/ci:/test: and friends do not release at all.
Releasing
Stable releases are fully automated by release-please. There is no manual release workflow, and the version is never chosen by hand — it follows from the commit history.
npm run release:preflight # verifies it is safe to release, prints the PR and version
gh pr merge <pr-number> --squash
The preflight is the guard-list as code; if it exits non-zero, follow what it prints rather than merging.
Every other push to main publishes a preview to npm — 0.73.1-preview.4 and
so on — under the preview dist-tag, tags the commit it came from, and updates
the agent registry the same way a release does. Only latest is reserved for
real releases. So anything merged to main is published within minutes; there is
no staging branch. Full runbook, including how to recover a stalled release:
docs/RELEASES.md.