# Phase 25: Perch Nesting (Psyche + Workers) + Wire psyche-download to Forked-Repo Layout - Discussion Log

> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.

**Date:** 2026-05-21
**Phase:** 25-perch-nesting-psyche-workers-wire-psyche-download-to-forked-
**Areas discussed:** cwd_project identification, live_context.md vs projects/{X}/{agent}.md split, Nested enumeration + is_worker_perch swap, Migration: auto-relocate vs coexist

---

## Area A — cwd_project identification

### A.1 — Identity key

| Option | Description | Selected |
|--------|-------------|----------|
| Reuse `derive_current_repo_names()` first element | Folder basename; falls back to origin basename. Zero new logic. Phase 24.1 D-09 mirror. | ✓ |
| First element + fallback scan | Primary key folder, scan project_history on miss | |
| Origin remote URL hash | Stable across renames; diverges from Phase 24/24.1 | |
| Explicit registry | Maintain $SPT_HOME/projects.json mapping | |

**User's choice:** Reuse derive_current_repo_names() first element.
**Notes:** Direct symmetry with Phase 24.1 D-09 `last_project_name`. Zero new identity logic.

### A.2 — Two-name case (folder != origin)

| Option | Description | Selected |
|--------|-------------|----------|
| First name only (folder) | Write to `projects/<folder>/<agent>.md` only | ✓ |
| Both names (mirror writes) | Two project worktrees, double commit churn | |
| First name + symlink/pointer | Real file + stub at second name | |

**User's choice:** First name only.
**Notes:** project_history still records both names per Phase 24.1 D-10; only one project file written.

### A.3 — psyche-download read-side fallback

| Option | Description | Selected |
|--------|-------------|----------|
| No fallback — omit project section | Strict existence check; SC4/SC5 literal | ✓ |
| Try second derived name | Asymmetric read vs write on miss path | |
| Scan project_history for any match | Most resilient; large lookup surface | |

**User's choice:** No fallback. Omit project section if missing.
**Notes:** Folder renames forfeit history until next commune; chosen for simplicity.

---

## Area B — live_context.md vs projects/{X}/{agent}.md split

### B.1 — Split policy

| Option | Description | Selected |
|--------|-------------|----------|
| All content → project file; live_context.md unchanged | Whole payload to project file when project known | |
| Mirror write — both files get same payload | Double writes | |
| Split body — LLM decides which slice | Composer routes per-section | ✓ (taxonomy locked by user) |
| Derived projection — live_context.md = digest | Project files canonical; digest derived | |

**User's choice:** Split body with EXPLICIT taxonomy.
**Notes:** User locked the taxonomy:
- `agents/{id}/live_context.md` (cross-project): agent's role, role evolution, latest choices, user interactions, agent-to-agent interactions
- `projects/{cwd_project}/{agent_id}.md` (project-scoped): work done, current state, outstanding priorities, next task, everything else usually in communes/context

### B.2 — Split mechanism

| Option | Description | Selected |
|--------|-------------|----------|
| Envelope tags from Psyche | `<live-context>` + `<project-context>` envelope | ✓ |
| Fixed heading sections | Hardcoded H2 routing; heading-drift fragile | |
| Two separate Psyche invocations | Doubled latency + cost | |
| Single payload + reserved-name files | Contradicts taxonomy | |

**User's choice:** Envelope tags from Psyche.
**Notes:** Added requirement — Psyche must observe current state of BOTH files when composing so important items don't get dropped; output must be a proper merge.

### B.3 — Merge input mechanism

| Option | Description | Selected |
|--------|-------------|----------|
| Inline in prompt | Composer reads both files, inlines as labeled blocks | ✓ |
| File paths + Read tool | Cheaper for large files; adds round-trips | |
| Inline live + path for project | Hybrid | |
| Composer pre-summarizes both | Bounded prompt; loses fidelity | |

**User's choice:** Inline in prompt.
**Notes:** Composer inlines as CURRENT_LIVE_CONTEXT + CURRENT_PROJECT_CONTEXT blocks. No new tool calls.

---

## Area C — Nested enumeration + is_worker_perch swap

### C.1 — Detection strategy + nesting layout

| Option | Description | Selected |
|--------|-------------|----------|
| Path-based, drop id-regex; separate psyches/ + workers/ subfolders | ROADMAP draft layout | (modified) |
| Path-based primary + id-pattern fallback | Two-rule maintenance | |
| Keep id-regex, add path index | Tight back-compat | |

**User's choice:** Path-based AND single `nested/` subfolder for both psyche + workers (deviation from ROADMAP draft).
**Notes:** Final layout: `owlery/<parent>/nested/<parent>-psyche/` AND `owlery/<parent>/nested/<parent>-w275/` — psyche and workers share namespace. Kind discriminated by id suffix.

### C.2 — Lifecycle cascade on parent death

| Option | Description | Selected |
|--------|-------------|----------|
| Cascade automatic on parent stop | Whole subtree gone | |
| Cascade only on graceful stop; orphans self-clean | Mixed | |
| Independent lifecycles | Children survive parent | ✓ |

**User's choice:** Independent lifecycles.
**Notes:** Psyche must survive parent death for post-orphan-detection + post-signoff ops. ALSO clarified: **only worker perches ever get fully cleaned.** Live agent + psyche perches stick around showing as OFFLINE.

### C.3 — parent_id source

| Option | Description | Selected |
|--------|-------------|----------|
| Path-derived only | Grandparent dir name; zero schema change | ✓ |
| info.json parent_id + path validation | Cross-check; survives offline listings | |
| info.json parent_id, path advisory | info.json authoritative | |

**User's choice:** Path-derived only.
**Notes:** No info.json schema change. Filesystem is single source of truth.

---

## Area D — Migration: auto-relocate vs coexist

### D.1 — Migration strategy

| Option | Description | Selected |
|--------|-------------|----------|
| Auto-relocate on first boot, idempotent | First-boot sweep | |
| Coexist permanently — path-aware enumeration | Walk both layers forever | (partial) |
| Auto-relocate gated on liveness | Dead-perch relocate | |
| Coexist + opt-in $LIVE migrate subcommand | User-controlled | |

**User's choice:** Hybrid — Coexist as default + auto-relocate psyches ONLY on `$LIVE start` / `$LIVE revive`. Worker perches: migration no-op (short-lived).
**Notes:** Bounded blast radius. No first-boot enumeration. Self perches never move. Worker migration code path is zero.

### D.2 — Duplicate resolution (same id at flat + nested)

| Option | Description | Selected |
|--------|-------------|----------|
| Nested wins, flat is stale | Doctor surfaces flat; auto-clean if dead | ✓ |
| Most-recently-touched wins | mtime compare | |
| Both surfaced as distinct, doctor warns | No automatic resolution | |

**User's choice:** Nested wins; flat is stale.
**Notes:** Auto-cleanup of flat duplicate only when pid is dead (handoff-safe).

---

## User-initiated amendment — Orphaned worker sweep (D-20)

After CONTEXT.md was written, user observed daily orphaned worker perches accumulating after subagents conclude — parent-death cascade and lazy on-removal both miss them.

Folded into Phase 25:
- Active worker-cleanup sweep on `$LIVE start` AND every signoff event
- Self-scoped (only sweeps THIS agent's workers — nested + legacy flat siblings)
- Predicate: `is_worker_perch(perch) AND !is_perch_online(perch)`
- Best-effort silent-on-error; single aggregated stderr line on success
- Concurrency guard via existing `is_perch_online` check + small mtime grace window for just-spawned dirs (planner finalizes heuristic)

Captured as D-20 + D-21 in CONTEXT.md.

---

## Claude's Discretion (deferred to research / planning)

- Exact directory-rename mechanism for D-16 psyche relocate (`fs::rename` vs Windows fallback)
- Where the D-16 relocate hook lives inside `src/live/start.rs` / `src/live/revive.rs` (one site or two helpers)
- Path string vs typed enum for `is_psyche_perch` / `is_worker_perch` signatures
- `<psyche-stamp/>` placement confirmation against drift-detector behavior
- D-11 envelope tag format (XML vs `<<<live-context>>>` sentinels)
- Doctor warning thresholds for OFFLINE perch counts
- D-12 inline-current-state composer location (`compose_haiku_prompt` extension vs new helper)
- D-20 concurrency grace-window heuristic (e.g., 30s mtime gate for just-spawned dirs)
- Test coverage breakdown — golden fixture regeneration

---

## Deferred Ideas (noted for future phases)

- Truncation cap on project section in psyche-download (Open Q2 from ROADMAP)
- Folder-rename graceful read fallback
- Symlink / pointer for two-name case writes
- `<psyche-stamp/>` on project file
- Hybrid prompt input (inline live + path for project)
- Doctor visual polish beyond Phase 25 essentials
- `$LIVE migrate` opt-in subcommand
- `parent_id` field in info.json (if cross-machine relocate ever needed)
- Phase 35 sync conflict policy for nested layout
- Phase 28 SessionStart deeper integration with three-section payload
- Sessions-log ↔ live_context.md / project file consistency checks in doctor
