Releasing

August 23, 2026 · View on GitHub

Versioning uses changesets in local mode — no CI is involved today (the CI rebuild is a recorded future item, and publishing uses an interactive npm passkey that automation cannot hold). The version's single source of truth is package.json. src/version.ts mirrors it, pinned by src/version-sync.test.ts, so a missed sync fails pnpm check.

During development

Any wave that ships user-visible change should leave a changeset behind:

npx changeset        # pick the bump level, write a human-readable summary

This creates a markdown file under .changeset/ that travels with the branch. Multiple changesets accumulate — changeset version later collapses them into one correct bump (two minors do not become two bumps).

Cutting a release

On a release branch off main:

pnpm release:version   # changeset version + sync src/version.ts + stamp the docs
pnpm check             # guard tests confirm every copy of the version agrees

release:version also runs scripts/stamp.mts, which rewrites two kinds of pinned version to the new one:

  • The skill launchers. PINNED in skills/pptwise/scripts/run.sh and $Pinned in run.ps1. This is the one that matters most: on a machine with no pptwise on PATH, that constant decides which release actually runs when a harness invokes the skill.
  • Every pinned install command in the repo's markdown (the dsh plugin add lines in the READMEs and INSTALL.md, the no-script fallback commands in both SKILL files).

The drift test (scripts/stamp.test.mts, part of pnpm check) reads each one back, so a forgotten stamp fails the release before it ships stale numbers.

Review CHANGELOG.md, commit, merge to main, then tag the merge:

git tag v$(node -p "require('./package.json').version")
git push origin main --follow-tags

Publishing (maintainer, manual)

  1. pnpm e2e — full chain on the built CLI.
  2. PowerPoint repair-dialog probe (docs/testing.md) — mandatory whenever the export XML changed since the last release.
  3. npm publishprepublishOnly reruns pnpm check && pnpm e2e as the final gate. On a machine running concurrent heavy sessions the vitest leg can hit spurious 30s timeouts — bound the workers for the publish run (VITEST_MAX_THREADS=2 VITEST_MAX_FORKS=2 npm publish) rather than skipping the gate, and isolate-rerun any failing file first to confirm it is contention, not a regression.

When CI is rebuilt, migrate publishing to npm trusted publishing (OIDC) and let the changesets action open version PRs — that is the current ecosystem best practice this local flow deliberately scales down from.