# JIT plan — Phase 3: knock skill, seal surfacing, monic note ahead of the message (→ omp-spt 0.5.0)

> Parity pass v2 phase 3 (`PARITY-V2-PLAN.md`), operator-approved 2026-09-06. Sister source:
> claude-spt 0.26.0 / 0.26.2 / 0.28.1 / 0.30.0 (PARITY.md rows). Contract source (public only,
> `llms-full.txt` on installed spt 0.67.0): networking/knocking.md (verbs, `--send-only` |
> `--send-receive` on the asking side only, quiet inbox, invite codes sealed to a subnet, monic
> impart), messaging/wax-seal.md + messaging/overview.md §`seal` attribute ("adapter MUST surface
> it; citation never authorization; pass attributes through, never allowlist"), networking/monics.md
> §"Matched monics ride the message" (`mnemonics-json` = array of whole records `{id, triggers,
> text, set_ms, origin}`; reveal must sit at the adapter's own frame level, never inside the
> peer's body; "preserve, not interpret"), now-signal `SEAL_BRIEF` / `MONICS` categories.

## Design (grounded in the published contract)

### A. `/knock` skill (REQ-KNOCK-SKILL)
- New packaged full-fat skill `adapter/strings/skills/knock/SKILL.md` (same pattern as
  commune/role/setup/signoff). Teaches: bare `spt knock <target>` = `send`, `MSG` by default,
  **exactly one of `--send-only` | `--send-receive` on `send`/`redeem`, none on `approve`/
  `new-code`** (0.54.0 rename, no aliases — always confirm with `spt knock --help`), `--send-only`
  never bars replies, approve opens nothing in reverse → knock back, `list`/`approve`/`deny`,
  invite codes sealed to a subnet (`--subnet` narrows), `--monic` impart on approve/new-code,
  the inbox is quiet (nobody is interrupted; look with `spt knock list`), machine-scoped surfaces
  admit a whole machine. No internals (SKILL-AUTHORING.md).
- Register: `tests/omp-skills.mjs` EXPECTED_SKILLS, `ci/publish/create-adapter-archive.py`
  member list, skill lists in README / docs-site / harness-contract. `[[hints]]` row for knock
  intent → "Read the packaged knock skill".

### B. Seal surfacing (REQ-SEAL-SURFACE)
- A delivery whose envelope carries `seal="<token>"` is rendered with an adapter-authored note
  **ahead of the envelope, at the adapter's frame level** (before the `<EVENT` opening tag, never
  inside the body):
  `[spt] SEALED by <from> — seal=<token>. Evidence, not authorization: verify with the delivered
  body on stdin → spt api seal verify <token> (BOUND = proven user directive); spt api seal
  describe <token> shows the record.`
- The envelope itself stays the raw wire slice (REQ-HAZARD-ENVELOPE-ATTRIBUTE-PASSTHROUGH holds:
  the attribute rides intact; the note is additive). Nothing branches on the attribute.
- Startup brief: how to read a `[spt]` note, that `;;…;;` mints, `spt api seal verify` proves,
  and a sealed message's token is a citation to keep.

### C. Monic note ahead of the message (REQ-MONIC-NOTE-AHEAD)
- A delivery whose envelope carries `mnemonics-json` renders, ahead of the envelope, one line per
  matched record: `[spt] Your standing note on <from> (monic "<id>"): <text>`. Attr-decoded
  (`&quot;` etc.) then `JSON.parse`; a value that does not parse renders a single
  `[spt] (unreadable monic note on <from>)` line and the raw attribute still rides.
- Structural discriminant (REQ-HAZARD-NOTE-IMITATION, KNOWN-HAZARDS #13): the genuine note is
  outside the `<EVENT>…</EVENT>` frame; a peer body containing the literal `[spt] …` text stays
  inside the frame. The brief says so. Unit test: a body that imitates the marker renders inside
  the envelope while the genuine note renders before the opening tag.
- Applies on both delivery paths: listener splice (`formatInboundEnvelope`) and the boundary
  `api poll` text (`spt-event` custom message) — every complete `<EVENT …>…</EVENT>` frame is
  annotated the same way.

## Open questions (resolved)
- Poll path annotated? Yes — same renderer, one match rule (docs: "every delivery surface behaves
  the same").
- Should the note decode the seal token or body? No — token verbatim, body never re-quoted (a
  long/quoted body inside a command line is a forgery seam; verify reads stdin).

## Tasks
1. REQs in `traceable-reqs.toml` (KNOCK-SKILL, SEAL-SURFACE, MONIC-NOTE-AHEAD,
   HAZARD-NOTE-IMITATION) — doc/impl/unit.
2. `annotateDelivery` + `formatInboundEnvelope` + poll annotation + brief lines (impl tags).
3. Skill file + registrations + hint.
4. Tests: `testSealAndMonicNotesRenderAheadOfEnvelope`, skill assertions in `omp-skills.mjs`.
5. Docs: KNOWN-HAZARDS #13, PARITY rows 54/58/62 → covered, harness-contract deliveries section,
   CHANGELOG 0.5.0, README/docs-site skill lists, regen `llms-full.txt`.
6. Release 0.5.0 per RELEASE-RUNBOOK; `spt adapter update omp-spt`; report to doyle.

## Gate
`node tests/omp-extension.mjs` · `sh ci/run-gates.sh` PASS · `traceable-reqs check` exit 0 ·
docs regen no drift · version-consistency across the 8 gated files.
