Files
quixos-protocol/src/execution-world
Timothy J. Aveni 60b44a6637 Load checked installations independently of the running compiler (WI-16)
Keep compiler-dependent checks in Nix builds; load stored plans and programs with original provenance and runtime artifact validation. Allow an identical executable world to receive a new activation epoch after a toolchain rebuild.

Compiler-update/altered-program regression, coordinator and full sandboxed integration checks pass; lint and formatting pass. Default platform/source wiring remains the next task.
2026-09-21 22:01:47 -07:00
..

Closed execution plans and artifacts

compileExecutionPlan validates a workspace, links its checked queries, resolves public forwarding, and emits one versioned plan with an SHA-256 digest. It retains exact interface/package revisions and generic applications, owner initialization, storage definitions/profiles, selected operation identities, query placement, and source provenance. quixos-workspace-compile --execution-plan-out PATH writes it.

The compiler emits operation dependencies as a graph. A traversed interface port retains its edge/projection and exact selected operations; native reads identify the canonical storage inputs. Cycles do not become infinitely expanded paths. Execution and admission must apply their runtime depth/work budgets when walking this graph. The plan includes the full linked GraphQL selections, not just root traversals or a list of fields.

Local and replica queries must have the same root contract. A local query cannot introduce a relationship path absent from its replica source; authors expand the source selection explicitly. Portable getters may require extra canonical fields and exactly-one dependency traversals, recorded in the dependency graph. Admission resolves those inputs on the server for selected objects. This never changes the source query's candidate membership, and does not claim a limited source is a complete interface extent. An incomplete runtime projection remains a coverage state, not permission to invent a missing value.

A portable transaction cannot depend on a local presentation query, including through a selector. Pass explicit references and preconditions as mutation input. Otherwise an admitted top-N list could select different mutation targets locally and at acceptance. Remote transactions can implement explicit server workflows. This restriction does not ban local queries from snapshot selectors. Such query ports are view-relative: both hosts must use the frame's admitted candidate universe. An executor must report unavailable coverage when that view is absent, not substitute a full-server extent. Query-port acquisition remains unavailable until the query executor implements this rule; emitting its checked dependency graph is not runtime support.

Artifacts and world identity

PackageArtifacts describes one package output containing a process service and optional target modules. Implementation IDs are stable manifest keys, separate from export capability IDs and JavaScript registry names. Each implementation covers its ABI, export map, entrypoint, and declared asset paths/digests/sizes/MIME. Its digest excludes its own digest field. Paths must be normalized and relative.

checkExecutionWorld verifies plan identity, supported codecs, exact source and binding schema, service fallback, promised targets, declared exports, and all supplied file bytes. The reader must confine paths/symlinks to the checked output and honor its byte limit before allocation. artifactFileReader supplies that adapter for trusted immutable output roots. loadArtifactWorld checks candidate outputs without importing package code. BrowserArtifactGateway registers only declared browser assets and verifies bytes before serving; Web Studio places it behind workspace authentication. LF-05 still checks actual module registries/imports and verifies build receipts; a manifest claim alone does not establish the JavaScript exports or an isolated process.

The returned camino-world-v1 descriptor includes every declared implementation and its digest, so executor choice does not change semantics or silently load new code. Each binding key is the JSON pair [packageRevisionId, implementationId]; there can be both a service and module for the server target. World hashing uses the core codec's canonical ordering and domain-separated SHA-256 framing. The monorepo camino-execution-world check compares the compiler and core implementations. No machine-local Nix path enters the world descriptor.

The current binding schema is the closed workspace schema. This is conservative: an unrelated contract change can require checking/rebuilding several packages. LF-05 may narrow it to exact checked per-package closures, but must use the same schema for generation, receipts, and world validation. It must not substitute an older package schema just because the source revision did not change.

Transaction-port ABI

quixos-transaction-ports-v1 uses coordinator-issued frame/invocation handles and monotonic invocation-local sequence numbers. A package receives its export ID, input, and optional receiver. Port calls name a declared port and its allowed primitive or exact interface operation; they never select arbitrary private slots, packages, or coordinator transactions. Creation uses an explicit stable call key. Interface calls into transaction operations also require a stable key, checked after resolving the selected operation. The coordinator extends the birth path; it never derives that path from an asynchronous completion order or the transport sequence number.

The coordinator resolves each port through the installed operation binding, checks effects/selected methods, validates typed arguments/references, and joins nested calls to the outer logical transaction. A nested failure poisons the outer domain transaction even if application code catches it; frame cleanup cannot turn it into a partial success. Process completion cannot independently commit. The coordinator owns savepoints, cancellation, frame expiry, and rejection. These enforcement mechanisms are LF-06/LF-08, not guarantees provided by TypeScript frame types.

The service control vocabulary includes readiness, cancellation, and shutdown; transport framing and generated adapters are LF-05/LF-08. Portable modules and services implement the same declared operation contracts. ABI compatibility is not a statement about package trust, co-location permission, or multi-user isolation.

Portable package bindings are generated with quixos-codegen-ts options {"portable":{"target":"browser"}} (or server). They expose Contexts, PortableImplementation, checked codec declarations, and createRegistry. Handlers import the shared replica core, never Replicache. Stable mutation keys are mandatory for creation and selected nested transaction calls. Snapshot contexts expose only their declared read methods; runtime frame checks remain mandatory even when the TypeScript source passed compilation.

The maintained reader source in tools/local-first/reader/portable.ts typechecks against both generated targets without casts. The root camino-portable-bindings qualification compares Node, Window, Worker and serialized-port behavior. Its simulated channel tests adapters, not installed operation acquisition or process isolation; those require the coordinator.

Closed generic package applications use the same portable adapters. The checked workspace specializes their input/output types and dependency ports before code generation. Each application has its own export ID and generated handler name (name$<specialization digest>); handlers are concrete, so a string application and a list-of-int64 application cannot accidentally share an untyped codec. Common implementation helpers can still be ordinary generic TypeScript functions. This does not implement universal runtime type application or legacy constructors. The camino-portable-bindings check compiles positive/negative typed consumers and executes both specializations in Node, Chromium Window, and Worker hosts.

Use selectArtifactImplementation(checkedManifest, selection) to choose an implementation by target, ABI, required export IDs, and optionally its exact ID. Without an ID, exactly one candidate must match. Missing exports, wrong targets, and ambiguous choices fail; manifest order never determines execution. This selects already checked bytes and does not grant permission to run untrusted package code in process. Multiple selected implementations remain part of the same checked world's complete artifact inventory.

const implementation = selectArtifactImplementation(manifest, {
  target: "server",
  compatibility: "quixos-service-v1",
  id: "isolated-service",
  exports: requiredExports,
});

Consumers use the selected entrypoint, registry export and export coverage from that manifest. The reader's Nix builder accepts per-package implementationSelection = { "package:reader-runtime@1" = { browser = "browser-module"; server = "server-module"; service = "service"; }; }; overrides. Its fixture requires one implementation per lane covering that lane's needed exports; the selector itself permits a smaller requested subset. The installation records the chosen service and module entries. Process lifecycle and trusted-module placement still belong to the existing runner.