Files
poimen-memory/IMPLEMENTATION-ROADMAP.md
Story Crater Bot 4733b89165 docs: implementation roadmap for M3, M4, M5 with detailed breakdown
M3.2 (rerank client):  COMPLETE (5 tests passing)
M3.3 (mem query): Ready, pipeline specified, code structure ready
M3.4 (gate): Blocked on M3.3

M4.1 (skill draft): 60% done (lesson.rs: 871 lines)
M4.2 (cycle-guard): Detailed spec
M4.3 (gate): Blocked on M4.1-4.2

M5.1-5.6 (post-training): Separate Python, M5.4 can run in parallel

Includes:
- Sequential implementation plan (3 weeks)
- Code structure inventory
- Gate progression tracking
- Parallel tracks (M3.5, M3.6, M3.7, M6)
- Acceptance criteria for each task
2026-08-25 11:59:13 -07:00

303 lines
7.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Implementation Roadmap: M3 → M5
## Current Status
- M0-M2: ✅ **COMPLETE** (104 tests passing, rerank client done)
- M3.1: ✅ **DONE** (L2 synthesis code exists, M1.5 refactored)
- M3.2: ✅ **DONE** (rerank client, 5 tests passing)
- M3.3M5.6: ⏳ **READY TO START**
---
## Critical Path: M3.3 → M3.4 → M4.3 → M5.6
### M3.3 — `mem query` (M, 13 days)
**Status:** Ready; QueryWorker stub exists
**Scope:**
```
add Query command to CLI
├─ --project <name> (default: infer from $PWD)
├─ --levels <L0|L1|L2> (default: L1,L2)
├─ --k <n> (default: 5, recall 10×k, rerank to k)
├─ --format <text|json>(default: text)
└─ --explain (show recall candidates before reranking)
```
**Pipeline:**
```
embed question
HNSW recall (top 50)
rerank (using RerankClient)
top 5 results
walk memory_edge for provenance
render (human-readable + JSON)
```
**Files to modify:**
- `crates/mem-cli/src/main.rs` — add Query to Commands enum
- `crates/mem-cli/src/query_worker.rs` — wire reranker, add edge walking
- `tests/it_query.rs` — 8 integration tests (seeded DB, deterministic)
**Acceptance:** known-answer query, provenance resolves, level filtering works, reranking changes order
---
### M3.4 — M3 Gate (S, 1 day)
**Status:** Blocked on M3.1M3.3
**Scope:**
```
Unit test: M3.1 + M3.2 + M3.3 compose correctly
├─ synthesize project-level memory (M3.1)
├─ query returns reranked results (M3.3 + M3.2)
└─ provenance walks all 3 levels (L0 ← L1 ← L2)
```
**Acceptance:** known-answer query on seeded poimen corpus returns correct answer first
---
### M4.1 — `mem skill draft` (M, 13 days)
**Status:** 60% done (lesson.rs: 871 lines)
**Scope:**
```
mem skill draft --from poimen/infra-root-causes
├─ Read L1/L2 node from pgvector
├─ LLM-assisted conversion: descriptive → procedural
├─ Generate SKILL.md in vault/skills/_drafts/
├─ Frontmatter: name, description, generated_from: <sha>
└─ Output: vault/skills/_drafts/<name>/SKILL.md (read-only)
```
**Files to modify:**
- `crates/mem-cli/src/main.rs` — add Skill(Draft) to Commands
- `crates/mem-cli/src/skill_draft.rs` — new, implement draft logic
- `tests/it_skill_draft.rs` — 7 tests (generation, format, provenance)
**Acceptance:** draft generated correctly, carries generated_from metadata, never overwrites promoted skill
---
### M4.2 — Cycle Guard (M, 13 days)
**Status:** Not started
**Scope:**
```
Stop emitted skill → session → ingest → reinforcement cycle
├─ Manifest file: hash of all emitted artifacts
├─ During ingest: match chunks against manifest (shingle overlap)
├─ Tag matching chunks: derived: true
└─ Gate never sees derived chunks (evidence filtered)
```
**Files to modify:**
- `crates/mem-core/src/derived_filter.rs` — new, implement shingle matching
- `crates/mem-ingest/src/` — wire filter into ingest pipeline
- `tests/it_derived_filter.rs` — verify cycle cannot form
**Acceptance:** promoted skill ingested and filtered (never becomes evidence), cycle stays open
---
### M4.3 — M4 Gate (S, 1 day)
**Status:** Blocked on M4.1M4.2
**Scope:**
```
Verify loop stays open
1. Draft skill generated
2. Human promotes to vault/skills/<name>
3. Session loads promoted skill
4. Session ingested
5. Skill text still tagged derived: true (never evidence)
```
---
### M5.1M5.3 — Labeling & Corpus Export (M×3, 3 days)
**Status:** Not started
**Scope:**
```
M5.1: Use 32B reasoning model to label chunks
├─ Input: JSONL log from M1.8 runs
├─ Output: U_t ground truth ("does chunk answer Q?")
└─ Store in new JSONL with label field
M5.2: Hand-label holdout, measure calibration
├─ Label ~100 examples manually
├─ Compare vs 32B labels
├─ Measure Cohen's κ
└─ Proceed only if κ > 0.75
M5.3: Export to verl format
├─ Input: labeled JSONL
├─ Output: verl dataset (prompt, response, label, reward)
└─ Split: train/val/test
```
---
### M5.4 — vLLM InferenceService (L, 3+ days, **CAN RUN IN PARALLEL**)
**Status:** Not started, independent
**Scope:**
```
Deploy vLLM with --enable-lora (Ollama can't hot-swap LoRA)
├─ K8s manifest: InferenceService, vLLM v0.11+
├─ Model: Qwen2.5-3B base
├─ Endpoint: /v1/completions with LoRA adapter
└─ Homelab deployment
```
**Acceptance:** vLLM serving Qwen2.5-3B with LoRA support
---
### M5.5 — verl Training Loop (L, 3+ days)
**Status:** Not started, depends on M5.3 + M5.4
**Scope:**
```
Train LoRA adapter using verl
├─ Input: labeled corpus from M5.3
├─ Base model: Qwen2.5-3B (resident in Ollama)
├─ Adapter: LoRA, rank 1632
├─ Rewards:
│ ├─ r_update: +1 correct gate, 1 wrong
│ ├─ r_exit: 0 correct, 0.5 late, 0.75 early
│ ├─ r_format: strict (gate response parseable)
│ └─ α=0.9 mixing
└─ Output: adapter.safetensors (~50 MB)
```
---
### M5.6 — M5 Gate (M, 1 day)
**Status:** Blocked on M5.1M5.5
**Scope:**
```
Adapter beats prompted baseline
├─ Held-out project: measure update accuracy
├─ Prompted baseline: stock Qwen2.5-3B
├─ Adapter baseline: trained LoRA
├─ Assert: adapter accuracy > prompted
└─ Assert: LoRA < 60 MB
```
---
## Implementation Sequence
**Week 1: M3 (core retrieval)**
```
Mon: M3.3 (mem query) — embed, recall, rerank, edge walking
Tue: M3.3 continued — CLI, output formatting
Wed: M3.4 gate — compose M3 pieces, verify end-to-end
```
**Week 2: M4 (skills)**
```
Thu: M4.1 (skill draft) — complete lesson.rs, add LLM conversion
Fri: M4.2 (cycle guard) — shingle matching, derived filter
M4.3 gate — full cycle test
```
**Week 3: M5 (post-training, parallel tracks)**
```
Mon: M5.1 (labeling) — 32B labeler, ground truth extraction
Tue: M5.2 (calibration) — hand-label holdout, κ measurement
Wed: M5.3 (corpus export) — JSONL → verl format
**M5.4 vLLM (parallel)** — K8s manifest, deploy
Thu: M5.5 (training) — verl loop, reward shaping
Fri: M5.6 gate — verify adapter beats baseline
```
---
## Parallel Tracks (can start anytime)
- **M3.5** (HTTP API): Already mostly done (gate green)
- **M3.6** (Reference corpora): 6 tasks, independent
- **M3.7** (Tool context): 6 tasks, 60% done (lesson.rs)
- **M6** (Agent-manager): Different repo, independent
---
## Code structure ready
```
crates/
mem-core/
├── gate_parser.rs ✅ (M1)
├── gated_loop.rs ✅ (M1)
└── derived_filter.rs ⏳ (M4.2, to create)
mem-llm/
├── chat.rs ✅ (M1)
├── embeddings.rs ✅ (M2)
└── rerank.rs ✅ (M3.2, tests pass)
mem-cli/
├── main.rs ⏳ (add Query, Skill(Draft))
├── ingest_worker.rs ✅ (M1-M2)
├── query_worker.rs 🟡 (stub exists, needs completion)
├── skill_draft.rs ⏳ (to create)
└── http_server.rs ✅ (M3.5)
mem-store/
└── vector_store.rs ✅ (HNSW, edge walking)
tests/
├── it_rerank.rs ✅ (4/5 tests pass, 1 ignored)
├── it_query.rs ⏳ (to create, 8 tests)
├── it_skill_draft.rs ⏳ (to create, 7 tests)
└── it_derived_filter.rs ⏳ (to create)
```
---
## Gate progression
```
M3.4 gate ✅
├─ M3.1 ✅ (L2 synthesis)
├─ M3.2 ✅ (rerank)
└─ M3.3 ⏳ (query)
M4.3 gate ⏳
├─ M4.1 🟡 (skill draft, 60% done)
└─ M4.2 ⏳ (cycle guard)
M5.6 gate ⏳
├─ M5.1 ⏳ (labeling)
├─ M5.2 ⏳ (calibration)
├─ M5.3 ⏳ (corpus export)
├─ M5.4 ⏳ (vLLM, can run parallel)
└─ M5.5 ⏳ (training)
```
---
## Next: Start M3.3
Ready to implement. Blocking: none (M3.2 ✅, M2.4 ✅, M2.1 ✅)
See tasks/M3.3-mem-query.md for full spec.