# CI and release acceptance

`omp-spt` uses two verification layers:

1. deterministic gates that run on every change; and
2. release acceptance against a real native OMP endpoint.

The first layer is repeatable and does not require a live model session. The second proves the user-visible hosting contract that deterministic tests cannot establish. A deterministic pass is necessary, but it is not release acceptance.

## Deterministic gates

Run these from the repository root:

```sh
sh tests/ci-gates.sh
sh ci/run-gates.sh
node tests/omp-extension.mjs
```

`tests/ci-gates.sh` guards the gate dispatcher itself. `ci/run-gates.sh` performs shell-syntax checks, validates `adapter/omp-spt.toml` against the vendored published schema, checks the native launch and session manifest, tests the fat archive contract, runs a hermetic release-acquisition dry run with fake `gh`/`spt` commands, and runs the `omp-spt` helper's Rust tests and release build. It also runs `traceable-reqs check` when the command is installed. `tests/omp-extension.mjs` exercises listener and active-poll delivery, core custody ownership, explicit outbound messaging, busy/idle transitions, nonfatal communications recovery, immutable session binding, and shutdown.

<!-- [doc->REQ-OMP-NATIVE-TUI] -->
<!-- [doc->REQ-OMP-CORE-DELIVERY] -->
<!-- [doc->REQ-OMP-COMMS-RECOVERY] -->
<!-- [doc->REQ-OMP-SESSION-IMMUTABLE] -->
<!-- [doc->REQ-OMP-MESSAGE-CONTEXT] -->
<!-- [doc->REQ-OMP-READY-LIVE] -->

These are binary pass/fail checks. A release run must treat any `SKIP` caused by a missing interpreter, Rust toolchain, platform binary, or `traceable-reqs` installation as an incomplete gate, provision the dependency, and rerun. The archive test may intentionally prove that the packer refuses missing target binaries, but a release still needs all three target builds before packaging. The live acquisition integration intentionally skips unless `OMP_SPT_ACCEPTANCE=1`; after opt-in, missing release version, target, tools, or GitHub authentication are failures. Its hermetic central-gate test opts in and exercises those fail-closed paths without network access.

## Native OMP release acceptance

ADR-0013 sets the release boundary. The supported helper targets are **x86_64 Windows** (`x86_64-pc-windows-msvc`), **x86_64 GNU Linux** (`x86_64-unknown-linux-gnu`), and a static **x86_64 musl Linux** compatibility tier (`x86_64-unknown-linux-musl`). The asset has no macOS or Arm64 payload. Acceptance must use the exact tagged candidate `adapter.spt`, a real `omp` installation, the native packaged extension, and disposable endpoint identities. Complete the full acceptance sequence independently on all three targets before promotion. Do not reuse an operator's long-lived endpoint id.

Install the tagged candidate on each acceptance host and verify its manifest version:

```sh
spt adapter add --release BigscreenVR/omp-spt --tag vX.Y.Z
spt adapter version omp-spt
```

The version command must print exactly `X.Y.Z`. Then record target-specific evidence for every item below; a pass on one target cannot stand in for either of the others.

### musl selected-helper boundary

Under [ADR-0019](adr/0019-musl-acceptance-follows-selected-helper.md), the musl record must come
from a disposable OMP-capable host where spt-core selects
`x86_64-unknown-linux-musl/omp-spt` from the tagged archive and the installed helper digest exactly
matches that member. The base distribution may use glibc; helper selection and native execution,
not distribution branding, define this adapter seam. Record `target:
x86_64-unknown-linux-musl`, native `spt --version` and `omp --version` output, tagged acquisition,
and the same endpoint evidence required below.

This is a helper compatibility tier, not a claim of generic Alpine support. Manually executing the
static helper does not qualify, and neither does a container where real OMP is absent.

### 1. Fresh bringup and attached TUI

```sh
spt endpoint create omp-spt-accept-fresh --adapter omp-spt
spt go omp-spt-accept-fresh
```

`create` mints the endpoint and brings its first session up; `spt go` attaches the terminal. Pass only if the broker-held terminal displays the real interactive OMP TUI, the packaged `adapter/strings/omp-spt.mjs` extension binds `omp-spt-accept-fresh`, and the endpoint becomes reachable. The attached native TUI is part of this proof.

### 2. Same-node message, turn, explicit reply, and state

From a second terminal on the same node. The host's installed `spt` must be **v0.46.0 or later**
(`spt --version`): earlier binaries let a `spt ring` from a perch-owning caller adopt and delete
that perch, so a ring from a live-agent session destroyed the ringer's own inbox. Fixed in
spt-core v0.46.0 (release counter 81); the constraint is on the binary running here, not on
what is published.

```sh
printf 'After reading this message, explicitly send exactly OMP-SPT-ACCEPTED to the sender using spt send or the peer-message shortform.' |
  spt ring omp-spt-accept-fresh --timeout 120
```

<!-- [doc->REQ-OMP-SESSION-TITLES] -->
Pass only if:

- the delivery becomes one ordinary OMP user turn containing the sender stub and complete SPT event context;
- the TUI visibly runs that turn;
- `spt ring` prints `OMP-SPT-ACCEPTED`, proving the agent used an explicit outbound messaging action;
- ordinary assistant prose visible in the TUI is not forwarded to the sender;
- `spt endpoint list --json` shows the endpoint move from idle to busy for the turn and back to idle after completion; and
- the OMP session name is `<endpoint-id> @ <node> (<project-name>/)`, the idle window title begins with `○`, and the busy turn visibly cycles braille spinner glyphs before returning to `○`.

This is an end-to-end delivery and explicit-messaging check. Turn failure, submission failure, and shutdown must remain local rather than synthesizing an outbound peer message.

### 3. Immutable in-TUI binding and native resume

Record the bound OMP session id. While the endpoint is running, attempt OMP's in-TUI new-session and resume/switch actions. Both must be blocked with an `omp-spt` warning, and the bound session id must remain unchanged.

End the endpoint gracefully, then bring its latest recorded session back:

```sh
spt endpoint shutdown omp-spt-accept-fresh
spt go omp-spt-accept-fresh
```

On an offline endpoint `spt go` resumes the latest session and attaches (`spt endpoint resume omp-spt-accept-fresh` is the same step without the attach). Pass only if this launches OMP's native resume path into an attached TUI, preserves the prior transcript, and rebinds the endpoint to the recorded OMP session id. In-TUI switching stays blocked after resume. Native resume happens at endpoint launch, never by moving a running endpoint to another session.

### 4. ReadyAgent and LiveAgent

Exercise both hostable roles through spt-core's current ReadyAgent and LiveAgent flows:

- **ReadyAgent:** the native OMP endpoint binds, listens, receives a same-node request, sends an explicit reply, keeps ordinary assistant output local, and shuts down without requiring a daemon-driven Psyche turn.
- **LiveAgent:** the same native OMP hosting path remains attached and reachable while the daemon drives the manifest's bounded `psyche-omp` role; a Psyche event completes successfully, and normal inbound delivery plus explicit outbound messaging still works afterward.

Pass only if `omp-spt` advertises exactly ReadyAgent and LiveAgent and both use the native OMP endpoint. A Worker or an alternate hosting process is not an accepted adapter role.

### 5. Graceful shutdown

```sh
spt endpoint shutdown omp-spt-accept-resume
```

Pass only if the extension ends the SPT session, reaps its listener, clears its TUI status, and the endpoint is no longer advertised as online. There must be no false-online endpoint and no orphaned acceptance process.

## Adapter release boundary

Cross-node transport is outside the `omp-spt` release gate. Once the exact message contract succeeds through the adapter on one node, subnet routing adds no OMP-specific seam and belongs to spt-core. A cross-node check may be useful for spt-core qualification, but it must not replace or block the same-node adapter acceptance above.

Release evidence must identify the candidate `vX.Y.Z` tag and asset, OMP and spt-core versions, disposable endpoint ids, fresh and resumed OMP session ids, gate outputs, state transitions, explicit messaging reply, both role outcomes, and final shutdown result separately for `x86_64-pc-windows-msvc`, `x86_64-unknown-linux-gnu`, and a host where spt-core selected the `x86_64-unknown-linux-musl` helper. Each target needs its own machine-readable release record; the musl record remains invalid if it omitted selected-member digest equality or any native endpoint check.
