Loom

Type to search across the guides, specification and decision records.

↑↓ navigate ↵ open esc close Pagefind

Decision records

ADR 0033 — SPI consolidation + conformance contracts

  • Status: Accepted (2026-07-10) — accepted item #6 in the Execution-OS evaluation (loom/docs/requirements/2026-07-10-execution-operating-system-evaluation.md). Implemented: C1 the SPI map (loom/docs/loom-2.0/12-extension-seams.md); C2 runEventStoreConformance / runSnapshotStoreConformance / runBranchRegistryConformance in @loom/testing, self-tested against in-memory + SQLite backends. Added a reference InMemoryBranchRegistry.
  • Date: 2026-07-10
  • Builds on: ADR 0016 (K1 kernel ABI + conformance test, K5 event-schema governance), the existing store / dispatcher / worker / effect / scheduler SPIs

Context

Loom’s extensibility (“Kernel Extensions” + “Runtime Contracts”, P3) is mostly shipped: there are already pluggable SPIs for event store, snapshot store, branch registry, dispatcher, worker runtime, effect, scheduler, and warmer, and K1/K5 give the syscall surface a versioned contract plus a conformance test. Two gaps remain:

  1. The SPIs are documented unevenly — each in its own package, no single map of “here is every replaceable seam and its contract.”
  2. Only the K1 syscall ABI and K5 event schema have conformance tests. The placement, memory, projection, and capability SPIs have interfaces but no portable test suite a third-party implementation can run to prove it conforms.

Decision

  • C1 — one SPI map. A single doc (docs/loom-2.0/) enumerating every extension seam (scheduler, placement, memory, decision, projection, transport, persistence, capability, auth, policy, tracing), its interface, its invariants, and its reference impl — the “kernel extension model” the requirements asked for, as documentation over the SPIs that already exist.
  • C2 — conformance kits. Extend the K1/K5 conformance-test pattern to each SPI: a shared @loom/testing suite (runEventStoreConformance(factory), runDispatcherConformance(factory), …) that any implementation imports and runs against itself. Makes third-party runtimes provable, not just possible.

No new kernel mechanism — this is consolidation + test scaffolding over the existing seams.

Consequences

  • Third parties can implement a store/dispatcher/memory backend and prove conformance in CI.
  • Kernel genericity strengthened (P10): the contract, not the reference impl, becomes normative.
  • No runtime overhead — pure docs + test kits.

Verification

  • Each conformance kit passes against Loom’s own reference impls and fails a deliberately-broken stub.
  • The SPI map lists every seam with a link to its interface and a reference impl.

Amendments (from the Execution-OS evaluation)

  • Merges the requirements’ “Kernel Extensions” (mostly shipped) and “Runtime Contracts” (partial) into one consolidation item; “Fiber Contract” dropped (fibers rejected).

Coverage extension (2026-07-13)

Conformance kits now cover 9 SPIs: runEventStoreConformance, runSnapshotStoreConformance, runBranchRegistryConformance, runExecutionDispatcherConformance, runTimerStoreConformance, runProjectionRuntimeConformance, plus runWorkerRuntimeConformance (worker factory + package factory; self-tested against LocalWorkerRuntime in @loom/worker-runtime-local), runLlmProviderConformance (complete shape + stream), and runCapabilityAuthorizerConformance (decision shape + determinism). The loom plugin new <seam> scaffolder (ADR 0043) emits the matching conformance-wired test for every seam it knows — run loom plugin seams for the list, which is authoritative in a way a list written here cannot stay. Remaining seams without a kit: widget-renderer, effect-middleware, telemetry (framework-specific or passive-observer contracts — lower value).

Amended 2026-09-16. The enumeration above used to be spelled out here and named six seams; by the time it was noticed it was missing five. The relationship is now the other way round and is enforced rather than described: every SPI that publishes a conformance kit is scaffoldable, checked by a fitness test in tools/scaffold. Publishing a kit without writing its seam fails the build, so this ADR no longer has a list to keep current.

ESM distribution (2026-07-13)

The kits moved out of @loom/testing/conformance into their own package @loom/conformance, shipped as ESM ("type": "module") with vitest as a peer dependency. The reason: the kits import { describe, it } from "vitest" at module scope; as a CJS build that becomes require("vitest"), which vitest forbids — so no other package could consume the kit in its own vitest suite. As ESM the import is native, so any plugin (1P or 3P) runs the kit in its own tests — e.g. @loom/plugin-sqlite/src/conformance.test.ts now runs all four store kits against the real SQLite backend. This also dissolved the @loom/testing ↔ @loom/plugin-sqlite build cycle (the kits’ self-test against the in-memory references lives in @loom/conformance; durable-backend conformance lives in each backend’s own package). Consumers add default export conditions on the SPI packages so the ESM kit can resolve them (harmless for CJS require consumers).

Source: docs/adr/0033-spi-conformance-contracts.md in the loom repository.