Skip to content

Releases: oren198/Strata

v1.13.0

Choose a tag to compare

@oren198 oren198 released this 21 Sep 21:57
841d969

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 writeback warns 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

Choose a tag to compare

@oren198 oren198 released this 19 Sep 21:05
020fd46

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 own initialize handshake. 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, an accepted column, and accounted for (contributed + closed out).
  • Close-out without hooks (M3, M3b, M3c): ended_at on 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-strict to 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. mcp pinned >=1.28,<1.30 (#206).
  • Binding fix: a scope named via STRATA_AGENT_SCOPE with an empty skill now takes its default_skill. Before this, every multi-scope fleet refused to bind.
  • Quickstart (M6): one path for both harnesses; strata doctor checks that the strata on 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

Choose a tag to compare

@oren198 oren198 released this 19 Sep 13:35
1c4fdff

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

Choose a tag to compare

@oren198 oren198 released this 30 Aug 19:30

What's Changed

  • feat(mcp): soft-start, in-session binding with user consent, elicitation by @oren198 in #174

Full Changelog: v1.10.4...v1.10.5

Strata 1.10.4

Choose a tag to compare

@oren198 oren198 released this 28 Aug 21:21

Unregister fixes from live QA.

  • strata unregister --harness codex now removes the entire mcp_servers.strata subtree — 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 register refreshes everything — no unregister needed.

Strata 1.10.3

Choose a tag to compare

@oren198 oren198 released this 28 Aug 20:14

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]" (--yes for 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-running strata register refreshes 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.yaml edits 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 — with strata_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

Choose a tag to compare

@oren198 oren198 released this 26 Aug 21:00

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 init hint. (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

Choose a tag to compare

@oren198 oren198 released this 25 Aug 14:40

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 register wires every installed harness it finds (--harness narrows; unregister is symmetric), strata set-default-harness records what strata launch starts, 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 start exists only for the Console); pipx-first quickstarts; a key in .env (bare ANTHROPIC_API_KEY or STRATA_-prefixed) is honored by the judge and the preflight check; strata --version survives a deleted working directory.

Strata 1.10.0 — all-local robustness

Choose a tag to compare

@oren198 oren198 released this 24 Aug 19:33

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 harnessesstrata register wires every installed harness it detects (--harness narrows; unregister is symmetric), strata set-default-harness records what strata launch starts, 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

Choose a tag to compare

@oren198 oren198 released this 15 Aug 19:29
e4a1c94

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