# ECHO-COMMUNE-PLAN — v0.15.2: author `[session.echo_commune]` + `[history]` (field-forced)

## Why now (field incident 2026-07-07)

flynn's psyche host died mid-field on core 0.28.0:

> `psyche per-event turn failed 3x consecutively: commune-sync: echo-commune spawn failed:
> manifest declares no [session.echo_commune] role` (info.json, 2026-07-07T06:06:29Z)

Our manifest deferred `echo_commune` (and its `[history]` feeder) since the v0.7-era parity
trim — harmless through core 0.25; core 0.27/0.28 now spawns the echo-commune summarizer on
commune ingest and 3-strikes the whole psyche host when the role is missing → checkpoints
dead. Core-side skip-vs-fail seam filed to doyle separately; adapter-side we author the role
regardless (it is real parity we deferred, and the published surface now documents it).

## Scope (this slice)

1. **`[history]`** — the transcript-access seam ("feeds the echo-commune verbatim",
   published contract). `strategy = "fetcher"`: `claude-spt history --session {session_id}
   --config-dir {CLAUDE_CONFIG_DIR}` locates the CC JSONL transcript (same
   locate/precedence machinery as the `[digest]` fetcher, v0.10.0) and streams it to stdout
   **verbatim** (opaque — core never parses it; only OUR summarizer reads it).
2. **`[session.echo_commune]`** — the bounded summarizer role. `claude-spt echo-commune
   --id {id} --session-id {session_id}`: reads the history on **stdin** (core feeds the
   `[history]` output verbatim), falls back to self-locating the transcript when stdin is
   empty (blind-build hedge — the exact core-side wiring of history→stdin is not published),
   takes a bounded tail, runs ONE headless `claude -p` turn (psyche-parity sandbox, Read-only
   tools), prints the context-delta summary to stdout. Loud nonzero on any failure.
   `recursion_guard_env = "SPT_ECHO_COMMUNE"` per the published role table.
3. **Hook recursion-guard bail** — `claude-spt hook` exits 0 immediately (no api calls, no
   perch writes) when `$SPT_ECHO_COMMUNE` is set: the summarizer's spawned claude must never
   seed/bind/stamp anything (no summarizer-of-summarizer loops, no perch stomps).

## Open design facts (assumptions to verify on-node, then with doyle)

* `[history]` fetcher fills: `{session_id}` published; `{CLAUDE_CONFIG_DIR}` assumed to fill
  like the `[digest]` fetcher (same read-var). Literal-`{...}` guard on the flag as the
  F-013-class hedge.
* echo_commune spawn: keys assumed `{id}` + `{session_id}` (parent/ended session); history
  assumed piped on stdin. The shim tolerates BOTH wirings (stdin-fed or self-locate).
  **Key catalog + I/O contract for echo_commune are unpublished — docs-gap finding to doyle.**

## Non-scope

`[session.signoff]` / `[session.notif]` stay deferred (no field forcing). Core skip-vs-fail
behavior is core's. Double-spawn + perch-stomp findings are core's (filed).

## Gate

cargo test green + `traceable-reqs check` green + manifest-schema CI gate green →
v0.15.2 cut (floor stays 0.27.0, cplugs skeleton unchanged) → publish → node update →
single flynn respawn → field verify (commune ingest with no psyche_host_error).
