Protocol migrations
September 18, 2026 · View on GitHub
Status: living compatibility reference for versioned protocols.
Audience: agent and tool authors, plus compiler contributors.
SEMAPRAX is alpha, but agent-facing changes are still explicit. Consumers must inspect the declared schema field rather than assuming every JSON object has the latest shape.
Bounded Native Agent Runtime v1 C1 is additive. Existing consumers require no
migration; callers opt into the injected AgentHost API explicitly, and no CLI,
language, Graph, backend, provider transport, write, or wallet surface changed.
Economic Agent v1 is additive and requires no migration. Callers may opt into the injected-host API; it adds no CLI, built-in transport, custody, wallet, language, Graph, cleanup, or backend authority.
CLI Help v1 to v2 typo guidance
Global help and successful scoped help bytes are unchanged. An unknown command
that has one unique nearby name in the capability-visible static catalog now
adds a did you mean suffix naming that candidate to stderr. Unrelated,
ambiguous, non-ASCII, and
over-limit names keep the v1 diagnostic. Scripts that intentionally snapshot a
near-miss diagnostic should accept the v2 suffix; status remains 2 and the
capability-appropriate global help remains on stdout.
CLI Help v2 to v3 known-command recovery
A capability-visible known command that rejects its invocation with status 2
now appends a stderr hint directing the user to <command> --help. Existing
diagnostic text and status are unchanged. Unknown and hidden commands, empty
invocations, and malformed help-flag placement retain their v2 bytes. Scripts
that snapshot known-command usage errors should accept the added final line.
Human diagnostic source locations
Human-readable diagnostics that carry a source path now render
path:line:column instead of only line:column. Pathless diagnostics are
unchanged, and --json output is unchanged. Terminal-output snapshots should
accept the added path; tools should continue consuming JSON rather than parsing
the human representation.
Graph-v6 CLI context to agent-context v1
semaprax context now emits semaprax.agent-context.v1 instead of a Graph-v6
context view. Consumers must check schema, honor byte/node budgets,
truncation reasons, omitted counts, and resume frontiers, and must not interpret
unavailable target/diagnostic/test filters as empty facts. The legacy Rust
graph::context_json(program, symbol, depth) API is unchanged; new Rust
consumers use graph::agent_context_json with AgentContextOptions. There is
no schema negotiation or silent fallback.
Agent Context v1 to v2 directional queries
Agent Context v1 remains the exact CLI and Rust API default. An explicit
--direction forward|reverse|both selects semaprax.agent-context.v2; Rust
consumers use AgentContextV2Options and agent_context_v2_json. Consumers
must bind replay to the query direction and treat frontier as omitted
selected-direction traversal nodes while treating reference_frontier as
referenced non-selected relation targets. Reference closure is not a
truncation reason and does not contribute to traversal omitted/deferred counts.
V2 retains the v1 byte, node, depth, filter, and fail-closed limits. It reports
the same program-selected Graph v10/v11/v12/v13/v14 schema and changes no Graph
bytes, source revision, HIR, or CleanupPlan. Frozen SHA-256 KATs are forward
922404133444942ab86607772362098e0f5656add6bea607a890be2bcfe5b7c9,
reverse 9a2ebfe569926e67f436379cf2b5c96d510daadd11d0a295ed54903cb612627b,
and both 4ec8a62a17551e87dc301d08f0a09c6159445757bca6dd9920a7db4e3790ce17.
V1 golden preservation and v2 execution are hosted green in run 31397881268,
Ubuntu job
93485198327.
V2 is not general impact analysis or a reverse index for non-call semantics.
Semantic Patch v1 to v2
Schema-less patches retain the exact v1 parser and operation domain: one
revision base, explicit function/resource renames, and require no-new-effects. The first non-comment line schema semaprax.semantic-patch.v2 opts into persistent record/case-member and
variant-case renames plus exact addressed i64/bool generic-call
type-argument replacement. V2 rejects schema placement confusion, duplicate or
overlapping selectors, automatic/compiler-owned identities, stale call tuples,
and any post-HIR semantic delta outside the selected identities. Pattern
shorthand expands its label while preserving the original binding, ValueId,
and Place root.
V2 does not migrate Graph or CleanupPlan: the program-selected Graph v10/v11/v12/v13/v14 schema and CleanupPlan v2/v3 remain authoritative. It also does not authenticate patch-file path/content provenance, add multi-file commit, or open general type, shape, generic-composition, repair, or impact operations. The frozen mixed-transaction post-edit revision and old/new function-instance KATs remain recorded in the v2 contract.
The implementation commit b92ce68 did not have a green hosted matrix: run
31400888352 was
cancelled after its isolated Wasmtime job failed on stale runtime-lock state.
Commit f95d243 reconciled that lock. Attempt 1 of its workflow was cancelled
and is not evidence; the exact head's run 31401200449 attempt
2 is
terminal green, including Ubuntu job
93505622044
and Wasmtime job
93505622110.
Semantic Patch to read-only Impact v1
semaprax impact <file> <patch.spatch> is an additive preview command. It
accepts the existing schema-less Patch v1 and explicit Patch v2 grammars and
does not alter either transaction format. Consumers must inspect report schema
semaprax.semantic-impact.v1, bind the source base/candidate revisions and
patch schema/digest, preserve operation and change indices, and honor exact
byte/node/depth truncation plus frontier and omitted/deferred counts.
The preview rechecks its source snapshot but performs no A0 lock, staging, or
commit. Its patch digest authenticates the exact bytes read once into the
preview, not the continuing patch path; provenance-sensitive callers must
authenticate that input externally. Rename source consumers are projection
facts, while only exact generic-call instance changes seed finite reverse-call
impact over explicit persistent callables. Automatic behavioral callers fail
closed as SPX-G110, and existing generic-function limits continue to report
SPX-T226. This is not a migration to repository-wide or general non-call
impact. The canonical report KAT is recorded in the Impact v1
contract. Its exact 1b3731a full matrix is hosted
green in run 31408654657 attempt
2,
including Ubuntu job
93530141404.
SPX-S103 to Diagnostic Repair v1 and isolated Semantic Patch v3
Existing SPX-S103 diagnostics remain unchanged. The additive command
semaprax repairs <file> assign-function-id <automatic-function-id> now
returns canonical semaprax.diagnostic-repair.v1 JSON for one eligible
automatic function in the closed acyclic scalar Graph-v10 domain. The additive
command semaprax repair <file> <repair-id> --persistent-id <persistent-id>
returns canonical semaprax.diagnostic-repair-preview.v1 JSON after
independently proving the exact one-annotation candidate. Both commands are
read-only.
The preview contains an exact three-line LF-terminated
semaprax.semantic-patch.v3 file with one assign-function-id operation.
Unlike the query and instantiation commands, semaprax patch may apply that
v3 file: it reauthenticates the revision-bound repair ID, diagnostic, target,
name, closed persistent ID, reduced program domain, and complete candidate
identity rebase, then uses unchanged A0. V3 is isolated from schema-less v1 and
explicit v2; it composes with neither grammar and admits no other operation.
Semantic Impact v1 remains a Patch v1/v2 preview and rejects every
syntactically valid, canonical v3 as SPX-G110 before semantic selector
interpretation. Malformed or noncanonical v3 remains SPX-G101.
The operation classification is exactly breaking_identity_rebase. Consumers
must not treat it as a stable-ID-preserving rename: the automatic function ID
and every revision-scoped identity below the selected function intentionally
change, while direct callers change their callee reference. Graph-v10 revision
and identity-bearing content therefore change, and identity-bearing CleanupPlan
content may rebase. No Graph or CleanupPlan schema/version or semantic shape is
widened, Graph v11-v14 is not admitted for repair, and backend/runtime semantics
do not change. The exact schemas,
key/line order, domains, KATs, limits, and nonclaims are frozen in
DIAGNOSTIC-REPAIR-V1.md. Local Phase A integration
is 13/13; the Phase B semantic integration corpus is 7/7; v3 A0 hook units are
4/4; aggregate v3 integration-plus-hook evidence is 9/9; and library 404/404,
full-preservation, and security gates are green. The exact dae957a full
matrix is hosted green in run 31418476217 attempt
1,
including Ubuntu job
93553147265;
all 12 jobs passed.
V3 additionally runs function/call-site bounds on parsed AST before HIR and
caps its initial A0 source read plus both final rechecks at 16 MiB. Initial
oversize fails SPX-R101; concurrent final growth past the bound fails
SPX-I207 without replacing the grown source. Patch v1/v2 reads are unchanged.
Patch and repair evidence to Semantic Review v1
semaprax review <file> <patch.spatch> is an additive, fixed-arity read-only
command. It changes no Patch v1/v2/v3 grammar, Impact v1 report, Diagnostic
Repair report, Graph schema, CleanupPlan schema, or A0 behavior. Consumers must
select the new top-level schema semaprax.semantic-review.v1 and preserve its
exact seven sections keys in wire order:
behavior, api_identity, security_authority, memory_ownership,
target_artifact, migration, unsafe
These fields map to RFC 0001's conceptual behavior, API, security, memory,
target, migration, and unsafe-code categories without renaming the wire keys.
Patch v1/v2 evidence has kind = semantic_impact_v1 and embeds one complete,
nontruncated canonical Impact v1 report produced under the Review contract's
fixed limits. The sole canonical Patch v3 evidence instead has
kind = identity_rebase_v1, embeds the exact shared repair identity rebase,
and contains no Impact report key. Impact v1 remains v1/v2-only and retains
its canonical-v3 SPX-G110 behavior.
Review has no flags, Context request, target/test execution, public verifier,
proof artifact, authenticated patch provenance, approval policy/UI, or
lock/stage/apply/commit authority. The three exact report KATs and all limits,
digests, key order, dispositions, findings, and nonclaims are frozen in
SEMANTIC-REVIEW-V1.md. Local Review integration is
10/10, hook/limit units are 4/4, library 408/408, full preservation and security
gates are green. The exact 2634011f3d205077d4533701e412bec8fdcff7c8 full
matrix is hosted green in run 31423743369 attempt
1,
including Ubuntu job
93570423170;
all 12 jobs passed.
Semantic Review artifacts to Semantic Patch Evidence v1
semaprax patch-evidence <file> <patch.spatch> and
semaprax verify-patch-evidence <file> <patch.spatch> <evidence.json> are
additive fixed-arity generation and independent-replay commands. Consumers
must select semaprax.semantic-patch-evidence.v1 or
semaprax.semantic-patch-evidence-verification.v1; a Review report is neither
schema and cannot be substituted. Review remains byte-for-byte unchanged,
retains its KATs and no_public_verify_api_or_proof_artifact nonclaim, exposes
only read-only review::preview, and adds no review::verify. Evidence v1 is
a separate artifact that domain-digest-binds the independently rebuilt Review.
semaprax patch-with-evidence <file> <patch.spatch> <evidence.json> is the
new opt-in application route. It acquires the ordinary A0 lock before input
reads, requires exact evidence replay before creating a stage, and
then uses unchanged A0. Existing semaprax patch behavior and Patch v1/v2/v3
grammars are unchanged and remain evidence-optional. A capsule is therefore
not continuing provenance, commit authority, or a reusable authorization
token.
Patch v1/v2 capsules bind complete nontruncated Impact v1 evidence; the sole
canonical Patch v3 capsule binds the shared identity-rebase object and does
not widen Impact. Exact key order, digest domains, KATs, bounds, diagnostics,
and nonclaims are frozen in
SEMANTIC-PATCH-EVIDENCE-V1.md. Local A+B
evidence is 11/11 integration plus 5/5 internal units; Phase C is 16/16
integration plus 11/11 hook/limit units; library 420/420, doctest 37/37, full
preservation, and security are green. The exact
34a8ed82e9ae96277aa51e7994c19644331f5e78 replacement matrix is hosted green
in run
31431768632,
including Ubuntu job
93596706949;
all 12 jobs passed. The earlier e04c2c9 run failed only the Rust 1.97 lint
and is not green evidence.
Evidence v1 to Target Evidence v1 and Patch Evidence v2
No v1 artifact or command migrates implicitly. Existing Evidence v1 capsule
and receipt bytes, KATs, APIs, and commands remain frozen. Consumers opt into
target-evidence for semaprax.semantic-target-evidence.v1, or the suffixed
patch-evidence-v2, verify-patch-evidence-v2, and
patch-with-evidence-v2 commands for the additive v2 schemas.
Evidence v2 adds one independently rebuilt target-report binding and overlays
Review only with exact zero security_authority delta and digest-based
target_artifact; Patch v3 is change_proven. These are input reads and
replay work, not authority. Reports/capsules contain no execution or project-
test result. Evidence-v2 capsules remain single-file; they do not migrate into
the separate managed workspace protocol, and 38 Partial/18 Missing is
unchanged. The exact fcdf3861d79faea27c526a8dc5105b92c6738213
matrix is hosted green in run
31440359793,
including Ubuntu job
93624123631;
all 12 jobs passed.
Raw source and single-file patch workflows to Workspace Transaction v1
There is no implicit migration. Existing .spx files, Semantic Patch
v1/v2/v3, A0, Review, Impact, Repair, Target Evidence, and Patch Evidence
artifacts and commands remain byte-, API-, and behavior-compatible. A consumer
opts into Semantic Workspace Transaction
v1 by authoring the exact sorted
semaprax.workspace-path-set.v1 for 2–16 pre-existing canonical sources and
running workspace-init once.
Initialization copies authenticated canonical sources into immutable managed
generation zero and publishes the first ACTIVE; it does not modify or delete
the original sources. Thereafter a cooperating reader must acquire the
permanent shared .semaprax-workspace/LOCK, authenticate the canonical
ACTIVE, and resolve that exact immutable generation. A writer uses
workspace-preview for the read-only projection and workspace-apply for the
exclusive-lock candidate-generation and ACTIVE-pivot route. Workspace patch
entries embed existing admitted single-file patches; they are not converted
Evidence capsules or a new cross-file repair language.
Do not migrate a raw-path/Git/editor reader by merely pointing it at the
workspace root. Original paths are not flat-materialized or atomically
rewritten. A reader that needs managed old-or-new visibility must implement the
locked ACTIVE resolution contract. Staging and unselected generations can be
retained after failure and count against exact limits. V1 has no automatic
rollback, recovery, cleanup, or garbage collection; operators must preserve
the authenticated tree until a future maintenance protocol defines those
actions. Power-loss, network/NFS/overlay, ACL/xattr/ADS, repository Graph, and
external-consumer compatibility are not implied.
Local integration 12/12, hostile wire/CLI 5/5, workspace units 37/37, library
482/482, full preservation, and security are green. The exact
afde3b3302e0f88fd8af3278efaf0ddd72e6dfe7 matrix is hosted green in run
31472847068,
including Ubuntu job
93719800613
and Windows job
93719800611;
all 12 jobs passed. Earlier run 31471716036 on 4daa407 failed only Windows
strict Clippy and is not green evidence. The completion ledger remains 38
Partial/18 Missing.
Workspace Transaction v1 to Workspace Patch Evidence v1
There is no implicit migration. Existing Workspace path-set, root, manifest,
snapshot, preview, Patch, initialization, and ordinary apply bytes, APIs,
commands, KATs, and authority boundaries remain unchanged. A consumer opts
into Semantic Workspace Patch Evidence
v1 by generating the separate
semaprax.semantic-workspace-patch-evidence.v1 capsule, retaining the exact
Workspace Patch bytes, and using verify-workspace-patch-evidence or
workspace-apply-with-evidence explicitly.
The outer capsule binds each changed path's independently rebuilt Semantic
Patch Evidence v1 facts by digest. It does not convert, embed, or widen a child
capsule; the child's no_multi_file_transaction remains exact. There is no
automatic upgrade to Target Evidence or Patch Evidence v2, no repository or
cross-file Impact/Review reasoning, and no migration of raw files, Git,
editors, or other noncooperating readers into the managed publication model.
Capsule and receipt are evidence, not authorization. The apply command takes
the exclusive permanent lock first, treats submitted evidence as immutable
owned untrusted bytes, requires exact typed and byte replay before candidate
or staging creation, and only then uses the existing live Workspace authority.
Operators must retain the original Workspace recovery/inventory rules: no
automatic rollback, cleanup, GC, raw-tree materialization, or power-loss/
network/ACL compatibility follows. Local gates are green. The exact
cda4892ee74100fd11c5161ad857d469ec5e5421 matrix is hosted green in run
31491573287, with
all 12 jobs passing. Completion remains 38 Partial/18 Missing.
Ordinary Workspace to Semantic Workspace and Change v1
There is no in-place schema reinterpretation. Ordinary Workspace v1 and
Semantic Workspace v1 share .semaprax-workspace and its permanent lock, but
their path-set, ACTIVE, and manifest schemas are disjoint. Create a fresh
semantic workspace explicitly with semantic-workspace-init; existing
ordinary Workspace bytes, commands, patches, evidence, and rejection behavior
remain unchanged.
A semantic consumer reads the selected generation through workspace-graph,
workspace-context, workspace-impact, or workspace-review. These routes
hold the shared lock through one unified build, render, final authentication,
and checked unlock. They inspect managed generation bytes, not the original
source paths. Pointing Git, an editor, a compiler, or another raw-path tool at
the root does not migrate it to the cooperative ACTIVE protocol.
Semantic Workspace Change v1 is opt-in and replacements-only. Generate a
canonical proposal and Evidence, then use
verify-semantic-workspace-change-evidence for a non-authorizing exact-replay
receipt. Apply accepts the proposal and Evidence—not the verification
receipt—and replays them again under a fresh exclusive lock before candidate
or staging creation. It cannot create, delete, move, or alter the managed path
set, and it never rewrites the original source projection.
Preserve bounded candidate and staging residue after failure. A pre-pivot
attempt can publish an inert candidate or staged pointer while leaving old
ACTIVE selected. Because that inventory is authenticated, Evidence from the
earlier state must then fail SPX-G187; regenerate Evidence against the new
state before exact reuse. Do not infer rollback, cleanup, GC, strategy parity,
raw-tree atomicity, or durability from either receipt. Process-termination
tests establish OS lock release and old/new managed state only; they are not
power-loss or reboot recovery evidence.
Semantic Workspace Operations v1 is additive and requires no migration of
Semantic Workspace or Change-v1 bytes. Consumers opt in through
semantic-workspace-operations-derive or
semantic-workspace-operations-change-proposal; the latter output is an exact
ordinary Change-v1 proposal. Existing Change-v1 Evidence may subsequently bind
those derived Change bytes, but it does not bind or authorize the Operations
proposal or intent. Consumers that require that binding opt in to the additive
Operations Evidence schema and its verify/apply commands. No old derivation or
Change-v1 Evidence is silently upgraded, no receipt is an apply token, and
there is no schema negotiation or fallback.
The exact dfc04278c6ba9a7dd247d4cc4add3af91f55b936 matrix is hosted green in
run 31570834457;
all 12 jobs passed, including the Operations process-termination gate on
Ubuntu, macOS, and Windows. Totals remain 38 Partial/18 Missing.
Persistent identities are NUL-free
Persistent semantic identities and logical import keys may not contain a literal NUL byte. Source validation reports the declaration-specific stable diagnostic before resolution or graph serialization; \0 remains an unsupported source-string escape. Public consumers of transformed resolved HIR must likewise reject NUL in declaration IDs, types, expressions, places, call/record/field references, and attached cleanup inventory or plan metadata before code generation or serialization. Regenerate or rename any pre-alpha fixture that constructed such an identity directly.
Semantic graph v1 to v2
Graph v2 adds:
- top-level declaration/expression identity policy;
- deterministic revision-scoped structural nodes for function bodies and local bindings;
requires_graphandensures_graphexpression structures;- contract calls in function call dependencies and bounded context traversal.
The existing textual requires and ensures arrays remain during this migration. A v1-only consumer should reject semaprax.graph.v2 explicitly. A compatible consumer may continue reading declaration IDs, names, signatures, effects, contracts, and calls while progressively adopting the new structural fields.
Semantic graph v2 to v3
Graph v3 is a breaking migration from parsed syntax to validated resolved HIR:
- public Rust APIs
graph::to_jsonandgraph::context_jsonare fallible and return verification/HIR diagnostics instead of producing an unchecked graph; - top-level
entrypointis a declaration ID andviewdistinguishes complete module graphs from bounded context slices; - context views report their declaration-ID
root, requesteddepth,truncatedstate, and sorted dependencyfrontier; - declaration nodes expose
identity_originandpersistent, because only explicit@ididentities survive renames; - parameters, local bindings, places, and function results use resolved value IDs; calls and dependency arrays use resolved declaration IDs rather than display names;
callsis a sorted, de-duplicated dependency set; individual call occurrences remain in contract and body expression trees;- expressions expose resolved
type_idandownership_mode;ownership_modeis a boundary mode, not flow-sensitive availability state; i64literalvaluefields are decimal strings, preserving the full signed 64-bit domain in JavaScript/TypeScript consumers;letstatements carry their binding's value ID only insidebinding; statements do not claim a separate identity until a dedicated statement-ID domain exists;- top-level
type_factsentries are keyed by the resolved type identity and carry resolved type structure plus copy, resource containment, size, drop, and layout facts; - context output includes only selected functions and their referenced nominal type declarations rather than every resource in the module;
- textual
requiresandensuresarrays are removed;requires_graphandensures_graphare authoritative structured contracts; - HIR spans are omitted because the canonical source revision is whitespace-insensitive while source positions are not.
The revision remains derived from the canonical human-readable source projection; graph wire-format changes alone do not alter it. A v2 consumer must reject semaprax.graph.v3 until it supports the new type/value identity tables and fallible API. Exact v3 module fixtures live in tests/snapshots/meaning.graph.json and tests/snapshots/control_flow.graph.json.
Semantic graph v3 to v4
Graph v4 adds the first algebraic-data declarations and expressions:
- record declarations are
recordnodes whose orderedfieldsarray contains stable field declaration IDs; - every field is a separate
fieldnode with its stable ID, display name, explicit/automatic identity origin, persistence flag, owner record ID, declaration-orderindex, and resolvedtype_id; - record construction expressions use
kind: "construct_record", a stable record declaration ID, and source-ordered initializer entries containing stable field IDs and values; - projection expressions and place projections use stable field IDs rather than display names;
- context slices close transitively over nominal record types referenced by selected functions and over the nominal types of their fields;
- the type-facts table includes every field type required by selected record declarations;
- validated-HIR and graph reference checks fail closed before an unresolved or foreign record/field reference can be serialized.
The SHA-256 revision contract is unchanged. A v3 consumer must reject semaprax.graph.v4 until it understands record/field nodes and record expression kinds.
Semantic graph v4 to v5 and explicit resource lifecycles
Graph v5 adds persistent resource-lifecycle, interface, and logical-import declarations. Resource nodes now reference a resource_drop node. Imported drop nodes reference an import node and target-neutral import_key; interface nodes expose their authority ceiling and import IDs; import nodes serialize parameter ownership, consumption on failure, unit-result publication rules, effects, required authority, and normalized failure contracts. Context slices close a referenced resource through its lifecycle, complete owning interface, import signatures, and their nominal types.
The initial source grammar deliberately uses an import's explicit @id as its v1 logical import key while resolved HIR stores import_id and import_key separately. This is a versioned source projection choice, not a permanent conflation of conceptual identity and target binding keys.
Rust API consumers must update exhaustive matches and construction code:
Programaddsinterfaces: Vec<InterfaceDeclaration>;TypeDeclarationKind::ResourcebecomesResource { lifecycles: Vec<ResourceLifecycleDeclaration> };- the parsed AST adds resource lifecycle kind/declaration, interface/import declaration, and import-failure types;
ResolvedProgramadds resolved interfaces;- resolved resource declarations carry
ResolvedResourceDropand its strategy; - resolved HIR adds interface/import parameter, unit-result publication, authority, and normalized-failure structures;
DeclarationKindaddsResourceDrop,Interface, andImport.
Legacy resource Name; still parses so check can report SPX-O112, but it is no longer a valid resource declaration. Migration requires an explicit, persistent lifecycle ID and an authored choice:
@id("token.type")
resource Token {
@id("token.type.drop")
drop trivial;
}
or a complete drop import plus interface/import contract. Formatting never invents drop trivial; it is an audited semantic assertion. Phase 1 by itself did not execute cleanup: native resource builds still retain SPX-B104, and Wasm retains SPX-W111 for every shape outside the later, separately versioned narrow owned ABI.
The SHA-256 algorithm and domain separator are unchanged, but migrated canonical source receives a new revision as expected. A v4 consumer must reject semaprax.graph.v5. The former exact v5 fixtures were superseded by the Graph v6 cleanup-plan migration below.
Rust HIR cleanup inventory
ResolvedFunction now carries a mandatory cleanup: CleanupInventory. Direct Rust consumers that construct or transform resolved HIR must preserve the exact inventory or rerun source resolution; hir::validate, native lowering, and Wasm lowering reject a missing or stale inventory with SPX-H006 before any target feature gate.
The inventory schema is semaprax.cleanup-inventory.v1. It catalogs canonical storage candidates for owned non-copy parameters, droppable local bindings, owned-producing expression temporaries, and droppable provisional results. Recursive shapes retain declaration-ordered field IDs, and every resource leaf has an exact projected place, lifecycle ID, and distinct liveness-flag identity. Entry state lists only owned droppable parameters. discovery_index is deterministic structural discovery order, not runtime initialization or finalization order.
The inventory remains a structural Rust HIR boundary. It does not itself contain CFG edges, path-sensitive liveness, transfers, call commits, status sources, cleanup regions/exits, finalization order, result publication, or a backend trace. Those facts now live in the separately versioned plan below.
Graph v5 to v6 and Rust HIR cleanup plans
ResolvedFunction now also carries mandatory cleanup_plan: CleanupPlan using schema semaprax.cleanup-plan.v1. Direct Rust consumers that construct or transform resolved HIR must rerun source resolution or preserve the exact canonical plan. Validation first checks core HIR, then rebuilds CleanupInventory, then rebuilds the plan without consulting the attached plan; any mismatch is SPX-H006 before native or Wasm lowering.
Graph v6 embeds the complete plan under each selected function's cleanup member. It adds tagged storage/place, recursive liveness shapes, status sources and stable arithmetic codes, transitions, blocks, edges, regions, guarded finalizers, exits, and scalar/owned result commits. Arrays are already in canonical semantic order and consumers must not sort them. Context slices include complete plans for selected functions without unrelated functions.
The canonical source revision algorithm and domain separator are unchanged. The same source can therefore have the same revision in Graph v5 and v6 while the graph payload differs; caches and protocol negotiation must key by (graph schema, revision). A v5 consumer must reject semaprax.graph.v6. Exact v6 scalar, control-flow, record, and lifecycle snapshots replace the v5 fixtures.
Graph v6 to v7 and executable record updates
Graph v7 adds the resolved update_record expression. Its base edge is
serialized before its authored fields vector; every replacement entry carries
the persistent field declaration ID and its value edge. Producers must preserve
replacement order because evaluation consumes the complete base first and then
evaluates replacements left-to-right. Consumers must not resolve fields from
display names or sort replacement entries.
The source revision algorithm is unchanged. Consequently identical source that
does not use record update can have the same revision under Graph v6 and v7,
while the graph payload and agent-context source_graph_schema differ. Cache
and protocol keys must include the exact graph schema. A v6 consumer must reject
semaprax.graph.v7, and a v7 consumer must reject semaprax.graph.v6; neither
may silently reinterpret an unknown expression kind. Agent Context v1 remains
the context-envelope schema and now declares semaprax.graph.v7 as its source.
Graph v7 to v8 and executable copy variants
Graph v8 adds persistent variant, variant_case, and variant payload-field
declarations plus revision-scoped construct_variant, match, match_arm,
variant-pattern, wildcard-pattern, and arm-local payload-binding structure.
Case and payload vectors remain declaration ordered. Match-arm vectors remain
authored ordered. CleanupPlan v1 keeps its schema identity while adding the
closed variant_case edge condition, which binds one scrutinee expression ID,
one stable case declaration ID, and a boolean match polarity. Producers and
consumers must not substitute display names, numeric tags, or boolean-result
edges for this meaning.
The source-revision algorithm remains unchanged, so identical source without
variants may retain its revision while the graph payload changes. Cache and
protocol keys must include the exact schema. A v7 consumer must reject
semaprax.graph.v8; a v8 consumer must reject semaprax.graph.v7 and every
unknown declaration, expression, pattern, or edge kind. Agent Context v1 keeps
its envelope schema but now declares semaprax.graph.v8 as its
source_graph_schema. Graph v8 does not imply generic variants, Option,
Result, ?, resource-bearing payloads, ownership-aware matching, a stable
public ABI, callable/component aggregate support, or public resource admission.
Graph v8 to v9, revision v2, and the ordinary prelude
Graph v9 adds owner/index-stable generic type parameters, exact ordered nominal
argument trees, compiler-owned declaration provenance, and the authenticated
semaprax.prelude.v1 contract. The ordinary compiler-owned Option<T> and
Result<T, E> declarations, cases, and payload fields use persistent reserved
IDs. Authored source must not redeclare their names or IDs, and consumers must
not reinterpret them as backend intrinsics or user declarations.
Graph revision v2 uses the domain semaprax.graph-revision.v2\0 and
length-delimits canonical source, prelude schema, and exact prelude contract
bytes. Therefore even source that does not mention generic variants can receive
a different revision from the v1 algorithm. A prelude-contract change cannot
silently retain an old semantic revision. Cache and protocol keys must include
the exact graph schema and revision; consumers that persist compiler-owned
facts should also authenticate the prelude schema/digest carried by Graph v9.
A v8 consumer must reject semaprax.graph.v9; a v9 consumer must reject
semaprax.graph.v8, an unknown prelude schema/digest, malformed type-parameter
identity, and every unsupported argument tree. Agent Context v1 retains its
envelope schema and now declares semaprax.graph.v9 as its
source_graph_schema, including referenced compiler-owned prelude declarations
only when the bounded context closes over them. Graph v9 does not imply generic
functions or records, nested/resource arguments, ?, non-copy matching, a
stable public aggregate ABI, callable/component aggregate support, or public
resource admission.
Graph v9 to v10 and CleanupPlan v1 to v2
Graph v10 adds revision-scoped try_result meaning for the bounded ordinary
Result<T, E> postfix-? slice. Each node authenticates the exact source and
outer concrete instances, compiler-owned Result/Ok/Err case and field IDs,
one operand evaluation, an Err exit classified as a normal result rather
than a physical failure, and the shared postcondition epilogue. A v9 consumer
must reject semaprax.graph.v10; a v10 consumer must reject v9, unknown Try
fields, and rehashed substitutions of any authenticated ID, instance, exit, or
epilogue meaning. Agent Context v1 retains its envelope schema and now reports
semaprax.graph.v10 as source_graph_schema.
CleanupPlan v2 adds StageCopyResult with two closed producers: the ordinary
body expression and an authenticated Try residual. A Try residual binds the
Try and operand expression IDs, exact source and target Result instances,
and all compiler-owned Result member IDs. Exactly one producer reaches the
shared postcondition/publication join on each normal path. Physical operation
failure remains the pre-existing sticky status path and must never be repaired
or reclassified as semantic Err. Consumers must reject v1 as missing the
staging contract, reject unknown producer kinds, and reject missing, duplicate,
wrong-instance, wrong-expression, or wrong-member staging before backend use.
This cleanup schema change does not broaden
semaprax.conformance-trace.v1; its reference executor authenticates staging
but still returns the stable unsupported-result boundary at terminal Copy
aggregate materialization. It also does not open resources, nested/non-copy
Result arguments, residual conversion, ? in contracts, public aggregate ABI,
or callable/component aggregate signatures. Historical Graph-v6/v7/v8/v9 and
CleanupPlan-v1 text above remains the migration record, not current schema
truth.
Graph v10/v11 to v12 for generic Copy records
Graph schema selection is now a program-wide ordered lattice. A validated
program containing any generic record declaration emits
semaprax.graph.v12; otherwise authenticated Option propagation emits v11;
otherwise legacy and Result-only programs remain byte-compatible v10. Every
Agent Context v1 envelope reports the same program-level source schema even
when its root or selected facts do not reference the declaration that caused
the upgrade. Consumers must reject relabeling between v10, v11, and v12.
V12 generic record declaration nodes carry ordered owner/index-stable type
parameters and type_id: null, because an empty concrete instance does not
exist. Generic record constructors retain their exact expression type ID and
add the structured concrete nominal record type with ordered direct
i64/bool arguments. Field IDs remain template-stable and field template
types retain owner/index identity. Programs without generic record
declarations preserve their prior v10/v11 bytes and KATs.
CleanupPlan does not migrate for this tranche: admitted generic records are resource-free Copy values, so canonical v2 (or v3 when Option propagation is independently present) remains sufficient and introduces no generic-record slot/action. This migration does not open generic functions/inference, nested/resource/non-Copy arguments or fields, public aggregate/callable/FFI ABI, or resource admission.
Graph v12 to v13 for irrefutable Copy-record patterns
Graph schema selection adds a higher program-wide branch. A validated program
containing any authenticated explicit record pattern emits
semaprax.graph.v13; otherwise a generic record declaration selects v12,
Option propagation selects v11, and legacy or Result-only programs remain v10.
Every Agent Context v1 envelope reports that same program-level source schema,
even when its selected root does not reach the pattern. A top-level wildcard
record arm creates no bindings and does not by itself select v13. Consumers
must reject relabeling among v10, v11, v12, and v13.
V13 record-pattern nodes bind the exact concrete record instance, stable record
and field IDs, declaration-ordered field entries, recursive nested patterns,
and canonical binding IDs and types. The bounded source form is irrefutable and
has exactly one arm: every record field appears once and contains a binding,
_, or another exact record pattern. A binding may receive an entire
resource-free Copy-record field by value. The scrutinee is evaluated once and
the arm result remains scalar i64/bool.
CleanupPlan does not migrate for this tranche. Record destructuring is
straight-line projection over an admitted Copy value, so it adds no storage
slot, transition, status source, cleanup action, or VariantCase edge;
canonical v2 remains sufficient, or v3 when Option propagation is independently
present. Programs without an explicit record pattern preserve their prior
v10/v11/v12 graph bytes and known answers. This migration does not open
refutable or literal patterns, guards, or-patterns, rest patterns, nested
variant patterns,
ownership modes, resource/non-Copy matching, aggregate-valued arm results,
generic functions/inference, or public aggregate/callable/FFI ABI.
Graph v13 to v14 for bounded generic Copy functions
Any validated generic function declaration selects semaprax.graph.v14,
including an unused template; otherwise explicit record patterns select v13,
generic records v12, Option propagation v11, and legacy/Result programs v10.
Every legacy and Agent Context root reports that same program-wide source
schema, and consumers must reject relabeling among v10-v14.
V14 adds exact function_template, function_instance, and call_instance
meaning. A same-schema v14 correction adds the previously missing array
delimiters around function-template type_parameters; two-parameter templates
previously produced invalid JSON in module, bounded-context, and Agent Context
projections. Template parameters still retain owner/index identity. A nonpersistent
concrete instance derives from the template declaration ID plus exact ordered
i64/bool arguments, and its domain-separated execution identity scopes
values and expressions. Only explicitly referenced instances are serialized
and lowered. An unused template is checked over every direct-scalar
substitution and selects v14 without fabricating an instance. Because the
schema name remains v14 while the corrected canonical bytes change, consumers
must migrate to these frozen SHA-256 KATs:
module: 7a61fa6229f2db7aca6a035fd961720e8a401c138cc66c9cd71c64d45bed5efd
Agent Context: 2841401e7ba85fa8e47b3c35a15ae401b4a271d2500d70bbf3627f1453869eb6
context: d7bda2be1fc366195ffb00a9e20b2b03204b4dd6f46e8019842dd84f70b54ab8
These corrected projections are parse-verified locally and hosted green in run 31390043736, Ubuntu job 93459346296. The earlier generic execution run 31385406865, Ubuntu job 93445428338 predates this serializer correction and remains separate backend evidence.
CleanupPlan does not migrate: canonical v2 remains byte/schema/meaning unchanged and propagated-call status producers retain the persistent template ID. Exact instance authentication belongs to validated HIR and Graph v14. Programs without a generic function preserve prior v10-v13 bytes and known answers. This migration opens no inference, constraints, aggregate/resource/ non-Copy signatures, generic-to-generic calls, recursion, effects, generic entrypoint, callable/resource/component admission, stable ABI, or CleanupPlan v4 claim. The separately gated exact private Component v9 profile does not broaden that Graph migration into general/public Component admission.
Graph v24 to v25 for native Rust import declarations
Any program declaring an import rust fn selects semaprax.graph.v25. The
selection predicate reads declarations rather than call sites, so a declared
but uncalled import still selects the schema that can represent its result
type. No earlier schema can represent such a declaration, so every program
without one keeps the schema it already selected and its previously emitted
bytes; the golden snapshots and every frozen digest are unchanged. Consumers
must inspect the declared schema field rather than assume the v10-v24
lattice, and must not relabel a v25 projection as an earlier schema.
The module Graph projects the declaration with its real result type: an import
node's result.type was previously always "unit" and now carries the
declared unit, i64, or bool spelling, which is unchanged for the
ordinary unit-result imports of every earlier schema. Only v25 appends the
additive native_rust boolean marker to an import node; earlier schemas close
the node exactly as before. A call projects as a native_rust_import_call
node carrying the import identity, result type, and arguments, mirroring the
existing host_command_call shape. ResolvedType::Unit gains a projection
because a unit-result import can now reach it, and the workspace and Project
graphs represent these declarations as well.
The projections that omit import nodes by construction stay closed and say so
with SPX-G218: agent context, review, impact, and target evidence would drop
authenticated meaning rather than represent it. Patch and evidence flows are
unchanged and remain fail-closed, because their verifiers authenticate only
semaprax.graph.v10-v14; v25 is outside that admission like every schema
above v14. This migration adds no CleanupPlan schema, admitted WebAssembly or
callable target, or public ABI. WebAssembly still rejects native Rust imports
(SPX-W114) and ordinary callable routes remain closed by SPX-B104.
Internal variant-layout digest v1 to v2
The compiler-internal Native64/Wasm32 variant-layout digest now uses the exact
domain semaprax.variant-layout.v2\0. Its authenticated preimage adds the full
concrete nominal instance identity plus each payload field's template and
substituted type identities. This prevents two instantiations that share the
same persistent variant/case/field declarations from sharing layout evidence.
Cached v1 digests and known answers are incompatible and must be regenerated;
consumers must not relabel a v1 digest as v2.
This migration changes only the internal evidence digest. Declaration-order
u32 tags, target-specific size/alignment/offset rules, the one-byte empty
payload policy, and emitted physical representations are unchanged. Neither
digest version is a stable public aggregate ABI, and v2 does not open public
aggregate signatures, resource-bearing variants, or callable/component
admission.
Normalized status v1 and conformance trace v1
This release introduces two independent public protocol schemas:
semaprax.status.v1is the target-neutral normalized failure record stored behind a context-local ABI token. It fixes the requiredschema, 1–255-byte UTF-8domain_idwithout NUL, nonzerocode,class, and boolean-or-"unknown"retryablefields; compiler-owned contract and arithmetic domains have exact versioned codes. The byte bound is normative for source, HIR, native, Wasm, and adapters. Token zero remains success and has no status record. A physical token, arena index, host exception, or opaque diagnostic detail is never part of status JSON.semaprax.conformance-trace.v1is the canonical semantic event envelope. It fixes resolved function/invocation identities, ordered cleanup places and projections, ownership transitions, atomic call commits, callable/finalizer import events, frame-localselect_failure, guarded finalization, result commits, and the terminal result/status outcome. Callable import completion may contain success or normalized failure. Finalizer import completion is a distinct success-only Rust variant even though both project to wire kindimport_endand are distinguished bysite.kind.
The exact JSON contract, event field order, status tables, examples, excluded physical fields, and outstanding validation requirements are documented in Conformance trace v1.
These are first-version protocols, not an in-place extension of an unversioned wire format. Consumers must inspect schema before reading any other semantic field. A status consumer must reject any schema other than semaprax.status.v1, an unknown class/retryability representation, an empty domain, or code zero. A trace consumer must reject any schema other than semaprax.conformance-trace.v1, every unknown event/site/result/outcome kind, and every required v1 field it cannot validate. In particular, consumers may not ignore select_failure, reinterpret a finalizer import_end as a fallible callable import, sort event/projection/argument vectors, accept physical target fields, or downgrade an unknown future schema to v1. Producers requiring a new event meaning, field meaning, status mapping, or incompatible encoding must publish a new schema rather than silently changing v1.
Trace data must also be bound out of band to the exact validated program, Graph schema/revision, cleanup plan, and scenario. A source revision alone is insufficient as a cache key because Graph and trace schemas can change without changing canonical source. Cache and negotiation keys must include at least the status schema, trace schema, Graph schema/revision, and scenario identity. A consumer must reject a trace whose referenced semantic IDs do not belong to that bound program and invocation path.
Implementation status remains deliberately bounded. Public normalized-status
types, compiler-owned mappings, a context-local status arena, public trace
types, deterministic canonical JSON, independent inventory/HIR coverage and
path-state replay, and a scenario-driven single-frame reference executor exist.
The new semaprax.semantic-event-dictionary.v1 projection assigns deterministic
nonzero ordinals to exact event shapes and fingerprints its complete canonical
JSON. Generated native callable C and the real narrow Wasm owned adapter emit
actual executed ordinals for the same authoritative 14-case corpus. The private
native loader/authority/ledger host now invokes those generated providers at
O0/O2; independent materialization proves exact reference/native-host/Wasm
traces and outcomes. Unknown or zero ordinals fail closed, and consumers may not
infer or repair events. Descriptor v2 additionally binds
semaprax.trace-path-certificate.v1, a canonical compiler-owned trie-DFA that
authenticates the complete ordinal sequence and terminal outcome before host
materialization.
That equality does not make the native resource backend publicly executable.
The ordinary compiler now exposes build-only preflight and a deterministic
hashed shared-library bundle for one explicitly selected direct-trivial owned
function; loading, invocation, adoption, and authority remain feature-gated,
and ordinary native execution still returns SPX-B104. General
physical/malformed-response fallback cleanup and quiescence, production
Android/iOS profiles, recursive callee execution, callable imports, imported finalizers,
aggregates, and broader control flow remain absent. The bounded Linux Rust-host
ASan lane is green in public job
93107277065.
Native resources, records, and every Wasm resource shape outside the documented
narrow slice remain fail closed.
The Linux dynamic-provider sanitizer job is green for all 14 O0/O2 ASan+UBSan generated-provider cases through the Rust host. It did not instrument the Rust host, and unrelated Clippy/GCC failures kept the overall workflow run red; it adds no Windows evidence.
The internal native invocation context and first-slice trace storage are now one-shot objects that require canonical C zero initialization before their initialization functions are called, for example struct spx_context context = {0};. This replaces the earlier accepted-but-indeterminate stack declaration form. Generated entry wrappers and repository probes have migrated. Embedders using SPX_NO_ENTRY_WRAPPER must zero-initialize context, trace-buffer, and trace-event storage; reinitialization or storage aliasing is rejected to preserve invocation isolation. This runtime scaffold remains private and does not lift native resource execution.
Rust AST resource declarations to nominal type declarations
The public pre-alpha Rust AST migration from the earlier graph v4 tranche represents both resources and records through Program::types: Vec<TypeDeclaration>. Program::resources is removed, and Type::Resource(String) becomes Type::Named(String) because a nominal reference may name either kind. Graph v5 further changes the resource variant as described above.
The lexer now tokenizes . separately so expression projection is unambiguous. Module names, capability/effect names, and named types still accept qualified identifiers through parser-specific IDENT ("." IDENT)* rules. Canonical formatting expands record initializer shorthand (Point { x } becomes Point { x: x }) and preserves initializer evaluation order.
This migration enables check, HIR, graph, and context for records. build fails closed with SPX-B103 (native) or SPX-W110 (Wasm) until aggregate layout and cleanup semantics land.
Whole-record to prefix-aware ownership
Resource-containing record projections now carry prefix-aware availability instead of conservatively moving the complete root. Moving one owned non-copy field leaves disjoint sibling fields available. Reusing that field or an enclosing parent reports SPX-O109; a place moved on only some control-flow paths reports SPX-O110. Existing whole-resource moves retain SPX-O101 and SPX-O107. Borrowed or shared projections cannot cross an owned field or parameter boundary and report SPX-O108. Validated HIR independently replays the same rules; Graph v6 additionally exposes the resulting cleanup-plan places, flags, transfers, and guarded exits.
Web manifest v2 to v3 and Wasm owned ABI v1
Browser packages now emit semaprax.web.v3. The existing module,
graph_revision, wasm, entry, and capabilities fields keep their v2
meanings and canonical order. Version 3 adds one required member:
{"owned_abi":{"schema":"semaprax.wasm-owned.v1","functions":[]}}
functions is in declaration order. Each admitted entry fixes its persistent
function, resource, and lifecycle IDs; deterministic semaprax_owned_N export;
source-parameter ABI kinds; and exact result kind. Scalar-only packages still
use web manifest v3 with an empty array. Consumers must not infer an owned ABI
from Wasm signatures or export spelling, and must reject an unknown
owned_abi.schema, a missing field,
an unknown parameter/result kind, or a mapping that disagrees with the module.
A v2-only consumer must reject v3; migration consists of validating the new
object before instantiation, not silently treating it as optional metadata.
semaprax.wasm-owned.v1 is narrower than RFC 0003 and the Component Model. It
admits one direct trivial-resource identity and a restricted direct body. Its
generated JavaScript facade binds invocation to the exact generated metadata,
uses branded one-shot trusted-adoption tickets, keeps ownership imports private,
authenticates the exact generated Wasm bytes with an embedded SHA-256 digest,
checks canonical argument encodings and aligned result ranges before commit,
and exposes normalized
semaprax.status.v1 records with the canonical domain_id field. Unsupported
resource shapes retain SPX-W111. A same-realm Symbol.for allocator
coordinates runtime tags across separately evaluated copies of the generated
host. The surrounding realm and that reserved global binding are trusted v1
host state; hostile pre-poisoning, cross-realm, and worker identity isolation
remain outside v1.
The adapter emits compiler-generated semantic event ordinals and the shared
14-case suite materializes them to exact reference/native-host/Wasm traces and
outcomes. The full owned-resource vertical
contract, Components, imports/finalizers,
broader shapes, public native execution/admission, and the remaining platform/fallback
evidence remain later gates.
Native adapter descriptor v1 to callable descriptor v2
Native adapter descriptor v1 remains descriptor-only and promises no callable
owner API. Callable admission uses a separate private SPXNABI2 wire rather
than extending or reinterpreting v1. Descriptor v2 binds twelve
independently domain-separated fingerprints, exact getter and callable symbols,
the required 0x0f call profile, request/response/event and dictionary bounds,
the complete ordered parameter signature, opaque-u64 owned payload kind,
and the exact result mapping. The event dictionary and trace-path certificate
are not embedded; their independent fingerprints are.
Private consumers must select a decoder from the eight-byte magic before
loading. They must never pass SPXNABI1 to callable admission, infer v2 fields
from a v1 function-template hash, accept unknown obligation bits, or repair
noncanonical fields. The compiler's staged encoder and the unpublished host's
independent strict parser are cross-tested, including every-byte mutation,
truncation, and trailing data. The physical ownership host now binds the exact
v2 getter/callable and uses the strict request/response protocol for the O0/O2
14-case corpus. Windows callable/dependency isolation is confirmed in
run 31257545008, job 93103151756.
The Rust-host ASan lane is green in public job
93107277065.
Mobile profiles, general fallback cleanup/quiescence, and public native
execution/admission remain absent, so this migration does not change
SPX-B104.
Native settlement proof model v1 to v2
The private draft settlement certificate and receipt projections move from v1
to v2. Version 2 replaces the misleading call_contract field with the
domain-separated recovery_contract, adds exactly one post-commit start plus
typed Finalize, StageOwnedResult, and trace-bound CertifyOutcome progress
edges, and authenticates those fields under new v2 certificate and receipt
fingerprint domains. Draft v1 bytes and fingerprints are intentionally not
accepted or reinterpreted as v2.
This is a private proof-model migration, not descriptor-v3 or runtime wiring.
No settlement file is added to callable-v2 bundles, no loader or host receives
v2 settlement authority, ordinary native resource execution remains
SPX-B104, and public callable-v3 admission remains absent.
Pre-v3 settlement phase model
The hidden NativeSettlementTransaction now supplements the atomic proof-model
settle helper with closed Executing, DecisionLocked,
ActionInProgress, ProviderSettled, model ReceiptCommitted, and
Quarantined phases. Future callable-v3 consumers must not treat either model
as one physical commit. The protocol has three ordered irreversible boundaries:
CallCommit, exact SettlementDecisionCommit, and host ReceiptCommit. A
host unwind before the decision lock selects
Abort(HostUnwind); after the lock it resumes the exact decision and may not
replace Accept with Abort. Unknown or conflicting phase evidence
quarantines. An action records Finalizing before its effect, and interruption
there quarantines without retry.
The model/provider Published disposition means only that a result was
selected in candidate evidence. It is not public ledger publication. Candidate
receipt bytes must be independently validated, exact-instance bound, and
authenticated by host-only authority before one ledger ReceiptCommit.
Existing certificate-v2, receipt-v2, SPXNPRF1, and callable-v2 bytes are
unchanged by this clarification; none may be reinterpreted as descriptor-v3 or
physical host authority. The phase model allocates and provides no
exact-instance reservation, host authentication, ownership ledger,
allocation-free postcommit guarantee, FFI/provider, loader pin, or physical
finalizer authority.
Private callable settlement proof v1
The compiler and unpublished native host add the private SPXNPRF1 proof
envelope. It embeds one exact, unchanged SPXNABI2 descriptor plus the
canonical binary settlement graph and binds them through separate schema,
v2-byte, graph, and envelope fingerprint domains. The graph also carries the
exact source v2 call-contract and trace-path-certificate fingerprints, which
the independent parser requires to match the embedded descriptor.
This is an additive proof format, not an in-place v2 migration and not callable
ABI v3. SPXNABI1, SPXNABI2, and SPXNPRF1 are mutually incompatible; there
is no negotiation or fallback. Existing v2 descriptor/provider/bundle bytes and
symbols do not change. The v2 loader rejects the proof magic before opening an
image, default consumers cannot import the proof surface, and no proof byte
grants loading, execution, adoption, settlement, or finalizer authority.
Pre-v3 proof to private SPXNABI3 metadata
The native callable ABI v3 is a new metadata
format, not an extension or reinterpretation of SPXNPRF1 or SPXNABI2.
Consumers must dispatch on the full eight-byte magic and exact version, reject
unknown or malformed versions, and never negotiate or fall back. V3 carries its
settlement graph directly and uses new descriptor, graph, wire-schema, ABI,
contract, and symbol domains. V2 and proof bytes, hashes, symbols, bundles, and
public build-only behavior remain unchanged.
The legacy dynamic-loader constructors reject every bounded descriptor
beginning with SPXNABI3 before path canonicalization, image load, or symbol
lookup. This includes a same-magic blob with a changed version, header size, or
total length; it must not fall through to v2 classification or generic
descriptor loading. A separate private dynamic-v3 constructor now admits only
an exact bounded descriptor whose getter, execute, settle, and returned
descriptor storage all prove canonical root-image provenance, then retains a
separate immutable copy of the admitted bytes. A distinct bounded process-
lifetime static-registration model binds exact descriptor/getter/execute/settle
addresses and target identity without exposing paths, close, or unload. It is
exercised with non-Apple fake functions, and a mandatory macOS gate now requires
the unpublished loader and host static-only path to type-check for five iOS
device, simulator, and Catalyst Rust targets. A new feature-only evidence
harness additionally cross-emits one exact arm64-Simulator provider and the
mandatory job is configured to link and run it against the private host at
-O0/-O2. Run 31318280135, job
93257002836
proved that path. This private migration changes no public API or compatibility
promise.
V3 now freezes six provider wire roles and a separate host-only committed
receipt: exact envelopes, tags, checked capacities, a six-argument execute ABI,
payload-bearing frames, digest DAG, and distinct receipt-key HMAC. Independent
compiler and host codecs intentionally replace the former provisional schema
identities, changing private v3 fingerprints, symbols, and known answers while
leaving v1, v2, and SPXNPRF1 unchanged. V3 CertifyOutcome carries the
canonical ordinal/outcome witness and a
nonzero digest over the trace-certificate fingerprint plus that transcript. The
host recomputes this digest and rejects resealed witness/digest mutations, but
does not thereby accept or walk the trace-path DFA certificate independently.
Provider candidate evidence must never be relabeled as a host receipt,
and model ReceiptCommitted must not be treated as public ledger
ReceiptCommit.
The ordinary emitter derives its target from the compiler build and exposes no
public or general machine-code cross-target configuration. A hidden selector
emits complete target-bound evidence providers for five closed iOS targets and
two closed Android targets. Android dynamic guards now bind architecture,
Android/Bionic, ELF, pointer width, and byte order; the x86_64 Emulator gate is
green in hosted run 31320436726. The bounded
arm64-Simulator and Windows dynamic runtime paths are green. Future iOS device,
simulator, and Mac Catalyst/macabi
profiles must retain distinct target strings even though they share static
registration. No migration may infer physical finalizer success from
Finalizing; interruption remains uncertain and quarantined without retry.
Subsequent private additions provide graph-derived providers for all 14 normal
corpus scenarios, a desktop v3 loader, an OS-seeded receipt authority, and a
fixed-capacity atomic ledger/facade. One O0/O2 invocation now connects all 14
normal scenarios through those components and observes zero Rust heap growth
from immediately before CallCommit through ReceiptCommit; injected decode-
reserve failure quarantines exact evidence and pins. Seven joint failure
fixtures add returned/malformed/interruption/replay/conflict evidence, and
canonical pre-execute unwind reaches authenticated abort receipt commit without
entering provider execute. The private static-registration model has non-Apple
runtime evidence plus a mandatory five-target iOS compilation gate. That gate
is now configured to link and execute one exact arm64 Simulator provider through
the same receipt ledger at -O0/-O2; hosted observation belongs only to a
green job for the revision. Consumers must not generalize this single standalone
process to device/app lifecycle coverage, the remaining iOS corpus, fatal
allocator/process-crash recovery, or representative or general mobile
application/device execution. These
additions provide no public admission,
general physical-finalizer, or general mobile application/device execution
guarantee. They change no
native execution gate and leave SPX-B104 closed.
Private Android JNI handle and status projections v1
The private Android JNI ownership adapter
v1 introduces two closed projections for its
Kotlin/native boundary. They are fixture protocols, not a stable public JNI or
resource ABI, and they do not replace semaprax.status.v1.
SPXAJH01 is one positive u64: reserved sign bit zero, nonzero 15-bit
process-lifetime runtime tag, nonzero 24-bit generation, and nonzero 24-bit
slot. The independent Kotlin/native known answer for tag/generation/slot
1/1/1 is 0x0001000001000001. Consumers must reject zero, negative,
reserved, zero-field, stale, forged, cross-runtime, or exhausted-generation
values; they must never reinterpret a handle as a pointer or ownership payload.
SPXAJS01 is one fixed u64 status projection: nonzero u32 code, closed
three-bit class, closed two-bit retryability, nonzero 16-bit manifest-domain
ordinal, and zero reserved high bits. Zero alone is success. Its base known
answer is 0x0000002d00000001; the declared fixture exception is
0x0000006b00000007, and every undeclared JVM throwable maps to
0x0000004500000001. Consumers must validate all closed fields and may not
derive semantic meaning from exception class names, messages, stacks, or
objects.
The implementation, source-lock/packaging evidence, and exact API-35 x86_64
APK/Instrumentation path are green in run 31324497016, job
93272580149.
No migration may infer
GC collection or process-exit cleanup from deterministic
cleanForTest()/cleanable.clean() evidence, reinterpret non-throwing
AutoCloseable.close() as SEMAPRAX's general fallible explicit close, or open
public admission/SPX-B104. Since both projections are private pre-alpha
fixtures, future incompatible changes must use new magic/schema identities and
new independent known answers rather than silently accepting old values.
Private Apple Swift ownership adapter v1
The feature-gated Swift adapter reuses generation-tagged handles and the callable-v3 receipt ledger, but is not a public handle ABI or framework compatibility promise. The generated zero-argument fixture is the sole open entry; migrations must not restore caller-selected evidence hooks or expose the hidden registration bridge. The bounded hosted Apple gate is green in run 31333469714, job 93295293995; that evidence must not be generalized to public frameworks, physical devices, UI, or general lifecycle support.
Private WIT boundary v1
SPXWIT01 freezes one exact private WIT/schema/JavaScript bundle. Changes to
its WIT text, mapping JSON, adapter bytes, status constraints, or framing
require a new known answer and explicit migration note. This identity must not
be reinterpreted as a Component Model binary or public WIT package version.
The separate private scalar Component Model profile freezes a standards-valid
binary with digest
sha256:3ed6bed8472eeae0ef17f96458622c9ae032dd7a13b115d2d7fea7fcfecde643.
Its section order, component function type, canonical lift, export, and embedded
core module are part of the known answer. An incompatible change requires a new
profile/version and migration note. This scalar fixture must not be
reinterpreted as the SPXWIT01 result/status interface or a public component
package.
Private source-result component v4
Private Source-Result Component v4 is a new profile, not an in-place change to
the v1 scalar fixture, checked component v2, or Portable Result Component v3.
Its package/interface version is semaprax:private@0.2.0, and its sole admitted
export is:
type language-result = result<bool, bool>;
evaluate: func(value: s64, reject: bool, divisor: s64) -> result<language-result, status>;
Consumers must preserve the nested result distinction: source-language
Ok/Err occupy the inner result, while recognized compiler status occupies
the outer error. They must not flatten language Err into status, treat status
as a language payload, or reinterpret the compiler's internal variant bytes as
the WIT canonical representation. Invalid internal tags and unknown statuses
remain traps.
The v4 known answers are:
source revision: sha256:4391bc27b5db547f2b162c2b5467c2b75797e8a5ef64e4ffe4abef15678c6254
generated core: 25161bf5c5eec37c13b6733d30e272dadafe3ea3905e8e05099f3664e869e32d
component bytes: adf85701ccd4d4f05c65742b6c8c65180f8be591dea58fbab8cc71db8f61bb78
artifact DAG: 639f5ce95a5d7b81e84ac7f7d9976649aeb9451065eeb3716e5dbae1e1108885
Any incompatible change to the exact source closure, selected signature, prelude/layout bindings, component type graph, canonical lift, export name, status mapping, or core/component topology requires another private profile version and new independent known answers. V4 adds no compatibility fallback from or to v1-v3 and creates no public component, aggregate, callable, FFI, or resource ABI. Its exact Wasmtime execution is hosted green in run 31356536123, job 93357169796.
Private generic-record component v7
Private Generic Record Component v7 is another separate default-off profile,
not an in-place change to any v1-v6 fixture. It freezes WIT package
semaprax:private@0.5.0, interface generic-records, world
semaprax-private-v7, and exactly four exports:
transform-i64-bool: func(input: duo-i64-bool, delta: s64) -> result<duo-i64-bool, status>;
transform-bool-i64: func(input: duo-bool-i64, delta: s64) -> result<duo-bool-i64, status>;
preserve-phantom-i64: func(input: phantom-i64) -> result<phantom-i64, status>;
invert-phantom-bool: func(input: phantom-bool) -> result<phantom-bool, status>;
The exact concrete types are duo-i64-bool { left: s64, right: bool },
duo-bool-i64 { left: bool, right: s64 }, phantom-i64 { marker: bool },
and phantom-bool { marker: bool }. The two Phantom types deliberately share
a physical field layout while retaining distinct semantic source instance,
layout-digest, component-type, and export identity. Every language record value
is nested in the unchanged outer result<record,status> so recognized
arithmetic or contract failure remains physical status rather than a record
value.
V7 authenticates the capability-free exact source table, ordered generic arguments, concrete Native64/Wasm32 layouts, Graph v12 and cleanup-plan bindings, source/core/profile/component mapping, and artifact DAG. Its primary known answers are:
source revision: sha256:2c2c38ae4a6400730bc6c91de659675074020651b9b58bb6a39d047630ef7303
generated core: d218ff1eaff5f3f677fee58c7b2feb500e9efed8225800cfc3a6562f97d117d8
profile: 7b19f74ab185da90445a042dbd04b6f39f7f9eff3ffff34fc5f0a3bdfd4a9bbf
component bytes: 780a0ccfc35c7ff6d933483711e958d29cfd44c290762b05cd5183e6bf04b5b0
artifact DAG: c3d1fd10501bfe8dcd4b5c8f24184d127e462b9ca4bc6b1f9422ad8fbcc0b26e
Local source-lock, hostile core/component, Node/core, default-consumer hiding,
strict quality, and independent security gates are green. The isolated Rust
1.97.1/Wasmtime 47 typed runtime is hosted green in run 31373317800, job
93406924922.
V1-v6 bytes and known answers remain
unchanged. V7 does not establish general source selection or generic-record
mapping, empty/nested/resource/non-Copy records, imports or capabilities,
callbacks/reentrancy/async, callable/FFI/public ABI, browser/multi-engine
conformance, package/version negotiation, or SPX-B104/SPX-W111 widening.
Private record-pattern projection component v8
Private Component v8 is another separate default-off profile, not an in-place
change to v1-v7. It freezes WIT package semaprax:private@0.6.0, interface
record-pattern-projections, world semaprax-private-v8, and four ordered
monomorphic preserve/invert exports over exact Phantom<i64> and
Phantom<bool> records. The two named records deliberately share physical
fields while retaining distinct source-instance, layout, WIT-type, and export
identity. Its primary known answers are:
source revision: sha256:2baac0c0920dbb153789767bf506a4a81713081586a81444d8e5f5a8f5a8516d
generated core: b6e1dbf9522dbb98df9b6fcd370b562a9a722fcc672d44488aed80f13b7ad39e
Graph v13: c587415819395e3d618b1e724d639d650e7c55b046f4b77b8bcb5de4ff95682b
plan: c77c4060fb0b0051af125f4ca353df3a6f5dbd367cdc5ffd61347a7c22847059
Phantom<i64>: d2ff6084bcfc95701b1dd59835d0ac3af96362e05e56dcadcbd4b8e5dc7d9d80
Phantom<bool>: 3e09cefc7d1ae9bc52ec827debdbcd0753d63bcca994ef776eadb66ba254e67a
profile: 79d4bade38dd3fff9c7145b406bb0bb265ff3ef7cf084edac83384c84610bce2
component bytes: d88590752ed7b08b0f0a32019ba8b4c5fc489d59f06b96986d7ad69e2554a10e
artifact DAG: e32fe0a15a3458f16aa4da59d87683013dbeba03754966f35e0cb63600e613a3
Admission binds exact source, generated core, two concrete layouts, Graph v13,
scratch/result plan, profile, component, and DAG. The exact validator rejects
all six same-signature function-index swaps; only the four polarity-changing
swaps are claimed behaviorally observable. Local independent/upstream,
every-byte, invalid-value/poison, Node/core, source-lock, strict, and security
gates are green. The isolated pinned Rust 1.97.1/Wasmtime 47 zero-import,
empty-linker, no-WASI typed runner is hosted green in run 31385406865, job
93445428268.
V1-v7 bytes and KATs remain unchanged. V8 provides no generic-function
component, general source selection or record mapping, imports/capabilities/
resources, callbacks/async, callable/FFI/public ABI, browser/multi-engine
conformance, package negotiation, or SPX-B104/SPX-W111 widening.
Private generic-function instance component v9
Private Component v9 is another separate default-off profile, not an in-place
change to v1-v8. It freezes WIT package semaprax:private@0.7.0, interface
generic-function-instances, world semaprax-private-v9, and these six exports
in exact order:
preserve-i64: func(marker: bool, control: s64) -> result<bool, status>;
invert-i64: func(marker: bool, control: s64) -> result<bool, status>;
preserve-bool: func(marker: bool, control: s64) -> result<bool, status>;
invert-bool: func(marker: bool, control: s64) -> result<bool, status>;
ordered-i64-bool: func(marker: bool, control: s64) -> result<bool, status>;
ordered-bool-i64: func(marker: bool, control: s64) -> result<bool, status>;
Those exports select exact Graph-v14 instances of the three phantom Copy
templates preserve<T>, invert<T>, and ordered<T,U>. Consumers must bind
the complete ordered FunctionInstanceId sequence, not declaration IDs,
monomorphic wrappers, inferred arguments, or same-signature core indices. One
monomorphic materializer calls all six exact instances and app.main checks
their expected results. No authored type, record, or layout root migrates into
the profile. Its primary known answers are:
source revision: sha256:218085fb5ea1bcc090c04ac0acb3395912d0dad09027b9118d8817978b2fde0c
Graph v14: 62907c4b95495bb573b2b37de9f0b08c7a82218934154521e8c0c8396158cc6e
generated core: 9f178207a0406f740198ee8c71d5d008efdf4d995ff04e11e80ea73b79155d44
plan: edd11c98bbc902d9dbc9c942375477fcf1e6c3f1befbe3c4a9f260107104485e
profile: 365897ddb2770cc25a11690dddbfef5d232244ec5d328c79a24a1410e684615e
component bytes: 3cf6c7d7d02e838fb374478a2b5b25077c7c612ad36e30deaffd15311a25a688
artifact DAG: 2623ff9a7eda5526616a15befd4951de86874a59911dcba2a7d3bcc2d178a474
Admission binds exact source, Graph, generated core, plan, profile, raw
component, and DAG. Independent validation rejects every byte mutation,
noncanonical unsigned LEB encodings, truncation/trailing bytes, cross-version
confusion, and all 15 same-signature pair swaps; eight swaps change observable
polarity and seven are identity-only evidence. Local core 5/5, component 4/4,
CI-lock 4/4, full gates, and independent security review are green. The
zero-import, empty-linker, no-WASI pinned Rust 1.97.1/Wasmtime 47 typed runner
is hosted green in run 31392541096, job
93467490492.
V1-v8 bytes and KATs remain unchanged. V9 opens no
inference/constraints, general source selection/export or generic-function
Component mapping, aggregate/resource/non-Copy values, imports/capabilities,
callbacks/async, callable/FFI/public ABI, browser/multi-engine conformance,
package negotiation, or SPX-B104/SPX-W111 widening.
Private source-Option propagation component v10
Private Component v10 is another separate default-off profile, not an in-place
change to v1-v9. It freezes WIT package semaprax:private@0.8.0, interface
option-propagation, world semaprax-private-v10, and this sole export:
evaluate: func(input: option<s64>, divisor: s64) -> result<option<bool>, status>;
The export selects exact source function
component.option-propagation.evaluate plus app.main, mapping the
compiler-owned Option<i64> through postfix ? to Option<bool>. Consumers
must authenticate Graph v11, CleanupPlan v3, prelude v1, both concrete
layout-v2 instances, and the selected source closure; they must not infer the
profile from a same-signature core function, declaration name, or caller-
provided self-consistent digest. No authored type, resource, template,
instance, import, or capability migrates into the profile. Primary known
answers are:
source revision: sha256:98b8fc892c183499153142d5bbdb4162e31bda95ef145d34dbb1ff57c9b8fc72
Graph v11: 96083f90fab18c919a96cee48109e606e089159e109869a42bdf48831743d45d
prelude v1: d37bad7e3911669bbf2c66b25c8b31d5c2e36eb181cc54fdc86c3a49a8fb9c5e
Option<i64> layout: 79194fc88011ac060877e60293d0a4272429dd9e2d720674d0d54e804562deda
Option<bool> layout: dec126293ece7ec0e48d3d85ccdb494f7c7cfe4c3d4a9b1a61b50f6f862ff038
CleanupPlan v3: d07fa51fc6f192a43318140264fa0e5964933ed90bc065cc8c74708e258ff92f
generated core: 967b0c4aff16ad55042a1c856079e0b387558909fa857fcf3aabc9fc53f54283
profile: f53a0c21638b5a360faa19ad4fdef68f6d861a5baffe39422847128686e82bef
component bytes: 741ff89e1ee67d1426ae12e576bc7c4187e065913baf5dea5507901bfa16f8db
artifact DAG: 1cc90d12b135b79a64b14b04d5c1d9851767bcebfbc4311a2b0fe679c017897d
Independent validation rejects every byte mutation, truncation/trailing or
noncanonical encodings, caller-supplied source/core KAT substitution, and
v1-v9 confusion. Typed and raw gates cover Some/None, contracts, checked
arithmetic, sticky failure, status-first/tag-last publication, full poison,
invalid input/output tags and booleans, unknown status, repeated/fresh
instances, and out-of-band fuel exhaustion. Local core 5/5, component 4/4,
CI-lock 4/4, full, hostile, and security gates are green. The zero-import,
empty-linker, no-WASI pinned Rust 1.97.1/Wasmtime 47 v3-v10 runner is hosted
green in run 31396483313, job
93481068502.
V1-v9 bytes and KATs remain unchanged. V10 opens no general source
selection/export, general Result/Option/? or algebraic Component mapping,
nested/resource/non-Copy carriers, imports/capabilities, callbacks/async,
callable/FFI/public ABI, browser/multi-engine conformance, package negotiation,
or SPX-B104/SPX-W111 widening.
Web v3 to Public Wasm Scalar Exports v1 / web v4
Ordinary semaprax build <file> --target web remains the legacy
semaprax.web.v3 package with semaprax_main. No migration is required for an
existing consumer unless it opts into selected scalar exports.
Adding one or more repeated --export <stable-id> options selects the separate
Public Wasm Scalar Exports v1 profile and emits
semaprax.web.v4. The v4 module exports only stable-ID-derived scalar adapters;
it does not export semaprax_main. Consumers migrate from:
const { instance } = await instantiate();
const value = instance.exports.semaprax_main();
to the generated stable-ID facade:
import { instantiate } from "./semaprax.bindings.js";
const runtime = await instantiate();
const result = runtime.call("calculator.add", 19n, 23n);
The selected IDs must be explicit persistent declaration identities and satisfy
the profile's bounded lowercase grammar. A display-name rename does not require
consumer migration when the @id remains unchanged. Unsupported programs fail
with SPX-W115/SPX-W116; the compiler never interprets them through the v3
entry ABI or aggregate/resource ABI. V4 also adds exact artifact digests and
generated .d.ts declarations. Its digest binding is integrity metadata, not
signature or provenance evidence.
Revision token FNV-1a64 to SHA-256
Graph v3 and later, semantic patch bases, CLI output, and semaprax.web.v2/semaprax.web.v3 manifests use one algorithm-tagged token:
sha256:<64 lowercase hexadecimal digits>
The digest input is exactly b"semaprax.graph-revision.v1\0" || canonical_source_utf8. The domain separator and canonical projection are part of the protocol. Paths, comments, and formatting-only differences do not affect the token; semantic source changes do. This is collision-resistant content addressing and stale-base detection, not source authentication.
Legacy fnv1a64: patch bases, graph caches, snapshots, and web manifest expectations are incompatible. Regenerate them from the current source. SEMAPRAX deliberately does not accept an FNV fallback: an old patch fails with SPX-G409 before modifying its source. Web consumers must reject semaprax.web.v1 when they require the SHA-256 revision contract.
There is not yet a stable compatibility guarantee. Before 1.0, every breaking public syntax, CLI, diagnostics JSON, graph, patch, web manifest, package, component, or ABI change must add a section here and update the changelog.