{
  "summary": "## Finding\n\n**Hyphenated endpoint ids are not the cause of the `slammie-n → gaki-n` shortform failure.** The shortform is adapter-owned syntax, not an `spt-core` CLI shorthand. In the sibling adapter, `tools/claude-spt/src/tag_scan.rs::scan_prose_segment` recognizes `@<…@>`, takes the target-list substring verbatim up to the first Unicode whitespace, splits that substring **only on commas**, trims each comma member, and copies each member into a `String`. It never splits on `-`, treats an internal hyphen as an option marker, lowercases, normalizes, or validates the target. The current source has an incident-specific unit test, `hyphenated_targets_parse`, asserting both `@<gaki-n hello over there @>` and `@<gaki-n,slammie-n,doyle fan out @>` parse exactly.\n\nThe production dispatch also preserves both ids verbatim. `hook.rs::scan_and_dispatch` iterates each parsed target and calls `HookEnv::spt_send(&[\"send\", \"--from\", id, target], Some(body))`. `SysEnv::spt_send` constructs `Command::new(SysEnv::spt_bin()).args(args)` and pipes the body to stdin. Thus the incident produces four distinct argv values after the executable: `send`, `--from`, `slammie-n`, `gaki-n`. Neither id is shell-interpolated; neither internal hyphen is exposed as a leading option token. In `spt-core`, clap binds `gaki-n` to `Cmd::Send::target: String` and `slammie-n` to the value of `--from`; `cli::run` passes them unchanged to `cmd_send`. Local delivery uses the target as an exact perch/registry key; WAN fallback parses it with `spt_proto::addr::Address`, whose validator explicitly permits `-`. `spt_proto::id::accepts_plain_and_composite_ids` already accepts `kebab-case`, `doyle-psyche`, and `doyle-w331`. `gaki-n` is also classified by `spt_store::perch::PerchKind::classify` as a normal flat `Self_` perch: only the exact suffix `-psyche` or `-w` followed by digits gets nested treatment.\n\n### Source-grounded incident cause\n\nThe adapter's own v0.24.0 requirement and manifest notes identify the `slammie-n → gaki-n` sequence:\n\n1. `gaki-n`'s perch had died because of the separate Windows live-anchor defect (`REQ-LIVE-ANCHOR-WIN32`; MSYS `$PPID` could collapse to pseudo-init `1`). That lifecycle defect is outside this message-parsing target.\n2. The shortform parser successfully extracted `gaki-n` and the hook attempted the exact call `spt send --from slammie-n gaki-n`.\n3. Core returned `NO_PERCH:gaki-n is not listening`; `hook.rs::send_landed` correctly classifies only `SENT*`, `QUEUED*`, or `DEFERRED*` as landed, so this became the shortform confirmation `[tag-send] NO PERCH (not delivered) → gaki-n`.\n4. The pre-v0.24 Stop path deliberately dropped the end-of-turn confirmation to avoid an older F-035 problem in which successful confirmations resurfaced during unrelated later turns. That policy accidentally dropped **failure** confirmations too. The sender therefore saw silence and could mistake the event for a parser failure.\n5. Current v0.24.0 source fixes the visibility defect in `handle_stop`: pure-success end-of-turn confirmations remain dropped, but a failed confirmation is self-sent to the sender as an ordinary spoolable message. If that self-send also refuses, the adapter logs `claude-spt hook: end-of-turn tag-send FAILURE could not be surfaced to <id> (self-send refused) — …`.\n\nThis is directly locked by `hook.rs::stop_failure_confirm_is_self_sent`, using the exact ids and transcript `@<gaki-n status ping @>`. Its recorder expects the peer attempt `send --from slammie-n gaki-n`, returns `NO_PERCH:gaki-n is not listening`, expects the failure-confirm self-send `send --from slammie-n slammie-n`, and asserts its stdin contains `NO PERCH (not delivered) → gaki-n`. `stop_failure_selfsend_refusal_logs_loud` covers the final log fallback. These tests falsify option parsing, splitting, normalization, and rejection as explanations for the incident.\n\n## Ranked, falsifiable mechanisms\n\n1. **Confirmed field mechanism: target perch absent/dead, followed by swallowed Stop-path failure feedback.** Evidence: adapter manifest v0.24.0 notes, `REQ-TAG-SEND-FAILURE-LOUD`, and exact-id hook tests. Falsifier: a captured dispatch where `spt send --from slammie-n gaki-n` returns `SENT`, `QUEUED`, or `DEFERRED` rather than `NO_PERCH`.\n2. **Shortform parser mishandles an internal hyphen — falsified by source and explicit unit coverage.** `scan_prose_segment` only searches whitespace and splits commas; `hyphenated_targets_parse` locks the exact ids. Falsifier of this conclusion would be a different installed adapter binary/version than the inspected v0.24.0 source, or a transcript in which the tag is quoted/incomplete and therefore intentionally not scanned.\n3. **Core clap treats `gaki-n` or `slammie-n` as options — falsified for these spellings.** Both hyphens are internal, not the first character of an argv token, and the adapter passes an argv array. A genuinely **leading** hyphen target such as `-gaki` is a different clap edge and is not equivalent to `gaki-n`.\n4. **Core target resolution splits or normalizes an internal hyphen — falsified.** Local perch resolution uses the exact string, except for the documented exact `-psyche` and `-w<digits>` suffix classifications; WAN registry lookup is `BTreeMap::get(&address.id)` on the exact id. `gaki-n` matches neither special suffix.\n5. **Elevation changes shortform parsing — falsified by architecture.** Neither `tag_scan` nor `scan_and_dispatch` receives an elevation bit, and `spt-core::cmd_send` has no elevation gate. Any observed elevated/non-elevated difference must arise after parsing—different installed adapter/core version, `SPT_HOME`, perch contents, daemon state, process ancestry, or permissions—not from hyphen grammar. The environment/state possibilities are an **[INFERENCE]** from the absence of elevation inputs on this call chain, not a claim that a particular one occurred.\n\n## Exact deterministic repro/test seams\n\n### Existing pure parser test\n\nRead-only investigation found the exact existing test:\n\n```text\ncargo test --manifest-path C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/Cargo.toml hyphenated_targets_parse\n```\n\nIt compares a single hyphenated target and a mixed comma fan-out. The test was inspected but not executed, per the read-only/no-broad-suite constraint.\n\n### Existing full hook-planning seam, with the incident ids\n\n```text\ncargo test --manifest-path C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/Cargo.toml stop_failure_confirm_is_self_sent\ncargo test --manifest-path C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/Cargo.toml stop_failure_selfsend_refusal_logs_loud\n```\n\nThese are deterministic and perform no live endpoint send: `Recorder` supplies a newline-terminated Claude transcript, a pre-seeded byte cursor (`state/digest/slammie-n.pos = 0`), canned `whoami --json`, and canned `spt_send` results. Pre-seeding the `.pos` cursor is load-bearing: with no cursor, `scan_and_dispatch` intentionally initializes it to transcript EOF and skips historical output.\n\n### Recommended paired matrix to close the remaining comparison gap\n\nAt the existing `Recorder` seam, table-drive two otherwise identical cases:\n\n```text\nplain:      self=slammien, target=gakin,  tag=@<gakin status ping @>\nhyphenated: self=slammie-n, target=gaki-n, tag=@<gaki-n status ping @>\n```\n\nFor both, seed `<self>.pos=0`, return the same `whoami` shape, and have `spt_send` return the same selected outcome. Assert:\n\n- parsed `TagSection.targets == [target]` byte-for-byte;\n- recorded argv is exactly `[\"send\", \"--from\", self, target]`;\n- recorded stdin is exactly `status ping`;\n- `SENT/QUEUED/DEFERRED` yields the same delivered classification;\n- `NO_PERCH` yields the same failed classification and Stop-path self-send;\n- the only differing bytes in calls/confirmations are the expected id spellings.\n\nThis is the minimal deterministic comparison because it crosses transcript extraction, cursor gating, shortform grammar, fan-out planning, argv construction, stdin routing, result-token classification, and failure feedback without touching a live endpoint.\n\n### Optional process-level adapter→core harness\n\nFor the deferred integration rung, place a fake `spt` executable first on `PATH`. Have it log NUL-delimited argv plus stdin and emit a chosen result token on **stderr** (matching core). Invoke the real `claude-spt hook Stop` twice with isolated adapter state and newline-terminated transcript JSONL—once for the plain pair and once for the hyphenated pair. Assert the logged argv/stdin matrices above and the failed-confirm behavior. Then a second isolated rung can replace the fake with the real `spt` binary and a temporary `SPT_HOME` containing offline perches, expecting `QUEUED:<target>` and exact spool `from`/body. This stays hermetic and does not involve `hertz` or any installed live endpoint.\n\n## Existing coverage gap\n\nPure grammar coverage and hook-level incident coverage now exist. The remaining gap is **process/live integration**, not hyphen grammar:\n\n- `traceable-reqs.toml` explicitly records the `REQ-TAG-PEER-MESSAGING` live integration as deferred: an agent emitting a tag should actually deliver through a bounced installed adapter and receive the confirmation.\n- `REQ-TAG-SEND-FAILURE-LOUD` describes an integration acceptance—kill a disposable target perch, emit an end-of-turn shortform, and observe the failure notice next turn—but its activated required stages remain only `impl` and `unit`.\n- There is no inspected subprocess test that compares non-hyphenated and hyphenated ids through the real adapter binary and real/fake `spt` argv boundary. The existing `Recorder` test proves the exact call logically, while `spt-core` separately proves hyphens are valid ids; the cross-binary composition remains unproven by an integration test.\n\nNo files were edited, no build/test command was executed, and no product message was sent. The live endpoint `hertz` was not touched.",
  "files": [
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/src/tag_scan.rs",
      "description": "Owns shortform grammar. `parse_tag_sections`/`scan_prose_segment` scan prose-only `@<…@>` blocks, stop target parsing at first whitespace, split only on commas, and preserve internal hyphens. `hyphenated_targets_parse` covers `gaki-n` and `slammie-n` explicitly."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/src/hook.rs",
      "description": "Production routing seam. `scan_and_dispatch` tails completed assistant transcript lines via a byte cursor, plans sends, and calls `HookEnv::spt_send([\"send\",\"--from\",self,target], body-stdin)`. `SysEnv::spt_send` uses an argv array and captures both streams. `send_landed`, `handle_pre_tool_use`, and `handle_stop` determine visible confirmation behavior. Exact incident tests are `stop_failure_confirm_is_self_sent` and `stop_failure_selfsend_refusal_logs_loud`."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/plugin/sptc/hooks/hooks.json",
      "description": "Wires Claude Code `PreToolUse` and `Stop` events (among others) to the thin plugin dispatcher; these are the mid-turn and end-of-turn shortform trigger surfaces."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/plugin/sptc/hooks/dispatch.sh",
      "description": "Static thin wrapper resolving the installed `claude-spt` adapter binary and execing it as `claude-spt hook <event> --host-pid <pid>` while preserving hook JSON on stdin."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/tools/claude-spt/src/main.rs",
      "description": "Routes the consolidated adapter binary's `hook` subcommand to `hook::run`; also tolerates stale plugin dispatch that omits the `hook` token for known CC event names."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/traceable-reqs.toml",
      "description": "Defines `REQ-TAG-PEER-MESSAGING`, `REQ-HAZARD-SEND-STATUS-STDERR`, and `REQ-TAG-SEND-FAILURE-LOUD`; documents the exact shortform contract, stderr result-token hazard, slammie-n→gaki-n failure visibility incident, and deferred live integration coverage."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/adapter/claude-spt.toml",
      "description": "v0.24.0 release note pins the field facts: gaki-n Win32 anchor failure and slammie-n→gaki-n end-of-turn shortform failure feedback being swallowed; states the fix is adapter-side and requires no new core seam."
    },
    {
      "path": "C:/Users/decid/Documents/projects/spt-claude-code/plugin/sptc/skills/send/SKILL.md",
      "description": "User-facing definition of the `@<t1,t2 body @>` shortform. Confirms the comma-separated targets-to-first-space and body-to-first-`@>` grammar."
    },
    {
      "path": "crates/spt/src/cli.rs",
      "description": "Core clap and routing boundary. `Cmd::Send` has required positional `target: String` and `--from: Option<String>`; `run` forwards them to `cmd_send`, which renders exact outcome tokens including `NO_PERCH:<target> is not listening`. No send elevation gate exists."
    },
    {
      "path": "crates/spt-msg/src/deliver.rs",
      "description": "Local send routing. `send_windowed` checks exact target perch existence, performs exact target TCP lookup, and spools against the exact resolved perch path. No target split or normalization."
    },
    {
      "path": "crates/spt-store/src/perch.rs",
      "description": "Exact perch classification/resolution. General hyphenated ids are flat Self perches; only exact `-psyche` and `-w<digits>` suffixes are structurally interpreted."
    },
    {
      "path": "crates/spt-proto/src/id.rs",
      "description": "Endpoint-id charset explicitly permits ASCII `-`; unit test accepts `kebab-case` and composite hyphenated ids."
    },
    {
      "path": "crates/spt-proto/src/addr.rs",
      "description": "WAN address grammar validates the id but preserves it; only reserved `:` and `@` qualifiers are split."
    },
    {
      "path": "crates/spt/src/wansend.rs",
      "description": "WAN fallback parses the exact target through `Address::parse` and passes `address.id` into registry resolution; malformed addresses become `WAN_FAIL … bad address`, not a hyphen-specific failure."
    },
    {
      "path": "crates/spt-net/src/net/registry.rs",
      "description": "WAN resolution performs exact `BTreeMap` lookup with `instances(&address.id)`; only node qualifiers are case-insensitively matched, not endpoint ids."
    }
  ],
  "architecture": "```text\nClaude assistant output\n  └─ appended as newline-terminated assistant JSONL in CC transcript\n       ├─ PreToolUse hook (mid-turn)\n       └─ Stop hook (end-of-turn backstop)\n            └─ plugin/sptc/hooks/dispatch.sh\n                 └─ claude-spt hook <event>\n                      └─ hook::run → dispatch\n                           ├─ handle_pre_tool_use\n                           └─ handle_stop\n                                └─ scan_and_dispatch\n                                     ├─ digest_cursor_rel(self) / read_file_tail\n                                     ├─ complete_line_prefix\n                                     ├─ assistant_texts_from_jsonl\n                                     ├─ plan_dispatch\n                                     │    └─ parse_tag_sections\n                                     │         └─ scan_prose_segment\n                                     │              targets = bytes to first whitespace\n                                     │                        split(',') only\n                                     │                        trim + copy verbatim\n                                     └─ for each target:\n                                          HookEnv::spt_send(\n                                            [\"send\", \"--from\", self, target],\n                                            stdin = body\n                                          )\n                                               └─ SysEnv: Command::new(spt).args(argv)\n                                                    └─ spt-core clap\n                                                         Cmd::Send { target, from, … }\n                                                          └─ cmd_send\n                                                               ├─ exact local perch/registry route\n                                                               │    └─ spt_msg::deliver::send_windowed\n                                                               └─ on NoPerch: exact WAN address route\n                                                                    └─ Address::parse\n                                                                         └─ resolve_across_visible\n\nResult feedback:\n  SENT* | QUEUED* | DEFERRED* → landed\n  anything else, notably NO_PERCH* → failed\n\n  PreToolUse: inline `[tag-send] …` as additionalContext.\n  Stop success: drop confirmation (avoids unrelated later noise).\n  Stop failure: self-send `[tag-send] NO PERCH …` to sender;\n                if self-send fails, write loud hook-log fallback.\n```\n\nThe decisive boundary is the argv array built in `scan_and_dispatch`: `slammie-n` and `gaki-n` are already separate, complete strings before core sees them. Internal hyphens have no syntactic role at any downstream layer. Therefore an elevated-vs-ordinary discrepancy cannot be diagnosed as a hyphen parser issue unless the installed adapter differs from this source; compare the recorded argv and core result token first. Equal argv plus a `NO_PERCH` only for the elevated endpoint points to endpoint/perch lifecycle or environment/state, while unequal/missing argv points to hook transcript/cursor/quotation behavior."
}