[feat] release: interactive release client, drop the CI linked-deps guard

`pnpm run release` (scripts/release.mjs, zx + enquirer + commander) replaces
the hand sequence of bump, changelog, gate, tag, push. It picks packages from a
list annotated with what npmjs already has, computes versions from the manifest,
collects notes in $EDITOR seeded with the commits since the package's last tag,
and prepends them to CHANGELOG.md in the format release.yml's parser expects.

The gate (lint:ci -> typecheck -> test:coverage -> build -> verify-pack) runs
against the bumped tree *before* the commit, so a failure leaves nothing to
unpick -- it offers to restore instead. Tags go out dependency-first, and each
version is polled on npmjs before the next tag is pushed.

That polling is what lets release.yml lose its `check linked deps are released`
step: the ordering is now enforced before CI ever sees a tag, rather than after.
linked-deps.mjs stays as a hand-check. The accepted cost is that a tag pushed
some other way is no longer caught.

Three things found by running it rather than reading it:

- Tags are annotated (`-a -m`). A lightweight tag is rejected outright under
  tag.forceSignAnnotated, which is set on the machine this was written on.
- pnpm 11 forwards the `--` in `pnpm run release -- --dry-run` literally, and
  commander reads a bare `--` as "the rest are positionals". The script takes no
  positionals, so it strips it and both spellings work.
- Prompts refuse with a message naming the flag that avoids them when stdin is
  not a TTY, instead of hanging as an unsettled top-level await.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCzYTAm9QUhvLNr2EpdagJ
This commit is contained in:
Benjamin Diedrichsen
2026-09-01 12:31:17 +02:00
co-authored by Claude Opus 5
parent 0aa0be5542
commit 2019626618
7 changed files with 1016 additions and 62 deletions
+6 -1
View File
@@ -14,6 +14,7 @@
"test:coverage": "pnpm -r run test:coverage",
"coverage:summary": "node scripts/coverage-summary.mjs",
"registry:status": "node scripts/registry-status.mjs",
"release": "node scripts/release.mjs",
"try:snapshot": "node scripts/try-snapshot.mjs",
"typecheck": "tsc --build",
"lint": "biome check .",
@@ -31,7 +32,11 @@
"@bitsquare/nopy-cubes-core": "workspace:*",
"@logtape/logtape": "^2.2.4",
"@types/node": "^26.1.1",
"commander": "^15.0.0",
"enquirer": "^2.4.1",
"semver": "^7.8.5",
"simple-git-hooks": "^2.13.1",
"typescript": "^7.0.2"
"typescript": "^7.0.2",
"zx": "^8.8.5"
}
}