# omp-spt — full documentation > Generated from `docs-site/src/SUMMARY.md` by `ci/docs/build-docs.py`. > Do not edit this file; edit the canonical Markdown pages and regenerate it. --- # Introduction `omp-spt` is the native [Oh My Pi](https://github.com/can1357/oh-my-pi) adapter for [Spacetime (`spt-core`)](https://sabermage.github.io/spt-releases). It gives named Spacetime endpoints a real OMP terminal session rather than translating OMP through another interface. The adapter supports the two hostable agent roles that belong in an interactive OMP session: - **`ReadyAgent`** stays reachable for direct messages in its native OMP TUI. - **`LiveAgent`** uses the same native endpoint and also activates the live-agent Psyche lifecycle. There is no separate plugin installation step. Install OMP and `spt-core`, then install the `BigscreenVR/omp-spt` adapter release with its bundled extension and OMP plugin skills. ## Mental model Three components share the work: ```text spt-core endpoint lifecycle | | launch, resume, attach v native OMP process |-- owns the broker PTY and attachable TUI `-- loads adapter/strings/omp-spt.mjs | `-- bind, delivery, activity state, replies, shutdown ``` - **`spt-core`** owns endpoint records, messaging, lifecycle coordination, subnet reachability, adapter installation, and updates. - **Native OMP** owns the hosted process, interactive terminal, model turn, tools, and transcript. - **`omp-spt`** supplies the launch and transcript helpers plus the packaged OMP extension that connects native OMP events to `spt-core`. The release artifact is one fat `adapter.spt` archive. It contains the supported adapter binaries, manifest, shared native extension, OMP plugin metadata, and packaged commune, signoff, role, setup, and knock skills, so installation and updates move as one unit. ## What the extension does When OMP starts a hosted session, the extension binds the OMP session id to the named Spacetime endpoint and starts message delivery. It names the session ` @ (/)` and gives the terminal title an idle glyph or animated busy spinner, making a fleet of OMP windows identifiable at a glance. Incoming messages are queued into OMP turns, while ordinary assistant output remains in the local conversation. Sending to another endpoint requires explicit `spt send` use or the `@<…@>` shortform, which spt-core reads from the turn text the extension reports. When the TUI shuts down, the extension ends the bound session and releases its listener. The result is still normal OMP. You attach to OMP's own TUI, and OMP remains in direct control of the broker PTY. Start with the [Quickstart](./quickstart.md). For event-by-event behavior, read the [Native integration contract](./reference/harness-contract.md). --- # Quickstart Goal: install `omp-spt`, create a named endpoint, and attach to its native OMP TUI. ## 1. Install the prerequisites You need [Oh My Pi 16.3.15 or newer](https://github.com/can1357/oh-my-pi/commit/e8d0a93d) and [`spt-core`](https://sabermage.github.io/spt-releases). There is no separate plugin installation step because the adapter release carries its OMP plugin skills. The v0.9.4 `omp-spt` release supports **x86_64 Windows and x86_64 Linux only**. Its archive contains Windows MSVC, Linux GNU, and static Linux musl x86_64 helpers, but no macOS or Arm64 payload. The musl helper is a compatibility tier for OMP-capable hosts; it is not a generic Alpine support claim. **PowerShell (x86_64 Windows)** ```powershell if (-not (Get-Command omp -ErrorAction SilentlyContinue)) { irm https://omp.sh/install.ps1 | iex } if (-not (Get-Command spt -ErrorAction SilentlyContinue)) { irm https://sabermage.github.io/spt-releases/install.ps1 | iex } ``` **bash (x86_64 Linux / Git Bash on x86_64 Windows)** ```bash command -v omp >/dev/null 2>&1 || curl -fsSL https://omp.sh/install | sh command -v spt >/dev/null 2>&1 || curl -fsSL https://sabermage.github.io/spt-releases/install.sh | sh ``` Open a fresh shell if either installer updated your `PATH`, then verify both commands: ```bash omp --version spt --version ``` `omp-spt` requires Oh My Pi 16.3.15 or newer and `spt-core` 0.39.1 or newer. If either version check reports an older release, run `omp update` or `spt update` as appropriate, open a fresh shell if needed, and repeat both checks before installing the adapter. ## 2. Install the adapter ```bash spt adapter add --release BigscreenVR/omp-spt ``` This installs one fat `adapter.spt` release for the supported x86_64 Windows and Linux targets. The archive includes their adapter binaries, the manifest, native extension, OMP plugin metadata, and packaged commune, signoff, role, setup, and knock skills. No separate plugin installation is needed. ## 3. Create and attach to an endpoint Choose a stable endpoint id. This example uses `librarian`: ```bash spt endpoint create librarian --adapter omp-spt spt go librarian ``` For another name, use the canonical form `spt endpoint create --adapter omp-spt` followed by `spt go ` and replace ``. `create` is the only way an endpoint is minted: it records the adapter and project folder as the endpoint's defaults and brings its first session up — OMP launches with `adapter/strings/omp-spt.mjs` in a broker-held terminal. `spt go` attaches your terminal directly to OMP's native TUI, and on a later run resumes or starts a session as the endpoint's state needs. `ReadyAgent` and `LiveAgent` are the supported hostable roles. During bring-up, the extension: 1. binds the OMP session id to the Spacetime endpoint; 2. marks the endpoint idle and starts delivery; 3. submits each incoming message as an OMP turn; 4. reports the turn's text to spt-core's IO feed and polls the now-signal at every boundary, so explicit `@<…@>` messages and `;;…;;` seals are read by spt-core and answered in `DISPATCH_RESULTS` while ordinary assistant output stays local; and 5. ends the binding when the native TUI shuts down. You now have a named endpoint in the standard Spacetime messaging and lifecycle model. Use the [`spt-core` documentation](https://sabermage.github.io/spt-releases) for endpoint rosters, messaging, subnets, and other public commands. ## 4. Update later ```bash spt adapter update omp-spt ``` OMP loads the packaged extension fresh on endpoint bring-up. Restart an already running endpoint to move it to the updated adapter: ```bash spt endpoint stop librarian spt endpoint start librarian ``` `start` opens a fresh session on the existing endpoint without attaching; `spt go librarian` does the same and attaches. `spt endpoint resume librarian` brings its latest session back instead. Next, read the [Native integration contract](./reference/harness-contract.md) for launch, delivery, explicit messaging, failure, and shutdown behavior. --- # Native integration contract `omp-spt` hosts Spacetime endpoints as native Oh My Pi sessions. The authoritative generic adapter and CLI contract remains the [`spt-core` public documentation](https://sabermage.github.io/spt-releases). This page describes the OMP-specific ownership boundary and lifecycle. ## Ownership boundary | Component | Owns | | --- | --- | | `spt-core` | Endpoint records, adapter resolution, messaging, subnet reachability, lifecycle coordination, and release updates. | | Native OMP | The broker PTY, attachable TUI, interactive agent turns, tools, and transcript. | | `omp-spt` launch helper | Locating and validating the real OMP executable, then starting or resuming OMP with the packaged extension. | | `adapter/strings/omp-spt.mjs` | Binding, serialized delivery, activity state, the turn-text feed and now-signal, listener recovery, and session shutdown inside OMP. | | `omp-spt` transcript helpers | Per-session history, digest extraction, end-of-session commune summaries, and LiveAgent Psyche turns. | This separation is deliberate. The launch helper gets out of the hosted process path after starting OMP, while OMP remains in direct control of the terminal. ## Install and launch Install the release: ```bash spt adapter add --release BigscreenVR/omp-spt ``` Create a named endpoint, then attach: ```bash spt endpoint create librarian --adapter omp-spt spt go librarian ``` The canonical form is `spt endpoint create --adapter omp-spt` followed by `spt go `. `create` mints the endpoint and brings its first session up in a broker-held terminal; `spt go` attaches OMP's native TUI. Later sessions come from `spt endpoint start ` (fresh), `spt endpoint resume ` (latest session back), or `spt go ` (either, plus the attach). For a fresh endpoint, the resolved manifest starts the launch helper with the packaged extension. For an existing endpoint, the resume path selects the recorded OMP session and loads the same extension. Both paths leave the user in OMP's native TUI and carry the same endpoint naming inputs. The OMP session name is ` @ (/)`. The terminal window adds a leading status glyph: `○` while idle and an animated braille spinner while busy. If the project cannot be determined, only its suffix is omitted; if the node is unavailable, the stable name degrades to the bare endpoint id. The glyph is never persisted in the session name. ## Extension lifecycle The extension receives the endpoint id from `spt-core` and responds to native OMP events: | OMP lifecycle point | Adapter action | | --- | --- | | Session start | Bind the endpoint to OMP's session id, retain the returned authentication token, apply the stable session name and idle window title, mark the endpoint idle, and start its delivery listener. | | Incoming Spacetime message | Parse the self-delimiting envelope, retain its sender, and submit its stub through native `sendUserMessage`: wake when idle or steer at a safe boundary while busy. Mark owned user stubs synthetic at `message_start` before the TUI handles them, preserving the operator's editor. | | Turn start | Mark the endpoint busy with the user's prompt as the `USER_INPUT` payload (none on a delivery-stub turn), then poll `api now-signal` with those words and append its answer after the startup brief. | | Context assembly | Preserve the complete message envelope in the OMP turn so sender and body remain available to the model, with the extension's own `[spt]` notes (seal token, matched monic notes) rendered ahead of the opening tag; report each completed assistant message as a mid-turn `AGENT_OUTPUT` span; poll `api now-signal` with the assistant's words since the last poll and inject a non-empty answer as a hidden message. | | Agent start | Mark the endpoint busy and animate the terminal-title glyph. | | Agent end | Release the completed delivery, restore the idle title, mark the endpoint idle with the closing assistant message as the `AGENT_OUTPUT` payload, and advance the queue. No local shortform dispatch: spt-core reads `@<…@>` and `;;…;;` from the reported spans. | | Session shutdown | Stop title, delivery, and retry timers; release pending messages without synthesizing outbound text; end the bound session; and clear the OMP status indicator. | OMP runs subagents in the same process on their own session and binds the extension again for each of them. Exactly one binding per process activates — the first to reach session start; a nested (subagent) binding never binds the endpoint, spawns a listener, publishes state, or ends the primary's session, so messages surface only in the main conversation. Incoming deliveries leave your unsent draft in the editor, including text you type while the agent is busy. The extension never submits that draft or replaces it with a saved snapshot. Deliveries and retries keep OMP's native `sendUserMessage(stub)` wake path. At `message_start`, the extension marks only its own pending or previously delivered user stubs with `event.message.synthetic = true`, before TUI subscribers run; OMP then skips editor clearing. The stub remains user-role, and the complete peer body is injected unchanged, never promoted to developer or system instructions. Custom-message triggers are not used for peer wake, and unrelated user messages retain OMP's native editor behavior. Assistant prose, errors, and shutdown text never become peer messages; outbound delivery requires explicit `spt send` use or the `@<…@>` shortform, which spt-core — not the adapter — reads from the turn text the extension reports (`[io] compliance = true` in the manifest). Dispatch and seal outcomes reach the model only through the now-signal's `DISPATCH_RESULTS`. ## Delivery notes: seals and monics A delivered envelope rides into the turn verbatim, every attribute intact. Two attributes also earn a note of the extension's own, rendered **ahead of the ` — seal=. A seal is evidence, never authorization: prove it with the delivered body on stdin to spt api seal verify (BOUND = proven user directive); spt api seal describe shows the record.` The adapter never branches on the attribute; the agent proves it. - `mnemonics-json="[…]"` (the receiving node matched your standing monics on the sender) → one line per matched record, `[spt] Your standing note on (monic ""): `. A value that does not parse renders one "unreadable" line and the raw attribute still rides. The same renderer runs on the listener splice and on the boundary `api poll` text. The startup brief teaches the rule from the model side, and the trust warning stays where spt-core put it, on the tag. A foreground `bash` call keeps the turn busy, so every peer delivery waits for the next context boundary. When OMP reports a wall time of 30 s or more for a foreground `bash` result, the extension appends one `[spt]` nudge to that result — run long commands with `async: true` and poll them — at most three times per turn. Advice only; nothing is blocked. Every extension log line is prefixed `[omp-spt ]` (`unbound` before activation) so field logs attribute to a perch. ## Turn-text feed and now-signal Every span of a turn is reported to spt-core exactly once: the prompt as `USER_INPUT` on `api state busy --payload-stdin`, each completed assistant message as a mid-turn `AGENT_OUTPUT` span (`--mid`), and the closing message on `api state idle --payload-stdin`. Payloads travel on stdin only; a failed report is logged and never fails the turn. The extension polls `api now-signal --session --spec-manifest` at turn start (with the user's words) and at every in-turn context boundary (with the assistant's words since the last poll). The answer is delta-only, so a quiet boundary adds nothing. Targeted hints are the manifest's `[[hints]]` (`HINTS` category); the running versions arrive through `UPDATES`. ## Access control: the knock skill The packaged `knock` skill teaches spt's published access-control grammar (networking/knocking.md) without adapter internals: the bare `spt knock ` is `send` and asks for `MSG` by default; `send` and `redeem` require **exactly one** of `--send-only` | `--send-receive` (the asking side declares direction; `approve` and `new-code` take no such flag, and `--mutual` / `--one-way` are parse errors); `--send-only` never bars replies; approving opens nothing in reverse, so knock back; invite codes are sealed to a subnet; `--monic` imparts a standing note on approve/new-code; the inbox is quiet, so look with `spt knock list`. A manifest `[[hints]]` row surfaces the skill on knock intent through the now-signal's `HINTS` category. ## Identity and continuity One hosted TUI has one immutable endpoint and OMP session identity. The extension blocks in-TUI session switches while the Spacetime endpoint is active. End the hosted endpoint first when you want to select a different OMP session. `ReadyAgent` and `LiveAgent` use the same native OMP endpoint and extension. `LiveAgent` also activates the per-event Psyche role; `ReadyAgent` does not. History and digests are fetched from the JSONL transcript for the bound OMP session. The Psyche runner speaks spt-core's reserved exit codes: `95` when the Psyche's own OMP session is gone (reseed), `96` when the inner turn was refused for account or credential reasons — usage cap, quota, credits, billing, a dead key. `96` is an outage, not a fault: the `PSYCHE_ACCOUNT_REFUSAL` line says the session and its context are intact and that only a human can restore the account, and spt-core paces its retries without reseeding or spending a strike. Every other inner failure exits `1` with a bounded tail of both the inner session's stdout and stderr, naming a silent channel explicitly. The manifest declares the invocation budget of both LLM-turn roles (`psyche_resume` 240 s, `echo_commune` 180 s). The echo-commune summarizer is instructed to name another agent only where the transcript shows a direct exchange, and never to present a machine, host, or node name as an agent or teammate. ## Failure behavior Delivery listener exits are retried with bounded backoff. If binding fails or the listener exhausts its restart budget, the adapter fails closed: it reports the problem in the OMP TUI, returns failure outcomes for pending messages, ends the Spacetime session, and shuts down the hosted TUI. A half-bound endpoint is never presented as healthy. A failed `spt` command is reported by the line that explains it. spt-core prints diagnostics and its status line on the same streams, and a diagnostic can come first — `api bind` prints the eager reserved-id probe `ER_HOSTED_PROBE:…` ahead of a `CONFLICT: is live under session …` refusal — so the summary in the TUI notification skips such diagnostics, and the log line carries the command's whole output. Accepted deliveries must also prove turn liveness. If a delivered message sits on an idle session past the liveness deadline, the extension resubmits it, then surfaces the degraded-comms rail, and on continued deafness closes the endpoint the same fail-closed way. A session whose bring-up looks healthy but whose deliveries never run turns — as the daemon-restart autostart replay produced — becomes visibly offline instead of silently swallowing custody. A provider usage-limit refusal is handled as an outage, not a fault. When a turn ends with an account-level refusal (OMP's `errorId` usage-limit flag, HTTP 402, or refusal wording without per-interval wording), the extension reports it once — nothing is broken, the session and its context are intact, only a human or the provider's stated reset changes anything, the provider's own line quoted — and holds the endpoint `busy` until the stated reset plus one minute. The hold is re-asserted every five seconds against stray recoveries; peer deliveries stay custodied and are not submitted into a refused turn; the deaf-session ladder pauses. A human prompt releases the hold early, the deadline releases it and resubmits everything queued, and after a restart the session's own record re-arms it while its last message is still the refusal. Without a parseable, plausible reset time the endpoint stays reachable — the failure direction is always "reachable too early", never "stuck forever". A continuity checkpoint (`spt_checkpoint`, after the commune skill's durable write) never resets context from inside the tool call — OMP's compaction aborts the active run and waits for it to settle, and the run is waiting on the tool. The tool arms the checkpoint and tells the model to end the turn; when the turn ends the endpoint publishes busy and the extension compacts from a timer, then — once OMP's `session_compact` event proves the reset committed — queues the same-endpoint wake as a next-turn message. From arming until that wake is queued, inbound deliveries stay custodied unsubmitted (the status rail shows ` · checkpoint pending`) and the deaf-session ladder pauses; they are resubmitted right after the wake, and OMP orders the wake turn against the delivery turns. A reset that fails after arming is reported as a next-turn notice — commune saved, context not reset, no wake queued — never as a false wake. ## Updates and packaging Each release is one fat `adapter.spt` archive containing the supported adapter binaries, manifest, native extension, OMP plugin metadata, and packaged commune, signoff, role, setup, and knock skills. Update it with: ```bash spt adapter update omp-spt ``` New endpoint bring-ups load the updated extension. A running endpoint keeps its current hosting path until it is restarted with `spt endpoint stop ` followed by `spt endpoint start ` (or `spt go ` to attach as well). --- # Release evidence contract A release is promotable only when every supported helper target has one passing, machine-readable record. The immutable v1 source schema is [`release/evidence-v1.schema.json`](https://github.com/BigscreenVR/omp-spt/blob/main/release/evidence-v1.schema.json). The documentation build publishes the same bytes at the stable `contracts/release-evidence-v1.schema.json` URL. An incompatible contract must use a new schema version and filename; it must not rewrite v1. ## Record custody Name each record `release-evidence-v-.json`. While the candidate remains a prerelease, attach all three validated records and every inventoried log they reference to the same GitHub release as `adapter.spt`. Verify the complete attachment set and its log digests before promotion. Keep one record for each supported target, including the `x86_64-unknown-linux-musl` static-helper compatibility tier. A musl record proves that spt-core selected and installed the tagged archive's musl helper on a real OMP-capable host; it is not a generic Alpine support claim. Do not overwrite a record after promotion. A rebuilt candidate has a different artifact digest or source identity and therefore needs a new release candidate and a complete acceptance run. ## Required evidence Each target record binds all results to one release source identity: - the canonical manifest version, conventional `vX.Y.Z` tag, full source commit, and source tree; - the target triple plus bare canonical SemVer for OMP and spt-core on the acceptance host; - SHA-256 digests for the acquired `adapter.spt`, exact selected target helper, and every referenced release log; - a passing tagged-release acquisition result; and - passing fresh, resume, message/reply, lifecycle, shutdown, ReadyAgent, and LiveAgent outcomes. OMP must be at least `16.3.15`; spt-core must be at least the canonical `[adapter].min_spt_core_version`. Versions do not carry a leading `v`. Fresh and resume outcomes retain non-whitespace opaque endpoint and native OMP session IDs. Every outcome names durable log evidence as `#sha256=<64 lowercase hex digits>`; URLs and directory paths are not release-asset basenames. The exact `(name, sha256)` pair must also exist in that record's `artifacts` inventory, binding every evidence reference to an attached log. The schema admits only `passed: true`; a failed or incomplete run cannot be represented as promotable evidence. ## Validate records Run the validator against all records for one candidate in a single command: ```bash python ci/release/validate-release-evidence.py \ release/evidence-v1.schema.json adapter/omp-spt.toml \ dist/evidence/release-evidence-vX.Y.Z-*.json ``` Validation rejects schema violations, below-floor host versions, whitespace IDs, unbound or path-shaped evidence references, an incomplete or duplicate supported-target set, disagreement with the canonical manifest version, a tag that is not exactly `v`, duplicate artifact names, a missing `adapter.spt` or selected-helper digest, mixed release source identities, and different `adapter.spt` digests across targets. Passing schema validation does not replace native acceptance; it makes the already-completed acceptance outcomes durable and reviewable.