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
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
# Changelog

## Unreleased
## 0.4.8 (2026-10-10)

### Breaking changes

- **StructuredOutput publishes the validated result file** — In `--output-schema` mode the `StructuredOutput` tool now takes only `{ "path": "<file>" }`. The model writes its final result as JSON to a file in the working directory and passes the path; the CLI follows symlinks, keeps the file inside the working directory, caps it at 2 MiB, validates it with Ajv and publishes the parsed file. Passing the result object as tool arguments is no longer accepted. Callers whose prompts say "call StructuredOutput with the result" must say to write a file and pass its path. Only `{ path }` reaches the provider, so provider schema conversion can no longer drop result fields (Gemini emptied map-typed fields, #139), and the model no longer re-emits the whole result as output tokens. Rejected files are counted corrective turns that ask the model to fix the file; their fixed diagnostics are listed in EVENTS.md. The prose-only `missing` diagnostic and reminder now read "write the final result as JSON to a file in the working directory, then call StructuredOutput with its path". (#140)
- **StructuredOutput publishes the validated result file** — In `--output-schema` mode the `StructuredOutput` tool now takes only `{ "path": "<file>" }`. The model writes its final result as JSON to a file in the working directory and passes the path; the CLI follows symlinks, keeps the file inside the working directory, caps it at 2 MiB, validates it with Ajv and publishes the parsed file. Passing the result object as tool arguments is no longer accepted. Callers whose prompts say "call StructuredOutput with the result" must say to write a file and pass its path. Only `{ path }` reaches the provider, so provider schema conversion can no longer drop result fields (Gemini emptied map-typed fields, #139), and the model no longer re-emits the whole result as output tokens. Rejected files are counted corrective turns that ask the model to fix the file; their fixed diagnostics are listed in EVENTS.md. This ships as a patch because schema mode is used only by the aictrl executor, which pins exact versions; consumers on a caret range (`^0.4.x`) must update their schema-mode prompts to the file+path form before upgrading. The prose-only `missing` diagnostic and reminder now read "write the final result as JSON to a file in the working directory, then call StructuredOutput with its path". (#140)

## 0.4.4 (2026-09-30)

### Fixes

- **Provider error finishes fail headless execution** — Normal streams ending in `error` or `content-filter` now persist a structured provider failure, emit consistent failure events, and exit nonzero while retaining partial output and usage. Empty successful responses remain successful. (#108)

## 0.4.3 (2026-08-20)

### Features

- **GPT-5.6 Codex models** — Added OpenAI's Sol, Terra, and Luna models with API and subscription-backed reasoning effort variants, including the Codex-only `ultra` alias for Sol and Terra.
- **GLM-5.3 model support** — Added the latest Z.AI Coding Plan model with its 1M-token context window and native `low`, `high`, and `max` reasoning efforts.

## 0.4.1 (2026-07-21)

### Compatibility

- **NDJSON v1 terminal reasons are an open set** — `session_error.reason` now includes `interrupted` for `SIGINT` and `terminated` for `SIGTERM`, and `code` may contain the conventional signal-derived exit code (`130` or `143`). Schema v1 consumers should treat unknown event types, fields, and enum-like string values as forward-compatible additions.

Releases 0.3.3–0.4.7 not listed here (0.4.2 was never published) have notes on [GitHub Releases](https://github.com/aictrl-dev/cli/releases) only.

## 0.3.2 (2026-04-11)

### Fixes
Expand Down
43 changes: 33 additions & 10 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

1. Prepare a PR against `main` with the fixes, the version bump in
`packages/cli/package.json`, and the matching `packages/cli` workspace
version in `bun.lock`. Run `bun install --frozen-lockfile`.
version in `bun.lock`. Run `bun install --frozen-lockfile`. In `CHANGELOG.md`,
retitle `## Unreleased` to `## <version> (<date>)`.
2. Run the release regressions from `packages/cli`:

```bash
Expand Down Expand Up @@ -36,16 +37,38 @@
`sandbox` before `main`; verify a sandbox review persists MCP findings and
a stalled stream reports a timeout rather than waiting for the job limit.

## 0.4.7 candidate
## 0.4.8 candidate

- Output-schema review follow-ups (#134):
- schemas are bounded by bytes (64 KiB) and structure (depth 64, 10,000 nested objects), on every path;
- configuration errors lead with the reason and name the resolved path;
- every rejected attempt is reported and counted;
- `retryCount` is capped at 10 (wire values clamp; the flag rejects above 10);
- queued telemetry drains before terminal failure, and failures settle in a single terminal path.
- Provider hints (#134): the StructuredOutput tool description embeds the canonical schema (constraints that the Vertex adapter drops); the corrective turn after a prose-only finish forces StructuredOutput by name (GLM).
- Executor adoption: bump the aictrl `docker/executor/Dockerfile` pin (application #5960 follow-up).
- **BREAKING for `--output-schema` callers (#142, closes #140):** `StructuredOutput`
takes only `{ "path": "<file>" }`. The model writes its final result as JSON to a
file in the working directory and passes the path. The CLI validates that file with
Ajv and publishes the parsed file. Result objects passed as tool arguments are
rejected. Callers must change prompts that say "call StructuredOutput with the
result" to say "write a file and pass its path".
- **Why a patch bump (0.4.8):** schema mode is used only by the aictrl executor,
which pins exact versions. Consumers on a caret range (`^0.4.x`) must update their
schema-mode prompts to the file+path form before upgrading.
- Only `{ path }` reaches the provider, so provider schema conversion can no longer
drop result fields. On 0.4.7, Gemini emptied map-typed fields (#139).
- The result file must:
- resolve inside the working directory (symlinks are followed when checking, and a
post-open inode re-check also covers swap races; `O_NOFOLLOW`/`O_NONBLOCK` are
used where the platform defines them);
- be a regular file of at most 2 MiB (reads are bounded).
- Every failure is a fixed, counted `structured_output_rejected` diagnostic; EVENTS.md
lists them verbatim. The prose-only `missing` diagnostic and reminder now say
"write the final result as JSON to a file in the working directory, then call
StructuredOutput with its path".
- Evidence (#139 reproduction, 6-key map):
- 0.4.7: Gemini 3.8 Flash published `elements: {}` 7/7 (silent on 2, exit 3 on 5).
- #142 builds (POC and first PR head): Gemini 10/10 and GLM 4/4 published all 6 keys identically.
- Gemini output + reasoning tokens fell from 2.5–3.9k to 1.0–1.8k.
- Executor adoption, in one aictrl PR:
- bump the `docker/executor/Dockerfile` pin;
- update the prompts that ask for the result as tool arguments: `prompt-builder.ts`
structured paragraph, `pr-explanation-output-contract.ts`, and the `explain-change`
skill step that says to call StructuredOutput "with the contents of `$RESULT`";
- confirm `$RESULT` lies inside the CLI's `--dir`.

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.4.7",
"version": "0.4.8",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 Breaking change shipped as patch bump 0.4.8.

🤖 Fix with your agent
Fix this code review finding (aictrl-dev/cli PR #143, packages/cli/package.json:3):

Problem: Breaking change shipped as patch bump 0.4.8
Detail: RELEASING.md's new 0.4.8 section (line 39) explicitly labels the StructuredOutput contract change "**BREAKING for `--output-schema` callers (#142, closes #140)**" — the tool now accepts only `{ "path": "<file>" }` and result objects passed as tool arguments are rejected — yet the manifest bump is 0.4.7→0.4.8 (package.json and the bun.lock workspace entry). npm/bun caret ranges `^0.4.x` resolve to `<0.5.0`, so existing consumers auto-receive 0.4.8 on any routine update and their previously-working `--output-schema` prompts start failing with `structured_output_rejected`. The repo's own changelog precedent uses a minor bump for a feature/breaking batch (0.2.0) and patches for fixes (0.3.x). Semver's major-zero allowance technically permits this, but the release notes' own "callers must change prompts" makes the user impact concrete, so the version choice should be deliberate — either 0.5.0, or an explicit note that a patch bump was chosen because consumers pin exact versions.
Suggested fix: Bump to 0.5.0 in packages/cli/package.json and the matching bun.lock workspace entry and retitle the RELEASING.md section to "## 0.5.0 candidate"; alternatively keep 0.4.8 but state in RELEASING.md why a labeled breaking change ships as a patch (e.g. consumers are expected to pin exact versions), or accept the legacy result-object shape with a deprecation diagnostic for one release before rejecting it.

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

RELEASING.md's new 0.4.8 section (line 39) explicitly labels the StructuredOutput contract change "BREAKING for --output-schema callers (#142, closes #140)" — the tool now accepts only { "path": "<file>" } and result objects passed as tool arguments are rejected — yet the manifest bump is 0.4.7→0.4.8 (package.json and the bun.lock workspace entry). npm/bun caret ranges ^0.4.x resolve to <0.5.0, so existing consumers auto-receive 0.4.8 on any routine update and their previously-working --output-schema prompts start failing with structured_output_rejected. The repo's own changelog precedent uses a minor bump for a feature/breaking batch (0.2.0) and patches for fixes (0.3.x). Semver's major-zero allowance technically permits this, but the release notes' own "callers must change prompts" makes the user impact concrete, so the version choice should be deliberate — either 0.5.0, or an explicit note that a patch bump was chosen because consumers pin exact versions.

{
  "$schema": "https://json.schemastore.org/package.json",
  "version": "0.4.8",
  "name": "@aictrl/cli",
  "description": "Headless execution engine for AI agent skills",
  "type": "module",

"name": "@aictrl/cli",
"description": "Headless execution engine for AI agent skills",
"type": "module",
Expand Down
Loading