Server release cut at 53290e22. Deploy is continuous off master, so this tag is a citation anchor and rollback target, not the delivery gate — everything here has been running.
148 merged changes since v2.20.0: 33 added, 9 changed, 48 fixed, 1 removed, 28 documentation. Full detail in docs/CHANGELOG.md.
What this release is about
This is the release where the outside of the system became specified.
A public interface contract. docs/interface-contract.v1.json and src/interface_contract.py publish a versioned, transport-neutral tool contract — schema unitares.interface-contract.v1, version 1.1.0 — spanning MCP streamable HTTP, REST /v1/tools, and stdio, with workflow aliases advertised consistently and a surface_sha256 over the canonical surface so a peer can detect drift without diffing.
A federation handshake. list_tools(lite=true) carries a federation block a peer can negotiate against without prior knowledge: where to find the contract, the MCP range actually supported (>=1.26.0,<3.0.0, majors 1 and 2 both tested, newest-in-range CI blocking), and the unitares.lifecycle-envelope.v1 success/failure envelope with the four lifecycle capabilities a Resident must implement — start_session, sync_state, check_working_state, record_result. Paired with the separate cirwel/unitares-resident repo, cross-pinned to contract commit d044d627.
Identity-bound coordination. The Elixir lease plane is packaged into the Tier-1 Docker Compose stack, and make coordination-demo proves acquire → held-by-other refusal → atomic handoff → status → release → bounded cleanup end to end. Lease mutations bind to a caller's governance identity through a short-lived Ed25519 lat.v1 attestation bound to deployment audience, holder UUID, method, path and exact request-body hash, with each (issuer, jti) consumed once in Postgres before mutation.
Answers before diagnostics. Check-in responses lead with an action-first envelope — normalized action, one-line reason, risk score, verdict confidence, evidence basis — with legacy ODE-derived coherence separated into an explicit non-behavioral block.
consult lands as the canonical advisory model-inference facade, with explicit purpose / effort / privacy / degradation contracts and REST parity. request_review remains the distinct governed peer-review verb.
Identity honesty. A fresh mint that misses the resident roster now says so in the response — status, on_roster, granted_tags vs required_tags, and a remedy — instead of silently minting an ephemeral identity that reports success and is archived later. Relatedly, is_agent_protected no longer grants archival immunity by label.
Where federation actually stands
The primitives are real and running. The multi-principal deployment is not, and this release does not claim it.
- Single trusted issuer. Lease attestation v1 accepts one issuer. Multi-issuer federation stays deferred until leases persist
(issuer, subject)principals. - Resolution attestations are symmetric. They are HMAC-keyed on each agent's
api_key, so a third party able to verify a signature could also forge one. A resolution record is therefore not independently verifiable today by an operator who does not already trust its issuer. This is a stated seam, not an oversight. - The federated EISV exchange is a pilot. Ed25519-signed and k-anonymity-enforced, but outputs stay
PILOT_AGGREGATE_ONLYwithdecision_authority: NONE, collection is disabled, and it enrolls no cohort and authorizes no paired score/outcome access. - Non-self-clearing — a paused agent cannot clear its own session over a standing reviewer objection — is named as a federation seam in the threat model.
Compatibility
mcp1.29.0 → 2.1.1 (major). Unhandled tool/resource/prompt exceptions now log server-side and reach the client only as a generic message unless raised throughToolError/ResourceError. The 1.x/2.x compatibility accessor covers theinputSchema→input_schemarename;mcp-newestis a blocking lane, so the newest in-range resolution can no longer silently become the tested configuration.- Production interpreter is Python 3.14.
constraints.txtcarries aproduction-python:marker and CI holds four surfaces to it (Dockerfile base,scripts/opsLaunchAgent templates, the test matrix). Minor-series compatibility is the contract; patch-level parity is not claimed. src/research_registry.pyremoved, with its MCP handler and schema, the three/v1/research/*routes, the dashboard tab, tests and ops doc. Its one distinguishing feature graded any non-empty free-textsourceas "anchored". Callers of/v1/research/*must drop them.- Label-based archival immunity is gone. Protection derives only from server-granted
pioneer/persistent/pinnedtags, which an identity cannot self-assign.
Migrations
None required. No schema migration gates this release.
Evidence
Release Seamsgreen at the tagged commit: changelog coverage 148/148 cited over a--first-parentdenominator (2 release-chore excluded, 10 declaredno-user-effect), every tracked release series level with its tag.- Skills bundle re-cut and reachable:
unitares-governance-pluginv0.4.17 mirrorsskills/byte-for-byte with a regeneratedSKILLS_MANIFEST.sha256. Docker Quickstartpassed ona5546835, the newest container-input commit in the range; the two laterconstraints.txtcommits (#2058, #2060) are comment-only, no pin moved.- Suite runs on both 3.12 and 3.14 across eight database-backed shards; the Elixir
wave3a_handlerssuite (83 tests) gained the CI coverage it had lacked since #1887.
Known limits
constraints.txtis a container build input (Dockerfile:33) but is not in theDocker Quickstartpath filter. It did not matter here because both in-range edits were comments, but a real pin change would slip that gate.seamsis still not a required status check in branch protection; it is a gate by convention.
Rollback
ghcr.io/cirwel/unitares:v2.20.0, or git checkout v2.20.0. Nothing in this release writes irreversible state.