Releases: OktoLabsAI/marginalia-dist
Release list
v0.2.0 — reliability prerelease
Marginalia v0.2.0, reliability prerelease.
Builds on the v0.1.0 agent-facing MCP surface. No MCP tool or parameter changes.
Providers
marginalia provider login chatgpt: interactive device-code login into Marginalia's own credential directory. Refuses~/.codexand~/.pi/agent(symlinks too), a non-TTY session, and an existing credential unless--forceis given.marginalia provider status chatgpt [--json]: read-only report of plan, account, subscription and token expiry; exits 1 when the credential is unusable.- Transient provider errors are now retried in
asksynthesis and in every ingest judge and curator step (curator, relation curator, merge judge, predicate resolution, type adjudication, correction judge, predicate-propose sweep judge). Two attempts, retryable errors only,Retry-Aftercapped at 60 s, each retry recorded. A single 503 used to turn an answer into empty text or silently degrade the step. The reconcile cluster judge stays single-shot on purpose.
Vaults that stopped accepting writes
- A case-variant re-mention of an existing entity no longer wedges the vault. The sealed-plan applier compared raw titles while the node id folds case, so one capitalisation variant made every later
rememberfail. - Committing a parked manual-review item no longer wedges when another document already committed the same node. A vault the old code wedged heals by re-running the same review resolution.
- Every
rememberwrite failure is logged on both MCP and REST: graph-write failures at ERROR with cause, caller mistakes at WARNING. REST previously logged nothing. Response codes unchanged.
Other
- Neo4j backend:
DriverErroris translated toGraphBackendErrorat every driver entry point (reads, writes, wipe,Neo4jStaging). - The bundled web UI was rebuilt to match its source.
- Private network addresses removed from published docs, including the README that ships as the wheel's long description.
- LoCoMo harness (source repo only):
--enable-chatgpt,--ingest-concurrencyfor parallel conversation ingest, andingest_units_failedin summaries, reports, compare and the ledger.
Verification, stated plainly
Source GitHub Actions did not run on the source commit. All four workflows were triggered and every job failed without starting: "The job was not started because recent account payments have failed or your spending limit needs to be increased." The gates were reproduced locally on that exact commit instead:
- tests:
uv lock --check, actionlint, ruff clean; canonical CI pytest selection 1 failed / 4440 passed / 65 skipped / 37 deselected / 1 xfailed (the failure is the known issue below); npm ci, audit (0 vulnerabilities), typecheck and build clean; no frontend_dist drift; docs build leaves the tree clean. - acceptance: every scenario PASS on grafx (54 skipped by design on that backend).
- eval floor: gold 32/32, distractors 20/20, provenance gate pass, recall_floor selftest PASS, regressions [].
- neo4j backend gate against a live neo4j:5-community: contract tests 9 passed / 0 skipped, CI pytest step 1 failed (same known issue) / 1394 passed, scenario 84 PASS with 25 assertions.
- Against this exact wheel: dependency contract 17 passed, install footprint 1 passed, live
[serve]start from an isolated HOME with zero vaults answering/health,/versionand the SPA, JSON-LD export through[jsonld], every extra in its own clean Python 3.12 env, both CLIs, retired constructors failing closed.
Not performed for this release:
- The Windows managed-credentials (DPAPI) gate needs a Windows runner and did not run.
- The interactive Windows PowerShell 5.1 lifecycle rehearsal was not performed. No published version has passed it.
Known issue, pre-existing, not fixed here: tests/store/contract/test_snapshot_concurrency.py::TestLadybugSnapshotPinnedDumpVsSwap::test_dump_never_mixes_pre_and_post_swap_rows fails under load. It is a race between the Ladybug staging commit's two renames and LadybugStore.snapshot() opening graph.lbug read-only. A deterministic probe reproduces it identically on v0.1.0. Waived for this prerelease.
Source: 314e3af15a901c71c0bcb7af75a63f081298859f
SHA-256: 59adee4483d8f85525e30a5e6271e6328238ac275d4b3fe05e29325d2ed29520
v0.1.0 — agent-facing MCP surface
Marginalia v0.1.0 — agent-facing MCP surface.
First release with a real public tool surface: five MCP tools and seventeen ask parameters, up from four tools and three.
Vault selection
- New
list_vaultstool — names only, no filesystem paths and no path-derived ids. - Optional per-call
vault=<name>onask,exploreandremember. Registry names only; a path-shaped value is refused. The connection's?vault=keeps precedence, and a discarded override is reported asvault_override_ignored. askandexplorenow report which vault served the response.
Retrieval control
askexposes the retrieval policy the web UI already had:enable_subgraph,source_block_policy,seed_k,max_degree_per_seed,neighbour_budget_tokens,source_block_budget_tokens,coverage_threshold,min_claim_confidence,max_nodes,max_relationships,max_claims,relationship_types, plusinclude_sources.enable_subgraphis opt-in and its default is unchanged: a grounded eval measured block-dump answers at 0.792 against the subgraph path at 0.6.exploregainsrelationship_types,min_claim_confidence,max_degree_per_seed, emitsblock_idon claims and relationships, and returns its ownretrievalblock.include_sourcesreturnsblock_id, byte range,content_hashand a vault-relative path.
A degraded answer no longer looks like a good one
synthesis_statusis always present:ok|empty|truncated|abnormal_stop|provider_error. An emptytextwithprovider_errormeans the model was unreachable — not that the graph lacks the answer.finish_reasonandnative_finish_reasonare surfaced; anything other thanstopis treated as suspect.- Reasoning that the provider inlines into the answer is now stripped even when the opening tag never arrives.
- Assembled context marks each excerpt with its path, byte range and file size, so the model can say the excerpts do not cover a period instead of inferring a value.
Hardening
- No filesystem path reaches a client-facing error: a vault-name length cap enforced before any filesystem access, one sanitiser for
OSErrorat the resolution and lease seams, ELOOP handled through theRuntimeErrorpathlib raises for it, and no resolved-path echo on the absolute-path branch. - The MCP handshake reports Marginalia's version instead of the framework's.
- A
401now distinguishes a missing header, an empty credential, an unsupported scheme and an invalid token. Theunauthorizederror code is unchanged.
Compatibility
Additive. New tool, new optional parameters that default to inheriting existing behaviour, new response fields. The only behaviour change is the 401 detail text; anything matching on the unauthorized error code is unaffected.
Verification, stated plainly
Passed, reproduced locally: 4052 tests passed / 94 skipped / 1 xfailed, ruff clean, uv lock --check clean, docs gate 47 passed. Against this exact wheel: dependency contract 17 passed, install footprint 1 passed.
Not performed for this release:
- GitHub Actions did not run on the source commit — the source organisation's Actions are billing-blocked. Every source gate above was reproduced locally instead.
- The Neo4j backend gate runs only in source CI, so it did not run. The Neo4j surface is unverified for this release.
- The interactive Windows PowerShell 5.1 lifecycle rehearsal was not performed.
Known, pre-existing, not fixed here: declining the installer's first-run vault prompt aborts the install and rolls it back. Pass --no-onboard to skip the prompt.
Source: 8e0e9ae2c51e6c452705548dcba5af8fd77d909c
SHA-256: 185d787947d524f6fd7a88d120c6bbbff1d36d55348eb18d11bdf2c65bce8591
v0.0.50
Prerelease: Linux Docker+tmux rehearsal pending; Windows lifecycle rehearsal deferred.
Wheel marginalia-0.0.50-py3-none-any.whl
SHA-256 cc524877686ad0227d6cd208c487f027acf1f1e25772c98afe00b96bbdf3ea1e
Source 5264b971dc3e97390a25cff06b8ff0d1dcfeb04d
Marginalia 0.0.49 (prerelease)
Public distribution for source tag v0.0.49
(85f2b28bd1c23c1cdc5fdf6389d7ba96862bda6b).
Changes since 0.0.48
-
The onboarding base URL is now canonicalized in one resolver, regardless of the form typed.
Discovery used to probe{base}/models(treating user input as the server root) while completions
POSTed{base}/chat/completions(treating input as already versioned), so a server root like
http://host:portpassed discovery but 404'd on the completion step, while a/v1-form base
failed discovery on servers that only serve/v1(oMLX). Every input form (root,root/,/v1,
/v1/, subpath variants) now derives the identical pair — discovery at{root}/v1/models,
completions at{root}/v1— and the base persisted tomarginalia.yamlis always the canonical
{root}/v1, so the saved config never depends on which form was entered. A query string on the
base (Azure-style?api-version=) is preserved on every derived URL; non-OpenAI-contract drivers
(Anthropic, Gemini, Azure, Ollama, …) are untouched. -
Onboarding runs a real completion before it saves anything. After discovery lists models, a
minimal completion runs through the exact canonical endpoint every real ask/ingest call uses. On
failure the run aborts with the exact attempted URL and nothing is saved — no LLM config block, no
env secret — instead of persisting a base the runtime could not actually use. -
A non-interactive run without
--modelnever silently defaults to the first discovered model.
On a multi-model servermodels[0]can be a non-chat model; the run now lists what it found and
demands an explicit--model(a preset's own declared default is still honored when it is among
the discovered models).Migration consequence. Existing vaults keep their pinned config; for OpenAI-compatible drivers
the storedapi_baseis now canonicalized to the runtime's own shape, so a previously saved
root-form base now resolves to the same/v1endpoint a fresh install would get — previously
broken root-form configs start working, and correctly saved/v1configs are unchanged.
Verification
GitHub Actions is unavailable for the private source repository (billing not enabled), so the
marginalia CI jobs did not run for this release. Every required gate was verified locally against
the exact release inputs:
model-free-tests / tests-> green on release-candidate commit2649f2a: 3,762 passed, per that
commit's recorded verification.eval-gate / floor-> run locally exactly as the workflow invokes it, against source SHA
85f2b28bd1c23c1cdc5fdf6389d7ba96862bda6b(manifest.code.git_rev/dirty: falseconfirm it).
Provenance gate: 32/32 gold targets, 20/20 distractors resolved, pass. Recall-floor selftest:
pass. Recall-floor gate against the committed baseline: hard-recall@10 0.4688 (15/32),
extraction-completeness 0.5625 (18/32), MRR@10 0.4348, precision@10 0.2 —regressions: [].release-artifact-gate / wheel-> clean wheel build from the exact tagged SHA; wheel
metadata/UI inspection passed; dependency-contract (17/17) and footprint (1/1) against this exact
wheel; base install plus every advertised runtime extra (embeddings, ladybug, jsonld, mcp, serve,
litellm, bedrock, sentence-transformers) resolved and smoke-tested in its own clean Python 3.12
environment.release-artifact-gate / windows-managed-credentials-> could not be reproduced. This job
proves a DPAPI CurrentUser credential round-trip; DPAPI is Windows-only and this release was
validated from macOS. Not covered by any local substitute in this release.- Public
marginalia-distdistribution-gate-> runs on push of the dist bake commit (pending on
publication). - Linux Docker+tmux public raw-URL rehearsal for
0.0.49(including the new verify-before-save
onboarding) -> runs after publication against the exact dist-main commit; will be recorded in the
dated section of themarginalia-distREADME with retained transcripts under
evidence/v0.0.49/in that repository.
This is a prerelease: no published Marginalia version, including 0.0.45 through 0.0.48, has yet
passed a real interactive Windows PowerShell 5.1 release-lifecycle rehearsal.
Artifact
- Wheel:
marginalia-0.0.49-py3-none-any.whl - SHA-256:
8274abea746e9ec6d1b8450e5d416ea626ec8e325effbe1f240929ad9ec9d4c3 - Built from the clean tagged SHA above; dependency-contract (17/17) and footprint (1/1) re-run
against this exact file and passed.
Marginalia 0.0.48 (prerelease)
Public distribution for source tag v0.0.48
(1242306425e4245bd4292ad24d6280e310ef8d26).
Changes since 0.0.47
-
The stale default LLM model is removed — the model default is now empty and discovery-first.
The hardcodedQwen3.6-35B-A3B-oQ4-fp16-mtpdefault (which assumed a local Qwen server
that most machines do not run) is gone. The config defaults (config/_vault.py), the
marginalia onboardlegacy-local preset, the web UI (rebuiltfrontend_dist), and
GET /api/v1/config/defaultsnow all ship an empty model default, so a fresh install
discovers what is actually reachable instead of assuming one. The model-free acceptance
scenarios 83/84/98 now pinllm.enabled=false, keeping them deterministic.Migration consequence. Fresh installs get discovery-first model behavior. Existing
vaults keep their pinned config: a model already recorded in a vault's config is untouched
by this change, so there is no behavior change for any configured vault. -
The public installer now offers a conditional first-run onboarding on greenfield installs.
On a fresh interactive terminal with no existing vault or config (greenfield + TTY), the
installer asks once, after installing the tool and before starting the app:Y(or Enter)
runs the terminalmarginalia onboardflow (you name your own vault in-flow; the installer
never creates one),nor EOF keeps the application-first path. The prompt is skipped
silently for piped/CI installs (no TTY),MARGINALIA_NO_OPEN=1,MARGINALIA_VAULT
preseeding, the new--no-onboardflag, and every reinstall or upgrade — it only appears
while the Marginalia home is greenfield, so upgrades never prompt. Six docker-tmux harness
scenarios cover the matrix; 18/18 pty checks pass.
Verification
GitHub Actions is unavailable for the private source repository (billing not enabled), so the
marginalia CI jobs did not run for this release. Every required gate was verified against the
exact release candidate:
model-free-tests / tests-> green on release-candidate commite5b2316: 3,751 passed.model-free-tests / acceptance-> green one5b2316: 33/33, including the Neo4j scenario.docs-gate / gate-> green one5b2316: 47 generated pages, no unstaged drift.ruff check+uv lock --check-> clean one5b2316and on the bump commit.eval-gate / floor->judge.py floor,recall_floor.py selftestandgateagainst the
committed frozensynthetic-civault, andjudge.py manifest— run locally exactly as the
workflow invokes them, against source SHA1242306425e4245bd4292ad24d6280e310ef8d26
(manifest.code.git_rev/dirty: falseconfirm it). Provenance gate: 32/32 gold targets,
20/20 distractors resolved, pass. Recall-floor selftest: pass (byte-stable,
regression-sensitive). Recall-floor gate against the baseline: hard-recall@10 0.4688 (15/32),
extraction-completeness 0.5625 (18/32), MRR@10 0.4348, precision@10 0.2 —regressions: []
against the committed baseline. This frozen fixture is opened read-only and not re-ingested.release-artifact-gate / wheel-> clean wheel build from the exact tagged SHA; wheel
metadata/UI inspection passed; dependency-contract (17/17) and footprint (1/1) against this
exact wheel; base install plus every advertised runtime extra (embeddings, ladybug, jsonld,
mcp, serve, litellm, bedrock, sentence-transformers) resolved and smoke-tested in its own
clean Python 3.12 environment.release-artifact-gate / neo4j-backend-gate-> green one5b2316(acceptance scenario 84
against a disposableneo4j:5-communitycontainer).release-artifact-gate / windows-managed-credentials-> could not be reproduced. This
job proves a DPAPI CurrentUser credential round-trip; DPAPI is Windows-only and this release
candidate was validated from macOS. Not covered by any local substitute in this release.- Public
marginalia-distdistribution-gate-> runs on push of the dist bake commit
(pending on publication). - Linux Docker+tmux public raw-URL rehearsal for
0.0.48-> green on 2026-09-13
against the exact dist-main commit6de65ad19df4dfd4d3d813e707010f6f6b3c5d84(the
pushed tip ofmain): the exact-commitrelease-lifecyclerun (thirteen
RELEASE_LIFECYCLE_*_OKmarkers plus the finalDOCKER_TMUX_RELEASE_LIFECYCLE_OK,
each exactly once, tmux pane status 0) and the new one-shot greenfield first-run
prompt run (prompt ->Y->marginalia onboard-> user-named vault, provider
skipped -> daemon up with UI:7777+ MCP:8201at version0.0.48-> clean
stop). Recorded in the datedv0.0.48 Linux release rehearsal (exact driver commit)
section of themarginalia-distREADME, with the retained transcripts under
evidence/v0.0.48/in that repository.
This is a prerelease: no published Marginalia version has yet passed a real interactive Windows
PowerShell 5.1 release-lifecycle rehearsal.
Artifact
- Wheel:
marginalia-0.0.48-py3-none-any.whl - SHA-256:
884a6721590583eda836dcb127b0e0bb729557db461b27100a3a8e6c99808b24 - Built from the clean tagged SHA above; dependency-contract (17/17) and footprint (1/1)
re-run against this exact file and passed.
v0.0.47
Public distribution for source tag v0.0.47
(ec523eced42e6616de825ee5d8df9e6c61dfaf0c).
Changes since 0.0.46
-
Default ingest chunk size halved: 12,000 bytes to 6,000 bytes.
ingest.chunk_size_bytes(IngestConfigand the ingest parser's
DEFAULT_CHUNK_SIZE_BYTES) now defaults to 6,000 instead of 12,000. This is
evidence-based: three repeats per configuration, manually adjudicated
against a 103-fact anchored corpus, measured mean fact-recall 0.4045
(sd 0.0148) at 6000/0 versus 0.2362 (sd 0.0056) at 12000/0 — a 0.1683 gap,
11 to 30 times either configuration's own standard deviation, with no
overlap across any of the six runs.Migration consequence. Vault config resolves
ingest.chunk_size_bytes
fresh from this default on every load — nothing is frozen into a vault's
marginalia.yamlat creation time. So any vault that has never explicitly
pinnedingest.chunk_size_byteswill, on the nextadd/edit/folder-watch
touch of an already-ingested document, find its stored Blocks' chunking
facet (12000) no longer matches the live config (6000). That orphans the
existing Blocks for that document, and the whole document is re-chunked
and re-extracted from scratch on that touch — not just the changed hunk.
Existing stored Blocks and their byte anchors are untouched until then;
this is not a retroactive rewrite, andkg rebuildalways uses the live
config regardless of what any vault has pinned.To keep the previous chunking behavior, pin the old value explicitly
before your next touch of an ingested document:curl -X PATCH http://127.0.0.1:<port>/api/v1/config \ -H 'content-type: application/json' \ -d '{"ingest": {"chunk_size_bytes": 12000}}'
or write it directly into the vault's
marginalia.yaml:ingest: chunk_size_bytes: 12000
Verification
GitHub Actions is unavailable for this org (billing not enabled). CI did not
run for this release. Every required CI gate was instead reproduced locally
against the exact release candidate:
docs-gate / gate->uv run python docs/build_knowledge_base.py, staged
with no unstaged drift.eval-gate / floor->tests/golden/bin/judge.py floor,
tests/golden/bin/recall_floor.py selftestandgateagainst the
committed frozensynthetic-civault,tests/golden/bin/judge.py manifest
— run locally exactly as the workflow invokes them, against source SHA
ec523eced42e6616de825ee5d8df9e6c61dfaf0c(manifest.code.git_rev/
dirty: falseconfirm it). Provenance gate: 32/32 gold targets, 20/20
distractors resolved, pass. Recall-floor selftest: pass (byte-stable,
regression-sensitive). Recall-floor gate against the baseline: hard-recall@10
0.4688 (15/32), extraction-completeness 0.5625 (18/32), MRR@10 0.4348,
precision@10 0.2 —regressions: []against the committed baseline. This
frozen fixture is opened read-only and not re-ingested, so it is
unaffected by this release's chunk-size default change.model-free-tests / tests->uv run --extra ladybug --extra litellm python -m pytest -m 'not slow and not realmodel and not perf and not footprint and not acceptance_private_corpus and not acceptance_judge' -q.model-free-tests / acceptance->./bin/acceptance.sh, unfiltered.release-artifact-gate / wheel-> clean wheel build, dependency-contract
and footprint tests, base install plus every advertised runtime extra
resolved and smoke-tested in its own clean Python 3.12 environment.release-artifact-gate / neo4j-backend-gate-> a disposable
neo4j:5-communitycontainer plus the[neo4j]-extra contract suite and
acceptance scenario 84, run against it locally.release-artifact-gate / windows-managed-credentials-> could not be
reproduced. This job proves a DPAPI CurrentUser credential round-trip;
DPAPI is Windows-only and this release candidate was validated from
macOS/Linux. Not covered by any local substitute in this release.
This is a prerelease: no published Marginalia version has yet passed a real
interactive Windows PowerShell 5.1 release-lifecycle rehearsal.
Artifact
- Wheel:
marginalia-0.0.47-py3-none-any.whl - SHA-256:
b9c62fb2e8690c3f62b0ad26b3bf84535fd245e8dc2c2a2171bb7ef2b2dd8d14 - Built from the clean tagged SHA above (not the Phase 2 validation build); dependency-contract
(17/17) and footprint (1/1) tests re-run against this exact file and passed.
🤖 Generated with Claude Code
v0.0.46
Public distribution for source tag v0.0.46
(f4e3ce4e337374257e1a007ece2ab25524633aa2).
Changes since 0.0.45
- Backend selection parity for REST and MCP vault creation. REST's
api_vault_createand the MCPinit_vaulttool now default new vaults
to the same backend as the CLI (Okto Grafx, D-94), and reject a
non-loopbackstorage_uriunlessallow_remote_dbis set, mirroring
the CLI's--allow-remote-dbconsent gate. - Graph backend visibility. Each vault's backend now shows up in
marginalia status,marginalia vault list,GET /api/v1/vaults,
GET /api/v1/status, and the web UI's vault manager. - Onboarding backend prompt. Interactive
marginalia onboardnow
asks which graph backend to use (Grafx, Ladybug, or Neo4j) when
--backendwasn't passed explicitly; non-interactive onboarding is
unchanged. - Grafx/Neo4j reembed fix.
kg reembedno longer raises
EmbeddingDimMismatchon its own live-graph read-back when a vault's
embedder dimension changes.
Artifact
- Wheel:
marginalia-0.0.46-py3-none-any.whl - SHA-256:
b5c3a825f7b734db62b2774c8a8cfb1b79ebfa23b8580d05619ae0b23dc5ab81
This is a prerelease: no published Marginalia version has yet passed a
real interactive Windows PowerShell 5.1 release-lifecycle rehearsal.
🤖 Generated with Claude Code
v0.0.45
Pluggable graph backends (ADR 0041): the storage-and-retrieval seam is now a
GraphStore/IndexStore connector pair with three gating backends.
- Okto Grafx is now the default backend, installed out of the box. A
post-M6 owner decision (D-94) promoted it from the earlier experimental,
--accept-experimental-gated path to Marginalia's non-experimental
default graph backend; no opt-in flag is required. - Ladybug remains fully supported and selectable (
--backend ladybug). - Neo4j remains selectable as a server-backed connector (
--backend neo4j,
[neo4j]extra). - LoCoMo quality parity holds across all three backends within judge noise
(ADR 0041, M6 Parity).
Wheel: marginalia-0.0.45-py3-none-any.whl
SHA-256: 8a10b4d65d04e70a4612aba6788547c2a51bd31f3e9de446494d271b5cb7aaa9
This release stays a prerelease. No published Marginalia version has ever
passed a real interactive Windows PowerShell 5.1 release lifecycle, and
0.0.45 inherits that gap unchanged; the Linux Docker+tmux rehearsal has not
yet been run against this exact bake either.
🤖 Generated with Claude Code
v0.0.44
Marginalia 0.0.44 (prerelease).
Source tag v0.0.44 = 07c2fd1e76a3ed562bbad46cb23028c27bc34295 (private OktoLabsAI/marginalia).
Wheel SHA-256: fbab50524b107436c19b0f790d10358789eae45222d0bf3ebe4ba5b79af8fed1 (1,022,801 bytes, 157 members).
Contents: ADR 0039 ingest correctness (integrity fence, generation sidecar, lease-guarded heal), ADR 0040 semantic graph quality, the effective-LLM-concurrency capacity owner, the three-tier laptop quality gate, judge rubric v2, and the reinstated search_claims answer partition.
This stays a prerelease. No published Marginalia version has ever passed a real interactive Windows PowerShell 5.1 release lifecycle; 0.0.44 inherits that gap unchanged. Promotion waits on that evidence.
Marginalia v0.0.43
Stable Marginalia 0.0.43 release.\n\nSource: e15d65a7c3baf018ade42910e64947dad882e9d5\nWheel SHA-256: 2ca924eadbad3819a32679fb4f2076e251f12921080c7510d281147ffad1ee44\n\nIncludes app-first browser launch, application-scoped multi-vault management and deletion, keyless private-LAN model configuration, clean-wheel dependency closure, and slower-host startup readiness.