# NOW-SIGNAL W3 — #133 shell adapter `[hints]` — DELIVERED, IN GATE (todlando, 2026-08-30)

Lane `.worktrees/ns23-w3`, branch `feat/ns23-w3-shell-hints`, base `aa5f80f6`, pool `ns23-w3`
claimed (lane identity written). REQ minted: **`REQ-SHELL-HINTS`** (doc/impl/unit/int).

## Premise, MEASURED before any code

1. `[[hints]]` was NEVER harness-gated — top-level `Manifest` field, `validate()` has no hints
   arm. A `kind = "shell"` manifest has always parsed/validated/merged hints. Nothing owed
   schema-side; the gap is entirely READ-side.
2. Nothing read a shell's hints: the only reader is `select_and_mark_hint(ctx.manifest, ..)`
   and `ctx.manifest` is the ENDPOINT-BOUND harness. Shell hints were dead text.
3. Both populations already exist at ONE seam: `shelldisc::discover` → `own` (instances, status
   DERIVED there per REQ-HAZARD-SHELL-STALE-ONLINE) + `instantiable` (active kind=shell rows).
4. HAZARD: `hint_key()` hashed keywords+text+regex only, no adapter identity, one flat
   `hints-seen` per session → two adapters shipping identical text would share one entry and the
   first to fire would silence the other invisibly.

## doyle's ruling (2026-08-30) — shape (a), PER-SOURCE CAP

Harness ≤1 line, EACH shell adapter ≤1 line, each still once per session, rendered inside
`<HINTS>`, no new category, no wire change. Authority chain written INTO the CONTEXT.md
amendment: the 2026-06-12 global clause was ratified when one manifest could speak; its ground
was flood protection from one adapter's chatter; #133 is operator-authored and GREENLIT and
cannot be delivered under a global cap; so the amendment implements the newer operator decision
while preserving the ground per source. Amended BY REPLACEMENT, citing #133's greenlight.

Two in-lane mandates, both honored:
1. adapter-qualified key — **required**, and the REQ states which back-compat arm was taken:
   the HARNESS key spelling is UNCHANGED (qualification is additive and shell-side only), so no
   live session's seen-set forgets at upgrade. Unit test seeds a pre-lane key and proves it.
2. the teaser's CLI string must name a verb that EXISTS at the head — the verb is MINTED in this
   lane (`spt adapter hints <adapter[:profile]>`) and guarded by a parse test built from the SAME
   constant the teaser renders, plus an e2e that RUNS it.

## Delivered so far

- `traceable-reqs.toml`: `REQ-SHELL-HINTS` minted (doc/impl/unit/int).
- `api/reporting.rs`: `select_and_mark` extracted as the shared selection core;
  `select_and_mark_hint` unchanged in behaviour AND in key spelling; new `ShellHintArm`,
  `SHELL_HINT_VERB`, `select_and_mark_shell_hint` (adapter+arm-qualified keys).
- `api/nowsignal.rs`: `gather_hints` is now harness-arm + `gather_shell_hints`; the shell arm is
  NOT gated on `ctx.manifest` (an endpoint with no bound manifest still owns shells). Sources are
  keyed on the adapter's BASE name; an instance's COMPOSITE spelling is what resolves, so a
  profiled instance fires its own overlay.
- `cli.rs`: `spt adapter hints <option>` (+ `--json` DTOs), and the phantom-verb parse test.
- `CONTEXT.md`: per-source amendment by replacement + a new **shell keyword hints** section.
- `docs-site/src/shells/overview.md`: a `[[hints]]` section where a SHELL adapter author looks
  (doyle's doc-stage mandate); `frames.md` HINTS row updated.
- Unit tests: identical-text-two-adapters (the hazard), teaser-then-full arm behaviour, harness
  key back-compat.
- Int test `crates/spt/tests/shell_hints_e2e.rs`: real binary, real registry, instantiated
  adapter OFFLINE (proves "regardless of link state") + uninstantiated teaser + the verb RUN +
  delta silence on the repeat poll. NOT registered in the HEAVY set — same shape as `shell_e2e`
  and `now_signal_delta_e2e`, which are phase A.

## Left to do

1. `cargo check -p spt --all-targets` (running; `W3_check.exit`), then fix + `cargo test`.
2. `cargo run -p xtask -- gen` → `docs-site/src/cli/reference.md` regen for the new verb, and
   `xtask check` — **build `--workspace --bins` FIRST**: the gate reads `target/debug/spt.exe`
   off disk and a stale binary makes that leg a statement about the binary, not the tree (W2's
   respin was exactly this).
3. `clippy --workspace --all-targets -D warnings`, `traceable-reqs check`, battery.
4. Commit, hand the sha to doyle.

## Also filed this session

- **releases#253** — `docs/MANIFEST.md` (70KB manifest contract) mentions hints ZERO times.
  Doc-only, deliberately NOT folded into this lane (doyle concurred).

## W2 state

Respin sha **`05a15396`** handed to doyle (was `081be523`; amended). Diff vs the gated sha is one
file/one hunk: the `ATTACH_OBSERVER_UNSPAWNED` continuation backslash. Verified by `cat -A`
byte-diff against a known-good continuation in the same file. Lane `.worktrees/ns23-w1` + pool
`ns23-w2` stay claimed until he lands it.

---

## DELIVERED — sha `d21aed6a`, handed to doyle's gate 2026-08-30

9 files, +641/-13, one commit on `feat/ns23-w3-shell-hints`, base `aa5f80f6`. Lane and pool
`ns23-w3` stay claimed and warm for a respin. `NS23-W3-JIT.md` deliberately uncommitted.

Every leg read from its own exit file, on a FRESHLY LINKED binary:

| leg | exit |
| --- | --- |
| `cargo build --workspace --bins` | 0 |
| `cargo run -p xtask -- gen` | 0 |
| `cargo run -p xtask -- check` | 0 (first read **1** — see below) |
| `cargo clippy --workspace --all-targets -- -D warnings` | 0, and zero `warning:`/`error:` lines in the raw |
| `traceable-reqs check` | 0 |
| `cargo test -p spt --bin spt` (whole suite) | 0 — **753/753** |
| `cargo test -p spt --test shell_hints_e2e` | 0 — **1/1**, first run |

### Two meter catches, both mine, both caught in-lane

1. **`xtask check` first read 1.** My clap doc-comment for the new verb leaked a tracker code into
   the PUBLIC generated `reference.md`. That gate only speaks after a real `gen` against a real
   binary — which is exactly why the order is build-bins → gen → check, never check alone.
2. **`cargo test -- <bare names> --exact` exited 0 having run NOTHING** (`0 passed; 753 filtered
   out`). libtest's `--exact` matches the FULL module path; bare names match the empty set, and
   unlike nextest (exit 4) libtest exits 0. Two of my tests would have shipped as unrun evidence.
   Fixed twice over: re-run with full paths (2/2 pass), and both tests RENAMED to carry `hint` so
   the ordinary `-- hint` filter cannot skip them again. Banked as the fourth face of
   `zero-match-filter-reads-as-absent.md`.

### W2 housekeeping

`ns23-w2` pool RELEASED (exit 0) after doyle landed `05a15396` → main `cb78f710`. Worktree
`.worktrees/ns23-w1` left standing with its `target/`: teardown is a classified operation and it
should ride the milestone reap party, not a solo call.

### Next, per doyle's order

1. His gate verdict on `d21aed6a`; respin here if red.
2. #11/#14 verify-close evidence comments (verify-don't-build).
3. The operator referral brief (#11c flags, #16 gap, #17/#246).
4. Golden head assembly.

---

## LANDED 2026-08-30 — lane closed

doyle gated `d21aed6a` GREEN and ff'd main `cb78f710` -> **`dc07e215`** (pick-audit 1/1 MATCH,
all six legs 0 by exit file, bins 753/753, e2e 1/1). **Zero respins this wave.** #133 -> ACCEPTANCE.
Pool `ns23-w3` **RELEASED** (exit file 0). Worktree left standing: teardown is a classified
operation and rides the milestone reap party with `.worktrees/ns23-w1`, never a solo call (IR-14).

Verify-close pass on #11/#14 handed to doyle as deltas against his W0-staged drafts — 7
confirmations, 3 deltas, all re-measured AT `dc07e215` (W3 touched `reporting.rs`, so the earlier
`cb78f710` reading was not carried forward). Report:
`…/ff964315-…/scratchpad/ns23-verify-deltas.md`. The load-bearing one is a DEFECT CANDIDATE: the
`spt-shells` deprecation gate is inert on 2 of its 3 callers (`cmd_boundary` = every `/clear`, and
post-spawn `cmd_bind`) because both route through `resurface_notifs(id)` -> `(id, None)`, and
`is_some_and` over `None` is unconditionally false. Predicted from the code, then observed in this
session's own transcript with a compliance-declaring adapter on a binary that carries the gate.
