Skip to content

The Product Ladder

The product ladder is an import and ownership rule, not merely a naming convention.

The bottom rung is the serializable product meaning every party agrees on: identifiers and values, suite and document definitions, record and telemetry contracts, prompt definitions, settings shapes, and the domain contributions an installed artifact declares. Data and serde only — no execution, no transport, no Harmos, no gates — and mise run check:wasm compiles it for wasm32 to keep that claim honest.

The second rung is the kit a plugin author writes against: the authoring attributes, the execution context and its grants, registration, the sidecar wire, and the evaluators that read the contracts below. It layers on dokime-api and re-exports every contract module under its original path, so a plugin compiles the kit, writes dokime::…, and never names the rung below directly. It never depends on the rung above.

The third rung is what the application is and how a runtime runs it. state/ owns the folded state Harmos replays and snapshots, transactions/ the closed vocabulary that is the only way that state changes, streams/ the typed rows it publishes, and traceability/ the projections read back out. Around them sit capabilities, commands, queries, jobs, storage assembly, sidecar composition, and shutdown. app.rs holds the identity and the entry verbs — builder, launch, simulate — a shell stands the application up with. It re-exports the vocabulary for interface convenience, but remains a distinct ownership layer.

The upper rung contains dokime-server, dokime-cli, the Tauri desktop, and the Python bridge. They translate transport or host concerns into runtime commands and queries, and own every process side effect the app crate must not: environment loading, the tracing subscriber, the config source, and rendering an error once. dokime-protocol serves them as the public dokime.v1 gRPC contract they speak over the wire; dokime-app::config resolves where an installation keeps its files and what the operator chose, before any runtime exists.

Plugins and sidecars sit beside the bottom rungs: they declare product contributions using dokime — and, through its re-exports, dokime-api — and nothing else. Packaging xtasks and sidecar crates may depend on Harmos authoring/package facilities, but a plugin does not reach into dokime-app to mutate product state. Nothing depends on a plugin crate. The only dokime-app entries under plugins/ are [dev-dependencies], where a test drives a real host to prove admission end to end.

This split is enforced structurally in the workspace and documented in the crate-level architecture comments and tests.

Dokime markDokime · Stokker Technologies