# Phase 25.1: Revise /commune + /signoff Skill Docs + Echo-Commune Instruction — Research

**Researched:** 2026-05-21
**Domain:** Self-facing skill markdown (doc-only revision); contract surfaces for two-slice envelope authoring + receive
**Confidence:** HIGH (every claim grounded in a file:line read this session)

## Summary

This is a **surgical doc-only phase** with five concrete file touchpoints, all decisions locked in CONTEXT.md (D-25.1-01..08). The Phase 25 substrate is fully shipped: the canonical two-slice taxonomy lives in `psyche.md` §`<output_envelope>` (lines 282–323), the parser lives in `src/common/envelope.rs::parse_two_slice`, the composer that wraps the two-slice body into `<EVENT type="echo_commune">` lives in `src/owl/echo_commune.rs` (not `src/live/echo_commune.rs` — that path does not exist; the live-side file is `src/live/wrapper/echo_fire.rs` which is the *gate*, not the *composer*). Self-side skill docs currently teach NONE of the two-slice contract — every touched file still talks as if there is one undifferentiated commune body.

The one open question (D-25.1-04: does `download_payload()` post-Phase-25 emit a marker Self can grep on?) **resolves to NO**: the project file body is appended **raw** with no header, no wrapping tag, no sentinel. The presence/absence of a project section is detectable only by content inspection or by line-counting against the live-context portion. **The planner should add a follow-up task to introduce an explicit sentinel** (`<project-context-resolved/>` or a `## Project Context` H2) OR rewrite D-25.1-04's instruction to key on a different signal (recommended below).

**Primary recommendation:** Plan five doc-edit tasks (one per touchpoint) plus ONE small Rust task adding a grep-able sentinel to `download_payload()`. The sentinel task is the only reason this phase touches code; without it the D-25.1-04 instruction "Self detects project section from psyche-download output" is non-operational and the doc rewrites would teach a contract Self cannot actually evaluate.

## User Constraints (from CONTEXT.md)

### Locked Decisions

- **D-25.1-01: Required two-slice envelope.** Self-authored commune and signoff bodies MUST wrap content in `<live-context>...</live-context>` and (when applicable) `<project-context>...</project-context>`. Symmetric with `psyche.md` §`<output_envelope>` (282–323).
- **D-25.1-02: In-project + no project-specific update → empty `<project-context></project-context>`.** Empty body = "in-project but quiet" signal.
- **D-25.1-03: Outside any tracked project → omit `<project-context>` entirely.** No empty envelope; missing tag = "no project resolved".
- **D-25.1-04: Self determines in-project status via existing `$LIVE psyche-download` output.** Skill must teach: "If the output contains a project section, you are in a tracked project — include `<project-context>`. If only memformat + live_context is present, omit it."
- **D-25.1-05: Two-slice echo-commune body absorbed as one brief.** No differentiated handling.
- **D-25.1-06: Echo-commune teaching surfaces live-only.** Touch `/live` (line ~268), `/revive`, and SessionStart `<psyche-context>` prose. Explicitly NOT `/listen`.
- **D-25.1-07: Skill docs stay SILENT on the untagged-commune fallback.** Psyche LLM auto-classifies — but don't tell agents.
- **D-25.1-08: Drop legacy "Memformat Guide" framing where it conflicts with two-slice routing.** Memformat informs CONTENT; envelope routing is independent.

### Claude's Discretion

- Exact rewrite shape of `commune.md` examples (recommend 3: in-project-both, in-project-empty-project, outside-project; anti-example optional).
- Whether `commune/SKILL.md` "Envelope shape (Phase 23 v1.8)" section needs reordering vs forward-link to the new two-slice teaching. Phase 23 EVENT envelope wraps the Phase 25 two-slice body — they nest; doc must not conflate.
- Exact prose for SessionStart `<psyche-context>` block header/footer.
- Whether to add "Why two slices?" link from each touched doc back to `25-CONTEXT.md` D-10.
- Cross-link tightness for `/live` echo-commune section → `/listen` parsing rules (recommend link, not duplicate).

### Deferred Ideas (OUT OF SCOPE)

- Memformat taxonomy split (role-vs-project topics).
- Diligence-trigger updates (project-state-shift trigger).
- `/listen` echo-commune teaching.
- Anti-example for `commune.md`.
- `download_payload` output marker — **flagged as deferred in CONTEXT, but research finds it is BLOCKING for D-25.1-04. See Open Question Resolution below.**
- Untagged-commune telemetry.

## Architectural Responsibility Map

| Capability | Primary Tier | Secondary Tier | Rationale |
|------------|-------------|----------------|-----------|
| Self-authored commune body shape | Self (agent prose) | — | Skill docs teach the contract; no runtime enforcement on Self side |
| Two-slice envelope parsing | Composer (`src/owl/echo_commune.rs`, `src/live/signoff.rs`) | `src/common/envelope.rs::parse_two_slice` | Already shipped Phase 25; docs only describe what the parser expects |
| Routing live slice → `agents/<id>/live_context.md` | `src/common/tracked.rs::commit_agent_payload` | — | Phase 24 substrate; no Phase 25.1 touch |
| Routing project slice → `projects/<cwd>/<id>.md` | `src/common/tracked.rs::commit_project_payload` | — | Phase 25 D-13 substrate; no Phase 25.1 touch |
| In-project signal for Self | `src/live/context.rs::download_payload()` output | `derive_current_repo_names()` upstream | **Currently lacks a stable marker — see Open Question Resolution** |
| Echo-commune `<EVENT>` envelope composition | `src/owl/echo_commune.rs::route_two_slice` | `src/live/wrapper/echo_fire.rs` (gate) | Already shipped; docs describe shape |
| SessionStart `<psyche-context>` injection | `src/owl/resume.rs:198-205, 326-333` | `src/live/context.rs::download_payload_for_injection` | Block content is from `download_payload()`; the **wrapper prose around it** is the discretionary doc surface |

## Phase Requirements

No formal requirement IDs were mapped (urgent insert per ROADMAP §Phase 25.1). Phase scope traces to CONTEXT D-25.1-01..08 directly.

## Touchpoint 1: `plugin/spt/skills/commune/SKILL.md`

### Current shape

Read 2026-05-21. 59 lines total. Two relevant sections:

- **Lines 14–42** — `## Flow` (3 steps). Step 1 (lines 17–22) runs `$LIVE psyche-download <your-id>`. Step 2 (lines 23) describes how to compare. Step 3 (lines 25–37) instructs `.claude/{your-id}-commune.md` via Write tool. **No mention of envelope wrapping anywhere.**
- **Lines 44–58** — `## Envelope shape (Phase 23 v1.8)`. Documents the OUTER `<EVENT type="commune" ...>body</EVENT>` envelope with 5-field stamp. Closes with: *"`$LIVE commune` composes this envelope automatically — Self does NOT manually construct EVENT XML."* (line 58). This is the Phase 23 nesting-clarity anchor.

### What must change (mapped to decisions)

- **Add new section** (recommended landing spot: between current "Flow" and "Envelope shape (Phase 23 v1.8)", as `## Two-slice body shape (Phase 25 D-10/D-11)`) — teaches D-25.1-01..04.
- **Update Step 3** of `## Flow` (lines 25–29) — current text reads *"with the delta body as its contents"*. Reword to *"with the two-slice body as its contents (see Two-slice body shape below)"*.
- **Strengthen the Phase 23 envelope section** (line 58) with one explicit sentence: *"The two-slice body (see above) sits INSIDE the EVENT envelope; the two layers nest."* Per CONTEXT D-25.1 specifics: "Doc nesting clarity for envelopes".

### Exact landing spots / section headers

- New header text: `## Two-slice body shape (Phase 25 D-10/D-11)` (matches established "Envelope shape (Phase 23 v1.8)" convention).
- The new section should cross-link `psyche.md §<output_envelope>` for canonical taxonomy (lines 282–323 of `psyche.md`).
- The Step 3 reword is one-line surgical.

### Acceptance evidence

- `grep -c "<live-context>" plugin/spt/skills/commune/SKILL.md` ≥ 2 (taxonomy mention + at least one inline example).
- `grep -c "<project-context>" plugin/spt/skills/commune/SKILL.md` ≥ 2.
- `grep "Phase 25 D-10" plugin/spt/skills/commune/SKILL.md` returns ≥ 1 match.
- `grep "nest" plugin/spt/skills/commune/SKILL.md` returns ≥ 1 match (Phase 23 ⊃ Phase 25 nesting clarity).
- The phrase "DOES NOT construct EVENT XML" (line 58 paraphrase) remains intact post-edit.

### Risks / drift hazards

- **Do NOT paraphrase the taxonomy.** `psyche.md §<output_envelope>` is canonical (lines 286–322). Skill doc should QUOTE the bullet lists verbatim or link to them. Paraphrase risks drift on future taxonomy revisions.
- **Do NOT add an EVENT-wrapping example into the new section.** The skill-doc convention is "Self never writes EVENT" (line 58); a worked example with raw `<EVENT>` tags would directly contradict it.
- The Phase 23 envelope section's `body` placeholder in the XML example (lines 49, 55, 62, 68) is now misleading — that `body` is the two-slice body. Consider a one-line comment in the example or a forward-link to the new section.

## Touchpoint 2: `plugin/spt/skills/commune/commune.md`

### Current shape

Read 2026-05-21. 81 lines. Six sections:

- **Lines 1–10** — `# Communes` intro + `## How to Send` (Write-tool path; states "wrapper composes the user-facing `<EVENT type='commune'>` envelope from your file body"). This line is currently TRUE but says nothing about two-slice wrapping inside the body.
- **Lines 11–15** — `## Memformat Guide`. **D-25.1-08 target.** Currently says: *"the memformat content appears first in the output, wrapped in `<memformat>` tags. Use the listed topics as a guide for what to include."* The guide tells Self what to think about; it must be clarified that topic-content and envelope-routing are independent dimensions.
- **Lines 17–19** — `## Visibility of Pending Communes`. Describes the `## Pending Commune (uncommitted)` section. Not directly touched.
- **Lines 21–30** — `## When to Send COMMUNEs` + `## Commune Diligence`. Triggers — out of scope (deferred).
- **Lines 42–53** — `## What to Include`. Bullet list of content categories. **Per D-25.1-08: needs a "routing" sub-bullet** clarifying that topics route to either slice depending on whether the captured info is role-bound or project-bound.
- **Lines 55–81** — `## Examples`. **Three current examples are all UNWRAPPED bodies.** Per CONTEXT specifics "Three worked examples": rewrite as in-project-both, in-project-empty-project, outside-project.

### What must change (mapped to decisions)

- **`## Memformat Guide` rewrite (D-25.1-08)**: keep the "topics inform content" framing, but ADD a paragraph: *"Memformat topics inform CONTENT (what to think about). Envelope routing (`<live-context>` vs `<project-context>`) is independent — a topic may land in either slice depending on whether the captured info is role-bound or project-bound."* No memformat schema change in this phase (CONTEXT D-25.1-08).
- **`## How to Send` (line 9)**: keep the EVENT-wrapper sentence; add an adjacent sentence: *"The body you write MUST itself be wrapped in `<live-context>...</live-context>` and (when in a tracked project) `<project-context>...</project-context>`. See `## Two-slice body shape` below."*
- **New `## Two-slice body shape (Phase 25 D-10/D-11)` section** (recommended landing: after `## How to Send`, before `## Memformat Guide`). Contents per D-25.1-01..04: taxonomy table or list (quote from `psyche.md` lines 298–312), rules paragraph (in-project-both / in-project-empty / outside-project, per D-25.1-02/03), and the **detection rule (D-25.1-04)** — but see Open Question Resolution: the detection rule will need to key on whatever sentinel the planner inserts.
- **`## Examples` rewrite (3 worked examples)**. Discretionary phrasing; CONTEXT specifics suggest:
  1. In-project, both slices populated.
  2. In-project, only role/agent state changed → empty `<project-context></project-context>`.
  3. Outside any project → `<live-context>` only.

### Exact landing spots

- New section header (proposed): `## Two-slice body shape (Phase 25 D-10/D-11)`.
- The "Nested envelopes" callout from CONTEXT specifics should land here as a one-paragraph note: *"The Phase 23 `<EVENT type=\"commune\">` envelope is composed by the runtime; you NEVER write EVENT tags. You write ONLY the inner two-slice body."*
- Doc-drift cross-ref line per CONTEXT specifics: `(see psyche.md §<output_envelope> for the canonical taxonomy)`.

### Acceptance evidence

- `grep -c '<live-context>' plugin/spt/skills/commune/commune.md` ≥ 5 (taxonomy + 3 examples + nesting callout).
- `grep '<project-context></project-context>' plugin/spt/skills/commune/commune.md` returns ≥ 1 match (empty-body example).
- `grep -c 'never write' plugin/spt/skills/commune/commune.md` (case-insensitive on "NEVER write EVENT") ≥ 1.
- `grep 'Memformat' plugin/spt/skills/commune/commune.md` still returns matches (section kept, not dropped) — D-25.1-08 is reframe, not deletion.
- No mention of "auto-classify", "Psyche fallback", "untagged" — D-25.1-07 silence rule.

### Risks / drift hazards

- **D-25.1-07 silence trap.** Resist writing prose like *"if you forget to tag, Psyche will figure it out"*. CONTEXT explicitly forbids this.
- The current `## Examples` section uses `waffle` as the agent id. Keep the same id for continuity, OR pick a fresh consistent name across all three examples — do not mix.
- Don't add the FRESH-01 first-commune path here — that's `/live` territory (lines 203–223 of `live/SKILL.md`).

## Touchpoint 3: `plugin/spt/skills/signoff/SKILL.md`

### Current shape

Read 2026-05-21. 72 lines.

- **Lines 14–51** — `## Flow` (3 steps). Step 3 (lines 25–35) describes plain signoff (empty body) vs signoff-with-FINAL-COMMUNE (non-empty body). **The FINAL-COMMUNE body is the Self-authored surface that needs two-slice wrapping** per D-25.1-01..03.
- **Lines 36–51** — offline path (no live listener) — psyche-download absorbs the body into the on-disk context under `## Pending Signoff` header. NOT touched.
- **Lines 57–71** — `## Envelope shape (Phase 23 v1.8)`. Documents `<EVENT type="init_signoff" ...>FINAL COMMUNE: ...body... | Signoff initiated by Self...</EVENT>` — the EVENT wrapper. Same nesting-clarity issue as commune/SKILL.md.

### What must change

- **Step 3 (lines 25–35) reword**: the "Signoff with a FINAL COMMUNE body" sub-bullet (line 31) currently says *"Write the file with the final commune body as its contents."* Reword to *"Write the file with the final commune body as its contents — the body MUST be wrapped in the same two-slice envelope as a regular commune (see `/spt:commune` → Two-slice body shape, or `psyche.md §<output_envelope>`)."*
- **NEW: short cross-ref section** (recommended placement: between Step 3 and "Signoff vs Stop", as `## Two-slice body shape` — short, since the full teaching lives in `/commune`). One paragraph + a link.
- **Strengthen line 71** (Phase 23 envelope section close) with nesting note, same as Touchpoint 1.

### Exact landing spots

- New short section header: `## Two-slice body shape (Phase 25 D-10/D-11)`. Body: 2–4 sentences pointing at `/spt:commune` for full teaching + reiterating the in-project / empty / outside-project rules.
- The Step 3 reword is one-line surgical.

### Acceptance evidence

- `grep '<live-context>' plugin/spt/skills/signoff/SKILL.md` ≥ 1 match.
- `grep 'two-slice' plugin/spt/skills/signoff/SKILL.md` ≥ 1 match (case-insensitive).
- `grep '/spt:commune' plugin/spt/skills/signoff/SKILL.md` ≥ 1 match (cross-link to full teaching).
- Phase 23 envelope examples (lines 62, 68) remain syntactically intact (don't accidentally rewrite the EVENT envelope examples).

### Risks / drift hazards

- The FINAL-COMMUNE body inside the EVENT envelope is currently shown as `"FINAL COMMUNE: ...body... | Signoff initiated by Self..."` (line 68). That `body` placeholder is now the two-slice body. Don't try to inline the two-slice tags into the EVENT example — that would compound nesting confusion. A forward-link to the new section is cleaner.
- Empty-body plain signoff (line 30) is NOT a two-slice body — it's literally empty string. The two-slice contract applies only when the file is non-empty. Make this clear in the new section.

## Touchpoint 4: `plugin/spt/skills/live/SKILL.md`

### Current shape

Read 2026-05-21. 388 lines. The `echo_commune` envelope catalog entry is at **lines 268** (single line in the four-shape catalog):

```
<EVENT type="echo_commune" from="<self-id>-psyche" timestamp="<ISO-8601>" note="<descriptor>">body</EVENT>
```

Followed by description (line 268 continues): *"...auto-fired echo-commune brief from the Psyche wrapper, emitted after a SessionStart-triggered `/clear` or `/compact` cycle (Phase 29 AUTO-EC). `from` is the psyche-id (`<self-id>-psyche`); `note` carries the trigger source... Body is the haiku-model summary."*

Body parsing rule reference is on **line 270**: *"Body parsing (applies to all four types — same escape conventions): split on literal `<br>` to recover newlines, then HTML-unescape each fragment..."*

### What must change (mapped to D-25.1-05/06)

- **Extend line 268's description** with the two-slice body shape: after *"Body is the haiku-model summary"*, append *"wrapped in the Phase 25 two-slice envelope: `<live-context>...</live-context>` + (when in a tracked project) `<project-context>...</project-context>`. After `<br>`-split + HTML-unescape per `/spt:listen` body-parsing rules, the two slices form a single SessionStart resume brief — absorb both as one continuous context."*
- **Do NOT duplicate listen/SKILL.md lines 169–173 parsing rules.** Link to them. CONTEXT code_context section explicitly: *"`/live` echo-commune teaching should LINK to these rules, not duplicate them."*
- **Add a one-line forward-pointer** to `/commune`'s "Two-slice body shape" section so a live agent reading `/live` knows where to find the authoring side of the contract.

### Exact landing spots

- Single-paragraph extension after the current echo_commune bullet at line 268.
- Cross-link target: `plugin/spt/skills/listen/SKILL.md` lines 169–173 (body parsing rules — `<br>`-split + HTML-unescape `&lt;` → `<`, `&gt;` → `>`, `&quot;` → `"`, `&amp;` → `&` LAST).

### Acceptance evidence

- `grep -A 5 'echo_commune' plugin/spt/skills/live/SKILL.md | grep -c 'live-context'` ≥ 1.
- `grep -A 5 'echo_commune' plugin/spt/skills/live/SKILL.md | grep -c 'project-context'` ≥ 1.
- `grep 'two-slice' plugin/spt/skills/live/SKILL.md` ≥ 1 match.
- `grep '/spt:listen' plugin/spt/skills/live/SKILL.md` continues to match (parsing-rule link preserved or added).
- The four envelope shapes (msg / alarm / echo_commune / init_signoff at lines 266–269) all remain present.

### Risks / drift hazards

- **Body parsing duplication.** The strongest temptation is to re-state the `<br>`-split + HTML-unescape rule here. Resist — it lives in `/listen` at exactly one place (lines 169–173) for good reason. Drift between two copies is inevitable.
- The drift-detection block (lines 225–258) handles `<psyche-stamp/>` and `<current/>` — unrelated to two-slice. Don't accidentally edit that.
- Do not touch listener best-practices sections (lines 370+) — out of scope.

## Touchpoint 5: `plugin/spt/skills/revive/SKILL.md`

### Current shape

Read 2026-05-21. 86 lines. Currently NO echo-commune mention. The doc ends with a brief reference to `/spt:listen` (line 83): *"After revive, message handling follows the same dual-path protocol... See `/spt:listen` for full details on EVENT envelope parsing."*

### What must change (per D-25.1-06)

- **Add a short section** (recommended placement: between line 83 and the "Important" footer at line 85, or as a sibling to the existing `### Primary (Monitor)` / `### Fallback` blocks). Header: `## Echo-commune brief on resume` or similar.
- Content: one paragraph that *(a)* alerts the user that a revive at SessionStart may surface an `<EVENT type="echo_commune">`-bearing brief, *(b)* points at `/spt:live` line ~268 for the envelope shape and `/spt:listen` for parsing, *(c)* notes the two-slice body absorbs as one brief (D-25.1-05).

### Exact landing spots

- Recommended new section header: `## Echo-commune brief (post-revive)` or `## On the first message after revive`.
- Cross-link target: `/spt:live` for full echo_commune envelope description (line ~268 of that doc post-edit).

### Acceptance evidence

- `grep 'echo_commune' plugin/spt/skills/revive/SKILL.md` ≥ 1 match (currently 0).
- `grep -c '/spt:live' plugin/spt/skills/revive/SKILL.md` ≥ 1.
- `grep 'two-slice' plugin/spt/skills/revive/SKILL.md` ≥ 1 match (or links out to `/commune` for taxonomy).

### Risks / drift hazards

- Revive is short by design — don't bloat. A one-paragraph section is the right size. If it grows past ~6 lines, refactor to a one-line cross-ref to `/live`.

## Touchpoint 6: SessionStart `<psyche-context>` injection prose (`src/owl/resume.rs`)

### Current shape

Read 2026-05-21. TWO emission sites:

- **Lines 198–209**: `inject_active_perch_context()` for live perches on every SessionStart. Block format: `<psyche-context id="{}">\n{}</psyche-context>\n\n`. The injected payload comes directly from `download_payload_for_injection(&id)` (line 203).
- **Lines 326–337**: `inject_reorientation()` for post-`/clear`/`/compact` re-orientation. Same block format. Same `download_payload_for_injection()` source.

The block content (the part Phase 25 D-14/D-15 actually reshaped) is from `src/live/context.rs::download_payload()`. The **wrapper prose** is just `<psyche-context id="...">` opener + `</psyche-context>` closer — there is **no current explanatory prose around the block**.

The surrounding `<spacetime-reorientation>` block (lines 343–393) has the live-only "Talking to your Psyche" addendum (lines 379–388) that ALREADY teaches `.claude/{id}-commune.md` + `.claude/{id}-signoff.md` drop-file conventions but does NOT mention two-slice envelope wrapping. **This is the natural surface for the SessionStart-side two-slice teaching** if any source-level prose addition is warranted.

### What must change (per D-25.1-06)

CONTEXT decisions are softer on this surface: D-25.1-06 says *"confirm the injected block's prose mentions the two-slice taxonomy so a freshly-resumed agent reading its first message understands what it's looking at."* The injected block content is `download_payload()` output (already correct shape) — Phase 25.1 should:

1. **Optionally extend the "Talking to your Psyche" addendum (lines 380–388)** with one sentence: *"Commune and signoff bodies MUST wrap content in `<live-context>...</live-context>` + (when in a tracked project) `<project-context>...</project-context>` — see `/spt:commune` for the full contract."* This is a Rust source touch (a string literal); rebuild required (per CLAUDE.md: psyche.md is embedded via `include_str!` — same pattern applies to this string literal at edit time, though it is NOT `psyche.md` itself).
2. **OR add a one-line header/footer around the `<psyche-context>` block** at lines 204–207 / 332–335 telling the agent that what follows may contain two-slice envelope content. CONTEXT discretion: *"Exact prose for the SessionStart `<psyche-context>` block header / footer (if any) that introduces the two slices..."*

The first option is lower-risk — it sits next to existing drop-file teaching prose and inherits its tone. The second option creates a new surface every SessionStart resume sees.

### Exact landing spots

- **Option 1 (recommended)**: lines 380–388 of `src/owl/resume.rs` — the `r#"\nTalking to your Psyche..."#` raw-string literal. Insert one sentence after the line ending `"See /spt:signoff."` (line 384) or as a new bullet.
- **Option 2**: lines 204–207 and 332–335 — `println!("<psyche-context id=\"{}\">\n{}</psyche-context>", ...)`. Would require adding header text after the opener and/or footer before the closer.

### Acceptance evidence

If Option 1 is chosen:
- `grep 'two-slice\|live-context\|project-context' src/owl/resume.rs` returns ≥ 1 match inside the "Talking to your Psyche" block.
- Cargo build still succeeds (string literal change).
- The existing drop-file teaching prose remains intact.

If Option 2 is chosen:
- Both emission sites updated symmetrically (lines 204–207 + 332–335).
- The `<psyche-context>` block content (from `download_payload_for_injection`) is unchanged.

### Risks / drift hazards

- **Code change requires rebuild.** Per CLAUDE.md, `psyche.md` is embedded; the string literals in `resume.rs` are NOT embedded `psyche.md` content but DO require `cargo build --release` to take effect. The Phase 25.1 plan must include a rebuild step if this touchpoint is exercised.
- **Don't edit `psyche.md`** for this touchpoint — that's Psyche-facing prompt territory, locked by Phase 25.
- The reorientation block at lines 343–373 has very dense existing prose about envelope shapes, EVENT-PART chunking, body parsing, etc. Don't expand it further — the two-slice teaching belongs ONLY in the "Talking to your Psyche" live-only addendum at 380–388, OR in the skill docs themselves (preferred).

## Open Question Resolution: Does `download_payload()` emit a grep-able marker for D-25.1-04?

### Question

D-25.1-04 instructs Self to read `$LIVE psyche-download` output and detect whether a project section is present, then decide whether to emit `<project-context>` in its commune/signoff body. Does `src/live/context.rs::download_payload()` (line 344) actually emit a marker Self can key on?

### Evidence (from `src/live/context.rs` reads this session)

**`download_payload()` output structure (lines 344–480):**

1. **Memformat block** (lines 353–362): when `agents/{id}/memformat.xml` exists, emits `<memformat>\n` + content + `</memformat>\n\n`. **Stable, grep-able tag.**
2. **`<psyche-stamp/>` block** (lines 378–385): when stored stamp exists in `live_context.md` front-matter. Self-closing tag. Grep-able.
3. **`<current/>` block** (lines 386–398): always emitted when any content. Grep-able.
4. **Same-project drift directive** (lines 405–414): HTML comment `ATTENTION SELF:`. Conditional. Grep-able when present.
5. **live_context.md body** (lines 416–426): RAW prose, front-matter stripped. **No surrounding header or tag.**
6. **Project file body** (lines 449–458): when `derive_current_repo_names().first()` resolves AND `projects/<name>/<self_id>.md` exists:
   ```rust
   if let Some(content) = fs::read_to_string(&proj_path) {
       out.push_str(&content);  // ← RAW APPEND, no header, no tag
       has_any = true;
   }
   ```
   **The project file body is appended raw with NO surrounding tag, NO header, NO sentinel, NO separator beyond what the file itself starts with.**
7. **Pending Commune / Pending Signoff sections** (lines 460–478): emitted as `## Pending Commune (uncommitted)` / `## Pending Signoff (written {mtime})` headers. Grep-able.

**The project file body itself**: per `psyche.md` §`<context_save>` (lines 342–352), it is the body of the `<project-context>` envelope from a prior Psyche save. So the body MAY start with `## Work Done` or similar H2 headers, but those are content choices by the Psyche LLM — not a stable framework marker.

### Conclusion

**There is NO stable marker.** A Self agent reading psyche-download output cannot reliably distinguish:
- "live_context.md ended and project file content began at this byte" from
- "live_context.md contained an H2 that happens to look like a project section"

Particularly because Psyche's two-slice context-save format (per `psyche.md` lines 326–354) puts symmetric H2 headers in BOTH slices (`## Current Focus`, `## Tracked Intentions`, `## Completed Items`, `## User Interactions`, `## Agent-to-Agent Interactions` live in `<live-context>`; `## Work Done`, `## Current State`, `## Outstanding Priorities`, `## Next Task` live in `<project-context>`). A heuristic like "if I see `## Work Done`, I'm in-project" depends on Psyche following its own template — that's an LLM-judgment-call dependency D-25.1-04 was specifically designed to avoid.

### Recommendation to planner

**Add ONE small Rust task** to Phase 25.1 that introduces an explicit, framework-emitted sentinel. Two viable shapes:

**Shape A (preferred — invisible to humans, easy to grep):** A self-closing XML tag emitted at the START of the project section, after the live_context.md body push and before the project file body push. Insert at `src/live/context.rs:449`:

```rust
if let Some(project_name) = owlery::derive_current_repo_names().first() {
    let proj_path = owlery::project_worktree_path(project_name).join(format!("{}.md", self_id));
    if proj_path.exists() {
        if let Ok(content) = fs::read_to_string(&proj_path) {
            out.push_str(&format!("<project-context-resolved name=\"{}\"/>\n", project_name));
            out.push_str(&content);
            has_any = true;
        }
    }
}
```

Pros: Grep-able (`grep '<project-context-resolved' <output>` is a one-liner instruction for Self). Carries the project name for free. Symmetric with existing `<psyche-stamp/>` / `<current/>` self-closing tag convention in the same function. Zero ambiguity.

Cons: Slight visual noise in CLI output. Mitigation: the existing `<memformat>` / `<psyche-stamp/>` / `<current/>` tags already establish the precedent.

**Shape B:** An H2 header `## Project Context (project name)` before the project body push. Pros: human-readable. Cons: collides with Psyche-LLM-authored H2s in the project body itself; less reliable.

**Shape A is strongly recommended.** It is the minimum viable code change to make D-25.1-04's doc instruction operationally sound.

### Planner action items from this resolution

1. **Add a "Sentinel introduction" task** (Task 0 or Task 1) — adds the `<project-context-resolved name="..."/>` tag emission at `src/live/context.rs:449`. Cargo build required. Unit test: extend existing `download_payload` tests in `src/live/context.rs` (search for `download_payload` tests around lines 1843–2645).
2. **Wire the sentinel into the D-25.1-04 doc instruction**. The skill doc rewrites for `/commune` and `/signoff` should say: *"After running `$LIVE psyche-download`, grep the output for `<project-context-resolved`. If present, you are in a tracked project — include `<project-context>` in your commune body. If absent, omit it."* This is a hard, deterministic check Self can run with zero LLM-judgment.
3. **Mirror the sentinel in `download_payload_for_injection`** automatically — that helper just wraps `download_payload` + strips Pulse Log (per `src/live/context.rs:442–443` comment). The sentinel will flow into the SessionStart `<psyche-context>` block for free.

## Standard Stack

Doc-only phase plus a small Rust addition (sentinel). No new dependencies.

| Library | Version | Purpose | Why Standard |
|---------|---------|---------|--------------|
| (existing) `std::fs`, `std::format!` | Rust std | Sentinel emission in `download_payload` | Already used throughout context.rs |
| (existing) markdown | Plugin doc format | All skill files | Established convention |

No new package installations. **Package Legitimacy Audit:** NOT REQUIRED (no external package installs in this phase).

## Architecture Patterns

### System Architecture Diagram (data flow for the contract Self must teach to)

```
Self authors            wrapper composes              Psyche absorbs +
.claude/<id>-commune.md      ↓                       writes two slices to:
[two-slice body]   →   <EVENT type="commune">   →   agents/<id>/live_context.md
                       wraps body in EVENT          projects/<cwd>/<id>.md
                       envelope w/ Phase 23 stamp
                                                            ↓
                                                    psyche-download reads BOTH
                                                    and emits payload with
                                                    <project-context-resolved/>
                                                    sentinel (after Phase 25.1
                                                    sentinel task lands)
                                                            ↓
                                                    Self greps sentinel →
                                                    decides envelope shape
                                                    for NEXT commune body
                                                            ↓
                                                    cycle continues
```

### Pattern 1: Decision cite-in-header

**What:** Skill docs cite Phase decisions inline in section headers (e.g., current `## Envelope shape (Phase 23 v1.8)`).
**When to use:** Every new section added in this phase.
**Example:** New sections use `## Two-slice body shape (Phase 25 D-10/D-11)`.

### Pattern 2: Quote canonical, link the rest

**What:** When teaching a contract authored elsewhere (`psyche.md`), quote the bullet lists verbatim and link to the source.
**When to use:** All five touchpoints when describing the taxonomy.
**Example:** `(see psyche.md §<output_envelope> for the canonical taxonomy)` — keeps two surfaces in sync via single source.

### Anti-Patterns to Avoid

- **Paraphrasing the taxonomy.** Risks drift on future revisions. Quote or link.
- **Duplicating body-parsing rules across `/live` and `/listen`.** Link only.
- **Mentioning the untagged-commune fallback.** D-25.1-07 forbids it.
- **Adding EVENT-wrapped examples to the new sections.** Confuses Phase 23 / Phase 25 nesting.

## Don't Hand-Roll

| Problem | Don't Build | Use Instead | Why |
|---------|-------------|-------------|-----|
| In-project detection prose | Heuristic ("check if `## Work Done` appears") | The new `<project-context-resolved/>` sentinel | LLM-judgment-dependent heuristics are exactly what D-25.1-04 was designed to avoid |
| Two-slice taxonomy lists | Re-derive what goes in each slice | Quote `psyche.md` lines 298–312 verbatim | Single canonical source |
| Body parsing rules | Re-state `<br>`-split + HTML-unescape | Link to `/listen` lines 169–173 | Drift hazard |
| EVENT envelope shape | Re-document Phase 23 wrapper | Existing `## Envelope shape (Phase 23 v1.8)` sections | Already canonical |

## Runtime State Inventory

This phase is **doc + 1 small Rust addition**. No rename / refactor / migration. Skipping detailed inventory.

- **Stored data:** None affected. Existing `agents/<id>/live_context.md` + `projects/<cwd>/<id>.md` files continue working as-is.
- **Live service config:** None.
- **OS-registered state:** None.
- **Secrets / env vars:** None.
- **Build artifacts:** `cargo build --release` after the sentinel addition; standard deploy via `docs/DEPLOY.ps1` per CLAUDE.md if shipping to plugin marketplace. Existing live agents that booted on an older binary will continue to work — the sentinel is additive (no parse-side requirement; Self only needs to detect its presence).

## Common Pitfalls

### Pitfall 1: Conflating Phase 23 EVENT envelope with Phase 25 two-slice envelopes

**What goes wrong:** Skill doc shows `<EVENT type="commune"><live-context>...</live-context><project-context>...</project-context></EVENT>` as a single combined example, leading Self to think it should write EVENT tags.

**Why it happens:** Both layers use XML-like syntax; both are called "envelope" colloquially.

**How to avoid:** Always teach them as **two distinct nested layers** in separate sections. Self writes ONLY the inner two-slice body. The runtime composes the outer EVENT wrapper. Reinforce with the line currently at `commune/SKILL.md:58`: *"`$LIVE commune` composes this envelope automatically — Self does NOT manually construct EVENT XML."*

**Warning signs:** Any worked example in `commune.md` that shows raw `<EVENT>` tags in body text.

### Pitfall 2: Teaching the untagged-commune fallback (D-25.1-07 violation)

**What goes wrong:** Doc says "if you forget to tag, Psyche figures it out." Agents skip tagging because it's easier.

**Why it happens:** Documenter instinct to surface graceful-degradation paths.

**How to avoid:** Treat the two-slice contract as the ONLY path in docs. The fallback is real but invisible to Self.

**Warning signs:** Any text containing "untagged", "auto-classify", "if you forget", or "Psyche will figure it out" in the touched docs.

### Pitfall 3: Stale Memformat Guide framing

**What goes wrong:** Memformat Guide section says "use memformat topics to structure your commune" — Self interprets this as "topic = slice", drops topic-to-routing decoupling.

**Why it happens:** D-25.1-08 framing change is subtle.

**How to avoid:** Per D-25.1-08, explicit reframe paragraph: *"Memformat topics inform CONTENT (what to think about). Envelope routing (`<live-context>` vs `<project-context>`) is independent — a topic may land in either slice."*

**Warning signs:** Memformat Guide section unchanged post-edit.

### Pitfall 4: Duplicated body-parsing rules

**What goes wrong:** `/live` echo-commune section restates `<br>`-split + HTML-unescape order. Later a parser bug fix updates `/listen` but not `/live`. Agents see divergent parsing rules.

**Why it happens:** Convenience — having the rule next to its consumer feels natural.

**How to avoid:** Single source of truth: `/listen` lines 169–173. `/live` echo-commune section LINKS, does not duplicate.

**Warning signs:** Two distinct prose statements of the `<br>`-split rule across skill files.

### Pitfall 5: Forgetting the rebuild for resume.rs touch

**What goes wrong:** If Touchpoint 6 Option 1 is chosen (edit `src/owl/resume.rs` string literal), and the plan omits `cargo build --release`, the new prose never reaches a SessionStart hook.

**Why it happens:** Doc-only mental model leaks across the one code touch.

**How to avoid:** If Touchpoint 6 source edit is in the plan, explicit "Rebuild" task with `cargo build --release` + redeploy if shipping.

**Warning signs:** Plan touches `src/owl/resume.rs` but has no build task.

### Pitfall 6: Sentinel task slipping if Open Question Resolution is ignored

**What goes wrong:** Planner treats D-25.1-04 as pure doc work. Docs say *"detect project section in psyche-download output"* with no instruction on HOW. Self agents either (a) hand-roll a heuristic that breaks on the next Psyche prompt revision or (b) skip the check and default to one envelope shape.

**Why it happens:** CONTEXT marks the sentinel question as "deferred" under `<deferred>`, but the research confirms no marker exists.

**How to avoid:** Promote the sentinel introduction from deferred to in-scope. ONE small task; massive contract-clarity dividend.

**Warning signs:** Plan has no `src/live/context.rs` task.

## Code Examples

### Sentinel emission (recommended addition to `src/live/context.rs:449`)

```rust
// Phase 25.1 D-25.1-04 enabling sentinel: emit a stable, grep-able marker
// at the start of the project section so Self can reliably detect in-project
// status from psyche-download output without LLM-judgment heuristics.
if let Some(project_name) = owlery::derive_current_repo_names().first() {
    let proj_path =
        owlery::project_worktree_path(project_name).join(format!("{}.md", self_id));
    if proj_path.exists() {
        if let Ok(content) = fs::read_to_string(&proj_path) {
            out.push_str(&format!("<project-context-resolved name=\"{}\"/>\n", project_name));
            out.push_str(&content);
            has_any = true;
        }
    }
}
```

### Self-side detection prose (for `commune.md` "Two-slice body shape" section)

```markdown
Before composing your commune body, run `$LIVE psyche-download <your-id>` and
check whether the output contains the `<project-context-resolved` marker:

- **Marker present** → you are inside a tracked project. Emit BOTH
  `<live-context>...</live-context>` AND `<project-context>...</project-context>`
  in your commune body. If you have nothing project-specific to add this cycle,
  emit `<project-context></project-context>` with an empty body (this is a
  deliberate "in-project but quiet" signal).
- **Marker absent** → you are outside any tracked project. Emit ONLY
  `<live-context>...</live-context>`. Do not emit an empty `<project-context>`
  envelope.
```

### Worked example 1 (in-project, both slices populated)

```markdown
<live-context>
Picked up phase 25.1 doc revision work. Coordinating with researcher and
plan-checker. User wants three worked examples in commune.md.
</live-context>
<project-context>
Wrote sentinel emission code at src/live/context.rs:449 and unit test for it.
Next: rewrite the five skill doc touchpoints to teach the two-slice contract.
</project-context>
```

### Worked example 2 (in-project, empty project slice)

```markdown
<live-context>
Spent the last 20 minutes catching up on the broader project landscape with
the user. No new project work yet — just orientation.
</live-context>
<project-context></project-context>
```

### Worked example 3 (outside any tracked project)

```markdown
<live-context>
Helped the user write a one-off shell script in ~/scratch. Not tied to any
tracked project. May resurface a similar pattern in real project work later.
</live-context>
```

## State of the Art

| Old Approach | Current Approach | When Changed | Impact |
|--------------|------------------|--------------|--------|
| Free-form commune body (pre-25.1) | Two-slice envelope (`<live-context>` + `<project-context>`) | Phase 25 shipped substrate; Phase 25.1 teaches Self side | Self now pre-classifies; Psyche routes verbatim; deterministic split |
| Self-LLM detects in-project status from prose heuristic | `<project-context-resolved/>` sentinel grep (after sentinel task lands) | Phase 25.1 (recommended) | Removes LLM-judgment dependency from contract |
| Memformat = "what to write AND how to organize" | Memformat = "what to think about" (content); envelope = "where it goes" (routing) | Phase 25.1 D-25.1-08 | Decouples two orthogonal concerns |

**Deprecated / outdated:**

- Memformat-as-routing-guide framing in `commune.md` lines 11–15.
- Implicit assumption in current `commune/SKILL.md:23` that a commune body is unstructured prose. Becomes wrong post-25.1.

## Assumptions Log

| # | Claim | Section | Risk if Wrong |
|---|-------|---------|---------------|
| A1 | The sentinel introduction is the minimal code addition to make D-25.1-04 operationally sound. | Open Question Resolution | If heuristic detection is acceptable to user, sentinel task is wasted effort. **Mitigation: planner / discuss-phase should confirm with user before locking the sentinel task.** |
| A2 | The "Talking to your Psyche" addendum (lines 380–388) is the right surface for SessionStart-side two-slice teaching, vs adding header/footer to the `<psyche-context>` block itself. | Touchpoint 6 | Either surface works — A1 / A2 is purely an aesthetic / discoverability call. **CONTEXT lists this under Claude's Discretion.** |
| A3 | Linking `/live` echo-commune section to `/listen` body-parsing rules (rather than duplicating) is the right call. | Touchpoint 4 | **CONTEXT specifies "lean toward link"** — assumption aligned with locked decision posture. |
| A4 | Three worked examples (in-project-both / in-project-empty / outside) are sufficient; no anti-example needed in this phase. | Touchpoint 2 | **CONTEXT lists anti-example as deferred / discretionary**. Aligned. |
| A5 | The `<project-context-resolved/>` tag emission can be added without breaking any existing Phase 25 tests. | Open Question Resolution | Existing tests (`src/live/context.rs:1843+`) assert ordering and presence of `<memformat>`, `<psyche-stamp/>`, `<current/>`. None assert "no other tags exist." Sentinel addition should be additive. **Mitigation: run `cargo test` after sentinel insertion; specifically check tests around `download_payload` (lines 1843–2645) and `test_*` functions for any "exact byte" assertions.** |

## Open Questions

1. **Should the sentinel task be in Phase 25.1 or deferred to a follow-up?**
   - **What we know:** No marker exists in current `download_payload()` output. D-25.1-04 instruction is non-operational without one.
   - **What's unclear:** User's tolerance for an LLM-judgment-based detection heuristic (e.g., "look for `## Work Done` header"). CONTEXT `<deferred>` section lists the marker question as "first verify Phase 25 output shape; only add a sentinel if needed" — this research confirms the need.
   - **Recommendation:** Surface to discuss-phase / user for confirmation before locking the sentinel task. **If user prefers heuristic for now**, rewrite D-25.1-04 instruction in skill docs accordingly (with explicit warning that heuristic depends on Psyche-template stability), and add the sentinel task to a follow-up quick.

2. **Should Touchpoint 6 (resume.rs prose) be exercised at all?**
   - **What we know:** CONTEXT D-25.1-06 says "confirm prose mentions two-slice taxonomy" — "confirm" is softer than "edit". Current prose at lines 380–388 mentions drop-files but NOT envelope wrapping.
   - **What's unclear:** Is touching resume.rs source acceptable in a "doc-only" phase? CLAUDE.md GSD enforcement is loose on this.
   - **Recommendation:** Either (a) edit resume.rs lines 380–388 with one sentence pointing to `/spt:commune` (rebuild + redeploy required), or (b) skip the source touch and rely entirely on the skill doc edits — Self reads `/spt:commune` skill on first commune anyway. Option (b) is lower-risk for a "doc-only" framing.

## Environment Availability

No new external dependencies. Existing build chain (`cargo build --release`) is the only requirement, and only if the sentinel task and/or Touchpoint 6 source edit lands.

| Dependency | Required By | Available | Version | Fallback |
|------------|------------|-----------|---------|----------|
| cargo / Rust toolchain | Sentinel task (if added), Touchpoint 6 source edit (if added) | ✓ | (project default) | None — required if source touch is in plan |
| PowerShell + `docs/DEPLOY.ps1` | Plugin redeploy (if source touched) | ✓ (Windows native per CLAUDE.md) | — | Skip if doc-only path is taken |

## Project Constraints (from CLAUDE.md)

- **Plugin deploy path:** `powershell -ExecutionPolicy Bypass -File docs/DEPLOY.ps1` (Windows). If Touchpoint 6 source edit or sentinel task lands, deploy step is required.
- **Edit sources in this repo only** — never edit `~/.claude/plugins/cache/cplugs/spt/` directly. All skill doc edits land in `plugin/spt/skills/*/SKILL.md` and `plugin/spt/skills/commune/commune.md`.
- **`psyche.md` is embedded via `include_str!`** — Phase 25.1 does NOT touch `psyche.md`. CONTEXT D-25.1-06 explicitly lists psyche.md as out-of-scope.
- **No emoji, no ANSI tags in docs** — applies to all skill markdown.
- **GSD Workflow Enforcement:** all Edit/Write goes through a GSD command. This phase enters via `/gsd:plan-phase` (current step is research) → `/gsd:execute-phase` for execution.
- **Testing convention:** if sentinel task lands, run `cargo test` before commit. Specific test surface: `src/live/context.rs` tests around `download_payload`.

## Sources

### Primary (HIGH confidence)

- `.planning/phases/25.1-revise-commune-signoff-skill-docs-echo-commune-instruction-t/25.1-CONTEXT.md` — locked decisions D-25.1-01..08, deferred questions
- `.planning/phases/25-perch-nesting-psyche-workers-wire-psyche-download-to-forked-/25-CONTEXT.md` — Phase 25 D-10/D-11/D-14/D-15 two-slice substrate
- `psyche.md` lines 282–354 — canonical `<output_envelope>` + `<context_save>` taxonomy
- `src/live/context.rs` lines 344–480 — `download_payload()` actual emission shape (verified the no-marker finding)
- `src/owl/echo_commune.rs` lines 575–613 — haiku-child prompt format; lines 287–291, 380–390 — `route_two_slice` ownership
- `src/common/envelope.rs` lines 1–93 — parser contract and robustness rules
- `src/owl/resume.rs` lines 198–209, 326–337, 380–388 — SessionStart `<psyche-context>` emission + "Talking to your Psyche" addendum
- `plugin/spt/skills/commune/SKILL.md` (59 lines, full read)
- `plugin/spt/skills/commune/commune.md` (81 lines, full read)
- `plugin/spt/skills/signoff/SKILL.md` (72 lines, full read)
- `plugin/spt/skills/live/SKILL.md` (388 lines, full read incl. lines 268, 169–173 cross-ref source)
- `plugin/spt/skills/revive/SKILL.md` (86 lines, full read)
- `plugin/spt/skills/listen/SKILL.md` lines 169–173 — canonical body-parsing rules (link target for `/live`)

### Secondary (MEDIUM confidence)

- `src/live/wrapper/echo_fire.rs` lines 1–80 — sentinel-gate location (NOT the composer; clarified naming during research)
- `.planning/codebase/CONVENTIONS.md` — naming + style conventions (limited applicability since this is markdown-only)
- `CLAUDE.md` — deploy + GSD workflow + plugin paths

### Tertiary (LOW confidence)

- None. All findings cite specific file:line evidence read this session.

## Metadata

**Confidence breakdown:**

- Standard stack: HIGH — no new dependencies; only existing Rust std + markdown.
- Architecture: HIGH — substrate fully shipped Phase 25; all touchpoints read.
- Pitfalls: HIGH — all six pitfalls grounded in evidence from current file contents or CONTEXT.md explicit decisions.
- Open Question Resolution: HIGH — `download_payload()` source read directly; no marker confirmed by code inspection.

**Research date:** 2026-05-21
**Valid until:** Through Phase 25.1 execution. If user defers Phase 25.1 past Phase 26+ and Psyche prompt format changes meaningfully, refresh the touchpoints listing.

---

*Phase: 25.1-revise-commune-signoff-skill-docs-echo-commune-instruction-t*
*Research completed: 2026-05-21*
