# Wake-safe draft preservation — 0.9.4

## Scope and decision

Keep `pi.sendUserMessage(stub)` for every listener submission and retry. 0.3.9 custom-message triggers failed under ACP and 0.3.10 restored user-prompt delivery; 0.3.17 made idle/streaming arbitration native and atomic. Discard the unreleased custom-message replacement.

At the public extension `message_start` event, identify an adapter-owned pending or previously delivered stub and mark the user message `synthetic = true` before OMP emits it to the TUI. This flag denotes system-injected text and the TUI skips editor clearing for it. Do not change message role, promote peer content to developer/system, snapshot editor text, restore stale text, or change the wake API. Match owned delivery identity, not arbitrary user text. Inspect and exercise native extension-before-subscriber ordering.

## Questions and gates

- Confirm the native flag preserves editor contents without changing provider message role.
- Prove real AgentSession user-prompt wake with ACP deferral enabled, then prove the extension hook runs before real EventController rendering.
- Cover idle, busy/queued, resubmitted deliveries, unrelated user messages, and body continuation.
- Run extension regressions, deterministic release gates, traceable-reqs check, docs drift/build.
- Advance the eight version-gated files to 0.9.4; regenerate docs; freeze a clean commit with the emphasys trailer.
- Build/validate Windows, GNU and musl helpers; pack the exact source into adapter.spt; tag/push and publish per RELEASE-RUNBOOK. Do not misrepresent unavailable native acceptance as passed.

## Ownership

Main owns adapter source, regression tests, integration and publication. NativeProbe owns a throwaway real-OMP verification script and evidence only. ReleasePrep owns version metadata and correction of the unreleased draft-preservation documentation. Neither worker runs project-wide gates while edits are in flight.

## Verification and release decision

- `node tests/omp-extension.mjs`: PASS. Disabled synthetic assignment in an isolated temporary copy: regression fails with an empty draft; restored source passes.
- `sh ci/run-gates.sh`: PASS, no dependency skips; 110 Rust tests, docs, version, manifest, packaging contracts, and 68 complete traceable requirements.
- Throwaway native probe: PASS, independently rerun by Main. Actual ExtensionRunner + AgentSession + EventController with ACP deferral enabled, six deterministic provider calls: idle wake/tool continuation, busy queued delivery/newer typing, already-delivered stub resubmission, unchanged user role/body, unrelated user behavior. Default custom trigger counterexample queues without a provider call.
- Native probe host: local OMP source commit `e8d0a93db61e756361aad84d4bcbc2dd2db88973`; unrelated render-utils worktree edits were present. Package-declared version alone is not a published-release runtime proof. Separately inspected local `v16.3.15` tag source: editor synthetic guard and extension-before-subscriber ordering both present. Existing floor retained.
- Release follows the operator-authorized patch-release precedent: publish the three-target `adapter.spt` as latest after deterministic gates and focused native proof. Full disposable three-host acceptance and per-target evidence JSON are not claimed. No live endpoint restart or registration replacement.

## 2026-09-13 follow-up — unproven

**Disposition:** the operator explicitly chose to leave the reported recurrence
unproven and will report another occurrence. No production code change, new
regression test, or release was made. Neither a current-version defect nor a
stale loaded extension was established for the affected session.

The most recent reported case was doyle's former OMP session,
`01a09428-8e3d-7000-9da0-baac169780f5`, which has ended. Its startup timestamp
and the installed directory's later mtime do not establish the loaded adapter
version. No update receipt or startup version record was retained. The operator
was ultimately uncertain about the historical version; do not infer one from
the absence of model-only UPDATES context in the transcript.

Measured evidence:

- Installed omp-spt was 0.9.4; its extension SHA-256 matched the repository:
  `ad1d575cca6aeb4f035936f0032e61c1ff7bc6d2d4dfc756176eab8dd75606c2`.
- Actual installed `omp.exe` TUI probes preserved exact drafts for idle delivery,
  busy delivery with newer typing, previously delivered stub replay, a two-message
  same-sender burst, and watchdog resubmission. Eight offline provider calls.
- Raw PTY keyboard input was erased with the published v0.9.3 extension and
  preserved with 0.9.4, including a probe importing the installed adapter path.
- A disposable real spt-hosted endpoint, attached through `spt rc`, preserved both
  the editor buffer and the rendered draft through a real `spt send` delivery.
  This used the installed adapter and an offline streaming provider.
- OMP reported 18.1.17 initially and changed to 18.1.19 during investigation.
  The final broker-path probe used 18.1.19; do not describe every run as pinned
  to one runtime version or as reproducing doyle's historical runtime.
- `node tests/omp-extension.mjs`: PASS (`OMP-EXTENSION OK`).
- `traceable-reqs check`: exit 1; 68 complete requirements, zero incomplete,
  13 existing evidence-placement findings. No release gate was claimed green.

Core's public-contract clarification ruled out delivery-time PTY writes for
this hook-only manifest, which declares no translation binary. The probes used
offline providers, not the historical session's model, settings, and turn history.
These passing paths do not disprove the reported experience.

Disposable endpoint/profile `draft-probe-20260913` and temporary probe programs
were removed. Evidence summary remains in the investigation session's
`local://draft-preservation-evidence.json`. On recurrence, capture the affected
endpoint, loaded runtime/adapter versions, and the editor-clearing boundary
before changing delivery semantics.
