Source-backed Semantic Image Store and Refresh v1
September 10, 2026 ยท View on GitHub
Audience: embedding-host authors, agent builders, compiler contributors, and reviewers.
Status: bounded implementation; HOSTED GREEN for v0.4.0. See the release baseline for evidence scope. No broader durability, performance or full-programme completion is implied.
This additive lifecycle persists an image's exact canonical Project inputs through the existing Project Revision Store v1. Loading authenticates those immutable inputs, performs the ordinary complete Project source rebuild, and derives the image again. No serialized HIR, typed index, graph, or image JSON is trusted as compiler input. Persistent storage therefore retains the source subject, not a warm cross-process compiler cache. Existing Semantic Image v1 bytes and nonclaims remain unchanged.
Host-selected persistence
persist_semantic_image(root, &image, expected_image_digest)
-> Result<ImageStoreReceipt, Vec<Diagnostic>>
load_semantic_image(root, receipt_bytes, expected_image_digest)
-> Result<Arc<ProjectSemanticImage>, Vec<Diagnostic>>
Both functions are explicit host operations. They do not discover, create, or
adopt an ambient cache root. On supported Unix hosts, the host provides an
existing absolute normalized real directory owned by the effective user with
exact mode 0700, along with the existing store's exclusive-root and ancestor
mutation guarantees. Secure handle-relative reads/writes, locking, exact file
inventory, no-follow checks, source reconstruction, bounded entry counts, and
atomic no-replace publication are owned entirely by the existing store.
Unsupported hosts retain its fail-closed behavior; this API does not silently
select the separate Windows private-host route.
A repository-local host can explicitly select a directory named
.semaprax-images, already excluded by the repository's
**/.semaprax-images/ ignore rule. Other host-selected roots and saved receipt
paths must likewise be excluded from Git by that host. This API performs no
repository discovery, ignore-file mutation, filesystem cleanup, or GC.
Persistence checks the expected image digest, prepares the complete bounded
receipt before any store effect, and invokes project_revision_store::persist
for the image's retained revision. It compares the published locator facts with
the expected facts. Duplicate entries reject under the existing no-adoption
rule; they are not overwritten or treated as successful publications. Store
errors and post-publication uncertainty retain their original meanings. A
receipt is neither reusable authority nor proof that the entry still exists.
The on-disk tree is exactly the existing store entry: canonical entry.json,
Project manifest, Workspace manifest, and declared source files under the
content-addressed entry digest. There is no additional image.json, HIR blob,
index file, or mutable image pointer. The caller receives the image receipt
separately and may retain it outside the strict store inventory.
Receipt and cold load
ImageStoreReceipt exposes to_json, receipt_digest, entry_digest,
image_digest, and project_revision. Its compact, recursively key-sorted JSON
has one terminal LF, a maximum size of 8,192 bytes, and schema
semaprax.semantic-image-store.v1. Its exact fields are:
schema,compiler,image_schema,image_digest, andimage_bytes;project_revision,workspace_revision, andproject_graph_digest;revision_storewith the existing entry schema andentry_digest;- the fixed nonclaim list.
Compiler metadata contains package name, package version, and the explicit
Semantic Image serialization compatibility identity. It does not claim a
compiler-binary identity. The receipt digest is SHA-256 over
semaprax.semantic-image-store.receipt.v1\0, little-endian u64 exact byte
length, and the complete receipt bytes including LF, rendered as lowercase
sha256: text. It is returned separately rather than embedded recursively.
Load checks the caller's expected image digest, the receipt bound, exact closed schema and compiler compatibility, bounded canonical digest fields, image length, and canonical receipt encoding before opening an entry. Unknown keys, duplicate keys, alternate JSON encodings, changed compatibility, or wrong expected image identity fail closed. A root/path cannot be supplied inside the receipt.
The existing store then independently reads and rebuilds the exact canonical source subject. Image derivation must reproduce the expected image digest and byte length, and re-identifying that derived image must reproduce every canonical receipt byte. The image digest binds the exact canonical image bytes; the original serialized image is neither stored nor deserialized. Missing or corrupted entries reject without reconstructing data from a working copy or trusting a previously retained image.
Manual edits in the original source checkout do not alter an older immutable store entry. Loading that entry intentionally yields its historical revision, not a claim about current disk freshness. Hosts requiring current checkout state must independently admit those current sources.
Retained workspace refresh
ImageWorkspace::new(Arc<ProjectSemanticImage>) -> ImageWorkspace
ImageWorkspace::image() -> &Arc<ProjectSemanticImage>
ImageWorkspace::refresh(new_admitted_revision, expected_old_image_digest)
-> Result<ImageRefreshReport, Vec<Diagnostic>>
The workspace retains no store root or filesystem authority. The caller
supplies an independently admitted Arc<ProjectRevision> and the exact old
image expectation. For an unchanged Project revision, refresh compares the
complete retained canonical manifest, source, Workspace, and graph facts and
reuses the original image Arc. The caller may already have spent compilation
work obtaining its fresh revision; this reuse does not claim that work was
avoided.
For a changed revision, refresh reconstructs the full Project through
build_owned from the supplied canonical manifest and sources, exact-compares
the rebuilt revision/graph/source facts, and derives a new image. It does not
splice cached HIR, skip source verification, or claim incremental compilation.
The deterministic report identifies changed source paths, then computes the
transitive reverse dependency closure using the union of old and new explicit
function/type import edges. Both graph versions matter when imports are added
or removed. Manifest or source-inventory changes conservatively invalidate all
old/new paths. Lists sort by path. unchanged_source_facts describes paths
outside that invalidation set; it does not assert reuse of their HIR or a
semantic equivalence proof.
The report schema is semaprax.semantic-image-refresh.v1, bounded to 65,536
bytes. It binds old/new image and Project digests, changed/invalidated paths,
manifest/inventory flags, the invalidation basis, image_arc_reused, and
compiler_work as either retained_image_arc_reused or
complete_source_rebuild_and_image_derivation. Its separate digest uses
semaprax.semantic-image-refresh.report.v1\0 with the same byte-length and
exact-canonical-JSON construction as receipts. Only after the entire report is
representable does refresh replace the retained image. Failure leaves the
previous Arc unchanged.
SPX-G249 covers malformed receipt/selector/compatibility facts, SPX-G250
covers lifecycle report/input capacity, and SPX-G251 covers stale image or
replay disagreement. Existing store, source-admission, and image-derivation
diagnostics retain their owning meanings.
Authored evidence and limits
src/project/image_store.rs owns this lifecycle. The original five-case corpus in
tests/semantic/image_store.rs cover unchanged Arc reuse, manual source
and manifest refresh, reverse-import invalidation, stale/invalid-source
preservation, cold rebuilding after dropping retained state, working-copy
independence, duplicate persistence, corruption/deletion, and hostile receipt
or compiler-locator substitution. Disk cases are limited to the existing
supported Unix store platforms. The implemented release corpus is HOSTED GREEN
for v0.4.0; historical test counts do not define the current inventory.
This slice does not provide persistent HIR/index reuse, warm cross-process compilation, selective module recompilation, automatic cache discovery, eviction, crash recovery, new durability guarantees, signatures/approval, current-source freshness, target execution, or evidence that the full graph-operational persistence/performance programme is complete.
The separate authenticated cache store and frontend/semantic reuse are implemented additions, not behavior silently added to this source-rebuilding store profile.