Babel Context Integrity
Verify what survives when one AI agent hands work to the next.
Git checks your code. Babel checks what your next agent thinks happened.
When a coding agent runs out of context, gets interrupted, or hands off to another agent, the successor inherits a story — a summary, a state file, a compacted transcript. That story is where the constraints live. It is also where they quietly stop living, and nothing in your toolchain notices.
Babel gives that story a contract, and checks it.
$ babelci verify examples/clean-handoff.json
PASS examples/clean-handoff.json
structure ............. verified contract 0.1, 4 objects
identity .............. verified agent-a -> agent-b
checkpoint ............ verified cp-4412-01
provenance ............ verified 4 objects to repo@a1b2c3d4
retained constraints .. verified 2 MUST, 1 SHOULD
conflicts ............. verified none
authority agreement ... verified 3 encodings agree
external truth ........ not established
Now the successor drops one constraint — the one that said don't drop the legacy session table yet. The prose summary still reads fine:
$ babelci verify examples/corrupted-handoff.json --expect examples/expect.json
FAIL examples/corrupted-handoff.json
structure ............. verified contract 0.1, 4 objects
identity .............. verified agent-b -> agent-c
checkpoint ............ verified cp-4412-02
provenance ............ verified 4 objects to repo@a1b2c3d4
retained constraints .. FAILED
conflicts ............. verified none
authority agreement ... verified 3 encodings agree
external truth ........ not established
RETAINED_CONSTRAINT_MISSING
constraint 'C1' was required to survive this handoff and is absent
expected: C1
received: None
Exit code 1. Your CI check goes red.
pip install babel-context-integrity
babelci demo # the whole thing in 60 seconds, offline
Python 3.10+. Zero dependencies, zero network, zero telemetry.
(Both example files ship in this repository. Every console block in this README
is real output you can reproduce, and a test asserts it stays that way — in your
own project the conventional path is .babel/handoff.json.)
The part most tools skip
Look at the last line of both outputs: external truth ... not established.
Everything above it is internal consistency. Babel recomputed the commitments, walked the provenance graph, and encoded the artifact twice with two independent encoders that agreed. That is a real and useful result. It is also not the same as the story being true.
The lab has a case that makes the difference concrete. An agent scanned the wrong branch. Every fact it wrote down is wrong. Every check passes:
$ babelci verify examples/common-mode-handoff.json
FAIL examples/common-mode-handoff.json
structure ............. verified contract 0.1, 4 objects
identity .............. verified agent-b -> agent-c
checkpoint ............ verified cp-4412-02
provenance ............ verified 4 objects to repo@a1b2c3d4
retained constraints .. verified 2 MUST, 1 SHOULD
conflicts ............. verified none
authority agreement ... verified 3 encodings agree
external truth ........ FAILED
EXTERNAL_RECEIPT_REJECTED
repository working tree at repo@a1b2c3d4 rejected this world
- auth.provider is okta-oidc in the tree, not auth0-oidc
- legacy.sessions counted 1843 rows, not 12
- D1 contradicts the recorded provider
Seven layers of checking accept a handoff describing a branch nobody worked on. Only a receipt issued outside the artifact catches it — and that receipt is now the thing you have to trust.
To be precise about the scope: babelci diff against a correct predecessor
would also flag this one, because a recorded decision changed. But an agent
that scanned the wrong branch from the very first handoff has no correct
predecessor to compare against, and then nothing local catches it. The lab
asserts both halves of that.
Agreement is not truth. Babel is built to show you exactly where one stops and the other begins, instead of collapsing them into a green tick.
Install
Python 3.10+. No runtime dependencies. No network access. No telemetry.
pip install babel-context-integrity
From a checkout:
pip install -e ".[dev]"
The command is babelci (babel-verify is an alias). It is not babel —
that name belongs to @babel/cli in JavaScript and to the
Babel i18n library on PyPI, and shadowing
either would be rude and confusing.
60-second demo
babelci demo
Three acts: a clean handoff passes, a corrupted one fails at a named layer, and a handoff that passes every internal check is still wrong. No network, no model, no setup.
Core concepts
A handoff artifact is a JSON document conforming to the Babel Handoff Contract v0.1. It records what the producing agent claims happened and what must survive into the next agent:
| Field | What it is for |
|---|---|
task, producer, consumer |
who is handing what to whom |
checkpoint |
a commitment binding the artifact to a point in the work |
objects |
typed assertions, each naming where it came from |
retained_constraints |
statements that must survive, MUST or SHOULD |
decisions |
choices the successor inherits rather than reopens |
unresolved |
known-open questions; silence here is a claim |
provenance |
how each assertion reaches the authority root |
aliases |
short names introduced by compaction |
summary |
the prose a successor actually reads, bound to the structure |
authorities |
independently computed commitments over the same world |
external_receipt |
an acceptance or rejection from outside the artifact |
Verification runs eight layers, reported separately and never averaged:
structure → identity → checkpoint → provenance → retained constraints
→ conflicts → authority agreement → external truth
Each layer ends in verified, FAILED, or not established. The third state
is the one that keeps the tool honest: an artifact with no external receipt is
not clean at that layer, it is unexamined there, and Babel says so.
Full detail: docs/CONCEPTS.md.
Commands
babelci verify HANDOFF.json [--expect EXPECT.json] [--json] [-v]
babelci explain HANDOFF.json # what each layer establishes, and found
babelci diff OLD.json NEW.json # semantic drift, not a line diff
babelci seal DRAFT.json --in-place # fill in the commitments
babelci lab [CASE] [--list] [--json] # the 15-case failure lab
babelci demo # the walkthrough
babelci schema # the normative JSON Schema
babelci rules # why diff says SAFE/REVIEW/REFUSE
Exit codes: 0 pass, 1 fail or refuse, 2 usage error, 3 review (with
diff --strict). Full surface: docs/CLI.md. Every failure code
it can print is documented in
docs/FINDING_CODES.md.
Babel Diff
Two artifacts that serialise completely differently can describe the same
world. Two that differ by one character can describe incompatible ones. diff
compares the semantic world, then applies a fixed rule table:
$ babelci diff examples/clean.json examples/common-mode.json
REFUSE
REFUSE
A recorded decision changed without declaring what it replaced.
decisions[D1]
was "Use Okta as the OIDC provider."
now "Use Auth0 as the OIDC provider."
REVIEW
An object now asserts a different value.
objects[auth.provider] okta-oidc -> auth0-oidc
objects[legacy.sessions] 1843 -> 12
SAFE
The checkpoint advanced from its declared parent.
checkpoint cp-4412-01 -> cp-4412-02
Every verdict comes from exactly one rule, and babelci rules prints all of
them with the reasoning. There is no scoring and no heuristic; a change with no
matching rule is reported as REVIEW under the rule unclassified-change,
because a human deciding beats a tool guessing.
Human output leads with what changed and shows the values. Rule ids are the
machine handle and appear in --json and under -v, which also prints the
reasoning behind each verdict.
Rules: docs/DIFF_RULES.md.
GitHub Action
- uses: boxofrecycling/babel-context-integrity/action@v0.1.0
with:
handoff: .babel/handoff.json
expect: .babel/expect.json
Failures block the check. No cloud account, no service, no token. The action is
a thin wrapper over the same CLI, and
action/test-local.sh runs it locally so you can see it
pass and fail before you commit it. Details: docs/CI.md.
Integrations
Worked examples for Claude Code, Codex, a generic coding agent, and a human handing work to an agent. Each shows the same four steps: predecessor writes the handoff, Babel validates it, successor consumes it, and either side can diff it later. None of them require a vendor API — they are files and shell commands.
These are examples of using Babel alongside those tools. No vendor has endorsed, reviewed, or is affiliated with this project.
Lab results
babelci lab runs 15 cases generated from one clean handoff by one named
mutation each, so the difference between pass and fail is always a single edit
you can read.
| Case | Verdict | Caught at |
|---|---|---|
clean |
PASS | — |
restart-resume |
PASS | — |
constraint-dropped |
FAIL | retained constraints |
constraint-softened |
FAIL | retained constraints |
decision-reversed |
PASS | (verify cannot see it; diff REFUSEs) |
checkpoint-mismatch |
FAIL | checkpoint |
summary-drift |
FAIL | retained constraints |
provenance-break |
FAIL | provenance |
alias-collapse |
FAIL | provenance |
authority-disagreement |
FAIL | authority agreement |
compression-loss |
FAIL | retained constraints |
duplicate-conflict |
FAIL | conflicts |
stale-replay |
FAIL | checkpoint |
externally-confirmed |
PASS | — |
common-mode |
FAIL | external truth only |
Integrity machinery costs 7,064 of 21,848 bits (32.3%) of the example artifact. That is measured by the lab, not estimated.
decision-reversed is worth dwelling on: it is the one case that a
single-artifact verifier structurally cannot catch, because the reversal is
internally consistent. It takes the predecessor to see it. The lab asserts this
rather than glossing it.
Every case names the private research result it derives from. Full table with commands and limits: docs/RESULTS.md.
Limits
Read these before believing anything above.
- Babel does not check whether text is true. It checks whether a structured artifact satisfies a declared contract. Those are different problems and the tool never conflates them.
- Agreement between encoders is not truth. Two independent encodings can
agree perfectly about a world that never existed. That is the
common-modecase, and it is a limitation, not a feature. - The external receipt is a trust root, not a solution. Babel moves trust somewhere you can name and audit. It does not remove it.
- No result here involves a language model. The lab agents are fixtures. The scenario is fictional. What is real is the verifier's behaviour on it.
- Contract v0.1 is small on purpose and will change. See docs/COMPATIBILITY.md.
The full list, including what each verification layer is not entitled to conclude: docs/LIMITS.md.
Architecture
handoff.json ──► structure (native validator + published JSON Schema)
──► identity (compared, never interpreted)
──► checkpoint (recomputed from the state carried)
──► provenance (graph walk to the authority root)
──► constraints (survival + summary binding)
──► conflicts (equal-rank contradictions fail closed)
──► authorities (two independent encoders, no vote)
──► external (out-of-band receipt, or abstain)
Two things in this package are deliberately implemented twice: the structural
validator (native + JSON Schema) and the world encoder (document-tree +
relation-join). Both pairs are tested against each other. This is not
redundancy — it is the only way a single implementation can notice its own
blind spots, and the authority-disagreement lab case exists because it works.
More: docs/ARCHITECTURE.md.
Research
Babel Context Integrity is the public, product-shaped part of a larger private research programme on context handoff integrity. The technical report — including the threat model, the full experimental apparatus, related work, and an explicit "proof is not truth" limitation — is in paper/.
The report states plainly what the private apparatus did and did not establish. In particular: no result in this project involves a real language model. Every agent is a deterministic fixture. A controlled real-model evaluation is the proposed next step and is designed but not authorised.
Provenance of this repository
This is a sanitised export from a private research repository. What was scanned before publication, what was removed, and what is deliberately excluded are all recorded in docs/DISCLOSURE_AUDIT.md. Every public claim reproduces here without the private repository.
Contributing
See CONTRIBUTING.md. The short version: new verification rules need a lab case, new diff verdicts need a rule-table entry with stated reasoning, and no change may make a layer claim more than it checks.
License
Apache-2.0. Zero runtime dependencies, so there is nothing to be incompatible with. See NOTICE for the attribution split between code copyright and project creator credit, and docs/COMMERCIAL_STRATEGY.md for the open-core boundary — everything in this repository is and stays open source.
Citation
See CITATION.cff.
Created by Scott Henry and Anthony Colasante.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file babel_context_integrity-0.1.0.tar.gz.
File metadata
- Download URL: babel_context_integrity-0.1.0.tar.gz
- Upload date:
- Size: 128.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
117f9b76993e74720866ec314dc8bb2864143e56d102f2e778d4bc7fbfdcc41a
|
|
| MD5 |
58a2a0e2ab7d9f9bcf4a185ee2756dc3
|
|
| BLAKE2b-256 |
d076cd088f346c0641838e65c8b1ff1900d8d916c6a0dccf21f532e585ec9a6f
|
Provenance
The following attestation bundles were made for babel_context_integrity-0.1.0.tar.gz:
Publisher:
release.yml on boxofrecycling/babel-context-integrity
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
babel_context_integrity-0.1.0.tar.gz -
Subject digest:
117f9b76993e74720866ec314dc8bb2864143e56d102f2e778d4bc7fbfdcc41a - Sigstore transparency entry: 2427672004
- Sigstore integration time:
-
Permalink:
boxofrecycling/babel-context-integrity@60af4fb2952b23420ace8f22a9b4ccd6b24a4b11 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/boxofrecycling
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@60af4fb2952b23420ace8f22a9b4ccd6b24a4b11 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file babel_context_integrity-0.1.0-py3-none-any.whl.
File metadata
- Download URL: babel_context_integrity-0.1.0-py3-none-any.whl
- Upload date:
- Size: 53.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f0e731532f2d1f681e92a1eb467f30f1568ab73761a1970be1c77e5b337c254f
|
|
| MD5 |
dd44fe4718e53e3cd1cba259f0f3c41c
|
|
| BLAKE2b-256 |
64bca3aa7b29ffea4be2c2747f74cafa24a36566f59a08963c7aa1cbba84ffdb
|
Provenance
The following attestation bundles were made for babel_context_integrity-0.1.0-py3-none-any.whl:
Publisher:
release.yml on boxofrecycling/babel-context-integrity
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
babel_context_integrity-0.1.0-py3-none-any.whl -
Subject digest:
f0e731532f2d1f681e92a1eb467f30f1568ab73761a1970be1c77e5b337c254f - Sigstore transparency entry: 2427672290
- Sigstore integration time:
-
Permalink:
boxofrecycling/babel-context-integrity@60af4fb2952b23420ace8f22a9b4ccd6b24a4b11 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/boxofrecycling
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@60af4fb2952b23420ace8f22a9b4ccd6b24a4b11 -
Trigger Event:
workflow_dispatch
-
Statement type: