Changelog

Every release, in the open.

The complete history of the Delta harness, from the first public package to today. Each version tracks the source CHANGELOG.md exactly — nothing shipped quietly.

v0.2.4

Latest

Harden what shipped; close the gaps.

Security, observability, and performance hardening. No wire changes, so upgrading is a one-line version bump — every change is provider-agnostic and lands with tests.

Added
  • Tunable concurrency. DELTA_MAX_CONCURRENCY sets how many sessions run at once — default 8 (up from 4), clamped 1–256. Sessions stay serial and the queue is tested correct to 128 concurrent runs; the practical ceiling is your provider's rate limit, so keep it low on a subscription key and 25+ on a high-limit API key. Budget roughly 4–15 MB per active run.
  • Live progress without a stream. GET /v1/tasks/:id/events?since=<id> returns a cursor-paged JSON page for hosts that can't hold an SSE connection, and model.call events now carry cache_hit_pct so you can watch per-turn prompt-cache warmth live instead of reconstructing it after the fact.
  • One-step operator-config updates. The new delta bundle apply command (also run on every boot) re-seeds the fixed operator files, validating each first and never touching the agent's learned DELTA.md.
Changed
  • Faster cold starts on scale-to-zero. A host can now flip stopsuspend and cut cold start from ~4.7s to ~1.1s. The write-lease reclaims itself across a suspend instead of exiting and stalling on the platform's restart cap.
  • Per-tenant task access. GET/DELETE /v1/tasks/:id and …/events now enforce that the caller owns the run — a cross-tenant or unknown id both return 404. Ownership comes from the gateway x-delta-user header, never a request body. Set DELTA_STRICT_TENANT to require an owner on every run.
  • Memory-widening can't be self-asserted. The metadata that widens a private memory to a broader audience is stripped from every request body by default, so a caller can't self-authorize it. DELTA_TRUST_REVIEW_METADATA=1 opts a single-tenant daemon back in.
  • Read-only research subagents. A research child is admitted only read-only tools; anything unmarked defaults to mutating, so it can never write, remember, or run code mid-run.
  • Earlier, cheaper compaction. The pre-send size gate now projects off the provider's real last-call input, so a long run compacts before it wastes a frontier call on an over-budget request.
  • Deterministic memory recall. An identical query returns the same set every time (ranking no longer drifts on a self-mutating counter). DELTA_ISOLATE_AGENT_MEMORY keeps agents on a shared database from reading each other's rows.
Fixed
  • Concurrent self-writes no longer clobber each other. Two runs calling remember at once used to overwrite each other's DELTA.md, silently dropping one lesson. A compare-and-swap now lets both survive.
  • No more silently dropped lessons. A malformed learning could throw and be lost entirely (latent since 0.1.0); it now degrades to a best-effort learning instead of none.

v0.2.3

Failure-visibility, from the field.

Driven by Aperture's production field report — two prod agents, the harness's heaviest real consumer. Every item ships with a test.

Added
  • A first-class error field on GET /v1/tasks/:id. It carries the run's last error — the provider or fatal error that ended it — so a plain HTTP poller learns why a run failed before its first token instead of seeing a merely-dead run. Both incidents that motivated it were provider errors that failed the run before its first token (Opus 5 rejecting thinking.type=enabled; an untranslated fallback id). Per-tool errors stay in the message stream.
  • Run lifecycle timestamps on GET /v1/tasks/:id: created_at (accepted), started_at (dequeued and began executing), and finished_at (terminal), so a host can measure queue wait separately from execution time instead of one faith-based spinner.
  • Native Anthropic adaptive thinking. DELTA_REASONING_EFFORT now maps to thinking:{type:"adaptive"} + output_config.effort on Claude 4.6+ and every Claude 5 model, which reject the legacy thinking:{type:"enabled"}; the budget wire is kept for Claude ≤4.5. On the adaptive path none/minimal map to low, and Delta raises max_tokens by an effort-based headroom. Effort control now works on frontier models.
  • Baked claude-opus-5 pricing, so the native and subscription paths meter real dollars without a DELTA_MODEL_PRICES override.
  • The four hosting lifecycle contracts are now documented guarantees in docs/hosting.md — idempotency keys freed on terminal runs, recover() resumes mid-flight runs on boot, /v1/busy reports the durable queued-or-running truth, and seeding never touches an existing DELTA.md — each pinned by a named guard test so it can't silently regress.
Changed
  • Categorical-failure breaker. A tool that returns the same categorical [tool error] on three consecutive turns (a missing CLI, a persistent schema reject) is quarantined for the rest of the run and the model is told to try another approach — a success, transient, or different error resets the count. This caps the field report's worst case (a missing code CLI that burned ~$3.50 of a $5.17 run by looping ~17 turns): a live replay spent pennies on the dead end and still filed its output.
  • The code tool self-disables when its CLI isn't an executable file — probed once at boot via Bun.which (bare name) or accessSync(X_OK) (explicit path), so a capability the daemon can't back is never offered. A CLI that passes the probe but fails at runtime is caught by the breaker instead; the two layers are complementary.
  • All native-wire model ids are normalized (prefix stripped, dotted versions → dashes) for the primary and every fallback, not just the utility model. An untranslated fallback id was one of the two silent zero-token failures the release targets.

v0.2.2

Self-write, budgets, and a channel edge.

Added
  • DELTA_ALLOW_SELF_WRITE — trusted-gateway self-write. Off by default. When set, the remember self-write tool is granted (and pinned) even on the restricted chat profile, for a daemon fronted by a trusted, authenticated gateway. This is what lets a chat agent learn safely.
  • DELTA_STEP_MAX_TOKENS — cap the tokens a single tool call may emit, with an honest truncation error for oversized tool calls instead of silent corruption.
  • Companion package [@carrara-labs/delta-connect](https://www.npmjs.com/package/@carrara-labs/delta-connect) — a thin, always-on edge that plugs a Delta agent into a chat channel (Telegram first). The agent scales to zero between messages; the edge holds the conversation. See [/connect](https://deltaharness.dev/connect).
Changed
  • DELTA_MAX_TOKENS / DELTA_MAX_COST_USD now override the profile budget instead of only narrowing it, so an operator can raise as well as lower a profile's budget explicitly.

v0.2.1

Scale-to-zero, made safe.

Added
  • GET /v1/busy — the scale-to-zero lifecycle signal. A host managing suspend and resume can ask the daemon “is it safe to suspend?” and get { busy, running, queued }, read from the durable run table so a machine is never suspended with work still owed — including a queued run that hasn't started. It sits behind the /v1/ control-token gate, deliberately not folded into the open, data-free /healthz.
  • docs/hosting.md — the hosting lifecycle contract: control-plane-owned suspend and resume, the three host hooks (wake before dispatch, busy-check before suspend, suspend after terminal), and the WAL suspend-safety guarantee that makes aggressive suspend safe.
Changed
  • DELTA_MCP_SERVERS parsing fails loud, never silent. A malformed value used to boot the agent tool-less and burn a full model run before anyone noticed. Malformed JSON, a non-array, and each unusable entry are now dropped with a specific boot-log warning — and a missing transport is inferred from the entry shape (urlhttp, commandstdio) so a common omission just works.
Fixed
  • A bad stdio MCP server no longer crashes boot. A command that spawns and throws synchronously is now caught inside the registry boundary and logged, and the daemon boots with the remaining backends — honoring the “one bad server is never fatal” contract.

v0.2.0

Sub-agents grow up.

Changed
  • Sub-agents (research) now hold the same rights as the parent, not a read-only subset. A child's callable tools are the parent's full registry minus a small withheld set (the delegation tools research/spawn_subagent/eval_n, plus the run-scheduling tools), so nesting stays exactly one level deep. A child can read, write, run code, remember, and call MCP reads and writes — whatever the parent can — and it's built from the same system spine, so it inherits the parent's rules along with its rights.
Removed
  • DELTA_RESEARCH_TOOLS. The operator allowlist that gated which MCP reads a research child could use is gone — children inherit the parent's tools directly. The variable is now ignored; remove it from any config.

v0.1.2

Safe-to-retry dispatch.

Added
  • Dispatch idempotency for POST /v1/tasks. A run request may carry an idempotency_key; a retry dedupes onto the live run instead of starting a duplicate, so fire-and-forget async dispatch is safe to retry. Race-safe with no schema migration, and it composes with store: false.

v0.1.1

Container image, cleaner clone.

Added
  • Published docker run image at ghcr.io/carrara-labs/delta-harness, documented on the Deploy guide.
  • Hardened release and secret-scan workflows: checksum-verified gitleaks, a tag-gated scan, and ghcr publish.
Changed
  • Clearer, more technical README and npm package description.
  • Removed stale monorepo doc-sync tooling so bun run check works on a clean clone.
Fixed
  • Sub-agents inherit the parent's model: childEnv forwards DELTA_MODEL_PRIMARY, not just the legacy DELTA_MODEL alias.

v0.1.0

Delta, in the open.

Initial public release.

Added
  • Product-neutral engine: a durable Run and queue (crash- and redeploy-resumable), a zero-dependency OpenAI-compatible provider with model failover and prompt-cache breakpoints, the tool-call loop with builtins and profiles, an MCP client with progressive tool disclosure, usage-aware compaction, a governed memory rail, and NDJSON observability.
  • The bundle model (agent = engine + bundle + state): delta init scaffolds a bundle and delta dev boots the local Cockpit.
  • The HTTP seam: POST /v1/responses, GET /healthz, and the async POST /v1/tasks surface.
  • Apache 2.0 license, single-binary builds, and the container image.

Delta follows Semantic Versioning. A daemon reports its running version at /healthz, and upgrades only ever move a deployed agent's database forward.

Watch the repository for what's next.