# Session Handoff

## Date

2026-05-16

## Summary

This session landed the wiki-style self-maintaining knowledge loop (7 PRs): auto-compile knowledge pages, wiki INDEX generation, wiki lint, MCP `memory_lint` tool, desktop facade `wiki_lint`/`read_wiki_index`, CLI `memory lint`/`memory sync-index`, selector test split, frontend lint health page, and frontend wakeup INDEX rendering. Subsequent sessions added: MCP sampling reverse-call integration for auto-compile (fire-and-forget via dedicated thread), project-first retrieval scoring (40% cross-project penalty on user/agent/team-scoped candidates when a project is matched), and frontend workbench batch actions.

## Changes This Session

### Wiki-style Knowledge Loop (PR #1)

- Added `src/knowledge/` module: auto-compile knowledge pages from related lifecycle records
- Added `src/wiki_index.rs`: generate and load wiki INDEX.md grouped by scope/project
- Added `src/wiki_lint.rs`: staleness, orphan, and quality lint checks on lifecycle records
- `vault_writer.rs` now routes `memory_type == "knowledge"` to `50-Memory-Ledger/Compiled/`
- `writeback_from_config` chains INDEX refresh + auto-compile after lifecycle writes
- Superseded records excluded from retrieval via `excluded_record_ids_from_scored`

### MCP `memory_lint` Tool (PR #2)

- New MCP tool `memory_lint` exposing wiki lint report as markdown

### Desktop Facade: wiki_lint + read_wiki_index (PR #3)

- `DesktopService::wiki_lint()` — run lint and return markdown report
- `DesktopService::read_wiki_index()` — load INDEX section for a project

### CLI `memory sync-index` (PR #4)

- New CLI command `memory sync-index` to rebuild INDEX.md
- New CLI command `memory lint` to run wiki lint checks

### Selector Test Split (PR #5)

- Refactored `src/engine/selector.rs` tests into `src/engine/selector/tests.rs`
- `src/engine/selector/` is now a directory module (`mod.rs` + `tests.rs`)

### Frontend Lint Health Page (PR #6)

- New frontend page consuming `wiki_lint` DTO from desktop facade

### Frontend Wakeup INDEX Rendering (PR #7)

- Wakeup result page now renders `knowledge_index` section when present

### MCP Sampling Auto-Compile Integration (2026-05-16)

- Fixed auto-compile to fire on a dedicated thread (`std::thread::spawn` + dedicated tokio runtime) so the main MCP dispatch loop is never blocked waiting for the sampling reverse-call round-trip (up to 180 s timeout)
- Added `mcp_lifecycle_write_should_not_block_when_sampling_supported_but_no_cluster` smoke test: single record write, verifies elapsed < 10 s
- Added `mcp_lifecycle_write_should_trigger_sampling_compile_when_cluster_ready` smoke test: writes 3 records with shared entities, proposes+accepts a 4th, harness fulfills sampling reverse-call, verifies a `knowledge` type record appears in pending review

### Project-First Retrieval Scoring (2026-05-16)

- Added `CROSS_PROJECT_PENALTY = 0.6` constant in `src/engine/selector/mod.rs`
- User/agent/team-scoped candidates receive a 40% score reduction when a project is matched, ensuring project-scoped records rank above cross-project ones
- Added two new tests in `src/engine/selector/tests.rs`:
  - `lifecycle_selector_should_apply_cross_project_penalty_when_project_matched`
  - `lifecycle_selector_should_not_apply_cross_project_penalty_without_project`

---

## Previous Session Summary

This session carried `spool` from a read-only lifecycle prototype into a usable local memory review loop, MCP gateway, and first daemon boundary, with a shared lifecycle service, append-only ledger events, latest-state projections, GUI review/history/create actions, broader CLI lifecycle flows, MCP lifecycle/retrieval tools, event-level write provenance metadata, in-process and disk-backed lifecycle projection caching, MCP prompts/resources, GUI metadata-aware create/propose forms, a minimal lifecycle read daemon, and post-integration fixes for daemon-backed reads, MCP resource loading/smoke coverage, plus malformed-JSON hardening on both stdio protocol boundaries.

## Current Status Audit

Audit date: `2026-04-14`

This document is still the best restart point, but some other planning docs now understate current progress.

Current repository status:

- latest implementation baseline has progressed through `Round 12`
- `cargo test` is green across library, CLI smoke, MCP smoke, daemon smoke, and Tauri smoke coverage
- the repository is beyond a routing-only prototype and now has a usable minimum memory lifecycle core
- `docs/ROADMAP.md` and `docs/PRODUCT.md` still describe some already-finished capabilities as future work and should not be used alone to judge implementation status

## What Is Completed

The following product slices are already implemented and verified in code/tests.

### Retrieval And Wakeup Core

- project routing from `cwd`
- scoped vault scanning and heuristic ranking
- multi-format output (`prompt`, `markdown`, `json`)
- wakeup packet generation
- wakeup policy enforcement for suppression / redaction / policy reporting
- shared retrieval gateway reuse across CLI and MCP surfaces
- superseded record exclusion from retrieval (via scored note frontmatter `record_id`)

### Knowledge Loop And Wiki

- wiki-style auto-compile: related lifecycle records → knowledge synthesis pages in `50-Memory-Ledger/Compiled/`
- wiki INDEX generation grouped by scope/project (`src/wiki_index.rs`)
- wiki lint: staleness, orphan, quality checks (`src/wiki_lint.rs`)
- `writeback_from_config` chains INDEX refresh + auto-compile after lifecycle writes
- CLI `memory lint` and `memory sync-index` commands
- MCP `memory_lint` tool
- desktop facade `wiki_lint` and `read_wiki_index` methods
- frontend lint health page and wakeup INDEX rendering
- MCP sampling reverse-call integration: auto-compile now fires on a dedicated thread (fire-and-forget) so the main dispatch loop is never blocked waiting for the sampling round-trip
- `McpSamplingClient` / `StdSamplingChannel` infrastructure for `sampling/createMessage` reverse-calls

### Retrieval Intelligence

- excerpt section-level precision: retrieval returns best-matching sections rather than full note content
- stale-memory hints surfaced in wakeup packet (`maintenance_hints` section)
- project-first retrieval scoring: 40% cross-project penalty (`CROSS_PROJECT_PENALTY = 0.6`) applied to user/agent/team-scoped candidates when a project is matched, ensuring project-scoped records rank above cross-project ones

### Developer Memory Core

- lifecycle domain model for memory records, sources, scope, and states
- append-only local ledger in `memory-ledger.jsonl`
- lifecycle transitions for manual create, AI propose, accept, promote, and archive
- latest-state projection queries
- in-process projection cache
- disk-backed rebuildable projection snapshot
- event-level write provenance metadata (`actor`, `reason`, `evidence_refs`)

### Client Surfaces

- CLI lifecycle commands:
  - `memory list`
  - `memory show`
  - `memory history`
  - `memory record-manual`
  - `memory propose`
  - `memory accept`
  - `memory promote`
  - `memory archive`
  - `memory lint`
  - `memory sync-index`
- MCP lifecycle tools for read/write actions (including `memory_lint`)
- MCP retrieval tools for search / explain / wakeup
- MCP prompts/resources for guided client flows
- MCP sampling reverse-call support (`sampling/createMessage`)
- experimental GUI review workbench with queue/detail/history/create/propose/action flows
- GUI workbench batch actions (accept/archive multiple records at once)
- optional daemon-backed lifecycle reads for CLI and MCP, with direct fallback preserved
- desktop-facing Rust facade in `src/desktop/` for future desktop hosts

### Validation Status

- unit coverage for lifecycle, daemon, desktop, retrieval, and formatting helpers
- smoke coverage for CLI, MCP, daemon, and Tauri-facing desktop flows
- malformed JSON recovery verified on both MCP stdio and daemon stdio boundaries

## What Is Not Completed

The following items remain incomplete or only partially implemented.

### Desktop Product Surface

- a minimal runnable Tauri host is now possible on top of the existing desktop facade and Tauri adapter layer
- a minimal static frontend shell now exists for lifecycle/retrieval flows
- desktop work is still not a finished desktop client and should be treated as an early host/workbench slice

### GUI Lifecycle Scope

- no edit-in-place for memory records
- metadata inputs exist only on create/propose forms, not on lifecycle action buttons

### Retrieval Intelligence

- ranking is still heuristic rather than semantic
- no contradiction detection
- no confidence scoring layer
- no graph-style wikilink traversal
- no large-vault benchmark coverage
- scoring breakdowns are not yet exposed richly enough for all debugging needs

### Memory Ingestion And Distillation

- no transcript importer
- no git importer
- no terminal metadata importer
- no durable extraction pipeline for incident/decision candidates from raw events

### Daemon Scope

- daemon boundary is intentionally narrow and read-only
- write operations still bypass the daemon
- daemon payload shape is still narrower than the richer shared lifecycle summary contract used by CLI/MCP

## Recommended Next Development

Current development should branch from the fact that the memory core exists, while product completion is still uneven.

### High Priority

1. choose whether the next product-facing milestone is:
   - finishing a real desktop host on top of the existing `src/desktop/` boundary, or
   - moving directly into retrieval intelligence work (semantic ranking, contradiction detection)
2. if daemon-backed read surfaces keep growing, align daemon payloads with `src/lifecycle_summary.rs` rather than creating a second response contract

### Recommended Default Path

If the immediate goal is a more usable product, finish the desktop host layer next:

1. convert the existing Tauri-shaped adapter layer into a real runnable host
2. wire a minimal desktop frontend shell to the existing context / wakeup / lifecycle read-write flows
3. keep GUI/Tauri behavior reusing the same lifecycle formatter and summary helpers

If the immediate goal is stronger core quality, move into retrieval intelligence next:

1. improve excerpt selection from best-matching sections
2. expose clearer score breakdowns in machine-readable output
3. add a heavier retrieval index for large vaults only after measuring current bottlenecks
4. evaluate semantic retrieval, contradiction detection, and confidence scoring after index/debuggability work is in place

### Medium Priority

- decide whether lifecycle action buttons should also capture provenance metadata
- design importer boundaries for transcript / git / terminal ingestion without polluting curated Obsidian notes
- keep all new lifecycle presentation logic flowing through `src/lifecycle_format.rs` and `src/lifecycle_summary.rs`

## Restart Guidance

When resuming development, use this status order instead of the older roadmap wording:

1. memory lifecycle core: implemented
2. cross-AI gateway: implemented in minimum viable form
3. optional daemon boundary: implemented for read-side flows
4. desktop client: minimum host/bootstrap slice exists, product surface not finished
5. retrieval intelligence and ingestion pipeline: not yet built

## Product Direction Confirmed

`spool` should evolve into:

- a local-first developer memory operating system
- Obsidian as curated knowledge-of-record
- a separate local ledger for captured session memory
- one retrieval gateway for multiple AI tools
- security and provenance before aggressive compression
- a growth path where manual memory and AI-proposed memory can be reviewed, promoted, archived, and later consumed by multiple clients

Reference docs:

- [PRODUCT.md](/Users/long/Work/spool/docs/PRODUCT.md)
- [ARCHITECTURE.md](/Users/long/Work/spool/docs/ARCHITECTURE.md)
- [OBSIDIAN_SCHEMA.md](/Users/long/Work/spool/docs/OBSIDIAN_SCHEMA.md)
- [ROADMAP.md](/Users/long/Work/spool/docs/ROADMAP.md)
- [PLANNING_ALIGNMENT.md](/Users/long/Work/spool/docs/PLANNING_ALIGNMENT.md)
- [adr/0001-local-developer-memory-os.md](/Users/long/Work/spool/docs/adr/0001-local-developer-memory-os.md)
- [adr/0002-wakeup-packet-v1.md](/Users/long/Work/spool/docs/adr/0002-wakeup-packet-v1.md)

## Code Work Completed

### Wake-up Contract Stabilization

- extracted wakeup policy from the builder
- isolated redaction / suppression / policy summary logic
- kept wakeup rendering stable across json / markdown / prompt modes

Relevant files:

- [src/wakeup_policy.rs](/Users/long/Work/spool/src/wakeup_policy.rs)
- [src/wakeup.rs](/Users/long/Work/spool/src/wakeup.rs)
- [src/output/wakeup.rs](/Users/long/Work/spool/src/output/wakeup.rs)

### Memory Gateway Core

- introduced a minimal shared gateway layer
- continued converging `get`, `explain`, and `wakeup` toward common domain-level orchestration
- kept rendering responsibility outside the core service boundary

Relevant files:

- [src/memory_gateway.rs](/Users/long/Work/spool/src/memory_gateway.rs)
- [src/cli/commands.rs](/Users/long/Work/spool/src/cli/commands.rs)

### Memory Lifecycle Core

- added lifecycle domain primitives:
  - `MemoryScope`
  - `MemorySourceKind`
  - `MemoryLifecycleState`
  - `MemoryPromotionAction`
  - `MemoryLedgerAction`
  - `MemoryRecord`
- added review-aware semantics:
  - manual memory starts as `Accepted`
  - AI proposals start as `Candidate`
  - only `Accepted` / `Canonical` records are wakeup-eligible

Relevant files:

- [src/domain/memory_lifecycle.rs](/Users/long/Work/spool/src/domain/memory_lifecycle.rs)

### Lifecycle Ledger Store

- implemented append-only local ledger storage in jsonl
- file name: `memory-ledger.jsonl`
- supports:
  - `record_manual_memory(...)`
  - `propose_ai_memory(...)`
  - `accept_memory(...)`
  - `promote_memory_to_canonical(...)`
  - `archive_memory(...)`
- transition events reuse the original `record_id`
- invalid lifecycle transitions now fail and do not append dirty audit entries

Relevant files:

- [src/lifecycle_store.rs](/Users/long/Work/spool/src/lifecycle_store.rs)

### Latest-State Projection Layer

Query optimization currently follows the chosen direction: **in-memory projection first**, not persistent indexing.

Added projection-backed reads for:

- latest state by `record_id`
- latest state by `scope` / `scope_key`
- latest state by `state`
- pending review queue
- wakeup-ready queue

This keeps the ledger append-only while reducing repeated query logic.

Relevant files:

- [src/lifecycle_store.rs](/Users/long/Work/spool/src/lifecycle_store.rs)

### GUI Review Workbench Surface

GUI has continued moving from a pure context shell toward a minimal memory workbench.

It now shows:

- `Context`
- `Explain`
- `Pending review`
- `Wakeup-ready`

The review workbench now supports minimum single-record lifecycle actions and refreshes projection-backed views after each successful write.

Relevant files:

- [src/gui/app_shell.rs](/Users/long/Work/spool/src/gui/app_shell.rs)

### Shared Lifecycle Service

- added a shared lifecycle service above `LifecycleStore`
- unified lifecycle reads for:
  - pending review
  - wakeup-ready
  - record lookup by `record_id`
- unified lifecycle actions for:
  - `Accept`
  - `PromoteToCanonical`
  - `Archive`
- GUI and CLI now reuse the same action path instead of each touching the store directly

Relevant files:

- [src/lifecycle_service.rs](/Users/long/Work/spool/src/lifecycle_service.rs)

### GUI Minimum Action Flow

- replaced read-only lifecycle text panes with selectable `Pending review` / `Wakeup-ready` lists
- added a detail pane for the selected memory record
- added minimal single-record actions in GUI:
  - `Accept`
  - `Promote`
  - `Archive`
- after each successful action, GUI refreshes both lifecycle panels and preserves selection when possible

Relevant files:

- [src/gui/app_shell.rs](/Users/long/Work/spool/src/gui/app_shell.rs)

### CLI Lifecycle Surface

- added `spool memory list`
- added `spool memory show`
- added `spool memory history`
- added `spool memory record-manual`
- added `spool memory propose`
- added `spool memory accept`
- added `spool memory promote`
- added `spool memory archive`
- CLI output now covers:
  - create result summary
  - action result summary
  - single-record detail
  - event history

Relevant files:

- [src/cli/args.rs](/Users/long/Work/spool/src/cli/args.rs)
- [src/cli/commands.rs](/Users/long/Work/spool/src/cli/commands.rs)
- [tests/cli_smoke.rs](/Users/long/Work/spool/tests/cli_smoke.rs)

### MCP Lifecycle Surface

- added `spool-mcp` as a minimal stdio MCP server
- added lifecycle MCP read tools:
  - `memory_review_queue`
  - `memory_wakeup_ready`
  - `memory_get`
  - `memory_history`
- added lifecycle MCP write tools:
  - `memory_record_manual`
  - `memory_propose`
  - `memory_accept`
  - `memory_promote`
  - `memory_archive`

Relevant files:

- [src/mcp.rs](/Users/long/Work/spool/src/mcp.rs)
- [src/bin/spool_mcp.rs](/Users/long/Work/spool/src/bin/spool_mcp.rs)
- [tests/mcp_smoke.rs](/Users/long/Work/spool/tests/mcp_smoke.rs)

### MCP Retrieval Gateway Surface

- added retrieval MCP tools on the same server:
  - `memory_search`
  - `memory_explain`
  - `memory_wakeup`
- these tools reuse the existing retrieval / wakeup core rather than duplicating route logic
- MCP now exposes both:
  - lifecycle review operations
  - retrieval / wakeup gateway operations
- resource reads now prefer docs adjacent to the active config, with repository-doc fallback for local smoke/integration paths
- MCP smoke coverage now provisions doc resources explicitly so prompt/resource flows are validated end-to-end
- malformed JSON on the MCP stdio boundary now returns JSON-RPC parse errors and the server continues serving subsequent requests
- lifecycle create/action tool responses now derive their summary fields from a shared lifecycle summary helper instead of hand-assembled per-tool payloads

Relevant files:

- [src/mcp.rs](/Users/long/Work/spool/src/mcp.rs)
- [src/memory_gateway.rs](/Users/long/Work/spool/src/memory_gateway.rs)
- [tests/mcp_smoke.rs](/Users/long/Work/spool/tests/mcp_smoke.rs)
- [src/bin/spool_mcp.rs](/Users/long/Work/spool/src/bin/spool_mcp.rs)
- [src/lifecycle_summary.rs](/Users/long/Work/spool/src/lifecycle_summary.rs)

### Write Provenance Metadata

- added optional event-level metadata on lifecycle writes:
  - `actor`
  - `reason`
  - `evidence_refs`
- preserved compatibility with older ledger entries that do not include metadata
- threaded metadata through:
  - `LifecycleStore`
  - `LifecycleService`
  - CLI write commands
  - MCP write tools
- surfaced metadata in:
  - CLI output
  - MCP structured tool responses
  - GUI lifecycle detail pane
- later refactors also converged repeated lifecycle presentation/summary logic into shared helpers:
  - `src/lifecycle_format.rs` for CLI/GUI state/action labels plus list/detail/history rendering
  - `src/lifecycle_summary.rs` for CLI/MCP create/action summary payloads plus queue/record/history shared payload and text helpers

Relevant files:

- [src/lifecycle_store.rs](/Users/long/Work/spool/src/lifecycle_store.rs)
- [src/lifecycle_service.rs](/Users/long/Work/spool/src/lifecycle_service.rs)
- [src/cli/commands.rs](/Users/long/Work/spool/src/cli/commands.rs)
- [src/mcp.rs](/Users/long/Work/spool/src/mcp.rs)
- [src/gui/app_shell.rs](/Users/long/Work/spool/src/gui/app_shell.rs)
- [src/lifecycle_format.rs](/Users/long/Work/spool/src/lifecycle_format.rs)
- [src/lifecycle_summary.rs](/Users/long/Work/spool/src/lifecycle_summary.rs)

### GUI Operator Console

- added a history pane for the selected lifecycle record
- GUI history now shows event-level metadata when present
- added minimal GUI write forms for:
  - manual memory creation
  - AI proposal creation
- GUI now refreshes:
  - pending review
  - wakeup-ready
  - selected detail
  - selected history
  after create/propose or lifecycle action success
- GUI lifecycle text rendering now shares the same lifecycle formatter module used by CLI for state/action/detail/history labels, while keeping small UI-specific differences (for example summary placement)

Relevant files:

- [src/gui/app_shell.rs](/Users/long/Work/spool/src/gui/app_shell.rs)
- [src/lifecycle_format.rs](/Users/long/Work/spool/src/lifecycle_format.rs)

### Lifecycle Projection Cache

- added in-process projection caching for lifecycle latest-state reads
- cache is keyed by ledger file fingerprint
- cache is invalidated immediately after append
- repeated reads in one process now avoid rebuilding the same projection when the ledger has not changed
- retrieval path remains on the existing vault snapshot cache; no extra retrieval cache was added in this round

Relevant files:

- [src/lifecycle_store.rs](/Users/long/Work/spool/src/lifecycle_store.rs)
- [src/vault/scanner.rs](/Users/long/Work/spool/src/vault/scanner.rs)

### Persistent Projection Snapshot

- added a rebuildable disk-backed lifecycle projection snapshot
- persistent snapshot is only used when its ledger fingerprint matches current source-of-truth state
- corrupted or stale snapshots fall back to direct ledger rebuild
- in-process cache still sits above the persistent snapshot for the cheapest repeated reads

Relevant files:

- [src/lifecycle_store.rs](/Users/long/Work/spool/src/lifecycle_store.rs)

### MCP Prompts And Resources

- added MCP prompts for common flows:
  - lifecycle queue review
  - project wakeup generation
  - project context retrieval
- added MCP read-only resources for:
  - current session handoff
  - current MCP prompts/resources plan
  - restart guide context
- prompts/resources are layered on top of the existing MCP server without changing tool behavior

Relevant files:

- [src/mcp.rs](/Users/long/Work/spool/src/mcp.rs)
- [tests/mcp_smoke.rs](/Users/long/Work/spool/tests/mcp_smoke.rs)

### GUI Metadata Inputs

- added optional GUI inputs for:
  - `actor`
  - `reason`
  - `evidence_refs`
- GUI manual/propose writes now produce the same provenance metadata shape as CLI and MCP
- GUI metadata remains optional and limited to the create/propose form

Relevant files:

- [src/gui/app_shell.rs](/Users/long/Work/spool/src/gui/app_shell.rs)

### Lifecycle Read Daemon

- added `spool-daemon` as a minimal resident-process boundary
- kept the daemon responsibility narrow to read-only lifecycle queries:
  - `ping`
  - `workbench`
  - `record`
  - `history`
- CLI and MCP now have optional daemon-backed read paths with direct fallback; daemon use is not mandatory
- current daemon client behavior now reuses a shared daemon stdio session keyed by `(daemon_bin, config_path)` for repeated reads inside one process
- if that shared session dies, the next request rebuilds it once before falling back, while CLI/MCP still preserve direct fallback if daemon transport remains unavailable
- daemon read helpers and MCP lifecycle read paths now both have explicit tests covering shared-session reuse and rebuild-after-exit behavior
- malformed JSON on the daemon stdio boundary now returns a structured `ok: false` error and the process continues serving subsequent requests

Relevant files:

- [src/daemon.rs](/Users/long/Work/spool/src/daemon.rs)
- [src/bin/spool_daemon.rs](/Users/long/Work/spool/src/bin/spool_daemon.rs)
- [tests/daemon_smoke.rs](/Users/long/Work/spool/tests/daemon_smoke.rs)

### Desktop Facade Boundary

- added `src/desktop.rs` as a pure Rust desktop-facing facade for future Tauri or other desktop shells
- introduced stable desktop DTOs for:
  - context requests/responses
  - wakeup requests/responses
  - workbench / record / history reads
  - manual record / AI propose / lifecycle action writes
  - daemon preference inputs and lifecycle action enums
- added `DesktopErrorEnvelope` so desktop hosts receive classified input/config/routing/scan/runtime failures with hints instead of surface-local ad-hoc strings
- kept desktop orchestration thin by reusing existing shared core layers:
  - `app::run_with_overrides` for context
  - `memory_gateway::execute` for wakeup
  - `read_workbench` / `read_record` / `read_history` for daemon-preferred read flows
  - `LifecycleService` for write flows
- desktop lifecycle responses now prefer the same shared `src/lifecycle_summary.rs` payload helpers already used by CLI/MCP rather than inventing a second desktop-only payload contract
- added focused tests for desktop parsing helpers, validation envelopes, context/wakeup flow, and lifecycle read/write workflow coverage

Relevant files:

- [src/desktop.rs](/Users/long/Work/spool/src/desktop.rs)
- [src/lib.rs](/Users/long/Work/spool/src/lib.rs)
- [CLAUDE.md](/Users/long/Work/spool/CLAUDE.md)

## Key Decisions Made In This Session

1. Do not open too many agents; default to the main agent driving work directly.
2. During the daytime, pause for user input on key architecture or workflow decisions.
3. For lifecycle query optimization, choose **in-memory latest-state projection first**, not persistent indexing.
4. Keep lifecycle actions narrow and append-only:
   - no batch actions
   - no edit-in-place
   - no history rewriting
5. Keep MCP thin and reuse existing app/service layers instead of adding a parallel business core.
6. Defer richer write metadata until all write surfaces are stable enough to carry the same contract.
7. Keep write provenance on ledger events rather than on `MemoryRecord` itself.
8. Keep GUI growth narrow: history + create/propose are acceptable, but batch edit is still out of scope.
9. Prefer the smallest safe cache first: in-process + freshness-checked before disk-backed persistence.
10. Add MCP UX layers after tools, not before them.
11. Keep GUI metadata optional and form-scoped before expanding it to action buttons.
12. Treat persistent caches as rebuildable derivatives, never as new sources of truth.
13. Keep the first daemon boundary read-only and optional.

## Current Working Capabilities

The repository now has a real minimal memory growth loop:

- manual memory write
- AI memory proposal
- append-only lifecycle ledger
- accept / promote / archive transitions
- latest-state projection
- pending review queue
- wakeup-ready queue
- shared lifecycle service for GUI / CLI reuse
- GUI lifecycle review and actions
- CLI lifecycle list / show / history
- CLI lifecycle record-manual / propose
- CLI lifecycle accept / promote / archive
- MCP lifecycle read / write tools
- MCP retrieval / explain / wakeup gateway tools
- event-level provenance metadata across lifecycle writes
- GUI history pane and minimal create/propose flow
- in-process lifecycle projection cache
- disk-backed lifecycle projection snapshot
- MCP prompts/resources for guided client usage
- GUI metadata-aware create/propose inputs
- minimal lifecycle read daemon
- desktop-facing Rust facade for future Tauri/desktop hosts
- desktop workflow DTOs and classified error envelopes
- desktop context / wakeup / lifecycle read-write workflow boundary

This is no longer just a retrieval prototype; it is the beginning of a memory lifecycle core.

## Current Gaps

- daemon-backed reads now reuse a shared stdio daemon session keyed by `(daemon_bin, config_path)` inside one process, with one rebuild attempt before direct fallback
- daemon read-side structured payload shape is still narrower than the richer MCP shared payload contract and can be unified further later
- desktop facade exists as a pure Rust boundary, a Tauri-shaped adapter layer exists, and a minimal runnable host/bootstrap slice now exists, but the desktop product surface is still early
- desktop documentation must continue to describe `src/desktop/` as the implemented backend-facing contract instead of implying a finished Tauri host already exists
- GUI still has no edit-in-place and no metadata on lifecycle action buttons

## Validation Completed In This Session

```bash
cargo test -q memory_lifecycle --lib
cargo test -q lifecycle_store --lib
cargo test -q lifecycle_service --lib
cargo test -q mcp --lib
cargo test -q --features gui --lib
cargo test -q
cargo check -q
cargo check -q --features gui --bin spool-gui
cargo check -q --bin spool-mcp
cargo test -q mcp -- --nocapture
cargo test -q daemon -- --nocapture
cargo test -q desktop --lib
cargo check -q --lib
```

## Next Critical Decision

### Daemon integration or heavier index layer first?

The local, GUI, and MCP workflow surfaces are now present, and the first daemon boundary exists. The next branch point is whether to integrate existing clients with the daemon or continue building heavier index artifacts first.

#### Option A — Daemon integration first
- let CLI and/or MCP optionally use the daemon for read-only operations
- preserve direct fallback paths
- exercise the new boundary under real clients

#### Option B — Heavier index first
- add more disk-backed derived state before daemonization
- optimize more reads first
- keep client/daemon relationship unchanged

### Current recommendation

Prefer **Option A — Daemon integration first**.

Reason:
- the daemon now exists but is not exercised by real clients
- integrating one narrow read path will validate whether the boundary is actually useful
- more index layers should wait until client/daemon interaction is clearer

## Recommended Next Steps

### High Priority

1. keep lifecycle formatter/summary helpers as the only place where presentation and summary field selection evolves
2. if new lifecycle surfaces are added, wire them through `src/lifecycle_format.rs` and `src/lifecycle_summary.rs` first instead of duplicating render logic
3. continue pushing repeated CLI/GUI/MCP contracts downward into shared helpers before widening feature scope
4. if daemon read payloads need to grow, align them with the existing shared lifecycle payload contracts instead of inventing a second shape

Relevant files:

- [src/lifecycle_format.rs](/Users/long/Work/spool/src/lifecycle_format.rs)
- [src/lifecycle_summary.rs](/Users/long/Work/spool/src/lifecycle_summary.rs)
- [src/cli/commands.rs](/Users/long/Work/spool/src/cli/commands.rs)
- [src/gui/app_shell.rs](/Users/long/Work/spool/src/gui/app_shell.rs)
- [src/mcp.rs](/Users/long/Work/spool/src/mcp.rs)
- [src/daemon.rs](/Users/long/Work/spool/src/daemon.rs)

### Medium Priority

1. evaluate whether lifecycle action buttons should also accept metadata in GUI
2. evaluate whether retrieval path eventually needs more than the current vault snapshot cache
3. evaluate whether heavier index artifacts are justified after daemon-backed client reads exist
4. keep extending new lifecycle payload/text behavior through `src/lifecycle_summary.rs` first rather than reintroducing surface-local assembly
5. keep GUI-specific presentation differences intentionally small and parameterized rather than forking formatter logic

Relevant files:

- [src/lifecycle_format.rs](/Users/long/Work/spool/src/lifecycle_format.rs)
- [src/lifecycle_summary.rs](/Users/long/Work/spool/src/lifecycle_summary.rs)
- [docs/SESSION_HANDOFF.md](/Users/long/Work/spool/docs/SESSION_HANDOFF.md)
- [src/gui/app_shell.rs](/Users/long/Work/spool/src/gui/app_shell.rs)

### Lower Priority

1. persistent index / snapshot cache
2. semantic retrieval enrichment for ledger-derived memory
3. revisit whether lifecycle formatter output should also back future API docs or exported markdown reports

## Recommended Restart Entry Point

When continuing later:

1. read [src/lifecycle_service.rs](/Users/long/Work/spool/src/lifecycle_service.rs)
2. read [src/lifecycle_store.rs](/Users/long/Work/spool/src/lifecycle_store.rs)
3. read [src/daemon.rs](/Users/long/Work/spool/src/daemon.rs)
4. read [src/mcp.rs](/Users/long/Work/spool/src/mcp.rs)
5. read [src/lifecycle_summary.rs](/Users/long/Work/spool/src/lifecycle_summary.rs)
6. read [docs/DAEMON_INTEGRATION_ROUND_12_PLAN.md](/Users/long/Work/spool/docs/DAEMON_INTEGRATION_ROUND_12_PLAN.md)
7. if extending lifecycle tooling, preserve these invariants:
   - append-only ledger
   - stable `record_id`
   - invalid transitions do not append
   - GUI / CLI / future MCP all go through the shared lifecycle service
   - every successful write refreshes projection-backed review and wakeup-ready views
