Releases: TraceFold/tracefold
Release list
v0.1.3-alpha: The Unmediated Write, Reported From Outside
Two defects in the OpenClaw plugin example were reported from outside, by a
reader who read the published code. Neither was found by us. Both are fixed
here, and the fixes are in the public tree as of this tag.
What was wrong
The admitted write was re-applied without a precondition. On Admit the
hook returned { params } and let OpenClaw's own write run afterward. A
comment in the source defended this as "a real property of this design, not an
omission". The comment was wrong about the part that matters: the
re-application was unconditional. Anything landing between our commit and that
native write — a later hook in the chain, a background process, the agent's own
bash, a file watcher — was overwritten with no receipt. A single caller was
enough; no concurrency required.
The refusal named the doors that were still open. cfg.tools covered
write alone. With the membrane unreachable, write came back blocked with a
careful paragraph explaining that gx could not be consulted, and that paragraph
landed in the model's context while edit and apply_patch sat there
untouched. The blast radius of an outage was "writes move".
What changed
Admit now returns block: true, naming the transformation and the receipt.
The effect is already in the substrate; the native write is redundant, and
allowing it was the only path by which unmediated bytes could move. Zero
unmediated byte movement now follows from OpenClaw's own control flow rather
than from our intent.
The reporter's suggested repair — rewrite params so the native call becomes a
verified no-op — turned out not to be expressible. hook-before-tool-call-result
carries {params, block, blockReason, requireApproval} and no result
substitution; writeSchema is {path, content} with no field for a
precondition; and params merges by lastDefined, so a later plugin overwrites
ours. Re-hashing afterward detects, it does not prevent. Blocking was the
stronger available shape, not the preferred one.
MEDIATED_TOOLS now covers write, edit and apply_patch, from one exported
constant instead of four separate call sites. edit and apply_patch describe
a delta rather than a target state, so they are covered by refusal rather than
escrow — worse for the agent, better for the invariant. The message was not made
vaguer. bash is declared statically in docs/LIMITS.md instead.
What this does not fix
bash remains unmediated. There is no in-plugin fix for it.
The drift case is proven by a unit test, not by the gx-backed demo.
An admitted write is now recorded by OpenClaw as blocked, so it emits a blocked
diagnostic and a security event for a write that succeeded. Telemetry built on
those counts will be wrong.
Also in this tag
action.yml called gx verify-receipts, a subcommand that has never shipped —
the action could not have passed. It now calls gx policy lint and
gx receipt verify --offline. Two inputs that mapped to no flag,
enforce-inverses and fail-on-tamper, were removed rather than left standing
as dials that did nothing.
Three engine accessors returned null after a restart because they read only the
in-memory table: deadline(), planned_delta(), and the pair behind
get_transformation/get_candidate. Each now falls back to the shadow row or
the blob store. undo_intent does not, and cannot without locator, context and
actor, none of which the shadow carries; that gap is pinned by an ignored probe
rather than papered over.
Five red tests were asserting facts that had gone stale, not defects. Package
names diverged from directory names, a manifest grew a member, a predicate that
once identified one crate had come to match seven. Fixed in the tests, with no
change to product source.
State
Alpha. 2,918 of 2,980 tests pass; 60 fail, of which 44 need database or probe
services this checkout does not start. Four adapters are public, three are on
crates.io. CI has not run a job since 2026-08-20 — the account's Actions billing
is blocked, and every check you see on recent commits is a check that never
started.
The limits page is still longer than the feature list.
v0.1.2-alpha: A Promised Target, Kept
Tracefold v0.1.2-alpha
Repairs and additions landed since v0.1.1-alpha, cut at commit 1cfdfa0001c8c31a9d0f4a2648354369794d00d3 (pub_sync round 6, from the private development tree's committed HEAD -- nothing staged from a dirty working copy).
What changed since v0.1.1-alpha
- A
plan()now actually promises a post-state digest, on both shipped stateful adapters.gx-adapter-fsandgx-adapter-git'splan()call thewith_promised_targetconstructor path for the first time in a shipped release (previously alwaysNone) -- WM-5a Phase 1. - A cold-undo / cold-redo data-loss-shaped defect was found and fixed while wiring the above. A second site in
gx-enginethat constructs aTransformation(rehydrate_committed, used after an engine restart) was zeroing the promised target instead of carrying it, which meant every undo or redo issued after a cold restart silently lost the promised-target check the hot path already had. Bothdemo30.shanddemo_one_screen.sh(the fs and git tamper-and-undo demos) now pass end-to-end against this build; they did not before this lane. PredictionOutcome: the engine used to record only a failed post-state prediction (as the seventhnot-attemptedcause added in v0.1.1-alpha) and stay silent when a prediction held. That made "the engine predicted correctly" and "the engine never checked" look identical from outside. The comparison is now recorded either way, at one site, for both branches. This is an internal engine record -- nothing on the wire changed, and no shipped client needs to do anything differently.- Escrowed-inverse resolution now falls through to a Σ-shadow fallback when the direct escrow lookup misses, per the R1017 ruling, instead of surfacing an avoidable failure.
GET /v1/transformations/{id}carriesinverse_status. A subsequent investigation (prompted by a TUI-side report of a spurious error state) confirmed the wire contract was correct from the start: the API was already sendingnullcorrectly for the no-inverse-yet case. The bug was on the reading side, in the terminal face, which is fixed separately in thetui/sources this sync also carries -- astatus_reasonclassifier now reads anullasAbsent(--) instead of misreporting it. Nothing in this repository'sgx-api/gx-engineneeded to change for that fix.- Four Cedar policy packs, previously private, now ship:
policies/{fs,git,mcp,postgres}/deny-*.cedar, each with its ownscenarios.jsonfixture beside it (PACK_FORMAT.mdF1). docs/ADAPTER_GUIDE.mdis new: how to write aSubstrateAdapteragainst the shippedfs/git/mcpadapters and the conformance harness, without reaching into engine internals.- A new example,
examples/openclaw-plugin-demo/: abefore_tool_call-hook plugin against a realgxbinary, demonstrating the escrow/undo membrane pattern for OpenClaw-shaped agent harnesses. It drives a real filesystem and a realgxprocess; it does not drive OpenClaw itself (the firing order is reproduced by a harness in the same example, and the README says so). One honest note about this example specifically: an earlier working copy of it defaulted an environment variable (GX_DEMO_BIN) to the machine-local absolute path of the machine that wrote it. That default was removed before this sync (the variable is now required, with a clear error if unset) -- named here because it is exactly the kind of thing a "diff, don't trust" sync gate exists to catch, and did. - Crate versions bumped
0.1.0->0.1.2across all 13 crates this tree ships plustui(gx-tui), workspace-consistently, including every internal path-dependency version pin.gx --versionnow printsgx 0.1.2(previous tags shipped a binary that printedgx 0.1.0regardless of the tag name; this one does not have that mismatch). Not bumped: the TypeScript SDK'spackage.json(still0.1.0) -- that drift is disclosed here rather than fixed silently, since fixing it was not part of what this bump covered.
What is still not true of this release (read before assuming otherwise)
- crates.io publishing is still blocked, for two independent, unresolved reasons found while checking: (1)
gx-core,gx-tui, and baregxare already registered on crates.io by an unrelated third party (a different Rust tool,galax, that happens to use the same short name) -- every crate in this workspace path-depends ongx-core, so the name collision blocks the whole dependency closure, not just one crate; a rename (candidate:tracefold-*) is pending an operator decision, not yet applied to any shipped file. (2)gx-gate'spacks.rsreaches three directories above its own crate root viainclude_str!for policy files that, percargo package --list, do not end up in the packaged tarball -- publishinggx-gate(and its dependentsgx-engine,gx-api,gx-cli) as-is from acargo publishtarball would build broken. Every crate in this tree still carriespublish = false. - CI has still run zero jobs on any push, unchanged since the GitHub Actions billing block that started 2026-08-15T17:25:29Z (
req/908) -- not a code defect. Seedocs/LIMITS.mditem 8 for the full, dated account; the last run before the block (commitf65aac2f) covered 16 of this tree's 17 workspace crates. - The postgres and mysql
SubstrateAdapters are not in this public tree at all (private-only, per the sync's own scope ruling), so anything they, or a PostgreSQL-17-specific suite, would test is not just unmeasured here -- the code that would run it is not present in a clone of this repository.docs/LIMITS.md's own postgres disclosures ("not measured for power cuts", four releases running as of that doc) describe the private engineering state, not something buildable from this tree. - The published Test Floor number (2,602 probes / 454 suites + SDK 36) is dated 25 Aug 2026 and was not re-measured for this release. Four new test files landed in this sync (
wm5a_promised_target.rsx2,r1017_escrowed_inverse_shadow.rs,wm5a_prediction_on_real_data.rs); the badge and README table do not yet reflect them. Re-counting is a docs-sync change, named here rather than silently left implying a number this release did not check. - No pre-built binary is attached to this release at publish time (unlike v0.1.0-alpha and v0.1.1-alpha, which each got one added by hand after the tag).
gx --versionon a self-built binary from this tag printsgx 0.1.2, confirmed on a fresh worktree of the exact tagged commit before this tag was cut; a binary asset may follow the same way the prior two tags' did. - Everything else this project does not guarantee is unchanged and still enumerated in
docs/LIMITS.md-- the same 8 clausesgx limitsprints.
Getting the source
git clone https://github.com/TraceFold/tracefold.git
cd tracefold
cargo build --release -p gx-cliNo binary asset ships with this tag; building from source is the only path for now.
v0.1.1-alpha: Fail-Closed Action Gate & Seventh Not-Attempted Cause
Tracefold v0.1.1-alpha
Repairs landed since v0.1.0-alpha, cut at commit a77f9432dd84ca5d3a405f39cbc73a10e2961ae1. One process note first: the v0.1.0-alpha binary was uploaded to the existing release on 2026-09-01, and adding an asset to an old release notifies nobody — this tag exists partly so the repairs and the binary actually reach release watchers.
What changed since v0.1.0-alpha
action.ymlwas fail-open and is now fail-closed (issue #5). The old stub printed "Tracefold gate validation passed (stub check)" when thegxbinary was not installed — a gate that could not run, passing. It now exits 1 with an error whengxis absent. The retired stub line is kept as a comment in the file, for the record. Second honest limit, stated in the file itself:gx verify-receiptsis not a shipped subcommand yet (the CLI shipsgx receipt verify), so even withgxinstalled the step currently fails — the intended fail-closed direction until the input mapping lands.- A seventh
not-attemptedcause,PromisedPostStateWasWrong, is now in the public tree. The cause enum had six reasons and the code needed a seventh: the case where a tool's promised post-state disagrees with what checking it would require. Previously this was collapsed into a neighboring cause. gx limitsre-synced its Lean clause (previously 117 theorems; see the number caveat below), and the stale CI claim in it was replaced with a dated statement bound to the diagnosis (req/908) rather than a present-tense sentence that goes quietly false.- README and docs overhaul: subcommand list corrected (13 said, 22 exist), Zenodo DOI
10.5281/zenodo.22168558integrated, architecture and org pages restructured.
Numbers, and one mismatch named rather than smoothed over
- This binary's
gx limitsclause 8 says 154 theorems, 14 of them counterexamples, over 14 files. A line-start count on this public tree at this commit returns 117 theorems (119 with leading whitespace tolerated) over 13.leanfiles, 12 named counterexamples, 0sorry, 1axiom— agreeing with the README badge (117) anddocs/LIMITS.md, not with the limits page. The 154/14/14 figures describe the development tree the sync came from; the public transplant carries 13 of its 14 Lean files. Fixing the text is a docs-sync change, not a release change, so it is disclosed here and will be corrected in the next sync. - Test floor as published in this tree's own README, with date and method: 2,602 probes across 454 suites plus the SDK's 36 (fresh clone, single run, 25 Aug 2026).
- Everything this project does not guarantee: docs/LIMITS.md — the same 8 clauses
gx limitsprints. A copy ofLIMITS.mdis inside the tarball.
Pre-built binary — Linux x86_64, glibc. That is the only platform this release ships a binary for.
gx-v0.1.1-alpha-x86_64-unknown-linux-gnu.tar.gz
What this asset is, and is not:
- Built from this release's commit
a77f9432on a fresh clone (Ubuntu 24.04, toolchain pinned byrust-toolchain.toml, rustc 1.97.1) withcargo build --release -p gx-cli. Smoke-tested before upload:gx --versionprintsgx 0.1.0;gx limitsexits 0 and prints the 8 documented limit clauses. --lockeddid not work, and that is a defect of this tree: the shippedCargo.lockat this commit still carries entries for development-tree crates that are not in this repository, so cargo refuses--locked. The build regenerated the lockfile; the diff is 913 removed lines (the absent crates and their unique dependencies) and 5 reflowed dependency-list lines — no version of any retained dependency changed.- The binary prints
gx 0.1.0, not 0.1.1. Crate versions were not bumped; this tag names a repository state, not a crates.io version. - Not a CI artifact. The
release.ymlpipeline has still never produced a run; this was built and uploaded by hand. No DSSE receipt of the build itself is attached, so issue #7's acceptance criteria remain unmet. - No macOS, Windows, or ARM binaries. On those platforms:
cargo install --git https://github.com/TraceFold/tracefold.git gx-cli(requires a Rust toolchain). - Dynamically linked against glibc — it will not run on musl-only systems (Alpine).
- Verify the download:
sha256sum -c SHA256SUMS. The tarball's SHA-256 is34f2a2615fca2f37367581cfa0d0495f6e93bae23e07511738056db59d6e0b07.
v0.1.0-alpha: Verified Transformation Calculus & Inverses Engine
Tracefold v0.1.0-alpha Initial Release
Tracefold provides formal reverse-execution guarantees, pre-commit inverse escrow, and offline-verifiable DSSE receipts for AI agent tool executions and filesystem mutations.
Highlights:
- gx-core: Verified transformation calculus with Lyapunov convergence proofs and invariant assertions.
- gx-witness: Ed25519 DSSE signed audit receipts with offline verification and full single-bit tamper detection.
- gx-log: Merkle tile log append, root consistency proofs, and checkpoint verification.
- gx-cli: Command-line tool for verifying receipts and inspecting execution histories.
Getting Started:
cargo install --git https://github.com/TraceFold/tracefold.git gx-cliPre-built binary (asset added 2026-09-01)
gx-v0.1.0-alpha-x86_64-unknown-linux-gnu.tar.gz — Linux x86_64, glibc. That is the only platform this release ships a binary for.
What this asset is, and is not:
- Built from this release's tag commit
e2de2a814ee630e51a3925381656b7a348961ca3withcargo build --release --locked -p gx-clion a fresh clone (Ubuntu 24.04, toolchain pinned byrust-toolchain.toml). Smoke-tested before upload:gx --versionprintsgx 0.1.0;gx limitsprints the 8 documented limit clauses. - Not a CI artifact. The
release.ymlGitHub Actions pipeline has never produced a run; this binary was built and uploaded by hand from the tagged source. No DSSE receipt of the build itself is attached, so issue #7's acceptance criteria are not met by this upload — it only closes the "release has no binary at all" gap. - No macOS, Windows, or ARM binaries. On those platforms use
cargo install --git https://github.com/TraceFold/tracefold.git gx-cli(requires a Rust toolchain). - Dynamically linked against glibc — it will not run on musl-only systems (Alpine).
- Verify the download:
sha256sum -c SHA256SUMS(checksum file is attached alongside; the tarball's SHA-256 is5c0fae3f27138ba0237d3533c0607668c43c778c057f327d9796187d1e652756).
Numbers for the tagged tree, as published in its own README with date and method: test floor 2,602 probes across 454 suites plus the SDK's 36 (fresh clone, single run, 25 Aug 2026); 117 Lean theorems, 12 of them counterexamples, 0 sorry, 1 named axiom (re-counted on a fresh clone, 26 Aug 2026). What this project does not guarantee is enumerated in docs/LIMITS.md — the same 8 clauses gx limits prints, and a copy of LIMITS.md is inside the tarball.
Demo recordings (not a software release)
Terminal recordings of the verification path, captured with script(1) from real runs against a fresh anonymous clone at commit 177141e on 2026-08-26 (WSL2 Ubuntu 24.04, dev profile).
- tracefold-demo-10s.gif - the atom: verify an intact receipt (exit 0), flip one byte, verify again (exit 7).
- tracefold-demo-30s.gif - the chain: an agent acts through gx, a receipt is issued, three files travel, a stranger verifies offline, a tampered copy fails.
- *.cast - the same two runs as asciicast v2, for anyone who would rather replay the bytes than watch a GIF.
Excluded from both recordings on purpose: cargo build --workspace, measured at 64 seconds on this run. The demos start after the binary exists. No output was retyped or staged.
Figures — 2026-08-19
Evidentiary figures for the census/retention measurements and instrument-hygiene write-ups. Generator: tools/census/figure.py and tools/math_cards/render.mjs. Not a software release.
Brand assets (not a software release)
Images the public pages point at. Not a software release; the tag exists so the files have a stable address that is served from a CDN.