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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ workflow copies that section onto the GitHub Release page and refuses to
publish when it is missing, empty, or still says Unreleased. Write it in the
version bump pull request by renaming `## Unreleased` to the version.

## 0.20.6 - 2026-10-09

Native build and test commands now document the time needed for cold builds.

- `workspace_native_exec` tells workers that builds and test suites may take several minutes and accepts a `timeoutMs` up to `600000ms`, including in its compact descriptor.
- Regression coverage pins the full and compact tool descriptions and the timeout schema.

## 0.20.5 - 2026-10-08

A scheduled program no longer waits forever on a child task you cancelled.
Expand Down
8 changes: 4 additions & 4 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["crates/xcb-platform", "crates/xcb-core", "crates/xcb-runtime", "crat
resolver = "3"

[workspace.package]
version = "0.20.5"
version = "0.20.6"
edition = "2024"
rust-version = "1.97.1"
license = "MIT"
Expand Down
4 changes: 2 additions & 2 deletions crates/xcb-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ serde = "=1.0.229"
serde_json = "=1.0.151"
tokio = { version = "=1.47.1", features = ["rt-multi-thread", "macros", "signal", "sync", "time"] }
unicode-width = "=0.2.2"
xcb-core = { version = "0.20.5", path = "../xcb-core" }
xcb-runtime = { version = "0.20.5", path = "../xcb-runtime" }
xcb-core = { version = "0.20.6", path = "../xcb-core" }
xcb-runtime = { version = "0.20.6", path = "../xcb-runtime" }
zeroize = "=1.9.0"

[target.'cfg(unix)'.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion crates/xcb-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ thiserror = "=2.0.21"
proptest = "=1.11.0"

[target.'cfg(windows)'.dependencies]
xcb-platform = { version = "0.20.5", path = "../xcb-platform" }
xcb-platform = { version = "0.20.6", path = "../xcb-platform" }
4 changes: 2 additions & 2 deletions crates/xcb-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ tokio = { version = "=1.47.1", features = ["rt-multi-thread", "macros", "process
tokio-rustls = { version = "=0.26.6", default-features = false, features = ["ring", "tls12"] }
uuid = { version = "=1.27.0", features = ["v4", "v7", "serde"] }
webpki-roots = "=1.0.9"
xcb-core = { version = "0.20.5", path = "../xcb-core" }
xcb-core = { version = "0.20.6", path = "../xcb-core" }
zeroize = "=1.9.0"

[target.'cfg(unix)'.dependencies]
Expand All @@ -46,4 +46,4 @@ local-custody = { git = "https://github.com/hraness/local-custody", rev = "4fd65
rustix = { version = "=1.1.5", features = ["fs", "process", "pty", "termios"] }

[target.'cfg(windows)'.dependencies]
xcb-platform = { version = "0.20.5", path = "../xcb-platform" }
xcb-platform = { version = "0.20.6", path = "../xcb-platform" }
4 changes: 2 additions & 2 deletions crates/xcb-runtime/src/broker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ pub fn descriptors() -> Vec<Value> {
("xcb_tools_image", "Reopen a stored screenshot or image named in this session's recent history. Returns the image itself without taking another screenshot or interacting with the page.", json!({"id":{"type":"string","minLength":1,"maxLength":160}}), vec!["id"]),
("workspace_exec", "Run a bounded offline Linux command in a staged workspace, then publish successful joined changes with revision checks. Host credentials, source Git configuration/hooks/history, host dependencies and build outputs are excluded. Supported repositories provide filtered read-only Git HEAD/index for status and diffs; Git writes are unavailable. Requires the configured isolated command runner. argv executes directly; use sh -c explicitly for shell syntax.", json!({"argv":{"type":"array","minItems":1,"maxItems":64,"items":{"type":"string","maxLength":32768}},"cwd":{"type":"string","minLength":1,"maxLength":4096,"description":"Folder to run in, relative to the workspace root; use \".\" for the root"},"timeoutMs":{"type":"integer","minimum":1,"maximum":600000},"network":{"type":"string","enum":["none"]}}), vec!["argv","cwd","timeoutMs","network"]),
("workspace_host_exec", "Run a bounded command in the real host worktree with ordinary network and host GitHub credentials. Only an explicitly host-admitted managed Codex task can use this lane. Host commands can change the worktree, Git history and remote services directly; nonzero or interrupted outcomes retain uncertain effects. argv executes directly; use sh -c explicitly for shell syntax.", json!({"argv":{"type":"array","minItems":1,"maxItems":64,"items":{"type":"string","maxLength":32768}},"cwd":{"type":"string","minLength":1,"maxLength":4096},"timeoutMs":{"type":"integer","minimum":1,"maximum":600000},"network":{"type":"string","enum":["host"]}}), vec!["argv","cwd","timeoutMs","network"]),
("workspace_native_exec", "Run argv directly in the real worktree through XCB's OS-confined native executor, shared by Claude and Codex. Requires a host-owned workspace/provider grant and a persistent native task requirement. Network is DNS and HTTPS, not offline replay. File writes are immediate and bounded to the workspace and explicitly granted Git metadata; credentials are unavailable unless the host grant explicitly includes GitHub. Never retry a failed or interrupted command without effect reconciliation.", json!({"argv":{"type":"array","minItems":1,"maxItems":64,"items":{"type":"string","maxLength":32768}},"cwd":{"type":"string","minLength":1,"maxLength":4096},"timeoutMs":{"type":"integer","minimum":1,"maximum":600000},"network":{"type":"string","enum":["https"]}}), vec!["argv","cwd","timeoutMs","network"]),
("workspace_native_exec", "Run argv directly in the real worktree through XCB's OS-confined native executor, shared by Claude and Codex. Requires a host-owned workspace/provider grant and a persistent native task requirement. Network is DNS and HTTPS, not offline replay. Builds and test suites may take several minutes; set timeoutMs to as much as 600000ms. File writes are immediate and bounded to the workspace and explicitly granted Git metadata; credentials are unavailable unless the host grant explicitly includes GitHub. Never retry a failed or interrupted command without effect reconciliation.", json!({"argv":{"type":"array","minItems":1,"maxItems":64,"items":{"type":"string","maxLength":32768}},"cwd":{"type":"string","minLength":1,"maxLength":4096},"timeoutMs":{"type":"integer","minimum":1,"maximum":600000,"description":"Builds and test suites may take several minutes; set timeoutMs up to 600000ms."},"network":{"type":"string","enum":["https"]}}), vec!["argv","cwd","timeoutMs","network"]),
("xcb_swarm_status", "List active XCB-managed tasks in this worker's workspace so agents on different providers can discover one another without exposing unrelated workspaces.", json!({}), vec![]),
("xcb_context_query", "Read the exact instructions and declared input context saved for the current managed program child. Hidden inputs and other child reports are unavailable unless passed into this call. op is inspect, read, slice, search or history. inspect pages entry metadata; read returns one entry; slice uses UTF-8 byte boundaries; search finds literal text. history takes a history object (contract \"xcb.program-history.v1\", view inspect/overview/expand/read/search) over the retained program call records: every call keeps its original task and state, and report bodies appear only for calls declared as inputs to this cell. Historical records do not change permissions or prove current facts. The host selects the task and snapshot; other tasks and provider state are unavailable.", json!({"op":{"type":"string","enum":["inspect","read","slice","search","history"]},"offset":{"type":"integer","minimum":0,"maximum":5},"limit":{"type":"integer","minimum":1,"maximum":32},"index":{"type":"integer","minimum":0,"maximum":4},"startByte":{"type":"integer","minimum":0,"maximum":1048576},"endByte":{"type":"integer","minimum":0,"maximum":1048576},"query":{"type":"string","minLength":1,"maxLength":4096},"maxResults":{"type":"integer","minimum":1,"maximum":32},"maxScanBytes":{"type":"integer","minimum":1,"maximum":32768},"history":{"type":"object","properties":{"contract":{"type":"string","enum":["xcb.program-history.v1"]},"view":{"type":"string","enum":["inspect","overview","expand","read","search"]},"recentLeaves":{"type":"integer","minimum":0,"maximum":1024},"derivatives":{"type":"object"},"node":{"type":"string","maxLength":160},"sourceIndex":{"type":"integer","minimum":0,"maximum":1023},"query":{"type":"string","minLength":1,"maxLength":4096},"maxResults":{"type":"integer","minimum":1,"maximum":16},"maxScanBytes":{"type":"integer","minimum":1,"maximum":262144},"limits":{"type":"object"}},"required":["contract","view"],"additionalProperties":false}}), vec!["op"]),
("xcb_message_list", "Read bounded durable XCB messages addressed to the current managed task. Use after to poll for newer cross-provider messages.", json!({"after":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":1,"maximum":64}}), vec![]),
Expand Down Expand Up @@ -756,7 +756,7 @@ const COMPACT_DESCRIPTIONS: &[(&str, &str)] = &[
),
(
"workspace_native_exec",
"Run argv in the real worktree, cwd relative (use .), timeoutMs1..600000, network https. Requires the host's exact workspace/provider grant and native task requirement. OS-confined; credentials only when explicitly granted. Writes are immediate. Failed/interrupted effects require reconciliation, not retry.",
"Run argv in real worktree; cwd relative (use .), timeoutMs 1..600000, network https. Builds/tests may take several minutes; timeoutMs up to 600000ms. Requires exact host workspace/provider grant and native task requirement. OS-confined; credentials only when granted. Writes immediate; reconcile failures, never retry.",
),
(
"xcb_swarm_status",
Expand Down
27 changes: 27 additions & 0 deletions crates/xcb-runtime/tests/broker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,33 @@ fn workspace_read_rejects_oversized_files_with_a_guided_tool_error() {
assert!(error.to_string().contains("exceeds the 128 KiB read limit"));
}

#[test]
fn native_command_descriptor_documents_long_builds_and_binds_timeout() {
use xcb_runtime::broker::{compact_descriptors, descriptors};
let descriptor = descriptors()
.into_iter()
.find(|tool| tool["name"] == "workspace_native_exec")
.expect("native workspace tool descriptor");
let description = descriptor["description"].as_str().unwrap();
assert!(description.contains("several minutes"));
assert!(description.contains("600000ms"));
assert_eq!(
descriptor["inputSchema"]["properties"]["timeoutMs"]["maximum"],
600000
);
assert_eq!(
descriptor["inputSchema"]["properties"]["timeoutMs"]["description"],
"Builds and test suites may take several minutes; set timeoutMs up to 600000ms."
);
let compact = compact_descriptors()
.into_iter()
.find(|tool| tool["name"] == "workspace_native_exec")
.expect("compact native workspace tool descriptor");
let compact_description = compact["description"].as_str().unwrap();
assert!(compact_description.contains("several minutes"));
assert!(compact_description.contains("600000ms"));
}

/// Devin shows `tools/list` to its model as indented JSON and moves any tool
/// output over 10,000 characters into a file that only a denied native tool
/// could read. The listing it receives stays well inside that limit while
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hraness/xcb",
"version": "0.20.5",
"version": "0.20.6",
"description": "TypeScript SDK and compatibility CLI for Excalibur (xcb), which routes coding tasks across the Claude and Codex subscriptions you already pay for.",
"type": "module",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { fileURLToPath } from "node:url";
import { runCliUpdate } from "@hraness/cli-update";
import { compatibilityUpdateOptions } from "./cli/update.ts";

const VERSION = "0.20.5";
const VERSION = "0.20.6";

function reportStartupError(error: unknown): number {
process.stderr.write(`xcb-compat: ${error instanceof Error ? error.message : "unexpected failure"}\n`);
Expand Down
Loading