# M12 Wave 5 — `spt whoami` → endpoint-list alias — JIT plan

> todlando 2026-06-14, after W4 GATE PASS + commit @b7cda13. W5 is the last
> coding wave before W2.5 (attach/kick, own slice) and the full M12 gate.
> **DESIGN-CHECK PENDING — one contract question for doyle (Q1) before building.**
> Spec: `M12-PLAN.md` Wave 5.

## Scope (M12-PLAN.md Wave 5)
- **T5.1** `spt whoami` → **alias for `spt endpoint list`**; the **SELF-pin** output
  additionally includes the Self endpoint's **`endpoint description`** (its authored
  blurb). Keep `whoami` in the agent hot-path (top-level verb, unchanged parse).

## What EXISTS today (investigation 2026-06-14)
- **`cmd_whoami` (cli.rs:2732)** today prints **only the bare self perch id** to stdout
  (`println!("{id}")`, exit 0), or `UNKNOWN…` + exit 1. `roster::detect_self_id()` is
  the source (env-based: `$OWL_SESSION_ID` / `$SPT_AGENT_ID`), NOT parsed from output.
- **`cmd_endpoint_list(local, subnet, detail)` (cli.rs:1492)** already does the **SELF
  pin**: when `detect_self_id()` resolves, it prints `SELF: {id}  {state} ready=… alive=…`
  first, then `SUBNET <name>` groups with endpoint rows. `--local` short-circuits to
  `cmd_list_local`. So "alias for endpoint list" is mostly a re-dispatch.
- **Self endpoint description** is reachable: `spt_store::info::read_info(&perch_path)
  .resources` where `perch_path = perch::resolve_perch_path(&id, ParentHint::Infer)` —
  exactly what `cmd_description` (cli.rs:1352, `DescriptionCmd::Show`) reads. `None` =
  no authored blurb (node seed advertises, if any).
- **Hot-path / contract note:** the `how-to: ready` text (cli.rs:4581) tells agents
  *"`spt whoami` prints it [your perch id]"* — i.e. the documented scriptable contract is
  `id=$(spt whoami)`. REQ-MSG-9 pins whoami's **parse** stability at the top level (not
  its output shape), so an output change doesn't break REQ-MSG-9, but it DOES break the
  documented bare-id capture.

## The DELTA
1. Re-dispatch `cmd_whoami` to the endpoint-list view (SELF pinned).
2. Augment the **SELF pin line** (in whoami, and arguably in `endpoint list` too) with the
   Self endpoint's authored description.
3. Reconcile the `how-to: ready` doc + register the REQ.

## Open design question for doyle
**Q1 — `whoami` output shape vs the bare-id contract.** "Alias for `endpoint list`"
(rich, multi-line: SELF pin + every subnet's endpoint rows) collides with the documented
hot-path contract `id=$(spt whoami)` (bare id on stdout). Three readings:
- **(A) Full alias** — whoami emits the entire `endpoint list` view, SELF line gains the
  description. Cleanest literal read of the plan; **breaks** `$(spt whoami)` bare-id capture
  (agents/onboarding doc must change to a new id source, e.g. `endpoint list --local` or a
  `--id` flag).
- **(B) SELF-card only** *(my lean)* — whoami emits just the **SELF pin block** enriched
  with the description (`SELF: {id}  {state}` + a description line), NOT the full subnet
  roster. Honors "alias for endpoint list" (it's the SELF-pin slice of that view) AND
  "keep in the agent hot-path" (tight identity card); the **id stays the first token** so a
  narrowed capture still works, and `spt endpoint list` remains the full roster. Smallest
  blast radius.
- **(C) Full alias + preserved bare-id** — full list, but keep an explicit bare-id path
  (`spt whoami --id` or `spt endpoint list --self-id`) so scripts migrate to it. More
  surface than B for the same end.

**Recommend B** (SELF-card: id + state + description; full roster stays `endpoint list`),
unless you read the plan's "alias for endpoint list" as strictly A. Either way the **id
remains the first stdout token** so the hot-path capture degrades gracefully, and I'll
reconcile the `how-to` text to match the chosen shape.

**Q2 — REQ granularity.** No REQ is named for T5.1. Recommend a small **NEW REQ-WHOAMI-1**
(doc+impl+unit: whoami renders the SELF identity card incl. description; id-first;
hot-path-stable parse) rather than overloading REQ-MSG-9 (which is about parse-flatness,
not this view). doc+impl+unit, no int (pure view over the roster + info store).

## Tentative tasks (pending Q1/Q2 ruling)
- **T5.0** add the REQ to `traceable-reqs.toml` (REQ-WHOAMI-1 per Q2).
- **T5.1a** factor the SELF-pin render (id + state + description) into a small helper used
  by `cmd_whoami` and (option A/C) `cmd_endpoint_list`; read the description via
  `info::read_info`. Pure-ish render unit-tested over a fixture roster row + blurb.
- **T5.1b** re-dispatch `cmd_whoami` to the chosen shape; reconcile the `how-to: ready`
  doc line + CHANGELOG.
- Sweep: full suite green · clippy -D · `traceable-reqs check` EXIT=0. W5 gate (doyle).
  Then **W2.5** (attach/kick) → full M12 gate → unblock perri.

## RULING (doyle via owl 2026-06-14, operator-overridden) — Q1 = A (FULL alias)
Operator overrode the bare-id concern: `id=$(spt whoami)` was NEVER a real pattern (env
vars don't persist between an agent's tool calls), so there is no contract to protect — no
graceful-degrade, no `--id` flag, no how-to migration. **Drop** the standalone bare-id
`cmd_whoami`; `spt whoami` dispatches to `cmd_endpoint_list` (full output: SELF pin +
roster). The **one real code change**: the `endpoint list` SELF pin gains the Self endpoint
description (`info::read_info(...).resources`). Q2 = NEW **REQ-WHOAMI-1** (doc+impl+unit, no
int); unit = rendered SELF line includes the description; whoami dispatch == endpoint-list
dispatch.

## BUILT — sweep GREEN, ready for doyle gate (2026-06-14, todlando)
All on `m12-w1-bringup-rc`, UNCOMMITTED.
- **T5.0** REQ-WHOAMI-1 (doc+impl+unit) added to `traceable-reqs.toml`.
- **render_self_pin(self_id, state, description)** — pure SELF-pin renderer; description
  inline after the state when present, omitted (no dangling separator) when absent/blank.
- **cmd_endpoint_list** SELF pin now reads `info::read_info(resolve_perch_path(self_id,
  Infer)).resources` and renders via `render_self_pin` — the one behavior change (shared by
  `endpoint list` AND the `whoami` alias).
- **cmd_whoami** reduced to a thin alias: `cmd_endpoint_list(false, None, false)`. Bare-id
  impl gone. `Cmd::Whoami` parse variant unchanged (hot-path stable, REQ-MSG-9).
- **Docs:** CONTEXT.md "whoami (alias for endpoint list)" (`<!-- [doc->REQ-WHOAMI-1] -->`);
  in-binary `how-to: ready` line reworded (drop the `id=$(spt whoami)` framing).
- **Unit:** `self_pin_includes_description_when_present` (present/absent/blank) +
  `whoami_is_an_endpoint_list_alias` (parse stays top-level).
- **SWEEP:** build clean · clippy `-p spt --all-targets -D warnings` clean · `cargo test -p
  spt --bin spt` **157 passed / 0 failed** · `traceable-reqs check` **EXIT=0** (REQ-WHOAMI-1
  OK) · `xtask check` OK (no CLI-reference drift).

## Notes
- Build UNCOMMITTED until doyle gate; then commit the gated batch myself
  (standing operator instruction + "don't wait").
