Releases: beyond10x/harness
Release list
harness 0.12.1
Changed
- Update the embedded confinement boundary to Substrate
3fafeae6(release0.7.7), which leaves
Git metadata untouched during host startup, Git-only observations and workspace destruction when
no Git sources are configured. Bothb10x-substrate-hostandb10x-substrate-wirekeep an exact
=0.7.7version requirement beside the revision, so a resolver cannot substitute a later
contract; the development wire bundle remains0.16.0. - Update the outbound MCP client crates and both testkit declarations to
bf7f9415(release
0.1.2). The release carries documentation-surface and publication changes only; no client API,
transport or credential behaviour changed. - Consume
@beyond10x/docs-systemat revision86cd6c6e(release0.7.0) in
website/package.jsonandwebsite/package-lock.json. The documentation bundle and Pages
delivery workflows keep their own catalog-owned pins and are unchanged.
The full cargo xtask gate is green against the updated Cargo.lock.
harness 0.12.0
Changed
- Honor named agents'
modelandeffortdeclarations on delegate requests, resolve model aliases
through the selected provider, and preserve parent settings, tool restrictions and shared budgets. - Update the embedded confinement boundary to Substrate
4d830f2f(package0.7.6, development
wire0.16.0), which leaves Git metadata untouched when Git sources are disabled, and the
outbound MCP client and testkits to3c68df04(0.1.1). - Move the real Agentplugins skill and agent compatibility suite to Atlas, removing the reverse consumer dependency from Harness tests and CI.
- Publish source through standalone bot tooling without an Atlas checkout or dependency-admission
requirement; retain Harness's own correctness checks and release requirements.
This source release was cut without running gates, tests or binary packaging, at the operator's
request. Existing historical test observations above are not new verification of this release.
Harness 0.11.1
Publishes the per-turn actor context and tool-inventory refresh seam, plus restart-safe durable approval checkpoints for hosted embedders. Resumption revalidates the current inventory and refuses revoked or structurally changed tools before any effect.
Harness 0.11.0
Added
- Outbound tools-only MCP support through the separately released
beyond10x/mcpfoundation, with stdio and Streamable HTTP transports, the shared registry, and owner-only OAuth storage. - Repeatable
--mcp-profilesupport forrun,chat,workflow run, andtools, plus explicit--mcp-registryoverrides and frozen reviewed tool snapshots. - MCP provenance in
started.mcp, with calls governed by the existing approvals, hooks, deadlines, result bounds, and failed-outcome semantics. - CLI contract
2026-09-02for the additive MCP option families.
Harness 0.10.1
Changed
- Read AEP planning skills and agents from the curated
beyond10x/agentpluginsrepository. - Run the real Agentplugins documents through an explicit scheduled upstream contract instead of silently skipping a missing checkout.
- Use the canonical
aepcommand throughout current Harness documentation, workflow guidance, and projected fixtures.
0.4.0
Added
-
A turn's
delegatecalls now run side by side (design 0002 § 2, milestone M4). A run that
asked for three sub-tasks in one turn paid three whole child runs of latency back to back,
because the loop resolved delegates strictly one at a time. Nothing about them required it: a
delegate starts from an empty conversation, so no child can read what another produced and there
is no ordering between them to preserve.Neighbouring
delegatecalls of one turn form a group, capped by the new
Delegation::max_parallel(--delegate-parallel <N>, default 4, minimum 1). Neighbouring rather
than gathered from the whole turn, exactly as a batch of pure tool calls is: a call between two
delegates is a barrier, because the second child may be there to look at what that call did.Each child gets its own model port and tool port, from two new defaulted trait methods —
ModelPort::forkandToolPort::fork, both answeringNone(cannot be run beside itself)
unless a port says otherwise.MessagesClientandResponsesClientfork by sharing: one
endpoint, one credential source, one connection pool, and — on the Responses wire — one request
counter, so two siblings cannot mint the samex-client-request-id.FlatandVerbsfork by
sharing the catalogue itself, so a fork publishes exactly what its parent publishes, entry for
entry. A fork that published one tool more would be a way to widen a run by delegating.Three things are not forked, because there is one of each by nature: the approver (one
person, asked one question at a time), the operator's hooks (how many copies of my guard are
running must not depend on how many sub-tasks a model asked for) and the event sink (the record
is one ordered stream). A child on a worker thread reaches all three by asking the run's own
thread, which sits answering for exactly as long as any child is running. Each proxy fails
closed: an approval nobody gave is a denial, and a hook that could not be consulted did not say
yes. A child that panics comes back as a failed tool result naming what happened, and its
siblings finish.This is an optimisation and never a difference in what a run can do. Where a port will not
fork, where--delegate-parallel 1is set, or where the run's remaining token budget will not
divide between the children, the same delegates run in order — the same children, the same
gate, the same results in the same order. Order is in fact the more accurate accounting: each
child is carved on what the one before it actually spent, where a group has to divide the
remainder up front. Tokens are divided because they add up; the wall clock is not, because
four children running at the same moment take one child's worth of it — the same figure a batch
of tool calls is handed.A reader of the record tells the two apart with no new event: two
DelegateStartedbefore either
DelegateFinished, and the children'sDelegatedevents interleaved, cannot happen in a run
that delegated in order.The
delegatetool's description now says several calls in one turn run at once — only on a
run that can actually do it, because a model told something false about what its next turn costs
is worse than one not told at all, and a model that is not told does not ask.Evidence is
provider_emulated: a newdelegate-pairscenario on both emulators, driven
through the shipped binary, whose record shows twodelegate-startedbefore either
delegate-finished— a bracketing a run that delegated in order cannot produce. Timing proves
nothing here; a fast serial run and a slow parallel one look alike. -
contracts/cli/b10x-harness/2026-08-30.1, cut for--delegate-parallel. Strictly additive:
every flag of2026-08-30keeps its spelling, itstakes_value, its default, its conflicts and
its requirements, and no subcommand changed. A consumer pinned to2026-08-30is correct against
this binary.2026-08-30is released and reachable onmain, so it was cut beside rather than
edited (AGENTS.mdinvariant 13), and a second cut on the same date takes the.1suffix. -
A tracked file carrying an absolute home directory now fails the gate.
scripts/check-no-home-paths.pyjudges the index, read withgit cat-file --batchover
git ls-files -s, because a commit records the index and not the working copy — content staged
with a leak and tidied afterwards would otherwise be committed by a green check; the worktree copy
is judged too, becausegit commit -astages it. Every file is searched as bytes, with a
second pass over the same bytes with NULs removed, so a path inside a committed.pycor UTF-16
text is visible: that.pycwas the one file of twenty the cross-repository audit found that no
text grep would have caught.A home directory needs no trailing separator —
HOME=/home/<name>publishes the account
exactly as a subpath does — and the account class admits non-ASCII, so a contributor named
mülleris protected like the author; a candidate is then trimmed to the name at its head, so an
elided path in a doc comment names nobody. One account,you, is a documentation placeholder in
every file type;userandusernameare not, because real machines have them. Two
planning-store paths are exempt with the reason in the script: the journal is append-only and
committed, and editing it would forge the record.--self-test(52 cases) is a gate step of its
own, because a check that passed everything would look exactly like a green one.
Changed
- A
delegatecall that names an agent this run does not have no longer emits a
DelegateStartedfor a child that never starts. The name was resolved after the event was
emitted, so the record carried a delegation that began and never finished — the one shape a
reader cannot interpret. Everything a child needs is now worked out before anything is emitted
and before any budget is carved, which is also what lets a group divide its remainder by the
number of children that will actually run. The refusal the model reads is unchanged; what moved
is that an unresolvable agent name is now reported instead of an exhausted budget when a call
would have failed both checks.
Fixed
-
A subscription token now reaches
claude-opus-5andclaude-sonnet-5on the Messages wire.
Both answered429 rate_limit_erroron every request, at any hour, against an account measured
at 8% of its five-hour window — and the refusal carried noanthropic-ratelimit-*headers at
all, so nothing downstream could tell it apart from an exhausted quota. The transport did what
it is supposed to do with aRateLimitedthat says it is retriable: four attempts, a back-off,
and a reported rate limit that was not one.The cause is a condition the documented API has no field for. Under a token obtained on a
person's behalf, this route serves a request only whensystemopens with a fixed block:"system": [ {"type": "text", "text": "You are Claude Code, Anthropic's official CLI for Claude."}, {"type": "text", "text": "<the run's own instruction>", "cache_control": {...}} ]This harness sent one block — its own instruction — which is one of the shapes that is refused.
Measured on 2026-08-30 againsthttps://api.anthropic.com/v1: the match is exact and positional.
Dropping the trailing full stop, adding a leading space, adding a trailing newline, or merging
the instruction into the same block each answer429; extra blocks after it are served.
claude-haiku-4-5-20251001is not gated at all, which is why the failure looked model-shaped and
not request-shaped. Theanthropic-betavalue makes no difference.harness_messages::SUBSCRIPTION_CLIENT_PREAMBLEholds the string, andrequest_bodynow takes
the credential presentation as an argument — on this route how the credential is presented
changes the body, so the projection has to be told. A key issued to a program sends exactly
what it sent before: one block, the instruction, breakpoint on it. The breakpoint stays on the
last block under both, so the cached constant head still covers the instruction rather than only
the preamble.Contract
contracts/provider-wires/anthropic-messages/2026-08-30.1cuts a version for it and
pins two request fixtures, one per presentation, both built by the one function in
crates/harness-messages/tests/contract.rs.2026-08-30stays as released.This is the harness naming itself as another vendor's client to that vendor. It is recorded
here rather than buried in a constant, and it is the operator's decision to send it, taken on
2026-08-30 against their own subscription credential. -
The CLI contract version in force,
2026-08-30.1, now says what actually moved, and a test
holds it to that.2026-08-30claimed "strictly additive" while measuring itself against
2026-08-29.1— two cuts back — and nine fields had moved against its real predecessor
2026-08-29.3:--modeland--base-urlstopped beingrequiredand--wirelost its
"openai-responses"default, onrun,chatandworkflow run. That directory is released and
immutable (AGENTS.mdinvariant 13), so the correction is carried in2026-08-30.1/README.md,
which a consumer of the current pin reads.2026-08-30was also dated the day after the commit
that cut it (719f6e3, 2026-08-29 23:08);2026-08-30.1was cut on 2026-08-30. No flag,
takes_valueor default moved in this change —ARGV_CONTRACT_VERSIONis unchanged and the
command line is untouched.the_version_in_force_names_every_field_that_moved_between_pinned_versionsdiffs every
consecutive pair of pinnedargv.jsonfiles and fails when a moved field is named by no README a
consumer of the version ...