-
Prepare a PR against
mainwith the fixes, the version bump inpackages/cli/package.json, and the matchingpackages/cliworkspace version inbun.lock. Runbun install --frozen-lockfile. InCHANGELOG.md, retitle## Unreleasedto## <version> (<date>). -
Run the release regressions from
packages/cli:bun test test/cli/run-mcp-discovery.test.ts test/mcp/discovery-recovery.test.ts test/cli/publish-workflow.test.ts test/cli/run-provider-finish.test.ts test/cli/run-signal-cancellation.test.ts test/cli/classify-session-error.test.ts test/session/idle.test.ts test/session/processor-idle.test.tsBefore publication, run the separate current-versus-previous native release comparison. Prepare and review explicit candidate and previous published binary artifacts, their SHA256/version/provenance pins and one existing immutable fixture image using the manifest contract. Provision the pinned Python counter in a fresh directory (requires Python3.12 and network access during setup only), then capture and count offline:
python3.12 -I -B script/token-budget/setup.py --directory /absolute/new-counter-env bun run --no-install --no-env-file script/token-budget/release.ts /absolute/release-inputs.json /absolute/new-release-evidence /absolute/new-counter-env/venv/bin/python3 -I -B script/token-budget/release-count.py /absolute/new-release-evidence/campaign.json
Run these commands from the repository root. Require valid current-default and previous-default task runs, raw requests/responses and actual Read-result evidence, verified versions/binary hashes, successful cleanup and
release-comparison.json. Review first-input and session input/output/total deltas before publication and record any accepted regression with rationale. Minimal arms are measured only when each actual binary advertises--tools; an unsupported previous arm must be labeled UNSUPPORTED, never synthesized through permission settings. This scripted reference-token gate is separate from source CI token budgets and from provider billing or model-quality claims.Wait for CI build, workspace typecheck and tests to pass and address reviews.
-
Merge the approved PR and record the resulting
maincommit SHA. Confirm its package version matches the intended tag. Publish the release against that exact commit, using reviewed notes:gh release create v<version> --repo aictrl-dev/cli --target <merged-main-SHA> --title v<version> --notes-file <notes-file> gh run list --repo aictrl-dev/cli --workflow publish.yml --limit 3
Do not use the legacy
script/releaseorscript/publish.ts; they refer to retired branches/workflows and do not implement these gates. -
Require the Publish to npm workflow to be green. It checks the tag against the wrapper package version before building, publishes the platform packages and wrapper, then retries npm installation through its propagation window and verifies the installed binary version. If publishing partially succeeds, inspect the failure before rerunning: npm versions are immutable.
-
Independently install
@aictrl/cli@<version>in a temporary directory and verify./node_modules/.bin/aictrl --versionequals<version>. -
In a separate aictrl application PR, update
docker/executor/Dockerfileto the published version. Build the executor image and rerun the headless discovery and idle-stream fixtures against its binary. Promote throughsandboxbeforemain; verify a sandbox review persists MCP findings and a stalled stream reports a timeout rather than waiting for the job limit.
packages/cli/script/build.ts builds one binary per OS, CPU and libc, and the
publish workflow publishes each as a platform package. It then lists them in
the wrapper's optionalDependencies:
| Package | os |
cpu |
libc |
|---|---|---|---|
@aictrl/cli-linux-x64-baseline |
linux | x64 | glibc |
@aictrl/cli-linux-x64-baseline-musl |
linux | x64 | musl |
@aictrl/cli-linux-arm64 |
linux | arm64 | glibc |
@aictrl/cli-linux-arm64-musl |
linux | arm64 | musl |
@aictrl/cli-darwin-x64-baseline |
darwin | x64 | |
@aictrl/cli-darwin-arm64 |
darwin | arm64 | |
@aictrl/cli-windows-x64-baseline |
win32 | x64 |
npm installs only the package that matches the host. Every x64 package is the
baseline (no AVX2) build: Bun ships the same binary for its baseline and AVX2
targets. The AVX2 names (@aictrl/cli-linux-x64, -linux-x64-musl,
-darwin-x64, -windows-x64) were last published with 0.5.2. Before adding
or renaming a platform package, update bin/aictrl's platformPackageNames
and its tests. The smoke job waits until every package in this table is visible
on npm before it installs @aictrl/cli.
The compiled binary embeds the Bun runtime that built it, so the Bun version is
part of the release. The root package.json packageManager field is the only
place it is set:
- CI and the publish workflow read it through
bun-version-file: package.json. .husky/pre-pushand@aictrl/script(imported bypackages/cli/script/build.ts) reject a local Bun outside^<version>.packages/containers/script/build.tspasses it to thebun-nodeimage asBUN_VERSION; the Dockerfile has no default.
Bump it deliberately, in its own PR, never as a side effect of another change.
Before merging the bump, build the binary with the old and the new Bun and
compare time to first response and RSS: run a one-turn aictrl run against a
stub model in a fresh, CPU- and memory-limited container, several times each.
Moving from Bun 1.3.10 to 1.4.3 alone changed them by about 85 ms and 85 MB.
- Why a patch bump (0.5.4): the range
v0.5.3..97cc5be868is four PRs, #233, #234, #235 and the test-only #237. They change the system prompt and add the GPT-6 family, which CLAUDE.md treats as patch-level model support, and fix a flaky test. No CLI flag, command, config key or NDJSON event field is removed, andschemaVersionstays"1". One model option is removed: with an API key,gpt-6-astraandgpt-6.1-solno longer offer thenoneeffort variant, which OpenAI rejects for them, so no working configuration loses it (#234). - System prompt: every model except Codex sign-in sessions now gets one
shared base prompt,
default.txt(#233 trims it and renames it fromqwen.txt; #235 removesanthropic.txt,beast.txt,gemini.txtandtrinity.txt). Codex sign-in still sendscodex_header.txtasinstructions. Gemini, Claude and GPT were not re-validated on the final wording; onlyzai-coding-plan/glm-5.3was (see the CHANGELOG). - Defaults: with nothing configured or recently used, an OpenAI-only setup
defaults to
gpt-6.1-sol(wasgpt-5.6-terra), and the small model isgpt-6-luna(#234). - Published package set: unchanged from 0.5.3 (the 7 packages above).
- Bun: the binary must embed
Bun v1.4.3. - Evidence, on the release commit with Bun 1.4.3 (on
e88ed7f432; after the rebase onto #237 the full suite and step-2 list were run again):- step-2 regressions: 95 pass, 0 fail (8 files);
bun test --timeout 30000(packages/cli): 1809 pass, 6 skip, 0 fail (1815 tests, 148 files), the same after the rebase onto #237; the formerly flakyhandles filenames with # charactertest (fixed by #237) also passes alone in a cleanenv -i CI=trueenvironment;bun turbo typecheck --force: 6/6;AICTRL_VERSION=0.5.4 AICTRL_BUILD_SINGLE=true bun turbo build --force(CI's build): 3/3 tasks, builds onlycli-linux-x64-baseline;aictrl --versionprints0.5.4and the binary embedsBun v1.4.3;- the five binary-capable
aictrl runsuites withAICTRL_TEST_BINARYset to that binary: 21 pass, 0 fail; wrapper-binary-resolution, the NDJSON schema tests (run-schema-v1,events-command,run-user-message,run-event-race),bun-version-pinand the prompt tests (system,llm,headless-prompt-budget): 76 pass, 0 fail;- a one-turn
aictrl run --format jsonof that binary against a stub OpenAI-compatible endpoint, with isolatedHOME/XDG dirs: exit 0, one model request, 10 events,schemaVersion"1", both terminal statusescompleted; the request's single system message starts with the trimmeddefault.txt(2,602 chars), including the new Task-tool and rejected-call lines, followed by the environment block; AICTRL_VERSION=0.5.4 bun run buildbuilds the 7 targets.npm packof each platform package givesbin/aictrl(aictrl.exeon windows),bin/aictrl.map,LICENSEand apackage.jsonwhoseos,cpuandlibcmatch the table. publish.yml's manifest step, run on a copy, writes exactly those 7 names at0.5.4intooptionalDependencies; the wrapper tarball has 4 files, 18.3 kB unpacked.- not repeated from 0.5.3: the local-registry (verdaccio) publish, the
visibility step and the fresh-container installs.
bin/aictrl,script/build.tsandpublish.ymlare unchanged inv0.5.3..97cc5be868, and the tarballs above match 0.5.3's except for the version, so those checks would exercise the same code. The publish workflow's visibility gate and install smoke, and the cleannpm installin step 5, still check 0.5.4 itself after merge.
Publication and executor promotion are separate gates. Preparing this candidate PR does not publish npm packages or deploy an executor image.