Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 0.5.3 (2026-10-19)

### Packaging

- **One platform package per OS, CPU and libc; the AVX2 x64 packages are no longer published** — This changes what is published. `@aictrl/cli-linux-x64`, `@aictrl/cli-linux-x64-musl`, `@aictrl/cli-darwin-x64` and `@aictrl/cli-windows-x64` get no new versions; x64 hosts use `@aictrl/cli-linux-x64-baseline`, `@aictrl/cli-linux-x64-baseline-musl`, `@aictrl/cli-darwin-x64-baseline` and `@aictrl/cli-windows-x64-baseline`. arm64 packages keep their names. Bun 1.4.3 ships the same binary for its baseline and AVX2 targets, and the 0.5.1 AVX2 and `-baseline` packages hold byte-identical binaries on all three x64 OSes, so no CPU loses a faster build. The linux packages now declare `libc` (`glibc` or `musl`), so npm installs one of them instead of every linux package for the CPU: `npm install -g @aictrl/cli` on linux-x64 drops from four platform packages and about 450 MB to one package of about 115 MB (glibc) or 110 MB (musl). A package manager that ignores `libc` still installs both libc packages, and the wrapper picks the host's. If you install a dropped package directly, switch to its `-baseline` name; its published versions up to 0.5.2 are unchanged. (#231)
- **`@aictrl/cli` publishes only the wrapper** — A `files` allowlist limits the package to `bin/aictrl`, `README.md`, `LICENSE` and `package.json`. `src/`, `test/`, migrations and build scripts are no longer published (378 files and 6.1 MB unpacked in 0.5.2, now 4 files and 18 kB). The platform packages ship `LICENSE` too. (#231)
- **The npm wrapper no longer probes the CPU or runs `ldd`** — `bin/aictrl` drops AVX2 detection. It reads the libc from `/usr/bin/ldd` and falls back to Node's diagnostic report (as npm does) instead of running `ldd --version`, which saves about 2.5 ms per start on glibc. When no binary of its version is installed, it no longer tries `bun run src/index.ts`, which failed with a misleading `Cannot find package` error; it exits 1 and names the platform package it expected. (#231)
- **The release waits for every platform package before the install check** — The publish workflow's smoke job checks that each platform package it published is visible on npm at the release version, retrying for up to 8.5 minutes, before it installs `@aictrl/cli`. The 0.5.1 and 0.5.2 install checks did not fail, but each installed only three of the four linux-x64 platform packages the wrapper lists (npm reported `added 4 packages`, where a complete install adds 5), and passed because one of the three held the binary. With one platform package per host, a missing package would leave no binary to run. (#231)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Moved bullet flips 0.5.1 install-check outcome.

🤖 Fix with your agent
Fix this code review finding (aictrl-dev/cli PR #232, CHANGELOG.md:10):

Problem: Moved bullet flips 0.5.1 install-check outcome
Detail: This PR moves the Packaging bullets from the 0.5.2 changelog section into a new 0.5.3 section, and the moved bullet reverses its historical claim: the removed 0.5.2 text ended "0.5.1's install check failed while a platform package was not yet visible", while the new 0.5.3 text says "The 0.5.1 and 0.5.2 install checks did not fail, but each installed only three of the four linux-x64 platform packages". The two statements are mutually exclusive accounts of the same CI event, and the diff itself carries no signal that the reversal is a correction. If the old claim was the accurate one, the new rationale justifying the 8.5-minute npm visibility wait is wrong. The new wording is mechanically plausible (npm silently skips a missing optionalDependency, so a partial install reports `added 4 packages` and still passes), which suggests a deliberate correction of an earlier overstatement, but it should be confirmed against the 0.5.1/0.5.2 release CI logs before the changelog ships.
Suggested fix: Check the 0.5.1 and 0.5.2 smoke-job logs. If the new wording is the intended correction, keep it (optionally noting "previously reported as failed"); if the old claim was right, reword to: "0.5.1's install check failed while a platform package was not yet visible; 0.5.2's passed but installed only three of the four linux-x64 platform packages (npm reported `added 4 packages`, where a complete install adds 5)."

Implement the fix on the PR head branch and add a regression test that fails before the fix and passes after.
Why this matters

This PR moves the Packaging bullets from the 0.5.2 changelog section into a new 0.5.3 section, and the moved bullet reverses its historical claim: the removed 0.5.2 text ended "0.5.1's install check failed while a platform package was not yet visible", while the new 0.5.3 text says "The 0.5.1 and 0.5.2 install checks did not fail, but each installed only three of the four linux-x64 platform packages". The two statements are mutually exclusive accounts of the same CI event, and the diff itself carries no signal that the reversal is a correction. If the old claim was the accurate one, the new rationale justifying the 8.5-minute npm visibility wait is wrong. The new wording is mechanically plausible (npm silently skips a missing optionalDependency, so a partial install reports added 4 packages and still passes), which suggests a deliberate correction of an earlier overstatement, but it should be confirmed against the 0.5.1/0.5.2 release CI logs before the changelog ships.

- **The release waits for every platform package before the install check** — The publish workflow's smoke job checks that each platform package it published is visible on npm at the release version, retrying for up to 8.5 minutes, before it installs `@aictrl/cli`. The 0.5.1 and 0.5.2 install checks did not fail, but each installed only three of the four linux-x64 platform packages the wrapper lists (npm reported `added 4 packages`, where a complete install adds 5), and passed because one of the three held the binary. With one platform package per host, a missing package would leave no binary to run. (#231)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TRUE · already addressed (no further change). This raises the same point as the round-1 finding (#232 (comment)), and this time it asks for exactly the confirmation that was done there. The new wording is a deliberate correction. I checked it against the release CI smoke logs:

  • v0.5.1, run 39169076845: success on attempt 1. The install got ETARGET six times, then added 4 packages, and audited 5 packages, then succeeded on attempt 7.
  • v0.5.2, run 39252929784: the same pattern.
  • For comparison, a full install of 0.5.2 today adds 5 packages.

The PR description records the correction in its Correction: line, which links both runs. The rationale for the visibility wait still holds. It does not depend on the old claim: if a platform package is missing when there is one package per host, there is no binary to run.


## 0.5.2 (2026-10-19)

### Features
Expand All @@ -14,13 +23,6 @@
- **Subagent token usage is reported** — `aictrl run --format json` emits a new `subagent_message_complete` event for each finished assistant turn of a `task` subagent, with the same usage fields as `message_complete` plus `subagentSessionID` and `parentSessionID`. Summing `message_complete` and `subagent_message_complete` gives the run's total when subagents do not delegate further (turns of nested `task` calls are not reported, so the sum is then a lower bound); before, a run that delegated reported only the parent's turns. `message_complete` is unchanged and still covers the primary session only. (#221, closes #213)
- **Lite build sends the same system prompt as the full build** — `aictrl run` from the lite binary (`script/build.ts --lite`, entry `src/headless.ts`) now sends the environment block (working directory, git status, platform, date) and loads `AGENTS.md` from `AICTRL_CONFIG_DIR` and the global config directory, as the published full binary always did. The lite-only short prompt is gone. The no-op `AICTRL_HEADLESS` build define and the `AICTRL_HEADLESS` environment variable are removed, with the README note that suggested setting it in CI; setting the variable now has no effect. The full binary's prompt is unchanged, except for runs that set `AICTRL_HEADLESS=true`: on 0.5.1 that also gave the full binary the one-line environment and skipped the `AICTRL_CONFIG_DIR` and global `AGENTS.md` files, and those runs now get the environment block and those files. (#219, closes #152)

### Packaging

- **One platform package per OS, CPU and libc; the AVX2 x64 packages are no longer published** — This changes what is published. `@aictrl/cli-linux-x64`, `@aictrl/cli-linux-x64-musl`, `@aictrl/cli-darwin-x64` and `@aictrl/cli-windows-x64` get no new versions; x64 hosts use `@aictrl/cli-linux-x64-baseline`, `@aictrl/cli-linux-x64-baseline-musl`, `@aictrl/cli-darwin-x64-baseline` and `@aictrl/cli-windows-x64-baseline`. arm64 packages keep their names. Bun 1.4.3 ships the same binary for its baseline and AVX2 targets, and the 0.5.1 AVX2 and `-baseline` packages hold byte-identical binaries on all three x64 OSes, so no CPU loses a faster build. The linux packages now declare `libc` (`glibc` or `musl`), so npm installs one of them instead of every linux package for the CPU: `npm install -g @aictrl/cli` on linux-x64 drops from four platform packages and about 450 MB to one package of about 115 MB (glibc) or 110 MB (musl). A package manager that ignores `libc` still installs both libc packages, and the wrapper picks the host's. If you install a dropped package directly, switch to its `-baseline` name; its published versions up to 0.5.2 are unchanged.
- **`@aictrl/cli` publishes only the wrapper** — A `files` allowlist limits the package to `bin/aictrl`, `README.md`, `LICENSE` and `package.json`. `src/`, `test/`, migrations and build scripts are no longer published (369 files and 6.1 MB unpacked in 0.5.1, now 4 files and 18 kB). The platform packages ship `LICENSE` too.
- **The npm wrapper no longer probes the CPU or runs `ldd`** — `bin/aictrl` drops AVX2 detection. It reads the libc from `/usr/bin/ldd` and falls back to Node's diagnostic report (as npm does) instead of running `ldd --version`, which saves about 2.5 ms per start on glibc. When no binary of its version is installed, it no longer tries `bun run src/index.ts`, which failed with a misleading `Cannot find package` error; it exits 1 and names the platform package it expected.
- **The release waits for every platform package before the install check** — The publish workflow's smoke job checks that each platform package it published is visible on npm at the release version, retrying for up to 8.5 minutes, before it installs `@aictrl/cli`. 0.5.1's install check failed while a platform package was not yet visible.

### Security

- **drizzle-orm 1.0.0-beta.20** — `drizzle-orm` and `drizzle-kit` move from `1.0.0-beta.12-a5629fb` to `1.0.0-beta.20`, the first release patched for GHSA-gpj5-g38j-94v9 (SQL injection through improperly escaped SQL identifiers; the CLI never passed untrusted identifiers to drizzle). Existing databases open as before: on first start drizzle adds `name` and `applied_at` columns to `__drizzle_migrations` and fills in the names of the migrations already applied, without running them again. The upgraded database still opens with 0.5.1. (#220, closes #61)
Expand Down
90 changes: 43 additions & 47 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,57 +79,53 @@ 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.

## 0.5.2 candidate

- **Why a patch bump (0.5.2):** only additive NDJSON events, fixes and
internal changes. No CLI flag, command, config key or NDJSON event field is
removed, and `schemaVersion` stays `"1"`. Range `v0.5.1..d4d9696dbc` (11 PRs):
#222, #220, #217, #218, #224, #225, #221, #226, #219, #228, #229.
- **NDJSON additions:** `user_message` (#224) and `subagent_message_complete`
(#221). `session_start.permissions` keeps its shape and now carries the full
evaluated ruleset (#218). `user_message` takes numbers from the shared
`sequenceNum` counter, so `text`, `reasoning` and `tool_use` numbers can have
gaps; they stay monotonic.
- **Behaviour changes worth knowing:**
- a retryable error asking for more than 5 minutes fails at once, for any
status (#217);
- a second prompt for a busy session fails with `Session <id> is busy`
instead of queuing; only parallel `task` calls resuming one `task_id`
reach it (#225);
- `AICTRL_HEADLESS` is ignored (#219). A full-binary run that set it now
gets the full environment block and the `AICTRL_CONFIG_DIR` / global
`AGENTS.md` files. The production executor does not set it.
- **Prompt:** #229 trims the `bash` and `task` tool descriptions (about
9.7k → 3.4k characters, first request −21.7% tokens on glm-5.3). Tool names
and parameters are unchanged; its A/B passed 24/24 with no extra steps.
- **Database:** drizzle 1.0.0-beta.20 (#220) adds `name` and `applied_at` to
`__drizzle_migrations` on first start; a database upgraded by 0.5.2 still
opens with 0.5.1.
- **SDK:** #228 regenerates the v2 `@aictrl/sdk` client with
`@hey-api/openapi-ts` 0.97.3 (GHSA-hhx9-57xq-r5rw) and hand-patches the
legacy client's `buildClientParams`. The CLI uses only the legacy client
(`--attach`, plugins), where only that helper changes. `@aictrl/sdk` is not
bumped by this release.
- **Bun:** the first release built under the `packageManager` pin (#226). The
binary must embed `Bun v1.4.3`.
## 0.5.3 candidate

- **Why a patch bump (0.5.3):** the range `v0.5.2..b95059eb3e` is one PR,
#231, and it changes which npm packages are published, not what the CLI
does. No CLI flag, command, config key or NDJSON event changes, and
`schemaVersion` stays `"1"`. Wrappers up to 0.5.2 pin their own platform
package versions, which stay on npm, so they keep working.
- **Published package set:** 7 platform packages instead of 11 (the table
above). `@aictrl/cli-linux-x64`, `-linux-x64-musl`, `-darwin-x64` and
`-windows-x64` get no 0.5.3. The linux packages declare `libc`. Every
remaining name already exists on npm with 0.5.2, so no new package needs
trusted publishing set up.
- **Wrapper:** a `files` allowlist ships `bin/aictrl`, `README.md`, `LICENSE`
and `package.json` only. `bin/aictrl` drops AVX2 detection and the
`bun run src/index.ts` fallback, and reads the libc from `/usr/bin/ldd`.
- **Publish workflow:** the manifest step copies `LICENSE` and exports the
platform package list; the smoke job waits until every listed package is
visible at the release version before the install check.
- **Bun:** the binary must embed `Bun v1.4.3`.
- Evidence, on the release commit with Bun 1.4.3:
- step-2 regressions: 88 pass, 0 fail (8 files);
- `bun test --timeout 30000` (packages/cli): 1760 pass, 6 skip, 0 fail
(1766 tests, 147 files);
- step-2 regressions: 95 pass, 0 fail (8 files);
- `bun test --timeout 30000` (packages/cli): 1784 pass, 6 skip, 0 fail
(1790 tests, 147 files);
- `bun turbo typecheck --force`: 6/6;
- `test/security/sdk-build-client-params.test.ts`: 12 pass, 0 fail;
- `AICTRL_VERSION=0.5.2 AICTRL_BUILD_SINGLE=true bun turbo build --force`
(CI's build): 3/3 tasks; `aictrl --version` prints `0.5.2` and the
binary embeds `Bun v1.4.3`;
- `AICTRL_VERSION=0.5.3 AICTRL_BUILD_SINGLE=true bun turbo build --force`
(CI's build): 3/3 tasks, builds only `cli-linux-x64-baseline`;
`aictrl --version` prints `0.5.3` and the binary embeds `Bun v1.4.3`;
- the five binary-capable `aictrl run` suites with `AICTRL_TEST_BINARY` set
to that binary: 21 pass, 0 fail;
- NDJSON schema tests (`run-schema-v1`, `events-command`, `run-user-message`,
`run-event-race`) and `bun-version-pin`: 27 pass, 0 fail;
- one-turn `aictrl run --format json` smoke runs of the binary against
a stub OpenAI-compatible endpoint: exit 0, one model request, every line
is JSON, `schemaVersion` `"1"`, `session_start.permissions` contains the
config rule, `user_message` precedes `text`, `message_complete.status`
`completed`, `invocation_complete.status` `completed`.
- `wrapper-binary-resolution`, the NDJSON schema tests (`run-schema-v1`,
`events-command`, `run-user-message`, `run-event-race`) and
`bun-version-pin`: 54 pass, 0 fail;
- `AICTRL_VERSION=0.5.3 bun run build` builds the 7 targets. `npm pack` of
each platform package gives `bin/aictrl` (`aictrl.exe` on windows),
`bin/aictrl.map`, `LICENSE` and a `package.json` whose `os`, `cpu` and
`libc` match the table. publish.yml's manifest step, run on a copy, writes
exactly those 7 names at `0.5.3` into `optionalDependencies`; the wrapper
tarball has 4 files, 18.3 kB unpacked;
- the 8 tarballs published to a local verdaccio: publish.yml's visibility
step passes on attempt 1. `npm install -g @aictrl/cli@0.5.3` in fresh
`node:20-slim` and `node:20-alpine` containers (Node 20.20.2, npm 10.8.2)
installs one platform package, `cli-linux-x64-baseline` (116,272 KiB in
`@aictrl/`) or `cli-linux-x64-baseline-musl` (109,960 KiB). `aictrl
--version` prints `0.5.3`, and a one-turn `aictrl run --format json`
against a stub OpenAI-compatible endpoint exits 0 with 10 events,
`schemaVersion` `"1"` and both terminal statuses `completed`. A local
(non-global) install gives the same single package on both images.

Publication and executor promotion are separate gates. Preparing this candidate
PR does not publish npm packages or deploy an executor image.
2 changes: 1 addition & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "0.5.2",
"version": "0.5.3",
"name": "@aictrl/cli",
"description": "Headless execution engine for AI agent skills",
"type": "module",
Expand Down
Loading