Grain
Source:
docs/canon/grain.md
Status: Current canonical document.
One paragraph is the whole architecture. Everything else is materialization of this cut.
Client (the shell — TUI or the eval client) evaluates named actions as JSON-RPC on the session socket and, for interactive execution, writes approved on a pending ApprovableJob. The unattended eval client submits source and policy, observes results, and requests cancellation; authorization is daemon-owned (../client/shell.md). Harness daemon — one process — owns the kernel plane (config files, whitelist, registries), the session plane (one SessionRoot plexus document per session), and the executor: it writes Job and PEW/Expectation bodies, matches PEW/Work to PEW/Driver + PEW/Connection, and attaches an independent Actor per PEW/Work. World is outside the document (files, processes, network). Session is the conversational unit; SessionRoot holds app behavior and the Actor’s work awareness — not a third region. Metaphor (soul, not mechanism): what if Datomic were both a reactive meta-framework on top of React and an OS kernel at the same time — entities, refs, and reaction, not services and journals. Inverted event sourcing: the CRDT entity is durable, the stream (awareness reports) is ephemeral presence. Authorization is host-owned on ApprovableJob, not an Actor consider: ../runtime/approval.md.
Shipped topology is that one process. Accepted names for the planned process split — the split does not ship: hypervisor (server topology and process lifetime), Yjs-server (public sync, server replicas, durable document images), runtime-server (connects the runtime assembly to the document service and supervision). Those names do not rewrite the causal spine.
Causal spine
Section titled “Causal spine”The full causal chain for one unit of work lives only here:
1. Client (or parent action) evaluates a named action — JSON-RPC; the daemon writes Job / PEW bodies2. ApprovableJob: host pipeline (always). Sole home: [`../runtime/approval.md`](/reference/harness/docs/runtime/approval/).3. When the `registerExecutor` guard returns true (`orchestrationResult === true`), licensed `ToolCallJob` kinds execute BODY. Completions and judges stay PEW. MCP / web BODY intern's the connection and calls `callTool` / `webSearch` / `webExtract`. Leftover intern PEW still honors one release.4. Executor seals `ToolCallJob.outcomeJson`. Completions still settle via Actor on PEW; unattended human-input requirements fail through the operation outcome5. Actor settles — durable outcome (successful | failed) only on that PEW/Work. Host cancel is `admitTermination` / `fail("cancel", …)`, not an Actor mailbox.6. Next conversational Turn: new Turn linked as `.tail`; head advancesClient Harness daemon Actor (PEW/Work)────── ────────────── ───────────────evaluate named action ────────► write ToolCallJob / PEW bodies (JSON-RPC) ApprovableJob: host pipeline; BODY on allow-sideturn/cancel · approved ───────► host writes ───────────────► Actor observes isDone / leaf bit settle / continue / refuseHarness law: completions remain PEW (tape, usage, live thought). Licensed MCP / web world work is Job BODY: intern the row, call callTool / webSearch / webExtract, seal ToolCallJob.outcomeJson. MCPToolJob.dispatched is the park pin. Honor still settles leftover intern PEW one release. A model tool_call is a ToolCallJob: license on the leaf. ToolCallJob is-a ApprovableJob. Shell lists (“models,” “tools”) are projections, not peer harness types.
Execution regions
Section titled “Execution regions”Where execution sits. Not privilege integers; not a feature catalog.
| Region | Seat | Does | Does not |
|---|---|---|---|
| Client | app peer (TUI, CLI, remote, headless) | Evaluate named actions (JSON-RPC); write approved / approvalComment on interactive pending ApprovableJobs; run sandboxed command Scheme; paint |
Orchestrate Actors; mint Job / PEW bodies; run the policy program |
| Harness daemon | one process: kernel plane + session plane + executor | Project config.json / kv.json onto KernelRoot (KernelReflector); run approval policy on ApprovableJob; registerExecutor guard writes orchestrationResult; run leaf BODY on allow-side; match PEW/Work → PEW/Driver + PEW/Connection; attach Actors for completions / judges / intern PEW; host programs + cross-session app storage |
Be the conversation tip; be the app chrome |
| PEW/Work | PEW/Expectation + its Actor | One obligation. Tools touch world via the leaf Job execute after allow-side orchestrationResult === true |
Be slash catalog; be the global registry; consider UAC |
| PEW/Driver · PEW/Connection | DriverSpec / ConnectionSpec | Self-describe via files + KernelReflector; ready on demand or eagerly; supply Actors; live extras on spec.live |
Be openWork peers as config rows; be envCapability |
| Program | harness-registered | Adjust Actor in/out (value); parallel world effects; interim commands/UI storage | Control the client app directly |
| World | outside the document | Files, processes, network | PEW identity |
Cancel, Permission, and confirm are host / shell crossings — not an Actor mailbox. Map: proposals.md. Permission / UAC: ../runtime/approval.md.
Session is the conversational unit. SessionRoot holds app behavior + work awareness.
Machine hosts a runtime (verb: machine hosts harness daemon). Prefer those words over “host” as an architecture noun.
| Noun | Job |
|---|---|
| PEW/Work · PEW/Expectation | Every unit of world-settling work. One more Plexus model node per unit — not nested sugar, not a chat ledger row. Prefix in docs; drop only inside PEW. |
| CompletionExpectation | The materialized PEW kind for one model completion. Siblings with ToolCallJob on the turn’s work lists — never head, never nested under a sealed completion. |
| ToolCallJob | Emission identity of one model tool_call (is-a ApprovableJob, not PEW). Outcome on outcomeJson. BODY is phase 2 of registerExecutor after an allow-side guard. Concrete kinds include SystemToolJob, FileMutateToolJob, MCPToolJob, WebSearchToolJob, WebExtractToolJob, AgentCallJob. |
| SessionTurn | Kernel orchestration, not PEW: one conversational turn — tail ref + doneWork + queue. Control chunks (TurnPromptChunk, CompactJob, ReACTChunk, ProgrammaticJob) are on the queue, not PEW/Expectation. CompactJob is a Job the turn loop runs; it is not an executor. A legacy TurnCompactChunk still reads the old way. |
| Spine | SessionRoot.head → SessionTurn → .tail (ref, not work) back to genesis SessionSystemPrompt (snapshotted packets). Next turn = new SessionTurn linked as tail + advance head. Interpretation is kernel orchestration (ProgrammaticJob), not PEW. |
| Actor | Independent handler attached for one PEW/Expectation (under a PEW/Connection). PEW and expectations processing only. |
| PEW/Driver | DriverSpec via files + KernelReflector (can = claimed PEW/Expectation model names) + PEWDriver after ensure. Contract: ../packages/plexus-expectations/README.md. Not an account and not an installed npm package. |
| PEW/Connection | ConnectionSpec via files + KernelReflector (config.json row + DriverSpec ref). PEWConnection after ensure. Also the transport link. Multi-account = multiple ConnectionSpecs. Not a network socket and not the whole driver provider. |
| Driver provider | Runtime package supplying one or more drivers, connections/actors, auth, discovery, and account projections. Product composition registers the roster. Not an extension plugin. |
| Extension plugin | Tools, actions, bots, behavior, state, and other existing extensions via the plugin SDK/runtime. @inhuman.tools/plugin-sdk is this SDK. Not a source of new drivers. |
| envCapability | Scheme environment capability. Never bare “capability.” |
| Catalog | One process-local table: registered ∪ expand(connection). Sources fill rows; admit/execute do not maintain three products. |
| Program | Harness-registered procedure: I/O adjust, world side-effects, interim command/UI storage. |
| Command | App program: sandboxed half is Client Scheme; effects half is a session/kernel RPC {type, args} (turn, compact, eval, kv/set, connect/adopt, …) — not a core region. |
| SessionRoot | Live session plexus document: expectations tree, head, KV. KernelRoot is the kernel-plane projection of config.json + kv.json. Entities = plexus models. |
| Hook / mode | Programmable edge on PEW/Expectation phases — not parallel work kinds. |
Rejected as product ontology: second PEW kinds for MCP/shell “special work”; nested “approval” PEW/Expectations; an awareness proposal lane the Actor considers; chat journals as product truth (dual book next to PEW); promoting app slash into harness PEW/Work; a SessionQueue between client and daemon (actions are RPC; the document is the queue); ring integers as product roles; treating an extension plugin as a driver provider; treating Hermes as a driver ID (it is an OAuth client of Nous Portal).
An npm package is a workspace dependency/exports/build/test boundary, not a process or independently released product. An assembly is a composition of real lower-layer packages, not a container of mock services. Driver IDs nous, chatgpt, grok, openrouter, connection IDs, PEW kinds, and sync tags are preserved. Plugins do not supply drivers. New capability arrives as connections on existing drivers, pack tools, or .scm commands. The shipped set is a registered driver-provider roster; plugin manifests do not load it. Roster law: ../runtime/drivers.md. Package graph: ../decisions/server-module-ownership.md.
PEW/Work truth (two substrates only): obligation + sealed outcome live on the CRDT PEW/Expectation; in-motion yields live on awareness for that PEW/Expectation. Process-local WAL is executor detail only. PEW never reads a tape to settle. A global session journal is intentionally not a product substrate.
Crossings (minimal)
Section titled “Crossings (minimal)”No PEW awareness mailbox. Cancel is host-owned. Permission is approved on the leaf. Confirm is shell chrome. Steer stays prompt-specific. Map: proposals.md.
Catalog and tool routing
Section titled “Catalog and tool routing”catalog = registered ∪ expand(connection)Registered is always-on host plugins (toolkit FS, shell, web_search, web_extract, metadata, scheme_repl, agent comms) plus user packs — one InhumanPlugin path. General bots are Scheme agent/send / agent/ask, not per-recipe catalog rows. shell is an ordinary catalog row (not a workspace mutator). scheme_repl is a work bag, not an Expectation: the catalog row is projection-only; model admit mints a bare ProgrammaticJob (turn orchestration, not PEW, not Approvable, not a ToolCallJob wrap). CLI eval mints that same bag on the turn queue — not through admit. Inner admits are nested ToolCallJobs. Mixer (JSON tools[] vs Scheme symbols, agent/send / agent/ask, period): standard-toolkit.md. Everything else is an ordinary catalog row.
canon DriverSpec = claimed Expectation model names (pre-load) — never tool names.- Reload = reproject sources into the one table (and session filter).
- Routing is the catalog source (pack handler, or ConnectionSpec + server tool name). Wire names are projection — only at the model edge. Not durable identity. Do not re-parse
mcp__…to route.
Cross-doc law: session cannot own a kernel ConnectionSpec as a child. The product meaning is still “this PEW/Work is that PEW/Connection”; materialization may be a lawful cross-doc pointer. Do not treat string name and id as dual product identities.
Default model-callable FS tools: standard-toolkit.md.
Demand and transport
Section titled “Demand and transport”Connection inventory is config.json, projected onto KernelRoot by the KernelReflector; the daemon ensures catalog rows (whitelist → import → PEWDriver / PEWConnection). Models are invocation ids on spec.live — (:models (:live c)) in Scheme, session KV key model.
MCP rows are not completion wires. MCPToolJob intern’s a connection via ensure(); the tool BODY is a Job executor, not PEW honor. Server settings + secrets.json are how to reach the server; tools are live listTools projections into the catalog union — not config fields. Do not productize PATH as CRDT or invent a spawn-policy entity. Spec / ensure / can contract: ../packages/plexus-expectations/README.md. Toolkit FS tools are Jobs, not a PEW driver.
Sequential conversation
Section titled “Sequential conversation”Each turn is another SessionTurn node. Cross-turn context is a direct ref to the previous turn (tail); head advances to the new tip. Not nested expect syntax and not a dead message ledger. Introspection proves the system by minting and awaiting real PEW/Expectations — a client without TUI chrome (headless app), not a special E2E ontology.
Compact is a CompactJob on the turn queue plus the config-addressed compact.scm fold. The job is a cutoff: everything strictly before it is projected (card, squeeze lines, verbatim keep). It is not a cursor that says the fold result is the new start. The turn loop runs the job when it is shifted. Fold failure stays on the job as a human notice and does not enter the next model prompt. A legacy TurnCompactChunk with representation still reads the old way. Fold ABI: ../runtime/control-effects.md.
Commands (app split)
Section titled “Commands (app split)”| Half | Where | Role |
|---|---|---|
| Sandbox | Client Scheme | Fast local UI / scheme pickers; no claim ownership of PEW/Work |
| Effects | Session/kernel RPC {type, args} |
turn, turn/rewind, compact, eval, kv/set, kv/clear, policy/set, connect/adopt, connect/drop, connect/always-allow, connect/exclude-tool, config/auto-allow |
Commands are not the conversational tip. They are app-managed program invocation; effects are JSON-RPC calls on the daemon. Commands run on the Client.
Control effects
Section titled “Control effects”Programs return data; the interpreter owns wait, fan-out, and re-invocation. Full law: ../runtime/control-effects.md.
The session application is a client shell over a SessionRoot document and RPC calls; the transcript is the render, not a store.
See also
Section titled “See also”| Doc | Role |
|---|---|
proposals.md |
Proposals, well-known shapes, substrate map, input face |
standard-toolkit.md |
Always-on model-callable FS membership + mixer |
../runtime/control-effects.md |
Flat program execution; interpreter owns wait |
../runtime/approval.md |
Approval: ApprovableJob, host pipeline, approved bit |
../client/shell.md |
Client-shell duties; unattended eval |
../client/operate.md |
Operator how-to |
plugins/tldr.md |
Author-facing overview |
../runtime/drivers.md |
Driver roster; plugins do not introduce drivers |
../decisions/server-module-ownership.md |
Package graph, ownership, allowed imports |
../packages/plexus-expectations/README.md |
PEW contract: Expectation / Driver / Connection / ensure / can |