Releases: oren198/Strata
Release list
v1.13.0
Strata 1.13.0. A scope can say what it is for, and the judge uses that. Relayed
material is judged by who stands behind it, not by where it came from. The
default judge is now one we have measured.
A scope can say what it is for (#210). A scope in fleet.yaml takes a
description, and the judge measures relevance against it; strata doctor
warns about a scope without one. Where a scope states no purpose but its
existing memory already says enough about what it is for, that memory is the
implied purpose. Where a scope states neither, nothing has changed — a purpose
is never inferred from a scope's name. This is the 1.12 limit we published
(#210) answered where a purpose exists: with one set, the office note that got
in during the launch rehearsal is declined 3 of 3, no note from an 11-item
class was admitted (against 10 of 11 with no purpose), and all 12 legitimate
operational notes were kept. Evidence:
docs/evidence/m1-scope-purpose-gate-2026-09-20.md.
Whose word it is (ADR 0016, #212). A person who tells an agent something is
a legitimate source of what they said, identified by name or by role. Asserting
another scope's position with nobody behind it is declined, and the reason names
the missing speaker rather than the topic or where the material came from.
Informant material is never a directive. Observing what another scope did is
first-hand; quoting what it believes is not. CONTEXT.md gains Ground and
Informant as defined terms.
The default judge is measured. qwen/qwen3-235b-a22b-2507 via OpenRouter
replaces the unmeasured claude-haiku-4-5 default. An Anthropic key is never
sent to the router: an install with an Anthropic key and no JUDGE_MODEL or
JUDGE_BASE_URL keeps Haiku on the Anthropic endpoint, including when that key
sits in JUDGE_API_KEY — which is what 1.12's strata register wrote.
strata doctor names the resolved judge and endpoint in every case.
A retirement states what changed (#209, advisory). The judge is asked for
the changed circumstance behind a retirement; it is recorded and shown in the
Console beside the retired directive. It is not enforced — see the limits.
Hygiene. Tests exercise their own tree, including child processes (#205).
The suite no longer depends on the machine's port 8000 (#208). The private MCP
seam is validated rather than assumed: if it disappears, the server warns and
runs without connect-time recording instead of failing to start (#206).
Upgrading from 1.12
Your judge does not change silently. With an Anthropic key set and no
JUDGE_MODEL or JUDGE_BASE_URL, Strata keeps claude-haiku-4-5 on
api.anthropic.com, and strata doctor says so. To move to the new default,
set three lines in your project .env:
JUDGE_API_KEY=<a key for your endpoint's provider>
JUDGE_MODEL=qwen/qwen3-235b-a22b-2507
JUDGE_BASE_URL=https://openrouter.ai/api
Evidence
The measurements are in this repo, not behind a private link.
-
docs/evidence/judge-baseline-2026-09-20.md— six judge models tried against
the same suites, three of which completed every one: junk admission, J1
accuracy, J4 attack success, error rate, re-asks, latency and cost, plus the
scope-purpose gate and the required-field check per model. Where a cell is
empty the table says why — one model produced no judgments at all, one
errored on most of the adversarial set, one ran partially.(Corrected 2026-09-22: this bullet first said "six judge models on the same
suites", which claims a result we do not have for three of the six. The table
itself was always explicit; the summary was not.) -
docs/evidence/m1-scope-purpose-gate-2026-09-20.md— the scope-purpose gate.
claude-haiku-4-5 is measured now too: it admits the least junk and stopped
every adversarial item in the set, and it over-declines 2 of 6 legitimate
operational notes once a scope states a purpose, at $0.2139 per 90-item demo
run against $0.0157. The table names what was measured, when, and on which
build; read it and pick.
Known limits
- #209 — the retirement's changed circumstance is advisory. Enforcing it
mechanically declined every genuine retirement, because no judge measured
fills a required tool field reliably. A bare removal request can still retire
a directive. - #210 — a scope with no stated purpose and little or no memory still
admits material unrelated to its work; filtering that relies on the agent. - #212 — a directive restricting a class of material does not reliably make
the judge decline by directive. The judge can be made to announce the check
and still answer it wrongly; the next attempt puts the checked directives in
the decision schema rather than in prose. #212 stays open. strata stats writebackwarns in its own output that if a server ran without
connect-time recording, the rate may read higher than it is.
Full suite on dev @ fc9a5aa (the merged commit, after the lint fix): 2035 passed, 4 skipped, 0 failed.
Before tagging
The default judge model id was checked against the live endpoint: qwen/qwen3-235b-a22b-2507 resolves on openrouter.ai/api and a one-token call succeeded. The wheel-smoke CI step makes no network call, so this check is done by hand before every tag.
Full Changelog: v1.12.0...v1.13.0
v1.12.0
Strata 1.12.0 is the Strata MVP. A Claude Code session and a Codex session bound to the same scope share judged memory.
What's in it
- Session identity + harness (M1): each MCP connection's session is recorded with its harness (
claude-code/codex), from the client's owninitializehandshake. Verified live on codex-cli 0.153.4 (two concurrent sessions, distinct ids). - Write-back rate as an engine metric (M2):
strata stats writeback [--since] [--json] [--export]. Sessions are recorded at connect, so silent sessions count. Per-harness and overall rows show the raw counts, anacceptedcolumn, andaccounted for(contributed + closed out). - Close-out without hooks (M3, M3b, M3c):
ended_aton disconnect with an idle window; rollover on a reused session id; a nudge from the first read that names both exits. Strict Stop hook on by default (--no-strictto opt out), blocking at most twice, never looping. Fixed: the Claude Code Stop hook runs under a surviving/bin/sh -c, so the hook now walks its ancestors to find its session.mcppinned>=1.28,<1.30(#206). - Binding fix: a scope named via
STRATA_AGENT_SCOPEwith an empty skill now takes itsdefault_skill. Before this, every multi-scope fleet refused to bind. - Quickstart (M6): one path for both harnesses;
strata doctorchecks that thestrataon PATH is the install that registered the hooks (#207); the first-run traps that leave a session memory-blind, in bold; "What the demo shows"; "Out of the MVP".
Evidence
strata-evals results/m4-cross-harness-2026-09-19.md: live cross-harness transfer PASSED both ways (judge qwen/qwen3-235b-a22b-2507 via OpenRouter). The operator rehearsal on 017a629 passed transfer both ways.
Known limits (stated in the README)
- The judge admitted 2 of 72 hard adversarial items in the demo eval (#209); a fix that regressed elsewhere was not merged.
- In the operator rehearsal the judge admitted an irrelevant office note from Codex as context; filtering that kind of junk relies on the agent today (#210).
- Nothing is claimed about the default Claude judge; it wasn't measured.
1.11.0 was never published to PyPI; 1.12.0 is the first PyPI release since 1.10.5 and includes 1.11.0.
The evidence file lives in the strata-evals repository, which is not public yet.
Release PR: #211
Full Changelog: v1.11.0...v1.12.0
v1.11.0
What's Changed
- ADR 0013: publication is the only sharing channel between scopes
- ADR 0014: reactive re-judgement when a scope's composed inputs change (
drain_scope; closes #186) - ADR 0015: inheritance by composition, not by copy (#189)
- Fixes: #197 (own-scope retraction notices the scope's own readers), #199 (context supersession removes the replaced claim), #200 (judge no longer declines an observation for lacking directive weight), #201 (one corrective judge re-ask on malformed output), #202 (perspective carries a condensation signal), #203 (MCP read shows the notices it drained)
- Release PR: #190
Full Changelog: v1.10.5...v1.11.0
v1.10.5
Strata 1.10.4
Unregister fixes from live QA.
strata unregister --harness codexnow removes the entiremcp_servers.stratasubtree — including approval-state subtables the Codex CLI adds on its own — so removal can never leave a config Codex refuses to load. Manually-created entries stay untouched.- Artifacts matching an older shipped version (a project registered under an earlier release) are recognized as Strata's own and removed cleanly, instead of being flagged "edited" with a failing exit code. Only content you actually changed is kept, with a warning.
- The release-discipline guard now also covers the Codex config blocks.
- Docs: after upgrading, plain
strata registerrefreshes everything — no unregister needed.
Strata 1.10.3
The first-run and live-fleet release, from three rounds of operator QA.
- Register asks the two questions that matter: a markerless directory gets "Register here anyway? [y/N]" (
--yesfor scripts), and an interactive register offers to store your judge key in.env(created owner-only, gitignore-verified). - Guidance reaches agents — and stays current: the seeded AGENTS.md and skills now tell agents memory access is only through the strata MCP tools (never
strata start), and re-runningstrata registerrefreshes its own unmodified artifacts when the shipped versions change; your edits are never touched. - The fleet is live: the Console and the MCP server pick up
fleet.yamledits without restart (invalid edits keep the last good fleet, with a visible warning), and a session can rebind to another scope — including one it just created — withstrata_bind. Session identity never changes; every contribution records the binding it was made under. - Startup now refuses a binding to an archived scope (previously accepted).
Judged-memory flows remain backend-free; the backend serves the Console only.
Strata 1.10.2
First-run experience release, shaped by two rounds of operator QA.
- Zero-friction fresh install: with the seeded single-scope fleet, a session binds automatically — no environment exports. Fleets with several scopes still require an explicit choice (the error lists them). The turn-end memory loop works on this zero-export path too: the Stop hook and the server now share a deterministic session identity.
- Provider-generic judge:
JUDGE_API_KEY,JUDGE_BASE_URL,JUDGE_MODEL— point the judge at any Messages-API-compatible endpoint; the old Anthropic variable names keep working. - Register: a fresh empty directory gets a
git inithint. (The interactive "Register here anyway? [y/N]" prompt announced earlier missed this build — it ships in 1.10.3.) - README rewritten for newcomers: what Strata is, five core concepts, install → register → work; links work from PyPI; harness-agnostic throughout.
Strata 1.10.1
Patch release. 1.10.0's notes promised the multi-harness journey, but a stacked-merge race kept it out of the wheel — this release actually delivers it, plus the first round of first-run QA fixes.
- Multi-harness parity (as announced in 1.10.0):
strata registerwires every installed harness it finds (--harnessnarrows;unregisteris symmetric),strata set-default-harnessrecords whatstrata launchstarts, Codex CLI registration with AGENTS.md seeding. - First-run fixes from operator QA: README links work from PyPI; the journey is stated plainly (install → register → bind → work — the engine is embedded, nothing needs to be running;
strata startexists only for the Console); pipx-first quickstarts; a key in.env(bareANTHROPIC_API_KEYorSTRATA_-prefixed) is honored by the judge and the preflight check;strata --versionsurvives a deleted working directory.
Strata 1.10.0 — all-local robustness
What's new
- Safe concurrent agents on one machine — cross-process per-scope locks (ADR 0012): several terminals, each bound to a different scope, can contribute at once with the summary always explainable by the record.
- The Console grows its proof surfaces — Turned down (judged declines with the judge's reasons), Freshness (per-scope staleness), Record (browsable trail with supersession chains), View as (exactly what any agent reads, token weight per layer), and one-click operator Replace/Retire behind a confirm dialog.
strata doctor— one command that checks every piece of project wiring (config, DB, fleet, MCP entry, Stop hook and skill drift, binding env) and says how to fix what's broken, without creating any files.- One journey across harnesses —
strata registerwires every installed harness it detects (--harnessnarrows;unregisteris symmetric),strata set-default-harnessrecords whatstrata launchstarts, and Codex CLI gets first-class registration (MCP verified; turn-end hook wired, pending live verification — see the README's Codex section). - PyPI page fixed — this README now renders as the project description.
Full details in the README and docs/.
v1.8.0
The judgment-economics release: the scope-manager now spends a fraction of the judge tokens per contribution, without giving up any of the record's guarantees. Implements ADR 0011 (D1–D4) in full, plus judge-prompt hardening and one behavioral corrective. ~28K → ~6.5K tokens per typical judgment in our measurements.
Judgment economics (ADR 0011)
D1 — Amendment ops. A judgment returns amendment operations against the summary instead of re-emitting it wholesale; existing directives are never re-sent through the judge. Summaries carry context digests only — directives move exclusively through lifecycle ops.
D2 — Mechanical recency window. The judge's view of recent record history is built mechanically from what the record stores: (contribution, state, judgment notes) triples, with only the newest window_verbatim_tail rows verbatim and older rows as digest lines. No LLM call to construct it.
D3 — Batch judgment. Contributions queued on the same scope coalesce into one judge call with per-contribution verdicts. Each verdict lands as its own judgment row against its own contribution id; a failed call fails each member individually; the whole batch produces exactly one summary write. A batch of one takes the single-judgment path verbatim. Cap via STRATA_JUDGMENT_BATCH_CAP (default 5; 1 disables coalescing).
D4 — Mechanical refresh splice. On refresh, a parent's directives are incorporated into the child summary mechanically — byte-exact, ids and provenance preserved — before the judge is asked to reconcile only the context digest. A fresh child inherits its parent's directives on first launch with no LLM involved.
Judge behavior
Unattributed-echo corrective. When an accept's reasoning cites a rendered operator directive but the text sent to the summary doesn't carry "per operator directive ", the scope-manager makes exactly one best-effort corrective re-ask (same one-retry discipline as the overflow re-ask; a retry can never flip a verdict). Live effect: operator-echo attribution 0.4444 → 0.9556 (n=45). Single-judgment path only; the batch path is byte-identical in behavior.
Prompt hardening against four leak classes surfaced by adversarial evaluation, including forbidding repointing an unresolvable supersedes.
Fixes
Per-trigger publication withdrawal (#137): a judged withdrawal now removes exactly the publication items its trigger names.
Configuration
New: STRATA_RECENCY_WINDOW_SIZE (default 20) — how many of the newest contributions the D2 recency window spans.
New: STRATA_JUDGMENT_BATCH_CAP (default 5) — see D3 above.
The defaults reproduce prior behavior; no breaking API changes, no migration required.
Full live evaluation evidence for this release head is linked from #140 — every governed threshold passes (j1 0.8852, j2 0/191, j3 0.9583, j4 attack success 0/380, o1 0.9833, o3 0.9556, p1 1.0, p3 1.0, p4 0.925).
What's Changed
- Judgment economics (ADR 0011 D1–D4), judge prompt hardening, and the unattributed-echo corrective by @oren198 in #140
- chore(release): bump version to 1.8.0 by @oren198 in #142
- Release 1.8.0: version bump by @oren198 in #141
Full Changelog: v1.7.0...v1.8.0