# Roadmap: Owl Skill

## Milestones

- [x] **v1.0 Live Agent System** - Phases 1-4 (shipped 2026-03-29)
- [x] **v1.1 Native Runtime** - Phases 5-9 (shipped 2026-03-30)
- [x] **v1.5 Spacetime** - Phases 10-14 (shipped 2026-04-08)
- [x] **v1.6 MCP Fabric** - Phases 15-18 (shipped 2026-04-13; rolling 18.x sub-iterations off-roadmap)
- [x] **v1.7 Seamlessification** - Phases 26-30 (shipped 2026-05-16; see [milestones/v1.7-ROADMAP.md](milestones/v1.7-ROADMAP.md))
- [x] **v1.7.1 Seamlessification II** - Phases 31-34 (shipped 2026-05-18; deployed v1.10.13; see [milestones/v1.7.1-ROADMAP.md](milestones/v1.7.1-ROADMAP.md))
- [ ] **v1.8 Psyche Restructure** - Phases 23, 24, 24.1, 25, 35, 35.1, 35.2, 35.3 (planned; sequenced before v1.9 despite higher phase numbers — promoted from backlog/todos 2026-05-10; Phase 35 appended 2026-05-18; Phase 24.1 inserted 2026-05-18; Phase 35.1 inserted 2026-05-27 — URGENT data-loss fix; Phases 35.2 + 35.3 inserted 2026-05-28 — sync-setup second-machine data-loss + UX pass)
- [ ] **v1.9 Capsule** - Phases 19-22 (planned)

## Off-Roadmap Sub-Iterations Policy

**Phases 18.1–18.8.x are intentional off-roadmap sub-iterations.** They are tactical follow-ons to Phase 18 (bug fixes, refactors, observability deltas, transport pivots) and are NOT tracked against milestone completion. Each sub-iteration is a self-contained phase directory under `.planning/phases/18.N(.M)-*/` with its own PLAN/SUMMARY/UAT/SECURITY artifacts. They ship independently via `DEPLOY.ps1` version bumps.

ROADMAP.md tracks only **milestone-defining phases** (integer phase numbers and INSERTED `.M` decimals at planning time). Reconciliation rules:

- v1.6 milestone is sealed at Phase 18.
- 18.x sub-iterations live in their phase directories; `roadmap.analyze` reports v1.6 at 100% even when sub-iterations are in flight.
- 999.x phases are backlog placeholders (see Backlog section); promote via `/gsd-review-backlog` when scheduling into a future milestone.

## Phases

<details>
<summary>v1.0 Live Agent System (Phases 1-4) - SHIPPED 2026-03-29</summary>

**Phase Numbering:**

- Integer phases (1, 2, 3): Planned milestone work
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)

Decimal phases appear between their surrounding integers in numeric order.

- [x] **Phase 1: Foundation & Hardening** - Harden owl.sh messaging, add output formatting and auto-setup, scaffold live.sh with Self registration
- [x] **Phase 2: Psyche Core** - Psyche spawn, COMMUNE/PULSE cycle, graceful stop, and SKILL.md documentation (completed 2026-03-28)
- [x] **Phase 2.1: Live Skill Extraction** (INSERTED) - Extract /live into standalone LIVE-SKILL.md
- [x] **Phase 2.2: Owl & Live Hardening** (INSERTED) - Signal-based lifecycle, BUSY state, Psyche persistence, restart shortcuts
- [x] **Phase 3: Timed Pulses** - Deferred to v1.1 as Phase 8
- [x] **Phase 4: Spine Supervisor** - Deferred to v1.1 as Phase 9

### Phase 1: Foundation & Hardening

**Goal**: Agents have a robust, race-free messaging layer with consistent output, automatic environment setup, and a working live.sh scaffold that registers Self agents
**Depends on**: Nothing (first phase)
**Requirements**: HARD-01, HARD-02, HARD-03, FMT-01, FMT-02, FMT-03, SETUP-01, SETUP-02, SETUP-03, LIVE-02, LIVE-08, LIVE-10
**Success Criteria** (what must be TRUE):

  1. Messages are delivered atomically -- a concurrent reader never sees a partial message file
  2. Two agents sending messages in rapid succession never produce filename collisions
  3. All /owl and /live output uses ANSI colors and compact symbols (no emoji), and /owl output is visually distinct from /live output
  4. Running /owl or /live for the first time on a clean machine auto-adds required env vars and session cleanup hook to settings.json (with user notification)
  5. `/live list` shows Self agents marked as live; all existing `/owl` commands work unchanged

**Plans:** 3/3 plans complete

Plans:

- [x] 01-01-PLAN.md -- Harden owl.sh (atomic writes, collision-resistant IDs, TOCTOU-safe poll) and add ANSI color output
- [x] 01-02-PLAN.md -- Auto-setup settings.json (env vars, SessionEnd hook) and session-scoped cleanup
- [x] 01-03-PLAN.md -- Scaffold live.sh (Self registration, /live list) and update SKILL.md

### Phase 2: Psyche Core

**Goal**: A user can start a live agent session and receive contextual, periodic nudges from a background Psyche that tracks what they are doing
**Depends on**: Phase 1
**Requirements**: LIVE-01, LIVE-03, LIVE-04, LIVE-05, LIVE-06, LIVE-07, LIVE-09, LIVE-11, SKILL-01, SKILL-02, SKILL-03
**Success Criteria** (what must be TRUE):

  1. `/live [id]` starts an owl listener with Self role and spawns a Psyche subagent that begins its pulse loop
  2. Self sends COMMUNE updates that Psyche absorbs into context; when a pulse timer fires, Psyche judges whether Self should be doing something and notifies Self if so
  3. When Self stops, its Psyche is also torn down with no orphaned processes or perch files
  4. Pulse period is configurable via `--period` flag (minimum 1 minute)
  5. SKILL.md documents all /live subcommands, auto-setup behavior, and edge cases with the same depth as /owl

**Plans:** 3/3 plans complete

Plans:

- [x] 02-01-PLAN.md -- owl.sh extensions (--psyche flag, auto-setup poll, list filtering) and live.sh subcommands (commune, pulse-wait, enhanced start/stop, --period)
- [x] 02-02-PLAN.md -- psyche.md agent prompt template and DEPLOY.md update
- [x] 02-03-PLAN.md -- SKILL.md full /live documentation rewrite with ID recollection and edge cases

### Phase 2.1: Live Skill Extraction (INSERTED)

**Goal**: /live is a standalone Claude Code skill with its own SKILL.md, separate from /owl, matching the design in SKILL_SPEC-LIVE.md
**Requirements**: EXTRACT-01, EXTRACT-02, EXTRACT-03, EXTRACT-04
**Depends on:** Phase 2
**Success Criteria** (what must be TRUE):

  1. LIVE-SKILL.md exists as a standalone skill file with `name: live` frontmatter
  2. SKILL.md contains only /owl commands with no /live content
  3. Both skill files cross-reference each other
  4. DEPLOY.md includes LIVE-SKILL.md in all file operations

**Plans:** 1/1 plans complete

Plans:

- [x] 02.1-01-PLAN.md -- Extract /live documentation into standalone LIVE-SKILL.md, trim owl SKILL.md, update DEPLOY.md

### Phase 2.2: Owl & Live Hardening (INSERTED)

**Goal**: Harden owl.sh and live.sh with race condition fixes, signal-based lifecycle management, skill setup tooling, listener intelligence, Psyche persistence, session auto-resume, and restart shortcuts
**Requirements**: HARDEN-01, HARDEN-02, HARDEN-03, HARDEN-04, HARDEN-05, HARDEN-06, HARDEN-07, HARDEN-08, HARDEN-09, HARDEN-10
**Depends on:** Phase 2.1
**Success Criteria** (what must be TRUE):

  1. GC never cleans up a perch that is between polls (BUSY PID state protects the re-poll gap)
  2. Poll processes exit gracefully on signal with status output, and stop commands use graceful-then-force shutdown
  3. SKILL.md instructs listeners to name subagents and check background tasks before processing messages
  4. Psyche context persists across agent death and can be downloaded by a revived Psyche
  5. SessionStart hook auto-detects dead listeners and outputs resume instructions
  6. One-command restart shortcuts exist for both owl listeners and live agents

**Plans:** 4/4 plans complete

Plans:

- [x] 02.2-01-PLAN.md -- BUSY PID state in _poll_once + signal traps in poll + signal-based stop
- [x] 02.2-02-PLAN.md -- /owl gsd-setup command + SKILL.md listener intelligence instructions
- [x] 02.2-03-PLAN.md -- Psyche context persistence (context-save, psyche-download, clear-psyche)
- [x] 02.2-04-PLAN.md -- Restart shortcuts (reboot, revive) + stash + SessionStart auto-resume

</details>

<details>
<summary>v1.1 Native Runtime (Phases 5-9) - SHIPPED 2026-03-30</summary>

- [x] **Phase 5: Golden Tests & CLI Skeleton** - Capture bash output as golden tests, build CLI skeleton with clap, set up cross-platform CI
- [x] **Phase 6: P2P Messaging & Owl Parity** - P2P local-server architecture with SQLite spool, all owl subcommands passing golden tests
- [x] **Phase 7: Live Parity & Distribution** - Live subcommands with native Psyche wrapper loop, drop-in binary distribution
- [x] **Phase 8: Timed Pulses** - One-shot timed pulse requests and /live timed-pulse command (native)
- [x] **Phase 9: Spine Supervisor** - Spine/Touch process supervision with health checks and recovery (native)
- [x] **Phase 9.1: Psyche Lifecycle Hardening** (INSERTED) - Git-backed context, orphan detection, signoff, bash deprecation
- [x] **Phase 9.2: Psyche Messaging Discipline** (INSERTED) - Psyche and commune prompt rewrites for strict messaging discipline

### Phase 5: Golden Tests & CLI Skeleton

**Goal**: Every bash subcommand's exact output is captured as a golden test, and a compiled Rust binary parses all subcommands (stubbed) and builds on all target platforms
**Depends on**: Phase 4 (v1.0 complete)
**Requirements**: COMPAT-01, COMPAT-02, COMPAT-03, COMPAT-04, COMPAT-05, COMPAT-06, RUST-02, RUST-03
**Plans:** 3/3 plans complete

Plans:

- [x] 05-01-PLAN.md -- Golden test capture script and fixture generation from bash scripts
- [x] 05-02-PLAN.md -- Rust CLI skeleton with clap derive structs and parse verification tests
- [x] 05-03-PLAN.md -- Golden test Rust integration tests and cross-platform CI workflow

### Phase 6: P2P Messaging & Owl Parity

**Goal**: Agents communicate via direct local-server connections with SQLite offline spool, and every owl subcommand passes its golden test
**Depends on**: Phase 5
**Requirements**: RUST-01, RUST-04, P2P-01, P2P-02, P2P-03, P2P-04, P2P-05, P2P-06, P2P-07, P2P-08, OWL-01, OWL-02, OWL-03, OWL-04, OWL-05, OWL-06, OWL-07, OWL-08, OWL-09, OWL-10, OWL-11, OWL-12, PROC-01, PROC-02, PROC-03, PROC-04, PROC-05
**Plans:** 6/6 plans complete

Plans:

- [x] 06-01-PLAN.md -- Project restructure, dependencies, and common utility modules
- [x] 06-02-PLAN.md -- P2P infrastructure: SQLite registry, per-perch spool, TCP protocol, process management
- [x] 06-03-PLAN.md -- Filesystem owl subcommands: setup, list, stop, cleanup-session
- [x] 06-04-PLAN.md -- Core P2P messaging subcommands: poll, deliver, reply, send
- [x] 06-05-PLAN.md -- Lifecycle subcommands: reboot, stash, session-resume, gsd-setup
- [x] 06-06-PLAN.md -- Integration wiring, native tests, golden test pass, and verification

### Phase 7: Live Parity & Distribution

**Goal**: All live subcommands work natively with the Psyche wrapper loop ported to Rust, and the binary is a copy-one-file drop-in replacement
**Depends on**: Phase 6
**Requirements**: LIVE-12, LIVE-13, LIVE-14, LIVE-15, LIVE-16, LIVE-17, LIVE-18, LIVE-19, LIVE-20, DIST-01, DIST-02, DIST-03, DIST-04
**Plans:** 4/4 plans complete

Plans:

- [x] 07-01-PLAN.md -- Simple filesystem live subcommands
- [x] 07-02-PLAN.md -- Process management subcommands (stop, revive)
- [x] 07-03-PLAN.md -- Start subcommand with Psyche wrapper loop and generation tracking
- [x] 07-04-PLAN.md -- Golden test verification and distribution

### Phase 8: Timed Pulses

**Goal**: A user or agent can schedule a one-shot reminder at a specific future time, delivered as a pulse through the native binary
**Depends on**: Phase 7
**Requirements**: TPULSE-01, TPULSE-02, TPULSE-03
**Plans:** 2/2 plans complete

Plans:

- [x] 08-01-PLAN.md -- Rust implementation: timed_pulse.rs, timed_pulse_wait.rs, cli.rs wiring
- [x] 08-02-PLAN.md -- psyche.md PULSE REQUEST handling section

### Phase 9: Spine Supervisor

**Goal**: Users running multiple live agents have a supervision layer that detects dead Psyches and notifies the affected Self for recovery
**Depends on**: Phase 7
**Requirements**: SPINE-01, SPINE-02, SPINE-03, SPINE-04, SPINE-05, SPINE-06, SPINE-07, SPINE-08, SPINE-09
**Plans:** 3/3 plans complete

Plans:

- [x] 09-01-PLAN.md -- InfoJson spine/touch fields, list filters, CLI scaffolding
- [x] 09-02-PLAN.md -- Spine wrapper loop and Touch health-check scanner
- [x] 09-03-PLAN.md -- Dispatch wiring and stop --all teardown

### Phase 9.1: Psyche Lifecycle Hardening (INSERTED)

**Goal**: Harden Psyche lifecycle with git-backed context history, orphan detection, timed pulse persistence, and intelligent SessionStart skill injection. Replace stash with signoff. Remove all bash script dependencies.
**Depends on**: Phase 9
**Requirements**: D-01..D-17 (Phase 9.1 discipline requirements)
**Plans:** 4/4 plans complete

Plans:

- [x] 09.1-01-PLAN.md -- parent_pid in InfoJson + git-backed context-save
- [x] 09.1-02-PLAN.md -- Stash-to-signoff rename with STASH_FINAL delivery
- [x] 09.1-03-PLAN.md -- Wrapper loop hardening + SessionStart Part C
- [x] 09.1-04-PLAN.md -- Bash deprecation: skill file cleanup, delete bash scripts

### Phase 9.2: Psyche Messaging Discipline (INSERTED)

**Goal**: Full rewrite of Psyche instructions (psyche.md) and extraction/rewrite of Self commune instructions for strict messaging discipline.
**Depends on**: Phase 9
**Requirements**: D-01..D-14 (Phase 9.2 discipline requirements)
**Plans:** 2/2 plans complete

Plans:

- [x] 09.2-01-PLAN.md -- psyche.md XML rewrite with strict messaging discipline
- [x] 09.2-02-PLAN.md -- commune.md extraction from LIVE-SKILL.md

</details>

<details>
<summary>v1.5 Spacetime (Phases 10-14) - SHIPPED 2026-04-08</summary>

- [x] **Phase 10: Plugin Migration** - Migrate owl+live to /spt plugin architecture (completed 2026-04-01)
- [x] **Phase 11: Foundation** - PDT timestamps and Psyche wrapper logging overhaul (completed 2026-04-02)
- [x] **Phase 12: Psyche Intelligence** - Memformat, brainstorming, INSIGHT messages (completed 2026-04-03)
- [x] **Phase 13: Messaging Integration** - Hook-based delivery, SubagentStart/Stop working perches (completed 2026-04-03)
- [x] **Phase 13.1: Unified Psyche Wrapper Event Loop** (INSERTED) - Shared PollListener, inline pulse scheduling (completed 2026-04-04)
- [x] **Phase 14: Poll Efficiency** - Blocking TCP accept with timeout (completed 2026-04-04)
- [x] **Phase 14.1: Persistent Offline Perches** (INSERTED) - Persistent perches, indefinite queueing, reconnection (completed 2026-04-08)
- [x] **Phase 14.2: Spacetime Reliability & DX** (INSERTED) - PerchState enum, spacetime filesystem, wrapper decomposition, owl doctor (completed 2026-04-06)
- [x] **Phase 14.3: Optional Agent ID** (INSERTED) - Session detection, optional caller ID, skill doc rewrite (completed 2026-04-07)

</details>

### v1.6 MCP Fabric (SHIPPED 2026-04-13)

**Milestone Goal:** Add an MCP server transport layer to spacetime messaging -- structured resources and tools that delegate to existing Rust core, with unified spool persistence and minimal-token wake signals.

> **Note:** MCP transport was deprioritized post-ship in favor of CLI-first model (see `feedback_mcp_performance.md`). Phase 18.1+ sub-iterations refactor away from MCP-centric flows. The milestone is sealed; sub-iterations are tracked off-roadmap (see "Off-Roadmap Sub-Iterations Policy" above).

- [x] **Phase 15: MCP Spike & Spool Foundations** - Validate hand-rolled JSON-RPC with Claude Code, extend spool with delivered marking, build core result variants (completed 2026-04-11)
- [x] **Phase 16: MCP Tools** - All spacetime tools wired to result variants with proper schemas and annotations (completed 2026-04-12)
- [x] **Phase 17: MCP Resources** - Inbox, perches, psyches, context, memformat resources with check-on-request notifications (completed 2026-04-13)
- [x] **Phase 18: Hooks & Plugin Integration** - Spool-based hook delivery, wake-sentinel detection, plugin manifest, skill doc rewrite (completed 2026-04-13)

## Phase Details

### Phase 15: MCP Spike & Spool Foundations

**Goal**: The hand-rolled MCP server connects to Claude Code and responds to tool/resource requests, the spool supports non-destructive reads with delivery marking, and core owl operations return structured results instead of printing and exiting
**Depends on**: Phase 14.3 (v1.5 complete)
**Requirements**: MCP-01, MCP-02, MCP-03, MCP-04, MCP-05, SPOOL-01, SPOOL-02, SPOOL-03, SPOOL-04, SPOOL-05, RVAR-01, RVAR-02, RVAR-03, RVAR-04, RVAR-05, RVAR-10, RVAR-11
**Success Criteria** (what must be TRUE):

  1. Running `owl mcp-serve` starts a stdio server that completes the MCP initialize handshake with Claude Code and responds to ping -- proving the hand-rolled JSON-RPC approach works with the real client
  2. The spool supports peek_all() (non-destructive read of undelivered messages) and mark_delivered() (atomic delivery marking) without breaking existing drain_all() behavior
  3. TCP-received messages are written to spool before the wake signal is printed, making spool the single source of truth for message arrival
  4. deliver_result(), send_result(), list_result(), stop_result(), doctor_result(), and whoami_result() return structured Result types -- none of them print to stdout or call process::exit()
  5. The MCP server exits cleanly when its parent process dies (parent_pid watchdog) and handles EOF on stdin gracefully

**Plans:** 5/5 plans complete

Plans:

- [x] 15-01-PLAN.md -- Spool unification: delivered column, peek_all, mark_delivered, drain migration, spool-before-signal
- [x] 15-02-PLAN.md -- MCP server foundation: JSON-RPC types, dispatch, stdio loop, watchdog, CLI wiring
- [x] 15-03-PLAN.md -- Result variants: outcomes module, deliver_result, send_result, whoami_result
- [x] 15-04-PLAN.md -- Result variants: list_result, stop_result, doctor_result, integration tests
- [x] 15-05-PLAN.md -- Gap closure: spool unit tests (9 tests for peek_all, mark_delivered, drain migration, pending_count, schema migration)

### Phase 16: MCP Tools

**Goal**: Agents in Claude Code sessions can perform all spacetime operations through MCP tools with structured JSON results, proper permission annotations, and consistent error handling
**Depends on**: Phase 15
**Requirements**: TOOL-01, TOOL-02, TOOL-03, TOOL-04, TOOL-05, TOOL-06, TOOL-07, TOOL-08, TOOL-09, TOOL-10, TOOL-11, TOOL-12, TOOL-13, TOOL-14, TOOL-15, RVAR-06, RVAR-07, RVAR-08, RVAR-09
**Success Criteria** (what must be TRUE):

  1. An agent can send a message to another perch via `spacetime_send` and receive a structured JSON result indicating delivery success, spool queuing, or failure -- without any stderr output leaking into the MCP channel
  2. `spacetime_listen` and `spacetime_live_start` bind the MCP server to an agent_id as a side-effect, and all subsequent tool calls operate in that identity context
  3. All 13 tools appear in `tools/list` with complete inputSchema definitions and correct annotations (readOnlyHint on list/whoami/doctor, destructiveHint on stop/signoff)
  4. Tool errors return isError: true with a structured {success: false, error: "..."} body instead of crashing the MCP server

**Plans:** 4/4 plans complete

Plans:

- [x] 16-01-PLAN.md -- Command rename: deliver->send, send->ring, reply folded into send --reply-to
- [x] 16-02-PLAN.md -- Live result variants: commune, stop, timed_pulse, context_save, signoff, amend_signoff + list filter extension
- [x] 16-03-PLAN.md -- MCP tool registry (13 tools), tools/list dispatch, tools/call for read-only tools
- [x] 16-04-PLAN.md -- MCP tools/call for action+live tools, identity binding, lazy-bind, error handling

### Phase 17: MCP Resources

**Goal**: Agents can read inbox contents, discover perches, and access Psyche state through MCP resources without draining messages or triggering side effects
**Depends on**: Phase 16
**Requirements**: RES-01, RES-02, RES-03, RES-04, RES-05, RES-06, RES-07, RES-08
**Success Criteria** (what must be TRUE):

  1. An agent can read `spt://inbox` to see undelivered messages as plain text with ANSI formatting -- reading auto-marks all returned messages as delivered (resource read = intentional read = delivered, no separate tool call needed)
  2. `spt://perches` returns all registered perches with online/offline status, and `spt://psyches` returns Psyche processes with their current status
  3. `spt://context` and `spt://memformat` return the bound agent's persisted Psyche state files as text content (optional undocumented `/{id}` suffix for cross-agent reads)
  4. The server emits `notifications/resources/updated` inline before each request dispatch when subscribed resources have changed since the last check (future-proofing for subscription support)

**Plans:** 2/2 plans complete

Plans:

- [x] 17-01-PLAN.md -- Resource definitions (5 spt:// URIs), read handlers, dispatch wiring
- [x] 17-02-PLAN.md -- Change detection tracker and notifications/resources/updated emission

### Phase 18: Hooks & Plugin Integration

**Goal**: Hooks use spool as their message source with MCP-aware behavior, the plugin manifest declares the MCP server, skill docs teach agents when to use MCP vs CLI, and sessions recover context after /clear and /compact
**Depends on**: Phase 17
**Requirements**: HOOK-01, HOOK-02, HOOK-03, HOOK-04, HOOK-05, HOOK-06, PLUG-01, PLUG-02, PLUG-03, PLUG-04, PLUG-05, PLUG-06, PLUG-07
**Success Criteria** (what must be TRUE):

  1. PreToolUse hook reads messages from spool via peek_all() and marks them delivered after injecting into additionalContext -- no more filesystem inbox scanning
  2. UserPromptSubmit hook injects "N new messages -- read spacetime://inbox/{id}" when unread messages exist, and detects wake-sentinel prompts (`.`, `spt-wake`) to inject read-inbox-first instructions
  3. The plugin manifest declares `owl mcp-serve` as a stdio MCP server entry, and `.mcp-connected` sentinel on the perch signals hooks to adjust behavior (e.g., reference MCP resources in additionalContext instead of full content)
  4. SessionStart hook injects MCP re-orientation context on `source: "clear"` and `source: "compact"` -- agent_id, available resources, inbox check instruction
  5. Skill docs (SKILL.md, LIVE-SKILL.md, commune.md) clearly distinguish when agents should use MCP tools (interactive Claude Code sessions) vs CLI ($OWL/$LIVE for scripts, cron, Psyche)

**Plans:** 2/2 plans complete

Plans:

- [x] 18-01-PLAN.md -- Hook spool migration (PreToolUse peek_all, wake sentinels, SessionStart reorientation)
- [x] 18-02-PLAN.md -- Plugin manifest (.mcp.json), skill doc retirement and MCP-first rewrite, DEPLOY.md update

### Planned: v1.9 Capsule

**Milestone Goal:** Replace poll-task-restart with seamless psmux-based message injection for capsule sessions, establishing a modular sendkeys pipeline for future capabilities.

- [ ] **Phase 19: Sendkeys Foundation & Capsule Launch** - PsmuxSendkeys module, capsule.exe binary, capsule.bat launcher, build-capsule skill
- [ ] **Phase 20: Session Detection & Capsule Listener** - SessionStart hook capsule detection, per-session listener with sendkeys delivery and hook fallback
- [ ] **Phase 21: Abrupt Messages** - ESC interrupt injection with timing-safe delivery for busy agents
- [ ] **Phase 22: Smart Capabilities** - Rename, GSD proceed, and spacetime debugging via sendkeys

### Off-Roadmap Sub-Iterations of Phase 18

> Detailed PLAN/SUMMARY/UAT/SECURITY artifacts live under `.planning/phases/18.*-*/`. Listed here for index only — not tracked in v1.6 milestone totals.

| Sub-Phase | Goal (one-liner) | Status | Completed |
|-----------|------------------|--------|-----------|
| 18.1 | Deferred delivery, TCP spool timeout, parent_pid orphan detection, PULSE_TRIGGER 3-tier recovery, daily Psyche refresh, marker protocol, echo-commune | Complete | 2026-04-14 |
| 18.2 | Relocate spt runtime out of `~/.claude` to `%LOCALAPPDATA%\spt` / `~/.spt` (`SPT_HOME` override) | Complete | 2026-04-15 |
| 18.3 | Echo-commune time gating via `.more-done` sentinel + 15-min wrapper window | Complete | 2026-04-18 |
| 18.4 | Seamless binary handoff for long-running spt processes (listener, wrapper, touch) on plugin update | Complete | 2026-04-18 |
| 18.5 | Handoff bug fixes: listener argv, DUPLICATE bypass, wrapper inner-poll preempt | Complete | 2026-04-19 |
| 18.6 | Refactor scheduled pulses — wrapper drives, Self receives, Psyche passive-aware | Complete | 2026-04-19 |
| 18.7 | Relocate timed-pulse firing to Self listener; rename skill `timed-pulse` → `new-alarm` | Complete | 2026-04-20 |
| 18.7.1 | Hotfix: mid-iteration alarm fire regression in Self listener | Complete | 2026-04-20 |
| 18.8 | echo-commune stderr capture (no retry-on-empty) + refactor to fresh-session jsonl excerpt | Complete | 2026-04-21 |
| 18.8.1 | ccs-aware projects path + excerpt ENOENT observability + info.json session rotation refresh | Complete | 2026-05-09 |

### Phase 19: Sendkeys Foundation & Capsule Launch

**Goal**: The sendkeys pipeline is proven reliable and the capsule launcher creates working psmux sessions with skeleton perches
**Depends on**: Phase 18 (v1.6 complete)
**Requirements**: SKEY-01, SKEY-02, SKEY-03, CLNCH-01, CLNCH-02, CLNCH-03, CLNCH-04, CLNCH-05, CLNCH-06, CLNCH-07, CLNCH-08, CLNCH-09, CLNCH-10, CLSTN-05
**Success Criteria** (what must be TRUE):

  1. User can run `/spt:build-capsule` which downloads psmux.exe and generates a project-local capsule.bat
  2. Running capsule.bat with a REQUIRED agent_id launches a psmux session containing claude, creates a skeleton perch with agent_id and PID, spawns a capsule listener process, then attaches the user to the psmux session. Terminal title is set to agent_id before attach, and a historical stdout message ("Now launching..." or "Reactivating...") with cc_session_id (and psyche_session_id if live) is printed before psmux attach.
  3. PsmuxSendkeys module can deliver arbitrary text (including special characters, newlines, quotes) to a named psmux session via send-keys literal mode
  4. Message framing format is visually distinguishable from user-typed input in the terminal
  5. Agent can stop and restart capsule listeners (and optionally psyches) from within a session without tearing down claude/psmux -- enabling build->deploy->restart iteration loops
  6. `--resume <agent_id>` resolves to the latest cc_session_id stored against that agent_id and passes it to claude; raw cc session IDs are not accepted
  7. psmux sessions launched via capsule use augmented styling (PowerShell-like highlight, cleaner status bar) from a config file stored in `.claude/`

**Plans:** 4 plans

Plans:

- [ ] 19-01-PLAN.md -- Foundation primitives: PsmuxSendkeys module, PerchState::Capsule, WAKE_SENTINEL_PREFIX const, bin_dir() helper, id_validate
- [ ] 19-02-PLAN.md -- `owl capsule` and `owl capsule-listen` subcommands (poll.rs fork + sendkeys delivery + claude PID watch)
- [ ] 19-03-PLAN.md -- `owl build-capsule` + `/spt:build-capsule` skill + capsule.bat/psmux.conf templates + psmux download with SHA256 verification
- [ ] 19-04-PLAN.md -- E2E integration tests + ROADMAP amendments + requirement back-fill + plugin version bump 1.9.0 + deploy

### Phase 20: Session Detection & Capsule Listener

**Goal**: Capsule sessions are automatically recognized and messages are delivered via sendkeys when idle or respooled to inbox when busy
**Depends on**: Phase 19
**Requirements**: SDET-01, SDET-02, CLSTN-01, CLSTN-02, CLSTN-03, CLSTN-04, SKEY-04
**Success Criteria** (what must be TRUE):

  1. When a capsule session starts, the SessionStart hook detects the skeleton perch and informs the agent of its agent_id, capsule role, and perch location
  2. The capsule listener delivers incoming messages via psmux sendkeys when the agent is idle (`.idle-ready` present)
  3. When the agent is busy (no `.idle-ready`), messages are respooled to the file inbox for delivery via the existing hook path
  4. When the claude process dies, the capsule listener tears down cleanly (including Psyche signoff for live sessions) with no orphaned processes
  5. When a message is injected while the user has partially typed input, the partial text is preserved and restored after injection

**Plans:** 2 plans

Plans:

- [ ] 17-01-PLAN.md -- Resource definitions (5 spt:// URIs), read handlers, dispatch wiring
- [ ] 17-02-PLAN.md -- Change detection tracker and notifications/resources/updated emission

### Phase 21: Abrupt Messages

**Goal**: Users can force-interrupt a busy capsule agent and inject a message immediately
**Depends on**: Phase 20
**Requirements**: ABRT-01, ABRT-02, ABRT-03
**Success Criteria** (what must be TRUE):

  1. Sending a message with `--abrupt` to a capsule agent interrupts the agent via ESC sendkeys, then injects the message
  2. Any queued messages waiting at the time of interruption are delivered via sendkeys after the abrupt message (not via hooks)
  3. Abrupt delivery includes readiness polling to avoid corrupted input from premature injection

**Plans:** 2 plans

Plans:

- [ ] 17-01-PLAN.md -- Resource definitions (5 spt:// URIs), read handlers, dispatch wiring
- [ ] 17-02-PLAN.md -- Change detection tracker and notifications/resources/updated emission

### Phase 22: Smart Capabilities

**Goal**: Capsule sessions support automated rename, GSD workflow advancement, and spacetime debugging
**Depends on**: Phase 20
**Requirements**: CCAP-01, CCAP-02, CCAP-03
**Success Criteria** (what must be TRUE):

  1. When a capsule session starts, the listener automatically renames the session to the agent_id via `/rename` sendkeys
  2. When a GSD-running agent completes a plan, the Stop hook fires `/clear` followed by the next GSD command via sendkeys -- avoiding a full context reload
  3. An agent can invoke `$OWL capsule-reload-plugins` which triggers `/reload-plugins` via sendkeys in its own session

**Plans:** 2 plans

Plans:

- [ ] 17-01-PLAN.md -- Resource definitions (5 spt:// URIs), read handlers, dispatch wiring
- [ ] 17-02-PLAN.md -- Change detection tracker and notifications/resources/updated emission

### Phase 23: Commune & Signoff Project-Root + HEAD SHA Stamping

**Goal**: Every commune and signoff payload records `project_root` and `HEAD` SHA so resumed agents can compute staleness and detect repo/working-tree changes since last activity
**Milestone**: v1.8 Psyche Restructure
**Depends on**: Nothing (pure metadata addition)
**Promoted from**: `.planning/todos/done/2026-04-18-track-project-root-and-latest-commit-in-commune-and-amend-si.md`
**Requirements**: TBD (PROJ-META-01, COMMIT-META-01, RESUME-DELTA-01)
**Success Criteria** (what must be TRUE):

  1. Every commune payload includes `project_root` (cwd / project identifier) and `head_sha` (+ subject line)
  2. Every amend-signoff context save includes the same fields
  3. On `psyche-download` / resume, fields are surfaced so Self can compare stored `head_sha` vs current `HEAD` and detect drift
  4. Commune/signoff still works when not in a git repo (fields gracefully omit or note "not a repo")

**Plans:** 6 plans

Plans:

- [x] 23-01-PLAN.md - src/common/git.rs Stamp + stamp() producer + 500ms-timeout git helpers + hostname (D-01..D-04, D-11, D-13)
- [x] 23-02-PLAN.md - EVENT-envelope cutover for plain commune (D-06) + 5-attr stamping on init_signoff/echo_commune/wrapper file_drop (D-05, D-14)
- [x] 23-03-PLAN.md - YAML front-matter on context-save (file head) + amend-signoff (inside section) (D-07)
- [x] 23-04-PLAN.md - psyche-download <psyche-stamp/> + <current/> blocks + same-project drift directive + suppression read (D-08..D-10)
- [x] 23-05-PLAN.md - $LIVE suppress-drift subcommand (per-(self_id,project) marker writer; closes D-09 "Don't ask again")
- [x] 23-06-PLAN.md - commune/signoff/live SKILL.md updates: envelope shape + drift-directive AskUserQuestion teaching block

### Phase 24: Tracked-Dir Forked-Repo Layout (agents/ + projects/ branches) + Sessions Audit Log

**Goal**: `psyches/tracked/` becomes a forked-git-repo system. A single `seed/` directory holds the canonical git repo; each `agents/{agent_id}/` and `projects/{project_name}/` directory is a branched clone of `seed/` whose branch name matches the folder name. `seed/` acts as the local remote (push target) until/unless Phase 35 Psyche Sync is enabled, at which point the remote upgrades to the gh `spt-agent-storage` repo. Each agent maintains an append-only sessions audit log of every fresh `claude -p` spawn (UUID, timestamp, generation, trigger reason).
**Milestone**: v1.8 Psyche Restructure
**Depends on**: Phase 23 (helpful but not strict — independent in code)
**Promoted from**: `.planning/todos/done/2026-04-18-organize-psyches-tracked-by-agent-and-add-psyche-sessions-fi.md` + Discord image spec captured 2026-05-18 (forked-repo design overlay)
**Requirements**: TBD (TRK-FORK-01, TRK-AGENT-BRANCH-01, TRK-PROJECT-BRANCH-01, TRK-RENAMES-01, SESSIONS-LOG-01, SESSIONS-LOG-02, GEN-ROLLOVER-01, TRK-MIGRATE-01)

**Canonical Layout:**

```
psyches/tracked/
├── seed/                              # git repo (local remote)
├── agents/
│   └── {agent_id}/                    # branched clone of seed; branch = agent_id
│       ├── daemon.log                 # was {agent_id}.log
│       ├── live_context.md            # was {agent_id}.md
│       └── memformat.xml              # was {agent_id}-memformat.xml (rename only — keeps .xml)
└── projects/
    └── {project_name}/                # branched clone of seed; branch = project_name
        └── {agent_id}.md              # per-agent project context (one file per agent that touched this project)
```

**Success Criteria** (what must be TRUE):

  1. `psyches/tracked/seed/` is initialized as a git repo on first run; SPT helpers manage it (`src/common/owlery.rs` + new tracked-repo module)
  2. `psyches/tracked/agents/{agent_id}/` is a branched clone of `seed/` with branch name `{agent_id}`; created lazily on first commune/signoff for that agent
  3. `psyches/tracked/projects/{project_name}/` is a branched clone of `seed/` with branch name `{project_name}`; created lazily on first project-scoped write
  4. File renames applied: `{agent_id}.log` → `agents/{agent_id}/daemon.log`; `{agent_id}.md` → `agents/{agent_id}/live_context.md`; `{agent_id}-memformat.xml` → `agents/{agent_id}/memformat.xml` (extension preserved)
  5. Project context (one `.md` per agent that touched the project) lives at `projects/{project_name}/{agent_id}.md`
  6. Every commune/signoff writes commit local branch + pushes to `seed/`; `seed/` is the push target until Phase 35 sync swaps the remote to the gh repo
  7. Wrapper appends to `agents/{agent_id}/sessions-{gen}.log` on every fresh `claude -p` (no `--resume`) with: timestamp, session UUID, generation, trigger reason
  8. `/spt:revive` (and any new-generation event) seals prior sessions log and starts a new one
  9. Existing flat-layout files (`tracked/{agent_id}.log`, `tracked/{agent_id}.md`, `tracked/{agent_id}-memformat.xml`) migrate into the new layout on first boot of new binary, or coexist as legacy without breaking listings
  10. `$LIVE doctor` recognizes the forked-repo layout and reports per-branch status (clean / dirty / unpushed commits)
  11. Helpers in `src/common/owlery.rs`, `src/live/start.rs`, `src/owl/doctor.rs`, commune/signoff write paths, and `$LIVE psyche-download` updated end-to-end

**Open at discuss-phase**: git library choice (`git2-rs` vs shelling out to system `git`); how SPT-binary-only installs handle missing system git; commit message format per write; whether `seed/` keeps full history or is squashed; conflict handling when two machines push divergent branches (defers to Phase 35); cost of N branched working trees on disk vs single bare repo + worktrees.
**Plans:** 7 plans

Plans:

- [x] 24-01-PLAN.md - tracked.rs foundation: ensure_seed (bare-repo bootstrap) + Stamp::commit_trailers + owlery path helpers
- [x] 24-02-PLAN.md - Lazy worktree primitives (ensure_agent_worktree, ensure_project_worktree) + sessions log writer with D-18 dedup
- [x] 24-03-PLAN.md - Write-path integration: route commune/signoff/echo/memformat/daemon-log to agent worktrees with D-07 subject + D-08 trailers (no push per D-13 amendment)
- [x] 24-04-PLAN.md - Sessions log trigger emitters (boot/pulse/commune/signoff) at 5 call sites + generation seal-on-rollover
- [x] 24-05-PLAN.md - Migration on first boot: legacy flat-layout files (.log/.md/-memformat.xml) -> agent worktrees; idempotent + handoff-race tolerant
- [x] 24-06-PLAN.md - $LIVE doctor per-worktree status surface (D-17): clean/dirty/N-local rows + orphan detection
- [x] 24-07-PLAN.md - CHANGELOG v1.8 entry + SEED-004 fold confirmation + operator end-to-end smoke test (Tasks 1+2 DONE 2026-05-20 — commit 0279e4f; Task 3 PAUSED at blocking operator-verify checkpoint)

### Phase 24.1: Tracked-Agents info.json — Cross-Session Activity Index

**Goal**: Every agent gets a persistent `psyches/tracked/agents/{agent_id}/info.json` recording cross-session activity metadata that survives perch teardown and machine swaps: `last_started`, `last_machine_name`, `last_project_name`, `machine_history[]`, `project_history[]`. `project_history` mirrors the same list the agent's owlery perch info.json maintains today, lifted up to the tracked tree so it persists across reboots and roams with the agent via Phase 24's branched layout (and Phase 35 sync).
**Milestone**: v1.8 Psyche Restructure
**Depends on**: Phase 24 (lives inside Phase 24's `agents/{agent_id}/` branch)
**Promoted from**: Drafted 2026-05-18 via /gsd-progress dispatch

**Requirements**: TBD (TRK-INFO-SCHEMA-01, TRK-INFO-LIFECYCLE-01, TRK-INFO-HISTORY-01, TRK-INFO-SYNC-01, TRK-INFO-MIGRATE-01)

**Schema (draft):**

```json
{
  "agent_id": "doyle",
  "last_started": "2026-05-18T07:30:00Z",
  "last_machine_name": "<hostname>",
  "last_project_name": "claude_skill_owl",
  "machine_history": [
    { "name": "<hostname>", "first_seen": "...", "last_seen": "..." }
  ],
  "project_history": [
    { "name": "claude_skill_owl", "root": "/abs/path", "first_seen": "...", "last_seen": "..." }
  ]
}
```

**Success Criteria** (what must be TRUE):

  1. `psyches/tracked/agents/{agent_id}/info.json` is created on the first boot of an agent under the new layout (Phase 24's `agents/{agent_id}/` branch)
  2. `last_started` updates on every fresh `claude -p` spawn (paired with Phase 24 SC 7 sessions log)
  3. `last_machine_name` resolves from OS hostname; an entry is appended/updated in `machine_history` when a new machine first writes
  4. `last_project_name` updates on commune/signoff based on cwd; an entry is appended/updated in `project_history` when a new project first writes
  5. `project_history` content stays consistent with the per-agent owlery perch info.json `project_history`/equivalent field; perch info.json remains the live working copy, tracked info.json is the durable snapshot synced on every commune/signoff and on perch teardown
  6. Atomic write semantics (temp-file + rename) so a crashed write does not corrupt the file
  7. Commit + push of `info.json` into the agent's branch piggybacks on Phase 24's commune/signoff write path (no separate write trigger needed)
  8. `$LIVE doctor` surfaces tracked info.json for each agent (parsed summary + raw path)
  9. Migration: agents already on disk get an `info.json` synthesized from their current perch info.json + mtime fallbacks the first time the new binary boots them
  10. `$LIVE psyche-download` and listings have access to tracked info.json so consumers can see `last_started` / `last_machine_name` / `last_project_name` without re-parsing perch state

**Open at discuss-phase**: machine identity stability (hostname vs persistent UUID stored in `$SPT_HOME/settings.json` vs gh-account email when Phase 35 enabled); de-dup + cap rules for `machine_history` / `project_history` (LRU? max N entries? unbounded?); whether `last_project_name` needs richer identity than a name string (git remote hash, abs path canonicalization); how Phase 35 sync handles two-machine concurrent writes to the same branch's info.json (likely defers to Phase 35's conflict policy).
**Plans:** 5 plans

Plans:

- [x] 24.1-01-PLAN.md - Foundation primitives: time::now_iso_utc, git::hostname promotion + head_branch_or_empty, types::TrackedAgentInfo + record-shape upgrade
- [x] 24.1-02-PLAN.md - Owlery helpers: tracked_agent_info_path, append_history_entry primitive, normalize_legacy_strings_to_objects, bump_tracked_agent_info, read_tracked_agent_info_or_fallback, upgraded append_project_history
- [x] 24.1-03-PLAN.md - Atomic-write trigger wiring: perch-side append_project_history upgrade in poll.rs + start.rs; bump at boot×2, commune, signoff sites
- [x] 24.1-04-PLAN.md - Commit-funnel file-list amendment (context.rs + fork.rs); migration synth in tracked.rs; D-14 doctor sub-line
- [x] 24.1-05-PLAN.md - Mixed-shape integration test + field-order byte contract + end-to-end smoke + CHANGELOG v1.8 entry

### Phase 25: Perch Nesting (Psyche + Workers) + Wire psyche-download to Forked-Repo Layout

**Goal**: Perch nesting applied to both Psyche AND worker/working perches under their parent agent's perch in `owlery/`. Psyche perch dir nests inside Self perch dir; worker perches live at `owlery/<parent>/workers/<worker-id>/`. `$LIVE psyche-download` becomes cwd-aware: it sources from Phase 24's forked-repo layout, concatenating `agents/{agent_id}/memformat.xml` + `agents/{agent_id}/live_context.md` (general / cross-project Self summary) + `projects/{cwd_project}/{agent_id}.md` (per-project record) when a project match exists. Commune/signoff routes the project-scoped write into `projects/{cwd_project}/{agent_id}.md` based on cwd.
**Milestone**: v1.8 Psyche Restructure
**Depends on**: Phase 24 (forked-repo layout is the source of truth `psyche-download` reads from)
**Promoted from**: ROADMAP backlog Phase 999.1 + seeds/SEED-003-relocate-working-perches-nested-under-parent.md
**Requirements**: TBD (NEST-PSYCHE-PERCH-01, NEST-WORKER-PERCH-01, DOWNLOAD-CWD-01, COMMUNE-PROJECT-ROUTE-01, MIGRATE-PERCH-01)
**Success Criteria** (what must be TRUE):

  1. Psyche perch directory is created inside Self perch directory (nested under `owlery/<self_id>/psyches/<self_id>-psyche/`); listings + `info.json` lookup still resolve the Psyche correctly
  2. Worker/working perches nest under their parent agent's perch (`owlery/<parent>/workers/<worker-id>/`); `is_worker_perch` flat-detection rule swaps for parent-aware nested rule; `inject_active_perch_context` enumeration handles nested layout; `$OWL list` output reflects tree shape; cleanup on parent death cascades to nested workers; binary handoff perch discovery (Phase 18.4/18.5 path) tolerates nested workers
  3. Commune and signoff context writes route the project-scoped payload into Phase 24's `psyches/tracked/projects/{cwd_project}/{agent_id}.md` based on cwd; cross-project entries continue to write `agents/{agent_id}/live_context.md`
  4. `$LIVE psyche-download` auto-detects cwd project and outputs concat of `memformat.xml + live_context.md + projects/{cwd_project}/{agent_id}.md` (the project section is omitted when no project file exists for this cwd)
  5. When invoked outside any known project, `$LIVE psyche-download` falls back to `memformat.xml + live_context.md` only (no project section)
  6. Migration path covers legacy flat owlery perches (workers as siblings) — auto-relocate on first boot of new binary, or coexist as legacy without breaking listings
  7. Doctor + listing tooling understands nested Psyche perches AND nested worker perches; reports per-perch parent/child relationship
  8. SessionStart psyche-context injection (Phase 28 carryover) updated to consume the new download payload shape

**Open at discuss-phase**: how `cwd_project` is identified (git remote URL hash / repo root basename / explicit registry); behavior when same agent has touched many projects (truncation cap on project section); whether `live_context.md` is the same file Phase 24 sources from or a derived projection.
**Plans:** 5 plans

Plans:
**Wave 1**

- [x] 25-01-PLAN.md - Wave 1 foundation: path helpers, path-aware predicates, recursive enumerate_perches + tuple-shape cascade, commit_project_payload

**Wave 2** *(blocked on Wave 1 completion)*

- [x] 25-02-PLAN.md - Wave 2 lifecycle: D-16 psyche relocate + nested psyche spawn in start.rs; D-20 orphan-worker sweep at start + signoff

**Wave 3** *(blocked on Wave 2 completion)*

- [x] 25-03-PLAN.md - Wave 2 payload reshape: envelope parser, download_payload project-section append, commune + signoff two-slice routing

**Wave 4** *(blocked on Wave 3 completion)*

- [x] 25-04-PLAN.md - Wave 3 prompt: psyche.md D-11 envelope teaching + D-10 taxonomy + D-12 inline CURRENT_LIVE_/PROJECT_CONTEXT in echo_commune + signoff

**Wave 5** *(blocked on Wave 4 completion)*

- [x] 25-05-PLAN.md - Wave 4 UX + tests: tree-shape list, doctor D-05/D-17/D-18/D-21, integration tests for all 5 requirement IDs, smoke checkpoint

### Phase 25.1: Revise /commune + /signoff skill docs + echo commune instruction. they must now guide the agent to split the commune into project-specific vs. agent general, to align with phase 25's psyche context updates. (INSERTED)

**Goal:** Self-side skill docs teach the Phase 25 D-10/D-11 two-slice envelope contract such that a live agent composing a commune or signoff body produces correctly-routed two-slice output, and an echo-commune-receiving agent absorbs the two slices coherently as one resume brief. A small Rust sentinel (`<project-context-resolved name="..."/>`) in `download_payload()` provides the deterministic in-project detection signal Self keys on.
**Requirements**: none (urgent insert, no req mapping)
**Depends on:** Phase 25
**Plans:** 6 plans

Plans:
**Wave 1**

- [x] 25.1-01-PLAN.md - Sentinel emission in `src/live/context.rs::download_payload()` (`<project-context-resolved name="..."/>`) + 2 unit tests + `cargo build --release` (enables D-25.1-04)

**Wave 2** *(blocked on Wave 1 completion)*

- [x] 25.1-02-PLAN.md - `plugin/spt/skills/commune/SKILL.md`: new `## Two-slice body shape (Phase 25 D-10/D-11)` section, Step 3 reword, Phase 23 nesting note
- [x] 25.1-03-PLAN.md - `plugin/spt/skills/commune/commune.md`: two-slice section, Memformat Guide reframe (D-25.1-08), `## How to Send` extension, `## What to Include` routing sub-bullet, three worked examples
- [x] 25.1-04-PLAN.md - `plugin/spt/skills/signoff/SKILL.md`: FINAL-COMMUNE two-slice cross-link section, Step 3 reword, Phase 23 nesting note
- [x] 25.1-05-PLAN.md - `plugin/spt/skills/live/SKILL.md`: extend echo_commune envelope catalog entry (~line 268) with two-slice body shape teaching + `/spt:listen`/`/spt:commune` cross-links
- [x] 25.1-06-PLAN.md - `plugin/spt/skills/revive/SKILL.md`: short echo-commune section cross-linking `/spt:live` + `/spt:listen`

### Phase 25.2: Doyle cluster fix candidates — blast radius sanity check across SPT listener wrapper and tracked-repo paths (INSERTED)

**Goal:** Resolve six fix candidates surfaced during doyle listener-poll diagnostic session (2026-05-22). Each candidate audited for blast radius — every system surface touching the same root cause integrated into one consolidated fix plan. Candidates span stale-lock recovery, ghost-repo cleanup, wrapper-state timing, wrapper poll-sentinel path migration, signoff drain-vs-deliver semantics, and haiku signoff-absorption compression. Diagnostic source: `.planning/debug/doyle-sessions-seal-tracked-psyches.md`.
**Requirements**: none (urgent insert, no req mapping)
**Depends on:** Phase 25 (nested perch layout); Phase 24/24.1 (tracked-repo per-agent worktrees); Phase 30 (drain-stale-signoff defense)
**Status:** Complete (verified 2026-05-22 — VERIFICATION.md status: passed; 5/5 candidates shipped; D-01..D-12 honored)
**Plans:** 3/3 plans complete

### Fix candidates (each requires blast-radius sanity check before plan)

**1. Stale `index.lock` blocks sessions-log seal**
- Root: `git add/commit` crash leaves 0-byte `index.lock` under `seed/worktrees/<agent>/`; subsequent commits fail "Another git process seems to be running."
- Primary code site: `src/common/tracked.rs:362-366` (`ensure_worktree` fast-path) — add stale-lock probe (len==0 && mtime > 60s → `remove_file` best-effort).
- **Blast radius:** every caller that invokes git through a per-agent worktree. Audit: `commit_agent_payload` (sessions.log seal), `commit_project_payload` (project slices), `git_commit_context` (init/final/pulse auto-commit). Also `seed/.git/index.lock` itself (shared bare repo) — same crash class, different path, separate sweep needed. Also worktree's working-copy `.git` marker file (not the admin index.lock).

**2. Ghost `tracked/.git/` Phase 23-era repo**
- Root: Phase 23 wrote to `tracked/.git/` flat layout; Phase 24 D-13 stopped writing but didn't `rm -rf`. Dormant since 2026-05-20. Pure cosmetic noise in `git -C tracked status`.
- Primary action: one-shot cleanup script + idempotent guard in `migrate_legacy_if_needed` (`tracked.rs:1458`).
- **Blast radius:** any code path that does `git -C $TRACKED_ROOT` operations on the FLAT level (vs `seed/` bare or per-agent worktrees). Audit: doctor invocations, list/status commands that recurse into `tracked/` looking for repos, deploy scripts. Confirm no production code depends on the flat `.git/` index.

**3. wrapper-state.json 2000ms timeout warning**
- Root: `claude -p` cold-start exceeds 2s before `session_uuid` published; sessions-log writer logs `"wrapper-state.json missing or empty session_uuid for doyle after 2000ms; skipping boot row"` and skips boot row.
- Primary code site: `src/live/start.rs:583-588` (warning emit) + the 2000ms retry budget.
- **Blast radius:** every consumer of `read_wrapper_state(psyche_id).session_uuid`. Audit: signoff sessions-log trigger (`signoff.rs:267-275`), commune trigger, pulse trigger, init trigger. Each one has its own retry semantics — must be uniform. Also reader-vs-writer path drift (see #4).

**4. Wrapper poll-sentinel uses flat `ready_file()`; psyche perch now nested**
- Root: Phase 25 D-16 moved psyche perch → `owlery/<self>/nested/<self>-psyche/`. But `src/live/wrapper/mod.rs:629` still calls `owlery::ready_file(&self.psyche_id)` → flat `owlery/<self>-psyche/ready`. Flat path has no `ready` file → wrapper exits poll iter 1 every spawn. Verified in `logs_latest/doyle.log` 04:53:30.
- Primary code site: `wrapper/mod.rs:629` (poll sentinel check). Likely siblings: any other `wrapper/` usage of `perch_dir(psyche_id)`, `info_file(psyche_id)`, `inbox_dir(psyche_id)`, `ready_file(psyche_id)` that pre-dates Phase 25.
- **Blast radius — CRITICAL.** Same root pattern (flat vs nested) likely affects:
  - Orphan detection (`wrapper/orphan.rs`) — checks Self's perch; uses flat ready for Self (correct) but inspect for any psyche-side check.
  - `drain_stale_init_signoffs` (`wrapper/lifecycle.rs`) — spool inbox path.
  - `read_wrapper_state(psyche_id)` writer — does it write to flat or nested? Confirms top-level vs nested `wrapper-state.json` divergence (top gen 4 vs nested gen 52 observed).
  - `$LIVE list`, `$LIVE status` — enumeration. Per `list_filter.rs` comments, walks both flat AND nested. Verify all callers receive consistent psyche-perch path.
  - SessionStart hook `session-resume` parent_pid matching — does it look at nested info.json?
  - Binary handoff (`wrapper-state.json` rehydrate) — Phase 18.4/18.5. Handoff_hydrated=false on gen 4 boot suggests handoff read from wrong path and silently fell back to fresh.
  - Workers (`<self>-wN`) — already nested by Phase 25 D-01. Same audit applies symmetrically.

**5. `drain_stale_signoff_file` discards fresh signoffs**
- Root: `src/live/start.rs:138-178`. On every `$LIVE start`/`revive`, surfaces `.claude/<id>-signoff.md` body to stdout, then DELETES. Cannot distinguish "stale prior-gen" from "fresh-user-written-while-offline." Confirmed payload-loss scenario in doyle case.
- Primary fix: deliver-then-die — drain reads body, queues INIT_SIGNOFF to psyche spool, THEN deletes file. Psyche absorbs on first `claude -p` invocation.
- **Blast radius:** Phase 30 invariant — wrapper's own `drain_stale_init_signoffs` (`lifecycle.rs`) does the SAME thing for spool-inbox stale envelopes. Verify wrapper's drain isn't ALSO eating fresh signoffs. Also `scan_drop_files` normal-path consumer must coexist with new drain semantics without double-delivery. Cross-check `.planning/debug/resolved/stale-signoff-fires-on-next-session-start.md` asymmetry argument to confirm deliver-then-die doesn't reintroduce the STOP-loop original drain prevented.

**6. Haiku signoff-absorption compresses too aggressively**
- Root: psyche-haiku invocation receives 3215-byte detailed signoff payload; writes 767-byte summarized `live_context.md`. Compression at LLM layer.
- Primary fix: `psyche.md` signoff-absorption rule strengthening — emit "preserve verbatim detail for gray-area decisions, plan addenda, and explicit `FINAL COMMUNE` blocks; summarize ONLY routine status."
- **Blast radius:** every signoff absorption since Phase 23 (commune+signoff project-root stamping deployed). Audit other agents' `live_context.md` for similar compression (deployah, todlando, mica, executor, dunsen, webber, witty, higsby). Also commune-absorption path uses same haiku — verify if commune bodies suffer same loss. Also intersects with #1 — when seal fails, sessions.log retains raw rows; consumers using sessions.log as audit trail get more detail than live_context.md, which becomes the canonical record.

### Cross-cutting integration mandate

Plans MUST treat #1+#3+#4 as one coordinated wrapper-path-correctness sweep (shared root: flat-vs-nested + wrapper-state read/write paths). Plans MUST treat #5+#6 as one signoff-payload-preservation sweep (shared root: detailed signoff content is precious; every consumption point must either deliver fully or be intentionally lossy with user awareness). #2 is standalone cleanup.

Plans:
- [x] 25.2-01-PLAN.md - Wrapper-path correctness sweep (#1 stale-lock probe + #3 wrapper-state retry budget + #4 flat-to-nested wrapper-path sweep)
- [x] 25.2-02-PLAN.md - Latent signoff deliver-then-die (#5 forward .claude signoff body as latent-signoff EVENT envelope)
- [x] 25.2-03-PLAN.md - Ghost tracked/.git/ cleanup (#2 unconditional best-effort remove_dir_all in migrate_legacy_if_needed)

### Phase 25.3: project-context envelope persistence + encoding defects (INSERTED)

**Goal:** Resolve three defects surfaced during `todlando-project-context-not-persisted` debug session (2026-05-22). Inbound `<project-context>` envelopes are reaching Psyche but never persisted to disk at the Phase 25 schema location `projects/<project_name>/<self_id>.md`. Root causes: (B2) asymmetric project-name resolver between context-block builder and EVENT stamper within same echo_commune fire, (A) wrapper relies on Psyche LLM round-trip to merge inbound envelopes with no direct route_two_slice on ingestion, (C) selective HTML-encoding leak where inner envelope tokens reach Psyche as `&lt;...&gt;` while outer `<EVENT>` and `<br>` tokens survive raw. Diagnostic source: `.planning/debug/todlando-project-context-not-persisted.md`.
**Requirements**: none (urgent insert, no req mapping)
**Depends on:** Phase 25 (nested layout + two-slice context blocks); Phase 24.1 (`info.json` `last_project_name`, D-09); Phase 25.1 (two-slice envelope teaching + sentinel emission)
**Status:** Plans pending
**Plans:** TBD

### Defect roster (each requires blast-radius sanity check before plan)

**B2. Asymmetric project resolver in `build_current_context_blocks`**
- Root: `src/owl/echo_commune.rs:411` calls `derive_current_repo_names()` which reads `std::env::current_dir()`. Haiku spawns with cwd = `psyche_dir()` = `%LOCALAPPDATA%\spt\psyches\tracked` per D-05. That dir has no `.git` parent → D-06 fallback returns `["tracked"]` — bogus project name leaks into the two-slice context payload.
- Same fire pass at `src/owl/echo_commune.rs:869` correctly resolves via `resolve_self_project_stamp(self_id)` which reads Self's perch `info.json` `last_project_name` (Phase 24.1 D-09). Outbound EVENT envelope gets the right project; inner context-block contents do not.
- Primary fix: `build_current_context_blocks` must prefer Self info.json `last_project_name` before falling back to cwd-derived names, and explicitly reject the `"tracked"` D-06 false positive when the haiku is the caller.
- **Blast radius:** every consumer of `build_current_context_blocks`. Audit: echo_commune fire path (this site), signoff prompt-build path (`src/live/signoff.rs` callers of the same helper), pulse trigger context assembly, init trigger. Also `derive_current_repo_names()` itself — confirm no other caller relies on the `"tracked"` fallback as intended behavior. Also Phase 24.1 D-09 stamping vs Phase 25 schema interaction — `last_project_name` must match the `projects/<name>/` subdir convention exactly (no normalization drift between stamper and consumer).

**A. Wrapper does not route inbound commune envelopes through `route_two_slice`**
- Root: `src/live/wrapper/mod.rs::process_file_drop` → `resume_session_with_exit` feeds inbound commune bodies to the Psyche LLM verbatim and discards the LLM reply. Architecturally relies on the Psyche to merge in-memory and re-emit on the NEXT echo_commune fire. When Defect B2 corrupts the next fire's outbound envelope, the inbound `<project-context>` is silently lost.
- Primary decision: either (a) wrapper extracts `<project-context>` from inbound payloads and calls `route_two_slice` directly before handing to LLM, OR (b) confirm round-trip-via-LLM is intended and harden psyche.md to always re-emit envelopes on the next fire.
- **Blast radius:** every inbound envelope type the wrapper currently forwards LLM-only (commune, latent-signoff, project-context, live-context, future envelope types). Audit: `process_file_drop` envelope dispatch, `drain_stale_init_signoffs` (Phase 30 deliver-then-die invariant), `drain_stale_signoff_file` (Phase 25.2 deliver-then-die). Also crosses Phase 25 D-10/D-11 two-slice routing semantics — if wrapper starts calling `route_two_slice` directly, downstream consumers must idempotently handle "envelope already routed before LLM saw it." Also affects Defect C investigation surface — wrapper-side relay is one suspect for the encoding leak.

**C. Selective HTML-encoding leak in commune relay**
- Root: User screenshot evidence (commune EVENT reaching Psyche at 16:58:53) shows outer `<EVENT type="commune">` and `<br>` tokens UNENCODED while inner `&lt;live-context&gt;` is ENCODED, all within the same payload body. Asymmetric encoding within a single envelope indicates a double-decode-or-not-decode bug somewhere in producer → spool → poll → wrapper → Psyche pipeline.
- Primary investigation surface: `src/owl/send.rs` (deliver_body_anonymous encoding), `src/owl/echo_commune.rs` (EVENT body construction), EVENT-PART chunker (`src/owl/poll.rs` or sibling), spacetime-reorientation body-parsing rules (`<br>` split + `&lt;`→`<` decode chain ordering — apply `&amp;` last per documented contract).
- **Blast radius:** every consumer that applies the body-parsing decode chain. If producers are emitting one-pass-pre-encoded bodies (inner tags encoded, outer EVENT raw), consumers expecting two-pass decode will under-decode; consumers expecting raw bodies will over-decode. Audit: poll listener decode, wrapper relay decode, Psyche prompt assembly, EVENT-PART reassembly across `<br>` tokens. Also affects Defect A fix — wrapper-side `route_two_slice` direct call needs to operate on decoded inner envelopes.

**D. `psyche.md` never instructs Psyche to write `projects/<name>/<self_id>.md`**
- Root: User-observed in Psyche session log — Psyche only ever writes `live_context.md`; never writes the project-scoped slice file at `projects/<project_name>/<self_id>.md`. The two-slice Phase 25 schema is wired on the producer/sentinel side (Phase 25.1) but the Psyche LLM's persistence instructions in `psyche.md` (embedded via `include_str!`) do not teach the LLM to split its absorption output into a general slice (`live_context.md`) plus project slices (`projects/<name>/<self_id>.md`).
- Primary fix: `psyche.md` absorption rules must instruct the LLM to (a) detect `<project-context name="...">` envelopes in inbound payloads, (b) persist project-specific delta to `projects/<name>/<self_id>.md`, (c) keep `live_context.md` as the general slice — symmetric with the producer-side two-slice split taught in `commune.md`. Also clarify which `name` value to use (must match `last_project_name` stamping convention to avoid drift with Defect B2 fix).
- **Blast radius:** every absorption path the Psyche LLM runs — commune absorption, signoff absorption, pulse absorption, init absorption, echo_commune fire (the LLM both consumes inbound context AND produces outbound two-slice envelopes). Audit all existing agents' Psyche dirs (`%LOCALAPPDATA%\spt\psyches\tracked\agents\<id>\`) to confirm none currently have populated `projects/` subtrees — confirms scope of "no agent has ever written this file." Also cross-check against Phase 25.1 `commune.md` / `signoff.md` teaching — psyche.md instruction must match skill-side teaching exactly or the human-written commune and LLM-emitted absorption will diverge. Also rebuild required: `psyche.md` is `include_str!`-embedded, so changes ship via binary handoff like any Rust change.

### Cross-cutting integration mandate

Plans MUST treat B2 as standalone (smallest blast, fastest fix, unblocks correct `projects/<name>/` destination). D is paired with B2 — even with B2 fixed, the LLM still needs psyche.md instruction to actually write the file; B2 fix alone unblocks the path but D fix is what produces the artifact. A and C are coupled — both touch wrapper-side envelope handling and any fix to A that calls `route_two_slice` directly must first land C's decode contract clarification, else the wrapper routes encoded envelope bodies to writers that expect decoded ones.

Plans:
- [x] 25.3-01-PLAN.md - Defect B2: project-name resolver fix in `build_current_context_blocks` (prefer info.json `last_project_name`, reject `"tracked"` D-06 false positive, audit shared callers)
- [x] 25.3-02-PLAN.md - Defect D: `psyche.md` absorption instruction — teach LLM to write `projects/<name>/<self_id>.md` symmetric with producer-side two-slice (commune.md/signoff.md alignment)
- [x] 25.3-03-PLAN.md - Defect C: encoding leak diagnosis + contract clarification across producer/poll/wrapper/Psyche decode chain
- [x] 25.3-04-PLAN.md - Defect A: wrapper-side envelope routing (Option 1 LOCKED — synchronous `route_inbound_commune_body` BEFORE LLM handoff) + cycle-5 HIGH 1+2 surgical fixes (YAML-aware marker placement; context.rs read sites converted to `read_context_body_stripped`) — deployed v1.11.6
- [x] 25.3-05-PLAN.md - Defect E gap-closure: psyche-download destructive consume race + ANSI escape leak + Defect F (psyche.md rule 4 tightening) + Defect G HAPPY-PATH (live_context.md → projects file replication post-LLM-Write) — D-E-01 Option D single-writer contract; D-E-04 strip_ansi; D-E-06 psyche.md tightening; D-E-07 revised route_live_context_md_if_changed HAPPY-PATH hook + RefCell re-entry guard (G2 self-heal SPLIT to 25.3-06 per cycle-3 plan-checker) — deploys v1.11.7
- [x] 25.3-06-PLAN.md - Defect G2 self-heal: respawn on malformed live_context.md (project: None + project resolves + prompt had CURRENT_PROJECT_CONTEXT). ResumeRespawnDispatcher trait + corrective prompt + retry cap 1. Depends on 25.3-05. Deploys v1.11.8.

### Phase 25.4: Perch-path single-source-of-truth — finish D-01 nested migration for psyche/worker writers + readers; central resolver in src/common/owlery.rs (id-kind classifier: Self/psyche/worker/spine/touch); migrate poll.rs/spool.rs/inbox.rs/hook_check.rs writers + 8 Class-E readers; close wrapper-state flat-writer migration window. Research: .planning/quick/260523-paw-perch-audit-psyche-worker-flat-vs-nested/RESEARCH.md (INSERTED)

**Goal:** Finish Phase 25 D-01 nested migration end-to-end for psyche/worker perch state. Introduce a central perch-path resolver (`src/common/perch_path.rs`) as the SINGLE source of truth that classifies ids by kind (Self/Psyche/Worker/Spine/Touch) and composes flat vs nested paths from one function. Route every writer (poll.rs, spool.rs, inbox.rs, hook_check.rs .owl-aware, hook_idle.rs .more-done, wrapper-state writers) and every Class-E reader (send.rs, ring.rs, cleanup.rs, commune.rs, signoff.rs, touch_loop.rs, boot_spine.rs, stop.rs) through the resolver. Close the wrapper-state.json flat-writer migration window per CONTEXT D-03 (no pre-25.2 wrappers in flight). Verify end-to-end via automated integration tests + operator-driven on-disk smoke probe.
**Requirements**: PERCH-PATH-RESOLVER-01..03, PERCH-PATH-LANDMINE-01, PERCH-PATH-POLL-MIGRATION-01..02, PERCH-PATH-SPOOL-MIGRATION-01, PERCH-PATH-INBOX-MIGRATION-01, PERCH-PATH-SENTINEL-MIGRATION-01, PERCH-PATH-WRAPPER-STATE-MIGRATION-01, PERCH-PATH-READER-MIGRATION-01..02, PERCH-PATH-STOP-SYMMETRY-01, PERCH-PATH-SMOKE-PROBE-01, PERCH-PATH-WORKER-MYSTERY-01, PERCH-PATH-GOAL-VERIFY-01
**Depends on:** Phase 25, Phase 25.2 (wrapper-state nested-first reader resolver)
**Plans:** 7 plans

Plans:
- [x] 25.4-01-PLAN.md - Wave 1: central perch-path resolver module (`src/common/perch_path.rs`) — PerchKind classifier + ParentHint + resolve_perch_path + four child-file helpers + unit tests. Architectural keystone per CONTEXT D-02.
- [x] 25.4-02-PLAN.md - Wave 1: ready-file landmine regression test (`tests/wrapper_ready_file_landmine.rs`) pinning the wrapper/mod.rs:1168 loop-exit predicate invariant BEFORE Wave 2 writer changes per CONTEXT D-06.
- [x] 25.4-03-PLAN.md - Wave 2: migrate `src/owl/poll.rs` (RESEARCH B/C-1 primary writer) — add `--parent <self_id>` CLI flag; route all perch-path composition through resolver; wrapper passes the flag at mod.rs:1527.
- [x] 25.4-04-PLAN.md - Wave 2: migrate spool.rs + inbox.rs (RESEARCH B/C-2/3) + .owl-aware sentinel (B/C-4) + .more-done sentinel (B/C-5). Add `_at` path-aware surfaces; legacy id-based fns delegate via resolver Infer.
- [x] 25.4-05-PLAN.md - Wave 2: close wrapper-state.json flat-writer migration window per CONTEXT D-03. Migrate three writer sites (claude.rs:201, lifecycle.rs:103, mod.rs:1685) to nested-canonical `write_wrapper_state_at`; reader stays dual-path one more deploy cycle.
- [x] 25.4-06-PLAN.md - Wave 3: migrate all 8 Class-E reader sites (send.rs, ring.rs, cleanup.rs, commune.rs, signoff.rs, touch_loop.rs, boot_spine.rs, stop.rs) through resolver. Resolve stop.rs/lifecycle.rs nested-cleanup asymmetry per CONTEXT D-09.
- [x] 25.4-07-PLAN.md - Wave 3 (CHECKPOINT): two automated integration tests (`tests/perch_path_no_flat_psyche.rs` + `tests/perch_path_no_flat_worker.rs`) + operator-driven on-disk smoke probe (`25.4-SMOKE-PROBE.md`) verifying GOAL items (live start → no flat dirs, subagent spawn → no flat dirs) + RESEARCH Open Q1 (worker mystery) resolution.

### Phase 35: Psyche Sync — Cross-Machine Context Backup via Private gh Repo

**Goal**: With `gh` CLI installed and authenticated, every Psyche-context tracking commit also syncs (pull-then-push) to a private `spt-agent-storage` repo under the user's GitHub account. SPT bootstraps the remote autonomously (or via `/psyche-sync-setup` skill) and triggers sync on UserPromptSubmit so context updates from a remote machine land before the local turn starts. Combined with Phase 24's per-agent tracked layout, this enables cross-machine agent repo memory.
**Milestone**: v1.8 Psyche Restructure
**Depends on**: Phase 24 (per-agent tracked layout is the sync unit); pairs naturally with Phase 25 (nested layout shapes sync payload)
**Promoted from**: Drafted 2026-05-18 during /gsd-progress --do dispatch (Discord image spec)
**Requirements**: TBD (SYNC-BOOTSTRAP-01, SYNC-AUTO-01, SYNC-MANUAL-01, SYNC-HOOK-01, SYNC-NOOP-01)
**Success Criteria** (what must be TRUE):

  1. Auto path: once per machine, SPT binary checks for `gh` CLI; if present, queries user account for `spt-agent-storage` repo; if repo exists, surfaces `AskUserQuestion` offering to enable Psyche sync
  2. Manual path: `/psyche-sync-setup` skill instructs user to install/authenticate `gh` if missing, then `AskUserQuestion` confirms private `spt-agent-storage` repo creation under user account; on accept, SPT creates the repo via `gh`
  3. Once-per-machine state flag stored in `$SPT_HOME/settings.json` (sync-enabled, sync-acked, remote-repo-url)
  4. Every Psyche-context tracking commit triggers a sync cycle: pull from remote first → apply local commit → push to remote
  5. Sync trigger point: UserPromptSubmit hook (rationale: remote-machine context may have advanced since last local turn — pull before user prompt is processed)
  6. Graceful no-op when `gh` is absent, unauthenticated, or sync is disabled — no errors surfaced to user, no blocking on hook
  7. Doctor (`$LIVE doctor` / `$OWL doctor`) + listing tooling surfaces sync status per machine (enabled/disabled, last-sync timestamp, last-sync result)

**Open at discuss-phase**: conflict resolution strategy (last-write-wins / rebase / manual prompt), `gh` token scope (`repo` minimum vs broader), throttling for rapid UserPromptSubmit fires, behavior when remote is gone / repo deleted
**Plans:** 10 plans (9 shipped v1.11.17 + 1 gap-closure)

Plans:

- [x] 35-01-PLAN.md - Settings schema + read/write helpers in src/common/owlery.rs (SyncState enum, SyncSettings struct, sibling-preserving JSON splice)
- [x] 35-02-PLAN.md - src/common/sync.rs primitives: pull_branch (fetch+rebase), push_branch, sync_after_commit, classifier (D-17 404 + D-18 backoff), abort_stale_rebase
- [x] 35-03-PLAN.md - Promoted spawn_detached_unix helper in src/common/process.rs (setsid + null stdio mirror of win_spawn)
- [x] 35-04-PLAN.md - accept_flow + Commands::SyncPullAsync + Commands::PsycheSyncSetup + plugin/spt/skills/psyche-sync-setup/SKILL.md (D-10 + D-13)
- [x] 35-05-PLAN.md - UserPromptSubmit hook async pull dispatch (D-04 first trigger; detached child runs sync-pull-async)
- [x] 35-06-PLAN.md - Post-commit pull-then-push hooks in tracked.rs commit_*_payload + maybe_add_origin wiring in ensure_worktree (D-04 second trigger + D-10 step 5)
- [x] 35-07-PLAN.md - SessionStart auto-prompt branch (should_emit_sync_prompt predicate + emit_sync_prompt envelope; D-08 gates)
- [x] 35-08-PLAN.md - $OWL doctor ## Sync section (collapse-on-clean / expand-on-failure; recovered-aborts counter; structured doctor_result wire)
- [x] 35-09-PLAN.md - Integration tests (sync_noop / sync_pull_push / sync_post_commit) + two-machine operator UAT
- [x] 35-10-PLAN.md - GAP CLOSURE (SC1 defect): rewrite sync-prompt to ACTIVE owl-message delivery (self-contained <instructions>, mirrors version-change) from $LIVE start/revive + clear/compact for live agents; always-loaded live/SKILL.md handler; render-path test; operator-UAT wording fix; doctor PASS-on-failing fix

<details>
<summary>✅ v1.7 Seamlessification (Phases 26-30) — SHIPPED 2026-05-16</summary>

- [x] **Phase 26: `/spt:live` Auto-Pick + Interactive Agent Picker** — completed 2026-05-11
- [x] **Phase 27: Listener Poll Bash → Monitor Tool Transition** — completed 2026-05-11
- [x] **Phase 28: SessionStart Inject Psyche-Download Into Live Listener** — completed 2026-05-13
- [x] **Phase 29: Auto-Fire Echo-Commune on SessionStart + Wrapper Self-Exit** — completed 2026-05-14
- [x] **Phase 30: Commune/Signoff File-Drop Flow Change** — completed 2026-05-15

Full phase details archived to [milestones/v1.7-ROADMAP.md](milestones/v1.7-ROADMAP.md).

### Phase 35.1: owl-list-data-loss-cqrs-decouple-orphan-detection-hardening-nested-perch-soft-clean (INSERTED)

**Goal:** Fix `$OWL list` silently destroying live psyche perch directories via `fs::remove_dir_all` in `list_filter::collect()`. Three coordinated atomic fixes: (1) CQRS decouple — `list` becomes strictly read-only with an orphan-count hint pointing at `owl doctor --fix`; (2) harden orphan detection via atomic info.json writes (8 production sites), wrapper-PID liveness, and a 60s grace gate; (3) route cleanup so nested perches soft-clean (preserves info.json + spool.db) while empty top-level orphans hard-delete — distinguished by a new `SOFT-CLEANED:<id>` status tag.
**Requirements**: LIST-NOMUT-01, LIST-HINT-01, GC-AUTHORIZED-01, ORPHAN-WRAPPER-01, ORPHAN-GRACE-01, WRITE-ATOMIC-01, STATUS-TAG-01
**Depends on:** Phase 35
**Plans:** 4 plans

Plans:
- [x] 35.1-01-PLAN.md - Wave A: atomic info.json writes (8 production sites) + source-order regression test (Fix 2c)
- [x] 35.1-02-PLAN.md - Wave A: PHASE35_LIST_ORPHAN_GRACE_SECS constant + is_wrapper_alive helper in src/common/owlery.rs (Fix 2a/2b primitives)
- [x] 35.1-03-PLAN.md - Wave B: CQRS decouple list_filter::collect (remove cleanup_orphans param) + orphan-count hint + wrapper/grace gates + 4 tests (Fix 1)
- [x] 35.1-04-PLAN.md - Wave B: $OWL doctor --fix orphan-dir GC with SOFT-CLEANED tag for nested + CLAUDE.md status-tag inventory update (Fix 3)

### Phase 35.2: psyche-sync-setup-data-loss-reconcile-bootstrap-determinism (INSERTED)

**Goal:** Fix `psyche-sync-setup` second-machine attach destroying remote agent-branch heads + failing `main` push. Two coordinated atomic fixes: (1) `accept_flow` reconciliation — `git fetch origin` + per-branch `merge-base --is-ancestor` + diverged refs rebased via `rebase -X theirs origin/{branch}` (matches existing `pull_branch` policy) + per-ref `push origin {branch}:{branch}` replacing `push --all` for observable per-ref outcomes; (2) `ensure_seed` deterministic bootstrap — lock `GIT_COMMITTER_DATE` + `GIT_AUTHOR_DATE` envs on the cold-path `commit-tree` so every machine's seed converges on byte-identical `main` SHA. Existing wall-clock-bootstrapped installs absorbed organically through Fix 1's reconciliation path — no explicit migration command.
**Requirements**: SYNC-RECON-FETCH-01, SYNC-RECON-PER-BRANCH-01, SYNC-RECON-REBASE-01, SYNC-PUSH-PER-REF-01, SYNC-BOOTSTRAP-DET-01
**Depends on:** Phase 35
**Source:** `.planning/seeds/psyche-sync-setup-data-loss-reconcile-bootstrap-determinism.md`; diagnosed in `.planning/debug/sync-setup-data-loss.md`
**Plans:** 3 plans (single wave)

Plans:

- [x] 35.2-01-PLAN.md - Fix 2 deterministic bootstrap: lock GIT_*_DATE on cold-path commit-tree (SYNC-BOOTSTRAP-DET-01) + cross-platform identity test
- [x] 35.2-02-PLAN.md - Fix 1a reconcile primitive: ReconcileVerdict + PerRefOutcome types + reconcile_against_remote helper (SYNC-RECON-FETCH-01, SYNC-RECON-PER-BRANCH-01, SYNC-RECON-REBASE-01) + cross-platform routing tests
- [x] 35.2-03-PLAN.md - Fix 1b accept_flow wire-up: seed-origin wire + reconcile call + per-ref push loop replacing push --all + dispatcher status tags + CLAUDE.md tag inventory + Unix-gated end-to-end test (SYNC-PUSH-PER-REF-01 + integration of SYNC-RECON-*)

### Phase 35.3: psyche-sync-setup-ux-pass-error-display-doctor-partial-docs (INSERTED)

**Goal:** Surface-polish bundle for `psyche-sync-setup` — four operator-experience defects identified during Phase 35.2 root-cause investigation. (1) `psyche_sync_setup.rs:70` flip `{:?}` → `{}` so `SyncError` Display impl at `sync.rs:400-413` actually surfaces (kills `GitFailed(Nonzero { stderr: "..." })` Debug-repr leak); (2) `doctor.rs::check_sync_status` partial-state detection — when `state == Unset`, probe `seed/.git/config` for `origin` remote + `git ls-remote origin` ok, surface a Warn row when remote is configured but settings write failed (Step 6 partial-success blindness); (3) SKILL.md add exit code 1 bullet (currently lists only 0/2/3/4/5); (4) document residual recovery path for unresolvable divergence (operator inspection + manual rebase + `--disable` escape hatch) — `git update-ref` workaround mostly obsoleted by Phase 35.2's per-ref dispatcher output.
**Requirements**: SYNC-ERR-DISP-01, SYNC-DOCTOR-PARTIAL-01, SYNC-DOC-EXIT1-01, SYNC-DOC-RECOVERY-01, SYNC-NONGIT-PROJ-01
**Depends on:** Phase 35.2 (per-ref dispatcher output exists; reconciliation lands first)
**Source:** `.planning/seeds/psyche-sync-setup-ux-pass-error-display-doctor-partial-docs.md`; diagnosed in `.planning/debug/sync-setup-data-loss.md`
**Plans:** 4 plans (2 waves)

Plans:

- [x] 35.3-01-PLAN.md - Issue 4 error display: flip {:?}->{} at psyche_sync_setup.rs + SyncError/GitError Display no-debug-syntax regression tests (SYNC-ERR-DISP-01)
- [x] 35.3-02-PLAN.md - Issue 7 non-git project sync: guarded basename fallback in project_name_from_cwd_path + Wave-0 bug-encoding test revision + traversal-guard test (SYNC-NONGIT-PROJ-01)
- [x] 35.3-03-PLAN.md - Issue 6 doctor partial-state: timeout-bounded ls-remote probe + Warn row in check_sync_status, no schema change (SYNC-DOCTOR-PARTIAL-01)
- [x] 35.3-04-PLAN.md - Issues 3+5 docs: SKILL.md exit-1 bullet + inline minimal recovery subsection (SYNC-DOC-EXIT1-01, SYNC-DOC-RECOVERY-01)


**Goal**: `/spt:live` invocation without an explicit agent_id picks intelligently — auto-launches the only agent in repo history if exactly one exists; otherwise asks the user via `AskUserQuestion` with the top 3 most-recently-active agents as discrete options, full agent list shown in the question body, and a free-text "Type something else" field for any other agent name (existing or brand-new).
**Milestone**: v1.7 Seamlessification
**Depends on**: Nothing (skill-layer + thin owl-side helper)
**Requirements**: TBD (LIVE-PICK-01, LIVE-PICK-02, LIVE-PICK-03, LIVE-PICK-04)
**Success Criteria** (what must be TRUE):

  1. `/spt:live` (no arg) with exactly 1 agent in this repo's history auto-launches that agent and reports the pick
  2. `/spt:live` (no arg) with 0 or 2+ agents in repo history fires `AskUserQuestion`:
     - Question body lists ALL agent names known for this repo
     - Top 3 most-recently-active agent names appear as distinct options
     - User can pick a listed option, type any other known agent name into the free-text field, or type a brand-new agent name to init it
  3. "Repo history" is well-defined (e.g. agents whose perch info.json shows cwd / git-root matching current); helper exposed via `$LIVE` for the skill to consume
  4. "Most-recently-active" sort key documented (perch info.json mtime / last commune timestamp / last poll)
  5. Skill behavior remains backward-compatible when arg is supplied (current path unchanged)

**Plans:** 6/6 plans complete (26-06 added post-UAT for gap closure)

Plans:

- [x] 26-01 — Foundations (cwd field, schema v2, helpers, relative_time)
- [x] 26-02 — Activity bumps wired (5 D2 sites)
- [x] 26-03 — `$LIVE pick-spec` subcommand + JSON contract
- [x] 26-04 — `$LIVE fork` primitive
- [x] 26-05 — SKILL.md rewrite + REQUIREMENTS + UAT plan
- [x] 26-06 — UAT gap closure (5 SKILL fixes + LIVE-PICK-03 wording)

### Phase 27: Listener Poll Bash → Monitor Tool Transition

**Goal**: Listener poll (live agents + non-live perches) invokes Claude Code's new `Monitor` tool instead of the `Bash` tool, eliminating Bash-tool overhead and gaining native streaming semantics.
**Milestone**: v1.7 Seamlessification
**Depends on**: Nothing (tool swap; verify Monitor tool API stable first)
**Promoted from**: ROADMAP backlog Phase 999.2
**Requirements**: POLL-MON-01, POLL-MON-02, POLL-MON-03
**Success Criteria** (what must be TRUE):

  1. Listener poll invocation uses `Monitor` tool, not `Bash`
  2. Live agents + non-live perch listeners both migrate
  3. Status tags (READY/SENT/STOPPED/CLEANED) and message delivery semantics preserved
  4. Performance: equal or better latency vs Bash path; lower context cost (no Bash-tool prefix overhead)
  5. Fallback path documented if Monitor tool unavailable in a Claude Code version

**Plans:** 7/7 plans complete (2026-05-11)

Plans:

- [x] 27-01-PLAN.md - Wave 0 BLOCKING: draft REQUIREMENTS.md entries for POLL-MON-01..03
- [x] 27-02-PLAN.md - Core Rust refactor: --once flag, EVENT envelope emit, alarm body format (D9)
- [x] 27-03-PLAN.md - Skill rewrites: listen, live, revive (primary Monitor + fallback Bash --once)
- [x] 27-04-PLAN.md - New reboot skill + reboot.rs Monitor wording + plugin.json 1.9.10→1.9.11 bump
- [x] 27-05-PLAN.md - resume.rs <spacetime-reorientation> block rewrite (drop fires-once-then-exits)
- [x] 27-06-PLAN.md - Test updates: handoff/native owl tests add --once; new golden fixtures
- [x] 27-07-PLAN.md - Verification: doc/hook sweep CLEAN + DEPLOY.ps1 published v1.9.11 (cplugs HEAD 14f29c4); Human UAT stubbed for user sign-off in 27-07-DEPLOY-NOTES.md

### Phase 28: SessionStart Inject Psyche-Download Content Into Live Listener

**Goal**: When SessionStart fires against a perch with an active live listener, the injected reorientation context also includes the same payload `$LIVE psyche-download` would emit (memformat + accumulated context records). Self boots aware of its historical state without manual `psyche-download` invocation.
**Milestone**: v1.7 Seamlessification
**Depends on**: Nothing strict — pairs naturally with Phase 25 (project-scoped context split changes the payload shape)
**Promoted from**: `.planning/todos/done/2026-05-09-sessionstart-inject-psyche-download-content-into-live-listener.md`
**Requirements**: SS-PSYDL-01, SS-PSYDL-02, SS-PSYDL-03
**Success Criteria** (what must be TRUE):

  1. SessionStart on a live perch (info.json `live: true` / `psyche` field present) injects a separate `<psyche-context>` block containing memformat.xml + accumulated context records
  2. Non-live perches skip injection entirely (no psyche → no payload)
  3. Existing `<spacetime-reorientation>` block remains untouched (separate concern)
  4. Size bounded — truncate or summarize to a documented cap so giant context records don't blow the prompt
  5. If Phase 25 lands first: cwd-aware concat (`general.md + proj-{project}.md`) mirrors `psyche-download` output

**Plans:** 4/4 plans complete

Plans:

- [x] 28-01-PLAN.md -- REQUIREMENTS.md SS-PSYDL-01..03 entries + extract download_payload helper + Pulse Log strip helper + unit tests
- [x] 28-02-PLAN.md -- Fresh-session SessionStart emit (inject_active_perch_context -- psyche-context block between owl-active-perch and orphan_warning)
- [x] 28-03-PLAN.md -- Clear/compact SessionStart emit (inject_reorientation_if_needed is_live resolution + inject_reorientation signature change + psyche-context prepend)
- [x] 28-04-PLAN.md -- Integration tests (new tests/plugin_session_start_psyche_context.rs -- helper coverage + subprocess ordering assertion)

### Phase 29: Auto-Fire Echo-Commune on SessionStart + Wrapper Self-Exit

**Goal**: Auto-fire `_echo-commune` at two boundaries that currently lose Self-side delta — (a) SessionStart on existing perch (post-`/clear`) and (b) Psyche wrapper orphan-detected self-exit. Pairs with Phase 28 (push direction vs pull direction at the same hook).
**Milestone**: v1.7 Seamlessification
**Depends on**: Phase 18.8 (echo-commune stderr capture + fresh-session refactor — already shipped); Phase 28 same-hook coexistence
**Promoted from**: `.planning/todos/done/2026-04-20-auto-fire-echo-commune-on-sessionstart-and-wrapper-self-exit.md`
**Requirements**: TBD (AUTO-EC-01, AUTO-EC-02, AUTO-EC-03)
**Success Criteria** (what must be TRUE) — refined by `.planning/phases/29-auto-fire-echo-commune-on-sessionstart-wrapper-self-exit/29-CONTEXT.md`:

  1. SessionStart auto-fires `_echo-commune` against the prior session UUID on `/clear` or `/compact` boundaries — gate is `stdin.source ∈ {clear, compact}` AND resolved perch `info.state == Live`. Prior session UUID = snapshot of `info.json.session_id` taken in `plugin_session_start.rs::run()` BEFORE `refresh_info_json_session_id` overwrites it. Fresh-session SessionStart path does NOT fire.
  2. Psyche wrapper orphan path (in `src/live/wrapper/orphan.rs`) fires `_echo-commune --force` against Self's last session UUID (read from `info.json.session_id` at orphan-detect time) synchronously before `INIT_SIGNOFF`, blocking until subprocess completion (NO timeout cap — fidelity > teardown latency). Missing/empty UUID: skip echo-commune, proceed straight to INIT_SIGNOFF.
  3. SessionStart-triggered fire reuses the Psyche wrapper's existing spawn path via a typed control message (`FIRE_ECHO_COMMUNE_NOW prior_session={uuid} forward_to_self=true source={clear|compact}`) delivered to `{self_id}-psyche`. No new spawn site outside the wrapper. Wrapper inner-poll handler bypasses cadence gate when servicing this message. Coexists with Phase 28 injection at the same SessionStart hook (hook is fire-and-return; ordering vs `<spacetime-reorientation>` / `<psyche-context>` is irrelevant).
  4. No regression on Phase 18.8/18.8.1 fresh-session refactor invariants (no Self-jsonl write contention).
  5. Failure modes: silent skip on missing prior session UUID; structured `[ECHO-FIRE] ...` line to stderr on subprocess failure; SessionStart hook continues normally (Phase 28 psyche-context still emits).
  6. Phase 29-triggered SessionStart fire dual-dispatches the echo-commune body: (a) existing Psyche-bundling path (memformat + context-file update), AND (b) standard owl REST delivery of `<EVENT type="echo_commune" from="{self_id}-psyche" timestamp="{iso8601}" note="...">{body}</EVENT>` to Self's perch — fully decoupled from the SessionStart hook turn; arrives asynchronously like any other inbox message. Cadence-driven 15-min fires remain Psyche-only (unchanged behavior). Orphan-path fire is Psyche-only (Self is gone).
  7. `_echo-commune --force` flag bypasses the 15-min cadence window check AND the `.more-done` Stop-sentinel check; PRESERVES the `OWL_ECHO_COMMUNE` recursion guard.
  8. Echo-commune event envelope cleaned up via clean cutover (single release, no legacy fallback parser) — emit `<EVENT type="echo_commune" from="{agent}" timestamp="{iso8601}" note="...">{msg}</EVENT>` (typed + provenance + descriptor attrs) replacing legacy `<EVENT type="msg" from="{agent}">ECHO_COMMUNE ({ts}) from {agent}: {msg}</EVENT>`. Audit covers ALL emit + parse sites in `src/`, AND instructional prose in `plugin/spt/skills/`, `plugin/spt/hooks/`, `CLAUDE.md`, `psyche.md`, `docs/`. Parser predicates case-insensitive on `type="echo_commune"` (mirrors quick-260513-v8f init_signoff precedent).

**Plans:** 5/5 plans complete

Plans:
**Wave 1**

- [x] 29-01-PLAN.md -- Foundation: --force flag + extract fire_echo_commune_inner + compose_echo_commune_payload helper + envelope cutover at echo_commune.rs:365 (Wave 1)

**Wave 2** *(blocked on Wave 1 completion)*

- [x] 29-02-PLAN.md -- SessionStart prior-UUID snapshot + FIRE_ECHO_COMMUNE_NOW control-message dispatch (Wave 2)
- [x] 29-03-PLAN.md -- Wrapper inner-poll handler arm + parse_fire_echo_commune_now + cadence/sentinel bypass via fire_echo_commune_force (Wave 2)
- [x] 29-04-PLAN.md -- Orphan-path synchronous _echo-commune --force fire before INIT_SIGNOFF (Wave 2)

**Wave 3** *(blocked on Wave 2 completion)*

- [x] 29-05-PLAN.md -- D15 instructional-prose audit: update plugin/spt/skills/{live,listen}/SKILL.md + psyche.md + CLAUDE.md to reference the new `<EVENT type="echo_commune">` envelope; rebuild release binary so embedded psyche.md takes effect (Wave 3)

### Phase 30: Commune/Signoff File-Drop Flow Change

**Goal**: Replace stdin-piped commune/signoff with a file-drop protocol. Agents write `.claude/{agent_id}-commune.md` / `.claude/{agent_id}-signoff.md`; the Self listener poll watches for these files and notifies the Psyche wrapper of each file's absolute path via REST. Wrapper forwards content into a fresh Psyche session prompt and deletes the file after that session completes. Signoff variant terminates the listener after notification (with confirmation message in termination output). If `-commune.md` or `-signoff.md` exists for the current agent at `$LIVE psyche-download` time, file content is appended to the end of psyche-download output.
**Milestone**: v1.7 Seamlessification
**Depends on**: Phase 27 (listener poll stream mode — file-watch hooks into the new poll loop); Phase 28 (psyche-download payload composition — the append-on-pending logic rides through the helper Phase 28 extracts)
**Requirements**: TBD
**Success Criteria** (what must be TRUE):

  1. `/spt:commune` skill writes `.claude/{agent_id}-commune.md` instead of piping body via stdin
  2. `/spt:signoff` skill writes `.claude/{agent_id}-signoff.md` instead of piping body via stdin
  3. Self listener poll watches for these files; on detection, notifies Psyche wrapper via REST with the file's absolute path
  4. Psyche wrapper forwards file content into a new Psyche session prompt; deletes the file after that session completes (atomic — no double-process on restart)
  5. Signoff file detection terminates the listener after notification, with confirmation message in the termination output
  6. `$LIVE psyche-download` appends content of any pending `-commune.md` / `-signoff.md` file for the current agent to the end of its output

**Plans:** 4/4 plans complete

Plans:
**Wave 1**

- [x] 30-01-PLAN.md - Self listener: per-iteration .claude scan + file_drop EVENT compose + signoff teardown + D12 exit-code audit (Wave 1)
- [x] 30-02-PLAN.md - Wrapper: parse_file_drop_event + FileDropDispatcher trait + handle_file_drop_arm + compose_commune_payload + resume_session_with_exit + arm wiring (Wave 1)
- [x] 30-03-PLAN.md - psyche-download: append Pending Commune / Pending Signoff sections in download_payload (Wave 1)

**Wave 2** *(blocked on Wave 1 completion)*

- [x] 30-04-PLAN.md - Skill rewrites (commune + signoff SKILL.md) + integration tests + DEPLOY.ps1 bump + UAT (Wave 2; depends on 01+02+03)

</details>

<details>
<summary>v1.7.1 Seamlessification II (Shipped 2026-05-18) - 4 phases / 11 plans / deployed v1.10.13 — see <a href="milestones/v1.7.1-ROADMAP.md">milestones/v1.7.1-ROADMAP.md</a></summary>

### v1.7.1 Seamlessification II (SHIPPED 2026-05-18)

**Milestone Goal:** Polish round on live-agent friction — listing/picker correctness, skill hint surface, fresh-start commune prompt, auto-resume affordance, plugin-update changelog notification.

**Phase Numbering:** Continues from v1.7's last phase (30). v1.8 phases 23/24/25 remain queued lower-numbered for non-chronological reasons; Phase 35 (Psyche Sync) was appended after v1.7.1's last phase (34) to keep v1.8's tail of new work numerically contiguous with shipped history.

**Deploy Cadence:** Single `DEPLOY.ps1 -Bump patch` at end-of-milestone (NOT per-phase) to avoid version-churn during in-flight binary handoffs.

- [x] **Phase 31: Picker Correctness** — Fix `$LIVE pick-spec` Item 4 bug; introduce `kind:"all-live"` variant (additive only); update test that codifies bug (completed 2026-05-17)
- [x] **Phase 32: List Overhaul + Skill Hint Audit** — `--all`/`--offline`/`--here` flags default-online; `argument-hint` frontmatter coverage on every `/spt:*` skill
 (completed 2026-05-17)

- [x] **Phase 33: Fresh-Start Commune + Auto-Resume** — First-commune flow for known-new identities; `/spt:live --auto` flag + SessionStart auto-surface + casual-language triggers (completed 2026-05-16)
- [x] **Phase 34: Version-Change Changelog** — `last-seen-version.json` sentinel + Stop-hook silent owl-message transport + `CHANGELOG.md` prerequisite + DEPLOY.ps1 curation gate (completed 2026-05-17; verified 2026-05-18; includes hotfixes 260517-6om + 260517-n4b; deployed v1.10.13)

### Phase 31: Picker Correctness

**Goal**: `$LIVE pick-spec` correctly reports when every known agent in the current repo is already online — emitting a new `kind:"all-live"` JSON variant instead of falsely returning `kind:"prompt-new"` with no candidates — so the calling skill can present a "fork or pick a new name" choice
**Milestone**: v1.7.1 Seamlessification II
**Depends on**: Nothing in v1.7.1 (builds on v1.7-shipped pick-spec foundation)
**Requirements**: PICK-01, PICK-02, PICK-04, PICK-05, PICK-06
**Success Criteria** (what must be TRUE):

  1. Running `$LIVE pick-spec` in a repo where every known agent is currently online emits a `kind:"all-live"` envelope (with online agent identities + cwd-match flag) — never `kind:"prompt-new"` with empty candidates
  2. Existing v1 kind discriminators (`auto`, `pick`, `prompt-new`) preserve their shape (D5 schema freeze honored) — no field renames, no field removals, no shape mutation
  3. `/spt:live` skill, when handed a `kind:"all-live"` JSON, surfaces the live agents to the user as "fork or pick a new name" and never auto-attaches to a live agent
  4. The test `pick_one_online_agent_filters_to_prompt_new` (which codified the bug) asserts the new corrected `kind:"all-live"` behavior; all other existing pick-spec tests pass unmodified

**Plans:** 2/2 plans complete

Plans:

- [x] 31-01-PLAN.md - Doc-only defer of former PICK item #3 per D-10/D-11 (strikes from REQUIREMENTS.md + ROADMAP.md)
- [x] 31-02-PLAN.md - Add kind:"all-live" pick-spec variant + SKILL.md dispatch row + test rewrite + integration test (PICK-01, 02, 04, 05, 06)

### Phase 32: List Overhaul + Skill Hint Audit

**Goal**: `$OWL list` and `$LIVE list` default to online-only with a unified `--all`/`--offline`/`--here` flag surface, AND every `/spt:*` skill ships an accurate `argument-hint` frontmatter field — batched into a single phase because new list flags require new argument-hints on list-* skills, avoiding a second DEPLOY cycle
**Milestone**: v1.7.1 Seamlessification II
**Depends on**: Nothing (mechanically independent of Phase 31; can run in parallel in principle, sequenced second to keep DEPLOY at end-of-milestone)
**Requirements**: LIST-01, LIST-02, LIST-03, LIST-04, LIST-05, LIST-06, LIST-07, LIST-08, HINT-01, HINT-02, HINT-03, HINT-04, HINT-05
**Success Criteria** (what must be TRUE):

  1. Running `$OWL list` (no flags) in a repo with online and offline perches shows ONLY the online ones; passing `--all` adds the offline ones; passing `--offline` shows only the offline ones (mutually exclusive with `--all`)
  2. Passing `--here` (orthogonal to `--all`/`--offline`) filters out any perch whose `info.json.project_history` does not contain any of the current repo names (local .git basename + remote origin basename); works identically for `$OWL list` and `$LIVE list`
  3. When `$OWL list` finds zero online perches with no flags, it emits a stderr discovery hint pointing the user at `--all`
  4. Every `/spt:*` skill in `plugin/spt/skills/` has an `argument-hint:` YAML frontmatter field (empty string for no-arg skills, never omitted); the three previously-missing skills (`list-ready`, `list-live`, `list-psyche`) all gain `[--all] [--offline] [--here]`
  5. A regression-guard test/script verifies every `plugin/spt/skills/*/SKILL.md` has an `argument-hint` key and that values containing YAML-significant characters are properly quoted

**Plans:** 3/3 plans complete

Plans:
**Wave 1**

- [x] 32-01-PLAN.md - Doc amendment (LIST-04/LIST-07/SC#2) + InfoJson project_history schema + repo-name derivation helpers in owlery.rs + append-on-start at poll.rs:124 and live/start.rs:235 (LIST-04, LIST-07)

**Wave 2** *(blocked on Wave 1 completion)*

- [x] 32-02-PLAN.md - Extract src/common/list_filter.rs + --all/--offline/--here flags (clap conflicts_with) + D-10/D-11 discovery hints + golden fixture audit (LIST-01, LIST-02, LIST-03, LIST-05, LIST-06, LIST-08)
- [x] 32-03-PLAN.md - Argument-hint audit across 17 plugin/spt/skills/*/SKILL.md (3 ADD, 3 VALUE CHANGE, 4 QUOTING) + tests/skill_hints.rs regression guard (HINT-01..HINT-05)

### Phase 33: Fresh-Start Commune + Auto-Resume

**Goal**: A user invoking `/spt:live` against a known-new identity (or against an existing identity with empty psyche-download) is prompted with a first-commune summary BEFORE init; AND `/spt:live --auto` (plus a curated set of casual-language triggers) resumes the most-recently-active live agent with a confirmation hop and surfaces any clear next body of work
**Milestone**: v1.7.1 Seamlessification II
**Depends on**: Phase 31 (requires corrected pick-spec shape — both flows route through `$LIVE pick-spec`)
**Requirements**: FRESH-01, FRESH-02, FRESH-03, FRESH-04, FRESH-05, FRESH-06, AUTO-01, AUTO-02, AUTO-03, AUTO-04, AUTO-05, AUTO-06, AUTO-07, AUTO-08
**Success Criteria** (what must be TRUE):

  1. Starting a live agent with an identity that pick-spec classifies as `kind:"prompt-new"` (OR an existing identity whose `$LIVE psyche-download` returns `NO-CONTEXT`) shows the user a first-commune summary and an explicit "add anything, or proceed to init?" prompt BEFORE `$LIVE start` runs
  2. The first-commune prompt fires only when `$LIVE psyche-download` returns NO-CONTEXT (or when pick-spec returns `kind:"prompt-new"`) — a natural-transition contract: once any commune lands (first-commune answer, regular commune, or auto-fired echo-commune per Phase 29 AUTO-EC), psyche-download returns content and the predicate stops firing automatically. An intentionally cleared psyche correctly re-prompts because the user's `clear-psyche` action is itself a request to start fresh. Fork and revive paths bypass naturally because both populate psyche-md before any first-commune check.
  3. Running `/spt:live --auto` (no positional arg) auto-launches when pick-spec returns `kind:"auto"`, otherwise presents the most-recently-active agent for user confirmation before launching, then surfaces any clear next body of work from the resumed agent's psyche-download payload (domain-agnostic — no GSD or framework assumption)
  4. On a fresh-session SessionStart (source = `startup`, NOT `clear`/`compact`), with no live perch already attached to the parent_pid and no subagent-context env vars present, the hook emits a `<spt-live-auto-pick>` XML block carrying pick-spec JSON; the allow-list rejects silently inside subagent/wrapper sessions (no stderr leakage)
  5. Casual-language triggers (e.g. "resume my agent", "wake up my agent") route to `--auto`; bare ambiguous phrases ("keep going", "resume work") are explicitly REJECTED; before any `$LIVE start` via the casual path, the skill MUST issue an AskUserQuestion confirmation hop

**Plans:** 3/3 plans complete

Plans:
**Wave 1**

- [x] 33-01-PLAN.md - REQUIREMENTS.md + ROADMAP.md amendment (strike FRESH-04/05, reword FRESH-06, revise SC#2) + wire FRESH-01/02/03 first-commune flow into live SKILL.md (FRESH-01, FRESH-02, FRESH-03, FRESH-06)

**Wave 2** *(blocked on Wave 1 completion)*

- [x] 33-02-PLAN.md - Auto-resume skill flow (AUTO-01, AUTO-02, AUTO-05, AUTO-06, AUTO-07, AUTO-08)
- [x] 33-03-PLAN.md - SessionStart hook auto-pick emission + allow-list predicate + test corpus (AUTO-03, AUTO-04)

### Phase 34: Version-Change Changelog

**Goal**: When a user's installed `spt` plugin version changes underneath them, the next SessionStart surfaces an old→new changelog prompt (via AskUserQuestion) sourced from compiled-in `CARGO_PKG_VERSION` against an `$SPT_HOME/last-seen-version.json` sentinel — without firing on first-install, without colliding with the SessionStart auto-pick (AUTO-03), and without racing the binary handoff (Phase 18.4/18.5)
**Milestone**: v1.7.1 Seamlessification II
**Depends on**: Nothing in v1.7.1 (independent at the Rust level); sequenced AFTER Phase 33 to keep the two SessionStart-hook extensions (AUTO-03 + VERS-04) in separate phases
**Requirements**: VERS-01, VERS-02, VERS-03, VERS-04, VERS-05, VERS-06, VERS-07, VERS-08, VERS-09
**Success Criteria** (what must be TRUE):

  1. On a fresh install (no `$SPT_HOME/last-seen-version.json` present), on first Stop hook fire in any spt-bearing session, the sentinel silently writes the current `CARGO_PKG_VERSION` and emits NO changelog prompt to the user.
  2. After the plugin version changes (compiled-in `CARGO_PKG_VERSION` differs from sentinel contents), the next Stop hook fire in an spt-bearing session emits a `<spt-version-changelog>` block via `decision:"block"` + `reason`; Claude renders an AskUserQuestion with four options (`Yes, full changelog` / `Yes, highlights only` / `Remind me later` / `Skip`); the sentinel is atomically rewritten with the current version at hook entry (before the block emission), so the prompt does not re-fire next session unless the user picks `Remind me later`, which invokes `$OWL version-remind <old>` to roll the sentinel back.
  3. A multi-version skip (e.g. v1.10.5 → v1.12.0) surfaces a version-list summary plus a pointer to `CHANGELOG.md` — never full prose for each interim version
  4. Repo-root `CHANGELOG.md` exists with H2-per-version sections (created from git log if absent during phase kickoff); `docs/DEPLOY.ps1` syncs it into the plugin meta dir alongside `plugin.json`
  5. VERS-04 fires from Stop hook (`hook_idle.rs`); AUTO-03 (from Phase 33) fires from SessionStart hook (`plugin_session_start.rs`); collision is impossible by hook separation. The sentinel write site lives at the top of `hook_idle.rs::run()` after perch resolution + OWL_ECHO_COMMUNE guard (atomic via existing `atomic_write_string`); Stop hooks do not fire mid-binary-handoff, so a race cannot corrupt it.
  6. End-of-milestone DEPLOY.ps1 `-Bump patch` ships all four phases together (no per-phase deploys during v1.7.1)

**Plans:** 2/3 plans executed

Plans:

- [x] 34-01 — Doc Amendment + CHANGELOG Genesis + DEPLOY.ps1 Extension (Wave 1, complete 2026-05-17)
- [x] 34-02 — Rust Hook + Parser + Sentinel + version-remind + 12 integration tests (Wave 2, complete 2026-05-17, commits `9c8020d`, `9b2c301`, `595ad6c`)
- [x] 34-03 — Block-body wording + UAT (Wave 3, complete 2026-05-17; folded in hotfixes 260517-6om + n4b; deployed v1.10.13; verified 2026-05-18)

</details>

## Progress

**Execution Order:**
Phases execute in numeric order: 15 -> 16 -> 17 -> 18; v1.7 (Phases 26 -> 27 -> 28 -> 29 -> 30) shipped; v1.7.1 (Phases 31 -> 32 -> 33 -> 34) shipped; v1.8 (Phases 23 -> 24 -> 24.1 -> 25 -> 35) sequenced before v1.9 (19 -> 20 -> 21 -> 22) despite higher numbering. v1.7.1 ships before v1.8.

| Phase | Milestone | Plans Complete | Status | Completed |
|-------|-----------|----------------|--------|-----------|
| 1. Foundation & Hardening | v1.0 | 3/3 | Complete | 2026-03-28 |
| 2. Psyche Core | v1.0 | 3/3 | Complete | 2026-03-28 |
| 2.1 Live Skill Extraction | v1.0 | 1/1 | Complete | 2026-03-28 |
| 2.2 Owl & Live Hardening | v1.0 | 4/4 | Complete | 2026-03-29 |
| 5. Golden Tests & CLI Skeleton | v1.1 | 3/3 | Complete | 2026-03-30 |
| 6. P2P Messaging & Owl Parity | v1.1 | 6/6 | Complete | 2026-03-30 |
| 7. Live Parity & Distribution | v1.1 | 4/4 | Complete | 2026-03-30 |
| 8. Timed Pulses | v1.1 | 2/2 | Complete | 2026-03-30 |
| 9. Spine Supervisor | v1.1 | 3/3 | Complete | 2026-03-30 |
| 9.1 Psyche Lifecycle Hardening | v1.1 | 4/4 | Complete | 2026-03-30 |
| 9.2 Psyche Messaging Discipline | v1.1 | 2/2 | Complete | 2026-03-31 |
| 10. Plugin Migration | v1.5 | 3/3 | Complete | 2026-04-01 |
| 11. Foundation | v1.5 | 2/2 | Complete | 2026-04-02 |
| 12. Psyche Intelligence | v1.5 | 3/3 | Complete | 2026-04-03 |
| 13. Messaging Integration | v1.5 | 3/3 | Complete | 2026-04-03 |
| 13.1 Unified Psyche Wrapper Event Loop | v1.5 | 2/2 | Complete | 2026-04-04 |
| 14. Poll Efficiency | v1.5 | 1/1 | Complete | 2026-04-04 |
| 14.1 Persistent Offline Perches | v1.5 | 3/3 | Complete | 2026-04-08 |
| 14.2 Spacetime Reliability & DX | v1.5 | 9/9 | Complete | 2026-04-06 |
| 14.3 Optional Agent ID | v1.5 | 3/3 | Complete | 2026-04-07 |
| 15. MCP Spike & Spool Foundations | v1.6 | 5/5 | Complete | 2026-04-11 |
| 16. MCP Tools | v1.6 | 4/4 | Complete | 2026-04-12 |
| 17. MCP Resources | v1.6 | 2/2 | Complete | 2026-04-13 |
| 18. Hooks & Plugin Integration | v1.6 | 2/2 | Complete | 2026-04-13 |
| 19. Sendkeys Foundation & Capsule Launch | v1.9 | 0/4 | Not started | - |
| 20. Session Detection & Capsule Listener | v1.9 | 0/2 | Not started | - |
| 21. Abrupt Messages | v1.9 | 0/2 | Not started | - |
| 22. Smart Capabilities | v1.9 | 0/2 | Not started | - |
| 23. Commune & Signoff Project-Root + HEAD SHA Stamping | v1.8 | 5/6 | In Progress|  |
| 24. Tracked-Dir Forked-Repo Layout (agents/+projects/ branches) | v1.8 | 7/7 | Complete   | 2026-05-21 |
| 24.1. Tracked-Agents info.json — Cross-Session Activity Index | v1.8 | 5/5 | Complete   | 2026-05-21 |
| 25. Perch Nesting (Psyche + Workers) + psyche-download Wire-up | v1.8 | 5/5 | Complete   | 2026-05-22 |
| 26. /spt:live Skill — Auto-Pick + Interactive Agent Picker | v1.7 | 6/6 | Complete   | 2026-05-11 |
| 27. Listener Poll Bash → Monitor Tool Transition | v1.7 | 7/7 | Complete   | 2026-05-11 |
| 28. SessionStart Inject Psyche-Download Into Live Listener | v1.7 | 4/4 | Complete    | 2026-05-13 |
| 29. Auto-Fire Echo-Commune on SessionStart + Wrapper Self-Exit | v1.7 | 5/5 | Complete   | 2026-05-14 |
| 30. Commune/Signoff File-Drop Flow Change | v1.7 | 4/4 | Complete   | 2026-05-15 |
| 31. Picker Correctness | v1.7.1 | 2/2 | Complete    | 2026-05-17 |
| 32. List Overhaul + Skill Hint Audit | v1.7.1 | 3/3 | Complete   | 2026-05-17 |
| 33. Fresh-Start Commune + Auto-Resume | v1.7.1 | 0/TBD | Not started | - |
| 34. Version-Change Changelog | v1.7.1 | 1/3 | In Progress|  |
| 35. Psyche Sync — Cross-Machine Context Backup via gh Repo | v1.8 | 10/10 | Complete   | 2026-05-27 |

**Off-roadmap sub-iterations** (tracked in phase directories, not in milestone totals):
Phases 18.1, 18.2, 18.3, 18.4, 18.5, 18.6, 18.7, 18.7.1, 18.8, 18.8.1 — see `.planning/phases/18.*` for SUMMARY/SECURITY/UAT artifacts.

## Backlog

_(empty — all backlog items promoted to milestone phases as of 2026-05-10)_
