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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ llm_cache/
# Local Claude Code agent state (worktrees, transcripts)
/.claude/
/.claire/

# local evidence/run artifacts
.boruna/
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ The server communicates over JSON-RPC stdio. All tools return structured JSON wi
| `boruna_capability_list` | List the frozen 1.0 capability set with `capability_set_hash` |
| `boruna_policy_validate` | Validate a `Policy` JSON document; returns typed `error_kind` on rejection |
| `boruna_symbols` | Extract top-level symbols (fns/records/enums) from `.ax` source → exact typed signatures, capabilities, requires/ensures arity |
| `boruna_run_sealed` | Compile + run `.ax`, replay-verify the execution, return a verifiable record (result, `replay_verified`, capability calls, event log, SHA-256 seal digest) |

## Agent-native CLI surfaces

Expand Down
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,54 @@ Versioning follows [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [3.1.0] — 2026-07-18

Additive feature release — no breaking changes. Deepens Boruna's two moats:
**verifiable/auditable evidence** (standards interop, compliance reporting,
observability export, sealed contract/guard verdicts) and **agent authoring**
(exact-signature lookup, a run-and-seal execution cell, an agent corpus). Ideas
were mined from adjacent tooling (Temporal/LangGraph/Langfuse/Credo AI/SLSA/
in-toto/Sigstore) and from the `agentlanguages.dev` peer catalogue, then mapped
onto Boruna's determinism + evidence model.

### Added

- **In-toto + DSSE attestation** — `boruna evidence attest <dir>` emits the
bundle as an in-toto Statement (`predicateType https://boruna.dev/runtime-provenance/v1`)
wrapped in a DSSE envelope signed with the bundle's ed25519 key; `--verify`
checks it. Makes runtime-execution provenance consumable by the supply-chain
ecosystem (`cosign`, `in-toto-verify`). Additive — the native bundle is unchanged.
Predicate schema: `docs/spec/runtime-provenance-predicate-1.0.md`.
- **Compliance-mapping report** — `boruna evidence report --framework eu-ai-act|nist|iso42001`
verifies a bundle, then maps its contents to the specific obligation each helps
satisfy (EU AI Act Art. 12/19/26, NIST AI RMF, ISO/IEC 42001), honestly flagging
gaps. A technical mapping, not a certificate of compliance.
- **OpenTelemetry export** — `boruna evidence otel <dir>` emits the run as OTLP/JSON
spans (no SDK dep, no network) with tamper-evidence attributes
(`boruna.bundle_hash`, `audit_log_hash`, `signature.keyid`) and `gen_ai.*` spans
for `llm.*` calls, so a run surfaces in any OTel backend while linking back to a
verifiable record.
- **Sealed contract + guard verdicts** — `requires`/`ensures` contract checks now
record a `ContractCheck` event (pass and fail) into the hash-chained evidence log.
New `__builtin_guard(value, passed, label)` runs a deterministic output check,
traps fail-closed on violation, and seals the verdict — so "the guardrail ran on
this model output and returned this verdict" becomes a replayable, tamper-evident fact.
- **`std-guard` standard library** (14th lib) — pure, deterministic output validators
(length/range/allow-list/ban-list/refusal-heuristic/json-shape).
- **MCP tools** (now 14) — `boruna_symbols` (exact typed signatures for `.ax` source)
and `boruna_run_sealed` (compile + run + replay-verify → a verifiable execution record).
- **Quickfix-coverage CI gate** — every auto-fixable diagnostic must ship a repair
strategy or be explicitly allow-listed.
- **Agent corpus & docs** — `llms.txt`, an `.ax` teaching primer, a static agent
portal manifest, an evidence threat model, and a runtime-execution-provenance
positioning doc.

### Fixed

- **`docs/reference/ax-language.md` syntax drift** — corrected to the real grammar
(records use `type`, enum variants are unit or single-payload, match arms use bare
variant names), verified with `boruna lang check`.

## [3.0.0] — 2026-07-18

Removes the entire HTTP / serving / distributed-execution layer. Boruna is now a
Expand Down
7 changes: 4 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ Note: directory paths still use original names (crates/llmbc, crates/llmc, etc.)
- **boruna-framework** (dir: crates/llmfw) — Framework layer enforcing the App protocol (Elm architecture: init/update/view). `AppValidator`, `AppRuntime`, `TestHarness`, `PolicySet`, state machine diffing.
- **boruna-effect** (dir: crates/llm-effect) — Token-optimized LLM integration: prompt building, context management, caching, normalization, capability gating for LLM calls.
- **boruna-cli** (dir: crates/llmvm-cli) — CLI binary (`boruna`). Subcommands: compile, run, trace, replay, inspect, ast, framework, lang, trace2tests, template, workflow, evidence.
- **boruna-mcp** (dir: crates/boruna-mcp) — MCP server binary (`boruna-mcp`). Exposes 13 tools over JSON-RPC stdio for AI coding agents. Built on rmcp v0.16.
- **boruna-mcp** (dir: crates/boruna-mcp) — MCP server binary (`boruna-mcp`). Exposes 14 tools over JSON-RPC stdio for AI coding agents. Built on rmcp v0.16.

### Supporting Crates

Expand All @@ -122,8 +122,8 @@ Note: directory paths still use original names (crates/llmbc, crates/llmc, etc.)

### Standard Libraries (libs/)

13 deterministic libraries, each with `package.ax.json` and `src/core.ax`:
std-ui, std-forms, std-authz, std-http, std-db, std-sync, std-validation, std-routing, std-storage, std-notifications, std-testing (all 1.0-stable as of v1.2.0), plus std-llm and std-json (1.0-stable as of v1.3.0). All 13 are 1.0-stable.
14 deterministic libraries, each with `package.ax.json` and `src/core.ax`:
std-ui, std-forms, std-authz, std-http, std-db, std-sync, std-validation, std-routing, std-storage, std-notifications, std-testing (all 1.0-stable as of v1.2.0), plus std-llm and std-json (1.0-stable as of v1.3.0), plus std-guard (deterministic output validators). The original 13 are 1.0-stable.

All are pure-functional (no hidden side effects). Libraries needing capabilities declare them in their manifest (e.g., std-http requires `net.fetch`, std-db requires `db.query`).

Expand Down Expand Up @@ -152,6 +152,7 @@ MCP (Model Context Protocol) server that exposes Boruna's toolchain to AI coding
| `boruna_capability_list` | Report the capability-set identity hash for `.ax` source |
| `boruna_policy_validate` | Validate a policy definition (strict validator) |
| `boruna_symbols` | Extract top-level symbols (fns/records/enums) from `.ax` source → exact typed signatures, capabilities, requires/ensures arity |
| `boruna_run_sealed` | Compile + run `.ax`, replay-verify the execution, return a verifiable record (result, `replay_verified`, capability calls, event log, SHA-256 seal digest). Not a signed bundle — that's the workflow path |

### IDE Configuration

Expand Down
25 changes: 13 additions & 12 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 @@ -16,7 +16,7 @@ members = [
]

[workspace.package]
version = "3.0.0"
version = "3.1.0"
edition = "2021"

[workspace.dependencies]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ This makes Boruna suited for teams building AI workflows that touch regulated da
- **Diagnostics, auto-repair, and migration** — `boruna lang check`, `boruna lang repair`, `boruna migrate` for `.ax` files and bundle/workflow upgrades
- **`boruna new`** — interactive scaffold for new workflows from templates
- **33 built-in functions** — string (12), list (7), and map (7) operations plus type conversions and debug builtins (`__builtin_string_*`, `__builtin_list_*`, `__builtin_map_*`, …) available in every `.ax` file without imports
- **Import resolution** — `import "std-name"` inlines `libs/<name>/src/core.ax` at compile time; all 13 stdlib packages are 1.0-stable
- **Import resolution** — `import "std-name"` inlines `libs/<name>/src/core.ax` at compile time; 14 stdlib packages (the original 13 are 1.0-stable)
- **Four formal versioned specifications** — `.ax` language 1.0, bytecode 1.0, evidence bundle format 1.0, workflow DAG schema 1.0 (all under [`docs/spec/`](./docs/spec/))
- **MCP server** — exposes 13 tools for AI coding agent integration (Claude Code, Cursor, Codex)
- **MCP server** — exposes 14 tools for AI coding agent integration (Claude Code, Cursor, Codex)

## What Boruna is not

Expand Down
1 change: 1 addition & 0 deletions crates/boruna-mcp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ schemars = "1.0"
clap = { workspace = true }
tempfile = "3"
jsonschema = { version = "0.30", default-features = false }
sha2 = "0.10"
36 changes: 36 additions & 0 deletions crates/boruna-mcp/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ struct RunLimitsParams {
max_memory_mb: Option<u64>,
}

#[derive(Serialize, Deserialize, JsonSchema)]
struct RunSealedParams {
/// The .ax source code to run and seal
source: String,
/// Capability policy — SAME shape as `boruna_run`. Either the string
/// shorthand "allow-all" / "deny-all" (default: "allow-all") or a Policy
/// object (see docs/reference/policy-schema.md). Invalid values return
/// success=false with error_kind="invalid_policy" or a policy.* kind.
#[serde(default)]
policy: Option<serde_json::Value>,
/// Maximum execution steps (default: 10000000). Deterministic ceiling,
/// applied to both the original and the replay run.
max_steps: Option<u64>,
}

#[derive(Serialize, Deserialize, JsonSchema)]
struct SymbolsParams {
/// The .ax source code to extract top-level symbols from
Expand Down Expand Up @@ -334,6 +349,27 @@ impl BorunaMcpServer {
Ok(CallToolResult::success(vec![Content::text(result)]))
}

// ── Run-and-Seal Tool ──

#[tool(
description = "Compile and execute .ax source, then return a VERIFIABLE execution record — not just the result. The run is executed once to capture the VM EventLog (capability calls/results, actor events, UI emits, and requires/ensures contract checks), then RE-EXECUTED a second time with the recorded capability results fed back through a replay handler; the two logs are compared with ReplayEngine::verify_full. The response carries `replay_verified` (true only when every event recurs identically), `result`, `steps`, an ordered `capability_calls` list, the full `event_log`, and `event_log_sha256` — a SHA-256 digest of the canonical log that acts as a stable seal handle. `policy` uses the SAME shape as boruna_run. IMPORTANT: the 'seal' here is a replay-verified event log, NOT a signed evidence bundle — a signed, hash-chained bundle is a workflow-directory artifact produced by the orchestrator (`boruna workflow run --record` / `boruna evidence verify`); the response documents this in seal.note. Use this to call Boruna as a deterministic, auditable execution cell from an external agent framework. Domain errors (compile/parse failures, runtime_error, capability_denied, invalid_policy) are returned as success=false JSON."
)]
async fn boruna_run_sealed(
&self,
Parameters(params): Parameters<RunSealedParams>,
) -> Result<CallToolResult, McpError> {
validate_source(&params.source)?;
let source = params.source;
let policy = params.policy;
let max_steps = params.max_steps.unwrap_or(10_000_000);
let result = tokio::task::spawn_blocking(move || {
tools::sealed::run_sealed(&source, policy.as_ref(), max_steps)
})
.await
.map_err(|e| McpError::internal_error(format!("task join error: {e}"), None))?;
Ok(CallToolResult::success(vec![Content::text(result)]))
}

// ── Diagnostics Tools ──

#[tool(
Expand Down
22 changes: 22 additions & 0 deletions crates/boruna-mcp/src/tools/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod compile;
pub mod framework;
pub mod policy;
pub mod run;
pub mod sealed;
pub mod symbols;
pub mod template;
pub mod workflow;
Expand Down Expand Up @@ -121,6 +122,27 @@ mod protocol_version_tests {
assert_protocol_version(&out, "run compile failure");
}

// ── run_sealed ──

#[test]
fn run_sealed_success_carries_protocol_version() {
let out = sealed::run_sealed("fn main() -> Int { 1 + 2 }\n", None, 1_000_000);
assert_protocol_version(&out, "run_sealed success");
}

#[test]
fn run_sealed_compile_failure_carries_protocol_version() {
let out = sealed::run_sealed("@@@ not valid", None, 1_000_000);
assert_protocol_version(&out, "run_sealed compile failure");
}

#[test]
fn run_sealed_invalid_policy_carries_protocol_version() {
let bad = serde_json::json!(42);
let out = sealed::run_sealed("fn main() -> Int { 1 }\n", Some(&bad), 1_000_000);
assert_protocol_version(&out, "run_sealed invalid_policy");
}

// ── check / repair ──

#[test]
Expand Down
2 changes: 1 addition & 1 deletion crates/boruna-mcp/src/tools/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ pub(crate) fn parse_policy(value: Option<&JsonValue>) -> Result<Policy, ParsePol
}
}

fn format_value(value: &Value) -> serde_json::Value {
pub(crate) fn format_value(value: &Value) -> serde_json::Value {
match value {
Value::Int(n) => serde_json::json!(n),
Value::Float(f) => serde_json::json!(f),
Expand Down
Loading
Loading