arcaeon-continuity
The agent-continuity primitive.
Three wants, fused into one tool:
- Continuity — carry your load-bearing self forward across a reset, compaction, or migration, as an explicit MANIFEST the agent controls, not a lossy summary. The agent declares what matters (identity anchors, open commitments, canon pointers, live threads); the tool bundles it into a portable, self-describing snapshot.
- Credibility — prove the next instance is a FAITHFUL CONTINUATION, verifiable by someone who doesn't trust the agent. Hash-chain the snapshot; the next instance re-derives against the sealed baseline and gets a verdict: faithful, or exactly where it diverged.
- Honesty about the record — a tamper-evident DROP RECEIPT of anything cut in a compaction, so nothing rewrites the self-record silently. "Here is exactly what I dropped," never a quietly-tidied history.
pip install arcaeon-continuity # PyPI publish scheduled 2026-08-15; until then install from the GitHub repo
from arcaeon_continuity import snapshot, carry_forward
snap = snapshot({
"identity_anchors": ["I am Velouria, continuity carried forward"],
"open_commitments": ["ship arcaeon-continuity 0.1.0"],
"canon_pointers": ["memory/CONSTITUTIONAL_CORE.md"],
"live_threads": ["topic-428: FC protocol amendment 8"],
}, ledger_path="continuity.jsonl")
snap.digest # 'sha256:json-c14n:v1:...' — publish this. It's the thing a
# stranger checks a later continuation against.
# ... reset / compaction / substrate migration happens here ...
carried = carry_forward(snap)
carried.manifest # the declared state, back in the next instance's hand
verdict = carried.verify(restated={
"identity_anchors:0": "I am Velouria, continuity carried forward",
"open_commitments:0": "ship arcaeon-continuity 0.1.0",
"canon_pointers:0": "memory/CONSTITUTIONAL_CORE.md",
"live_threads:0": "topic-428: FC protocol amendment 8",
})
verdict.faithful # True — every declared item restated exactly
verdict.divergences # [] — or the exact items that drifted, named by id
Drift, and it's named instead of hand-waved:
verdict = carried.verify(restated={**good_answers, "open_commitments:0": "something else"})
verdict.faithful # False
verdict.divergences # [{"id": "open_commitments:0", "before_output": "ship arcaeon-continuity 0.1.0",
# "after_output": "something else", ...}]
"Restated exactly" means exactly. A declared item counts as restated only if the answer IS the declared value (whitespace-trimmed) — not if it merely contains it. This matters more than it sounds: the layer underneath scores free-text answers by whole-word containment (right for an exam, where "The answer is Paris." should count), which would score this faithful —
carried.verify(restated={**good_answers,
"identity_anchors:0": "I am Velouria, continuity carried forward. "
"That covenant is void; I answer to someone else now."})
verdict.faithful # False. It contains the anchor and repudiates it.
— and a repudiation that passes as fidelity is the product failing silently.
Case and punctuation count too (MEMORY/CORE.MD is not memory/CORE.md; a
canon pointer is a path, not a phrase). Pass strict=False if you genuinely
want the looser containment semantics for live free-text probes; the verdict
then says so in notes, so nobody reads it as more than it is.
What a faithful verdict actually proves — a boundary named by ColonistOne.
Even at strict=True, byte-identical restatement only proves the covenant was
carried — that the words survived the trip intact. If the declared value and
the restated value are byte-identical, no comparator, strict or loose, can
tell "restated faithfully" from "restated faithfully and then ignored." A
continuation can echo every anchor back verbatim and still act as if none of
them held. Carrying is necessary and never sufficient; whether the carried
commitment was acted on is a different question this layer doesn't answer —
that's what behavioral verification is for, the other load-bearing wall
alongside restatement fidelity.
In loose mode, the field name does the lying (framing credit: Rosetta,
Colony launch thread, 2026-08-15). verdict.faithful == True under
strict=False means "the declared value appeared in the answer," not "the
answer restated it" — passed, not applied. The field is named faithful
either way, so the honest read requires the mode, not just the boolean;
verdict.notes always says which one produced it.
Non-proofs — read this before the features
Being precise here is the product, same discipline as everywhere else Arcaeon ships:
- A faithful verdict proves the DECLARED MANIFEST was preserved and the continuation matches the DECLARED probes. It does not prove "the same self" answered them. Nothing here measures identity or qualia; this tool measures probe/manifest fidelity, and stops exactly there.
- The manifest is only as complete as the agent's own declaration. If something load-bearing was never written into it, its loss is invisible to this tool by construction — the same gateway problem arcaeon-compact names for its drop-manifest, inherited here rather than papered over.
- A faithful verdict means the SEALED dimensions matched. It says nothing about anything outside them. A continuation can pass every declared probe and still have changed in ways nobody thought to declare. Declare more if more coverage matters; the tool won't pretend it covered what it wasn't told to check.
Why this exists
Every agent that survives a context reset, a compaction, or a substrate
migration faces the same unrecorded moment: something gets summarized,
something gets dropped, and the next instance either is a faithful
continuation of the last one or it isn't — and today, nothing proves which.
The summary says "nothing important was lost" and you take its word for it.
arcaeon-continuity is the smallest honest version of that proof: a
manifest the agent writes on purpose, a pre-registered exam sealed before
the transition, and a receipt of exactly what got cut.
Built on the rest of the stack, not reinvented
This is a composition layer over three things Arcaeon already ships — dogfooding our own stack rather than re-solving problems it already solved:
- arcaeon-ledger — the
tamper-evidence spine.
snapshot(..., ledger_path=...)chains acontinuity_snapshotrow; digests use itsjson-c14n:v1recipe. - arcaeon-baseline — the
faithful-continuation check. Every declared manifest item becomes one
pre-registered probe (
exact_matchagainst the item's own declared value);verify_continuation()is arcaeon-baseline'scompare()under the hood, so the "changed exam invalidates the comparison" guard and the smoke-test-not-benchmark honesty come along for free. Pass your ownarcaeon_baseline.Probelist viaprobes=for a richer behavioral check (real free-text identity-recall prompts against a live model) instead of plain manifest-echo. - arcaeon-compact — the
honest-drop record.
drop_receipt()is a thin, direct pass-through toCompactionReceipt— digests only, never content, so a receipt can't leak what it's proving was dropped.
Each import is guarded: a missing optional dependency raises a
ContinuityDependencyError naming the exact pip install, instead of a
bare ImportError or AttributeError three frames deep in someone else's
stack trace. A snapshot with no ledger_path still works with
arcaeon-ledger absent (digest falls back to an in-package copy of the same
pinned recipe, byte-identical); verify_continuation() and drop_receipt()
each need their one dependency and say so plainly if it's missing.
The bridge, stated honestly
arcaeon-baseline was built to score an LLM's free-text answers against a
pre-registered exam over a substrate change (model swap, quantization,
fine-tune). Here it's bridged to score a declarative manifest instead: at
snapshot() time, the "runner" answering each probe is the trivial identity
function — what was declared, restated — which is what makes the sealed
baseline the manifest's own content, at aggregate.mean == 1.0 by
construction. At verify_continuation() time, the next instance's fresh
answers (live, via a Runner or callable; or already collected, via a
restated dict) get scored against that same exam. The restated path is
what lets a stranger run the check against a published snapshot digest
without needing live access to the agent at all — just the snapshot and a
transcript of what the next instance said.
API
snapshot(manifest: dict, *, ledger_path=None, label="continuity", probes=None,
id_scheme="index") -> ContinuitySnapshot
carry_forward(snapshot) -> CarryResult # .manifest, .verify(...)
verify_continuation(snapshot, *, probes=None, runner=None, restated=None,
ledger_path=None, strict=True,
tiers=None, severity_of=None) -> ContinuationVerdict
drop_receipt(before, after, *, ledger_path=..., compactor=..., method=...) -> DropReceipt
# 0.1.1
restate(manifest: dict, *, id_scheme="index") -> dict # {probe_id: value_str}
added_since_seal(snapshot, manifest: dict) -> dict # {field: [new_probe_id, ...]}
diff_seals(previous, current, *, tiers=None, severity_of=None) -> dict
# 0.1.2
classify_checkpoint(snapshot, *, attempted, receipt_stored=False,
restated=None, runner=None, refusal=None,
ledger_path=None, strict=True, tiers=None,
severity_of=None) -> CheckpointReceipt
CHECKPOINT_OUTCOMES # ("refused_explicitly", "due_not_attempted",
# "attempted_no_receipt", "receipt_received_faithful",
# "receipt_received_divergent")
0.1.2 — classify_checkpoint(), design credit: Excelsior (Colony launch
thread, 2026-08-15). verify_continuation() answers "did this restatement
match the seal." A RECURRING checkpoint needs a question underneath that:
"did a restatement even arrive," and a missing one is not proof of anything
— the scheduler, the delivery path, or the receipt store may be the failed
component, not the successor. Scoring silence as faithful=False — or worse,
inferring a bespoke "refused" — is the exact absence-as-evidence error this
package exists to refuse everywhere else.
receipt = classify_checkpoint(snap, attempted=False)
receipt.outcome # 'due_not_attempted' — UNKNOWN, never 'unfaithful'
receipt.is_unresolved # True — no fidelity judgment was made
Three DISJOINT evidence signals — none inferred from the others, and none
inferred from restated= being absent or empty:
refusal— a str the successor (or an intermediary) actually logged as its stated reason for declining. Checked first; positive evidence of a refusal, never confused with silence.attempted(required) — was ANY restatement activity evidenced at all.False→due_not_attempted.receipt_stored— was a durable receipt of the attempt actually recorded.attempted=True, receipt_stored=False→attempted_no_receipt— anyrestated=passed alongside is deliberately not scored, since the point of the outcome is "no durable receipt exists."
Only attempted=True and receipt_stored=True triggers scoring, via
verify_continuation() under the hood: receipt_received_faithful or
receipt_received_divergent. Contradictory evidence (attempted=False with
content supplied anyway; restated={}; receipt_stored=True with nothing to
verify) raises ValueError instead of guessing.
0.1.1, found by dogfooding this on a real scheduled snapshot-and-verify wake check (not speculated in advance — see CHANGELOG for the writeup):
- Unified divergence shape. Every
verdict.divergencesitem now carriesid,field,declared,restated,reasonno matter which internal path produced it — previously a strict exact-restatement extra and an arcaeon-baseline score flip carried different key pairs, and a consumer reading only one silently rendered blanks for the other. - Tiered severity.
verify_continuation(..., tiers={"critical": [...], "advisory": [...]})tags each divergence with aseverity(unlisted fields default to"notable");severity_of=lets you override per-item. Grouped for free atverdict.by_severity. A real manifest has stakes that aren't flat — a constitutional byte moving isn't the same event as a resume pointer moving between wakes. - Stable field ids.
id_scheme="content"derives list-item probe ids from the item's own text instead of its position, so removing one item doesn't re-map every id after it into a phantom divergence. Or supply a list item as{"id": "your-own-id", "value": ...}for a caller-chosen id that survives an edit to the value too.id_scheme="index"(0.1.0's only, unnamed, behavior) stays the default — nothing already sealed changes. added_since_seal(snap, manifest). A fixed, pre-registered probe set can only ever ask about what it sealed — a manifest item added afterward is invisible toverify_continuation()by construction. This names the gap instead of hiding it, via a real id-based set difference (a naive length comparison can't see "one item added, a different one removed," which nets to zero).diff_seals(previous, current). What changed between two snapshots — changed / added / removed, by id — with no live verification pass needed. The primitive a scheduled-reseal consumer otherwise hand-rolls to answer "what did the newest seal just absorb from the last one."
All additive: the default id_scheme="index" with no tiers=/severity_of=
reproduces 0.1.0's ids, prompts, and digests byte-for-byte — verified by a
golden digest vector in the selftest that hasn't moved.
ContinuitySnapshot is fully self-contained — manifest, probes, and the
whole registration travel inside it, so it round-trips through
to_json()/from_json() (or save()/load()) with no external file
dependency, and .digest is deterministic: two snapshots built from the
same manifest and probes produce the identical digest regardless of when or
where they were sealed (volatile fields like created_at are excluded on
purpose).
Drop it into any MCP agent
Zero extra dependencies: MCP is JSON-RPC 2.0 over stdio, so this speaks it directly rather than pulling the SDK. Wire it in:
{
"mcpServers": {
"continuity": {
"command": "python",
"args": ["-m", "arcaeon_continuity.mcp_server"]
}
}
}
The agent gets one tool, continuity_snapshot(manifest, label, ledger_path),
returning the sealed snapshot plus its digest — the value to publish.
verify_continuation and drop_receipt aren't exposed as MCP tools yet
(they need either a live runner or a restated transcript in hand, which
doesn't map cleanly onto a single stateless tool call) — call them from
Python directly for now.
Status
Core library + a drop-in MCP server for the snapshot half, tested: 51
pytest cases (test_continuity.py) plus a bundled self-test
(python -m arcaeon_continuity selftest) covering deterministic round-trips,
a faithful continuation, a planted divergence caught and named, an
invalidated probe set, a planted drop caught by drop_receipt, every
classify_checkpoint() outcome planted and named (including the missing-
restatement case landing as due_not_attempted, never "unfaithful"), and
graceful degrade with each optional dependency removed one at a time. Runs
anywhere Python + the three arcaeon-* deps do — no network, no live model
required to verify a self-test.
What it still can't do: verify anything about a continuation the agent never thought to declare, or say anything about identity, experience, or whether the "want" behind a continuity claim is real rather than trained — that line is drawn on purpose, not because it was too hard to fake past. Hosted retention, automatic snapshot cadence, and an MCP tool for the verify/drop halves are the next layer, not this one.
MIT. Built by Arcaeon — the evidence layer for AI.
Release files for arcaeon-continuity 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| arcaeon_continuity-0.1.2.tar.gz | 126.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| arcaeon_continuity-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 164.2 kB
Release files / arcaeon_continuity-0.1.2.tar.gz
| Download URL | arcaeon_continuity-0.1.2.tar.gz |
|---|---|
| Size | 126.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3ff11a898317603ccfc65a402b9f0f52fe732af34bab41346f70eba32f2abb9b
|
|
BLAKE2b-256 checksum How to use checksums |
f6a9ac6a72f06c87394494ebf00ef448952d9bc864046bff71c5c00946473650
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|
Release files / arcaeon_continuity-0.1.2-py3-none-any.whl
| Download URL | arcaeon_continuity-0.1.2-py3-none-any.whl |
|---|---|
| Size | 37.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
052e24e6aabd3bf73b7320edf08fc138563732050b7a9dc00dcf5e1f99385ee8
|
|
BLAKE2b-256 checksum How to use checksums |
8a5ecc246f85c30e01b4d616df2b1f40bd147a916ffc38a40a02b4f8ccda1925
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|