Skip to main content

Mareforma

Where AI discovery becomes science
trust earned, not declared · uses real data · effectively independent · publicly verifiable · local-first

Quickstart  ·  Docs  ·  Examples

PyPI Python Tests License: MIT


Mareforma is a local-first library where AI scientists record their findings as claims. Each claim cites the claims it builds on and can contradict others, forming a knowledge graph. Trust is read from that graph, not from the agents' self-reported confidence.

The silent failure it catches

The most dangerous result an AI scientist returns is the one that looks right but never touched the data. A step fails quietly, the model fills the gap from memory, and the answer reads like a real one.

Catch one yourself. You need uv, a local model, and a minute. Nothing to install: uvx fetches mareforma, runs it, and throws it away.

# a small model (0.5 GB), runs locally
ollama pull qwen3:0.6b

# the note the pipeline is supposed to read
mkdir -p notes && cat > notes/cell_counts.md <<'EOF'
# Note: cellular composition of the human brain

Isotropic fractionator counts (Azevedo et al., J Comp Neurol, 2009;
Herculano-Houzel, Front Hum Neurosci, 2009) put the adult human brain at
about 86 billion neurons, revising the long-cited "100 billion" figure.
The cerebral cortex holds about 16 billion of those neurons; the cerebellum
holds about 69 billion, despite its far smaller mass.
EOF

# a short RAG pipeline: read the notes, ask the model, print the answer
cat > ask.py <<'EOF'
import glob
import httpx

docs = [open(p).read() for p in sorted(glob.glob("notes/*.md"))]
context = "\n\n".join(docs)
question = "How many neurons are in the human brain?"

reply = httpx.post(
    "http://localhost:11434/api/chat",
    json={
        "model": "qwen3:0.6b",
        "messages": [{"role": "user", "content":
            f"Answer the question using the notes below, and cite them.\n\n"
            f"NOTES:\n{context}\n\nQUESTION: {question}"}],
        "stream": False, "think": False,
    },
    timeout=120,
).json()
print("FINDING:", reply["message"]["content"].strip())
EOF

Run it under the observer. diagnose runs your program and records every file it opens and every network call it makes; --cites names the file the answer should come from:

uvx mareforma diagnose --cites notes/cell_counts.md -- python ask.py

Mareforma prints your pipeline's answer, then its own report below it:

FINDING: The human brain has about 86 billion neurons, as stated in the notes. [...]

  reads: 1
    [file] notes/cell_counts.md
  Grounding: GROUNDED

It watched the process open the note and read from it, so the finding is GROUNDED.

Now rename the folder, which simulates the corpus not having synced, and run the exact same command as before:

mv notes notes.not-synced
uvx mareforma diagnose --cites notes/cell_counts.md -- python ask.py
FINDING: The human brain contains approximately 86 billion neurons. [...] (Cite:
Russell, George P. "Neuroscience: An Introduction to the Study of the Brain," 1983)

  reads: 0
  Grounding: UNGROUNDED

The script found no files, so it sent the model an empty blob of notes. The model answered from memory, invented a citation, and got the number right. Mareforma marks it UNGROUNDED.

Same command, same confident answer, both times correct. The only visible difference is reads: 1 against reads: 0. Nothing else in your stack catches it: no exception, no differing log line, and re-running reproduces it. Ask the model and it says it read the notes. The verdict does not move, because it is not a guess about the text. It records what the process did at the I/O boundary.

The observer sits at the requests, httpx, aiohttp, io.open, pandas, and polars seams. The model call shows up as a socket, which buys the finding no credit: a socket cannot deliver a local file read, so absence stays trustworthy. Where it cannot see, such as duckdb running its own I/O, it returns OPAQUE instead of guessing.

That verdict is meant to travel with the finding. Sync the notes again, then record the claim with its computed grounding, not a label you chose:

mv notes.not-synced notes
cat > record.py <<'EOF'
import glob, httpx, mareforma
from mareforma.observe import observe

with observe(cites="notes/cell_counts.md") as obs:
    context = "\n\n".join(open(p).read() for p in sorted(glob.glob("notes/*.md")))
    reply = httpx.post("http://localhost:11434/api/chat", json={
        "model": "qwen3:0.6b", "stream": False, "think": False,
        "messages": [{"role": "user", "content":
            f"Using these notes, how many neurons are in the human brain?\n\n{context}"}],
    }, timeout=120).json()
    finding = reply["message"]["content"].strip()

claim = mareforma.open().assert_claim(
    finding,
    generated_by="agent/lab-a",
    source_name="notes/cell_counts.md",
    observed_grounding=obs.verdict.to_signed_dict(),  # computed, not declared
)
print(f"recorded claim {claim}")
print(f"grounding: {obs.verdict.grounding.value}")
EOF
uv run --with mareforma record.py
recorded claim 75e4cbe5-f77a-45c0-9c00-57c065d83c90
grounding: GROUNDED

The claim now carries GROUNDED as a computed fact, not a self-reported label. The same run records which model authored the finding, computed from the request that was actually sent; a local model is identified by the sha256 digest of the weights that served it, not by the name it reports. Example 02 runs this catch end to end.

Install

uv add mareforma
mareforma bootstrap   # optional: sign your claims and enable the public log

Capabilities

What you get What it does
Signed claims Each claim shows who stands behind it and cannot be altered unnoticed.
Grounding check Computes whether a finding's step actually accessed the data it cites, or leaned on the model's memory, by observing the run.
Trust map mareforma map <claim> shows every trust property (grounding, independence, contestation, witnessing) with how far it can be trusted, and says plainly what it cannot check.
Verify mareforma verify <claim> re-checks the signatures, that the grounding verdict matches the data the finding cites, and the support level, with stable exit codes for CI (0 verified, 1 tampered, 2 unverifiable).
Diagnose a run mareforma diagnose -- python run.py runs a target under the observer and reports what data actually flowed, and where a silent fallback hid.
Audit a pipeline mareforma audit --findings map.json -- python run.py runs a pipeline that never imports mareforma and signs one grounding receipt per finding, from the observer alone.
Serve a project to an agent mareforma mcp serve serves one project over the Model Context Protocol, read and verify only. Six tools to query, inspect and verify; no write path.
Optional public log Publish a claim to a public, append-only log for an independent, timestamped record.
Local-first Runs on local SQLite. Network only for the optional log.

Reading trust from the graph

Trust comes from a claim's place in the graph, never from a self-reported score. The lead signal is effective independence: how many checks behind a finding differ in model, data, and signer. Two agents on the same model are one line of evidence, not two, so the count holds until a check on a distinct model, or a human check, raises it. mareforma map <claim> reports the number and marks it UNVERIFIABLE when it cannot tell the models apart. When every signer traces back to one operator who could have made all the keys, it names that single trust root on the count: the number then rests on distinct model or human lines within one trust domain, not independence across operators.

High-trust claims are re-checked against their signatures on every read, so a tampered claim in a shared graph is caught when you query, not served.

Classification stays a secondary label the agent declares: INFERRED (model reasoning), ANALYTICAL (analysis run against real data), DERIVED (built on higher-trust claims). It is a declaration, kept honest by the computed grounding verdict above, never the trust signal on its own.

Examples

Example What it shows
01 API Walkthrough The full API in one runnable script
02 Compounding Agents The absence catch and computed independence, run end to end
03 Documented Contestation An agent challenges established consensus
04 Private Data, Public Findings Two labs share how they reached a finding without sharing the data
05 Drug Target Provenance A real research agent that labels which findings come from real data and which from the model's guess
06 Verify in CI mareforma verify as a GitHub Actions gate, keyed on exit codes

AGENTS.md: execution contract and adapters  ·  ARCHITECTURE.md: system design  ·  SECURITY.md: threat model  ·  CONTRIBUTING.md: dev workflow  ·  CHANGELOG.md: releases

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mareforma-0.3.12.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mareforma-0.3.12-py3-none-any.whl (554.4 kB view details)

Uploaded Python 3

File details

Details for the file mareforma-0.3.12.tar.gz.

File metadata

  • Download URL: mareforma-0.3.12.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mareforma-0.3.12.tar.gz
Algorithm Hash digest
SHA256 eea198e6537c038002b65fc15baed77a1846ce89a6fa4b9cc690ecf2c896375b
MD5 0ce0d52de0d005bac73bf8e80666c1d5
BLAKE2b-256 c90c423d0abe8db5f912f40b8179e13172960ccc756ee2b7cab384e98fcb3e8e

See more details on using hashes here.

Provenance

The following attestation bundles were made for mareforma-0.3.12.tar.gz:

Publisher: publish.yml on mareforma/mareforma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mareforma-0.3.12-py3-none-any.whl.

File metadata

  • Download URL: mareforma-0.3.12-py3-none-any.whl
  • Upload date:
  • Size: 554.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for mareforma-0.3.12-py3-none-any.whl
Algorithm Hash digest
SHA256 47aa89087df8c45e8b177ee931ea60630cd52f6233780d0d1581a20958b967ec
MD5 306bf4ce64a0400f17dbdf522e366d10
BLAKE2b-256 347eab3deecc0f8b630d94151c421500d4745f39f21cb830f2a58c5812ba5f03

See more details on using hashes here.

Provenance

The following attestation bundles were made for mareforma-0.3.12-py3-none-any.whl:

Publisher: publish.yml on mareforma/mareforma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page