# M5 K-Pruner Execution Notes

## Scope

M5 completes the internal K-pruner feature slice without adding MCP transport.
The expansion surface is an in-process service API; M7 will wire it to
`cachelane:expand`.

## Decisions Implemented

- Pre-request composition lives in `src/hooks/pre-request.ts`.
- The pure orchestrator remains storage-free.
- Prompt stub materialization uses explicit `block_placements`; prompt text is
  never parsed to find replaceable blocks.
- Stub text is deterministic:
  `[stub:<8-char-id>] <summary> | refetch via cachelane:expand(block_id=<8-char-id>)`.
- `expandStub` returns a trusted refetch request derived only from SQLite
  `refetch_handle` metadata and records the restore turn.
- Restored blocks are forced into the suffix for exactly one warming turn via
  `restored_at_turn === current_turn - 1`.
- No MCP SDK dependency was added.

## Verification Targets

- Storage migration and restore tests cover `restored_at_turn`.
- Pruner tests cover K=3 pruning, disabled mode, stub materialization, prefix
  ambiguity, missing rows, non-stubs, and missing refetch handles.
- Pre-request tests cover the hot-path order, turn-4 pruning, warming, normal
  post-warming classification, and fail-open behavior.

## Corpus Status

The existing corpus gate remains regression coverage. The independent annotated
reference corpus called out in `corpus/README.md` is still the quality bar before
M5 can be treated as complete beyond code/test readiness.
