From 59213dfbeb6f82e5a5b19c244d2a5c4bb9211263 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 30 May 2026 10:42:05 +0800 Subject: [PATCH] chore(release): bump version to 3.4.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Programmable orchestration (AgentExecutor seam, parallel/pipeline/resumable combinators, WorkflowCheckpoint, Node + Python SDK grammar) + the #31/#32/#43 hardening since v3.3.0. Backward-compatible feature additions → minor bump. Bumps the full version-sync surface (core/sdk Cargo.toml + core-dep pins, package.json + optionalDeps, pyproject + bootstrap __version__, Cargo.lock, npm lockfiles); scripts/check_release_versions.sh passes at 3.4.0. Adds the [3.4.0] CHANGELOG entry. No source changes — prep only. --- CHANGELOG.md | 73 +++++++++++++++++++ Cargo.lock | 2 +- core/Cargo.toml | 2 +- sdk/node/Cargo.toml | 4 +- sdk/node/examples/package-lock.json | 14 ++-- sdk/node/package-lock.json | 16 ++-- sdk/node/package.json | 14 ++-- sdk/python-bootstrap/pyproject.toml | 2 +- .../src/a3s_code/_bootstrap.py | 2 +- sdk/python/Cargo.toml | 4 +- sdk/python/pyproject.toml | 2 +- 11 files changed, 104 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dc3b18..50a5459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,79 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.4.0] - 2026-05-30 + +Programmable, deterministic multi-agent orchestration — a grammar for +expressing fan-out, pipelines, and resumable workflows in code (not only via +model-driven delegation), drawn along the framework / host (书安OS) boundary: +the framework owns the grammar + serializable contracts; the host owns +placement, transport, and scheduling. All additions are backward compatible +(new types/methods, new optional fields, new `SessionStore` methods with +default no-op impls). + +### Added + +- **`AgentExecutor` seam** (`orchestration` module) — the boundary between the + orchestration grammar and the host's placement/transport/scheduling. The + in-box `TaskExecutor` runs each step as a child agent locally; a host + substitutes its own executor to place steps across a cluster. + `concurrency_hint()` is advisory, not a hard local bound, so orchestration + scales past a single process. `AgentSession::agent_executor()` / + `session_store()` expose a session-backed executor + its store. +- **Serializable step contracts** — `AgentStepSpec` (`task_id` / `agent` / + `description` / `prompt` / `max_steps?` / `parent_session_id?` / + `output_schema?`) and `StepOutcome` (`+ structured?`), serializable for + cross-node transport and checkpoints. +- **Combinators** — + - `execute_steps_parallel` — barrier fan-out, input-order preserving, + per-branch panic isolation, bounded by the executor's concurrency hint. + - `execute_pipeline` — per-item chains through stages with **no inter-stage + barrier** (item A can be in stage 3 while item B is still in stage 1); + stages are pure spec-builders that branch on the prior outcome. + - `execute_steps_parallel_resumable` — journals completed steps to a + `SessionStore` at each step boundary; on resume it skips completed steps + and re-dispatches the rest. Records only successful steps (a failed step + retries on resume). The checkpoint is serializable, so a host can resume an + interrupted workflow on a *different* node. +- **Schema-forced step output** — a step carrying `output_schema` returns a + schema-validated object in `StepOutcome.structured` (reuses the + structured-output coercion + repair). A coercion failure demotes the step to + unsuccessful, so callers never treat unvalidated text as the promised object. +- **`WorkflowCheckpoint`** (`schema_version` / `workflow_id` / `steps` / + `checkpoint_ms`) + `SessionStore::{save,load,delete}_workflow_checkpoint` + (default no-ops; the file store writes crash-atomically). Loads from a + future, incompatible schema version are rejected. +- **SDK grammar (Node + Python)** — `session.parallel(specs)`, + `session.pipeline(items, stages)`, `session.parallelResumable(specs, + workflowId)` (Node, camelCase) / `parallel` / `pipeline` / + `parallel_resumable` (Python, snake_case). Pipeline stages are JS/Python + callbacks `(ctx) -> spec | null`; the bridges fail closed — a hung, + null-returning, or raising stage stops only its own chain. (A Node stage + callback must not throw — return `null` on error, same constraint as + `setBudgetGuard`.) +- **`LoopCheckpoint::ensure_loadable()`** — loads from a future, incompatible + loop-checkpoint schema version are now rejected at the store layer (both + file and memory), honoring the documented contract. + +### Changed + +- The resumable combinator now distinguishes "no checkpoint" from an + *unreadable* one: an unreadable (e.g. future-version) checkpoint logs a + warning and re-runs the workflow from scratch rather than silently swallowing + the error. +- Documented the FFI panic-safety contract in each SDK's module doc (napi 2.x + does not catch panics in sync `#[napi]` bodies by default; PyO3 0.23 catches + `#[pyfunction]` / `#[pymethods]` bodies). No code change — both boundaries + were audited panic-safe. + +### Tests + +- Persisted-schema round-trip fuzz extended to the new migratable types + (`AgentStepSpec`, `StepOutcome`, `WorkflowCheckpoint`) — round-trip stability + + forward/backward compat. Comprehensive unit **and** real-LLM integration + tests for the orchestration layer (parallel fan-out, multi-item pipeline, the + resume path, nested-schema coercion) run against `.a3s/config.acl`. + ## [3.3.0] - 2026-05-29 Cluster-grade runtime: everything needed for a host platform (e.g. 书安OS) diff --git a/Cargo.lock b/Cargo.lock index 7c488e4..a275b01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,7 +37,7 @@ dependencies = [ [[package]] name = "a3s-code-core" -version = "3.3.0" +version = "3.4.0" dependencies = [ "a3s-acl 0.2.0", "a3s-ahp", diff --git a/core/Cargo.toml b/core/Cargo.toml index 93a310b..a207dd3 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-code-core" -version = "3.3.0" +version = "3.4.0" edition = "2021" authors = ["A3S Lab Team"] license = "MIT" diff --git a/sdk/node/Cargo.toml b/sdk/node/Cargo.toml index 0db1b7b..545f22f 100644 --- a/sdk/node/Cargo.toml +++ b/sdk/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-code-node" -version = "3.3.0" +version = "3.4.0" edition = "2021" authors = ["A3S Lab Team"] license = "MIT" @@ -11,7 +11,7 @@ description = "A3S Code Node.js bindings - Native addon via napi-rs" crate-type = ["cdylib"] [dependencies] -a3s-code-core = { version = "3.3.0", path = "../../core", features = ["ahp", "s3"] } +a3s-code-core = { version = "3.4.0", path = "../../core", features = ["ahp", "s3"] } napi = { version = "2", features = ["async", "napi6", "serde-json"] } napi-derive = "2" tokio = { version = "1.35", features = ["full"] } diff --git a/sdk/node/examples/package-lock.json b/sdk/node/examples/package-lock.json index 61413f9..38743a3 100644 --- a/sdk/node/examples/package-lock.json +++ b/sdk/node/examples/package-lock.json @@ -18,7 +18,7 @@ }, "..": { "name": "@a3s-lab/code", - "version": "3.3.0", + "version": "3.4.0", "license": "MIT", "devDependencies": { "@napi-rs/cli": "^2", @@ -27,12 +27,12 @@ "typescript": "^5.9.3" }, "optionalDependencies": { - "@a3s-lab/code-darwin-arm64": "3.3.0", - "@a3s-lab/code-linux-arm64-gnu": "3.3.0", - "@a3s-lab/code-linux-arm64-musl": "3.3.0", - "@a3s-lab/code-linux-x64-gnu": "3.3.0", - "@a3s-lab/code-linux-x64-musl": "3.3.0", - "@a3s-lab/code-win32-x64-msvc": "3.3.0" + "@a3s-lab/code-darwin-arm64": "3.4.0", + "@a3s-lab/code-linux-arm64-gnu": "3.4.0", + "@a3s-lab/code-linux-arm64-musl": "3.4.0", + "@a3s-lab/code-linux-x64-gnu": "3.4.0", + "@a3s-lab/code-linux-x64-musl": "3.4.0", + "@a3s-lab/code-win32-x64-msvc": "3.4.0" } }, "node_modules/@a3s-lab/code": { diff --git a/sdk/node/package-lock.json b/sdk/node/package-lock.json index f8c85cf..9a681e3 100644 --- a/sdk/node/package-lock.json +++ b/sdk/node/package-lock.json @@ -1,12 +1,12 @@ { "name": "@a3s-lab/code", - "version": "3.3.0", + "version": "3.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@a3s-lab/code", - "version": "3.3.0", + "version": "3.4.0", "license": "MIT", "devDependencies": { "@napi-rs/cli": "^2", @@ -15,12 +15,12 @@ "typescript": "^5.9.3" }, "optionalDependencies": { - "@a3s-lab/code-darwin-arm64": "3.3.0", - "@a3s-lab/code-linux-arm64-gnu": "3.3.0", - "@a3s-lab/code-linux-arm64-musl": "3.3.0", - "@a3s-lab/code-linux-x64-gnu": "3.3.0", - "@a3s-lab/code-linux-x64-musl": "3.3.0", - "@a3s-lab/code-win32-x64-msvc": "3.3.0" + "@a3s-lab/code-darwin-arm64": "3.4.0", + "@a3s-lab/code-linux-arm64-gnu": "3.4.0", + "@a3s-lab/code-linux-arm64-musl": "3.4.0", + "@a3s-lab/code-linux-x64-gnu": "3.4.0", + "@a3s-lab/code-linux-x64-musl": "3.4.0", + "@a3s-lab/code-win32-x64-msvc": "3.4.0" } }, "node_modules/@a3s-lab/code-darwin-arm64": { diff --git a/sdk/node/package.json b/sdk/node/package.json index b78afd4..a4ca377 100644 --- a/sdk/node/package.json +++ b/sdk/node/package.json @@ -1,6 +1,6 @@ { "name": "@a3s-lab/code", - "version": "3.3.0", + "version": "3.4.0", "description": "A3S Code - Native Node.js bindings for the coding-agent runtime", "main": "index.js", "types": "index.d.ts", @@ -43,11 +43,11 @@ "test:helpers": "node test-helpers.mjs" }, "optionalDependencies": { - "@a3s-lab/code-darwin-arm64": "3.3.0", - "@a3s-lab/code-linux-x64-gnu": "3.3.0", - "@a3s-lab/code-linux-x64-musl": "3.3.0", - "@a3s-lab/code-linux-arm64-gnu": "3.3.0", - "@a3s-lab/code-linux-arm64-musl": "3.3.0", - "@a3s-lab/code-win32-x64-msvc": "3.3.0" + "@a3s-lab/code-darwin-arm64": "3.4.0", + "@a3s-lab/code-linux-x64-gnu": "3.4.0", + "@a3s-lab/code-linux-x64-musl": "3.4.0", + "@a3s-lab/code-linux-arm64-gnu": "3.4.0", + "@a3s-lab/code-linux-arm64-musl": "3.4.0", + "@a3s-lab/code-win32-x64-msvc": "3.4.0" } } diff --git a/sdk/python-bootstrap/pyproject.toml b/sdk/python-bootstrap/pyproject.toml index 2388250..32c03fc 100644 --- a/sdk/python-bootstrap/pyproject.toml +++ b/sdk/python-bootstrap/pyproject.toml @@ -7,7 +7,7 @@ name = "a3s-code" # Keep in sync with crates/code core release. The bootstrap loader fetches # the matching native wheel from `https://github.com/AI45Lab/Code/releases/tag/v` # at import time. -version = "3.3.0" +version = "3.4.0" description = "A3S Code Python SDK — pure-Python bootstrap that fetches the native wheel from GitHub Releases" readme = "README.md" license = {text = "MIT"} diff --git a/sdk/python-bootstrap/src/a3s_code/_bootstrap.py b/sdk/python-bootstrap/src/a3s_code/_bootstrap.py index ac6bd83..5757701 100644 --- a/sdk/python-bootstrap/src/a3s_code/_bootstrap.py +++ b/sdk/python-bootstrap/src/a3s_code/_bootstrap.py @@ -31,7 +31,7 @@ # Version is the bootstrap's own version, which equals the matching native # wheel version on GH Releases. Bumped by the release workflow. -__version__ = "3.3.0" +__version__ = "3.4.0" _DEFAULT_BASE_URL = "https://github.com/AI45Lab/Code/releases/download" _REQUEST_TIMEOUT_S = 120 diff --git a/sdk/python/Cargo.toml b/sdk/python/Cargo.toml index 0a6b5a0..8df0172 100644 --- a/sdk/python/Cargo.toml +++ b/sdk/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "a3s-code-py" -version = "3.3.0" +version = "3.4.0" edition = "2021" authors = ["A3S Lab Team"] license = "MIT" @@ -12,7 +12,7 @@ name = "a3s_code" crate-type = ["cdylib"] [dependencies] -a3s-code-core = { version = "3.3.0", path = "../../core", features = ["ahp", "s3"] } +a3s-code-core = { version = "3.4.0", path = "../../core", features = ["ahp", "s3"] } pyo3 = "0.23" tokio = { version = "1.35", features = ["full"] } serde_json = "1.0" diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index 53a4ad1..34d75fa 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "maturin" [project] name = "a3s-code" -version = "3.3.0" +version = "3.4.0" description = "A3S Code - Native Python bindings for the coding-agent runtime" readme = "README.md" license = {text = "MIT"}