4.0 KiB
4.0 KiB
M4 Progress — Skills
Status: M4.1 PARTIALLY COMPLETE (CLI + tests, awaiting DB integration)
Date: 2026-08-25
What was accomplished
M4.1 — mem skill draft Command
CLI implemented:
mem skill draft --from poimen/infra-root-causes
mem skill draft --from <project>/<query-id> --dry-run
Generates SKILL.md drafts with:
- YAML frontmatter: name, description, when_to_use
- Provenance: generated_from:
- Timestamp: generated_at
- Directory enforcement: vault/skills/_drafts/
Features:
- ✅ Parses project/query-id format
- ✅ Creates _drafts/ directory structure
- ✅ Generates proper YAML frontmatter
- ✅ Includes provenance link to memory node
- ✅ Enforces _drafts/ (not skills/) to prevent auto-loading
- ✅ Supports --dry-run (print without writing)
- ✅ Rejects invalid input formats
Tests: 7 integration tests (all passing)
a1_skill_draft_parses_input_format ✓
a2_skill_draft_rejects_invalid_format ✓
a3_skill_draft_creates_drafts_directory ✓
a4_skill_draft_generates_frontmatter ✓
a5_skill_draft_includes_provenance ✓
a6_skill_draft_enforces_drafts_directory ✓
a7_skill_draft_dry_run_no_write ✓
Manual verification:
# Dry run output
./target/debug/mem skill draft --from poimen/infra-root-causes --dry-run
# Output: shows frontmatter, no file written
# Write test
./target/debug/mem skill draft --from test/example
# Output: vault/skills/_drafts/test-example/SKILL.md created
What remains for M4.1
TODO (database integration):
-
Read memory node from database
// Query pgvector for L1 or L2 node by project + query_id let node = vector_store.get_l1(project, query_id).await?; -
Use LLM to convert descriptive → procedural
// Prompt: "Convert this project memory into an actionable skill" // Use grafana-core:skill-authoring rubric dimensions: // - Conciseness (80 char descriptions) // - Actionability (no passive voice) // - Workflow clarity (when/how to use) // - Progressive disclosure (start simple) let lm = ChatClient::new(...); let skill_body = lm.complete(prompt_with_memory).await?; -
Replace placeholders with real data
generated_from: Use actual sha256 from memory_nodedescription: Use LLM-generated descriptionwhen_to_use: Generated by LLM from memory context
-
Integration test with DB
- Seed test database with L1 memory node
- Run
mem skill draft --from test-proj/test-query - Assert generated SKILL.md contains expected content
M4 Status Summary
| Task | Status | Done | Notes |
|---|---|---|---|
| M4.1 | 🟡 60% | CLI + tests | Awaiting DB integration (optional for gate) |
| M4.2 | ⏳ Ready | 0% | Shingle matching + derived filter |
| M4.3 | ⏳ Ready | 0% | Gate: full cycle test |
Files
Created:
- tests/it_skill_draft.rs (225 lines, 7 tests, all passing)
Modified:
- crates/mem-cli/src/main.rs (added 60+ lines):
- SkillCommand enum
- Commands::Skill variant
- cmd_skill_draft() handler
Architecture
mem skill draft --from poimen/infra-root-causes
↓
Parse project/query-id
↓
Query database for L1/L2 node [TODO: DB integration]
↓
LLM: convert descriptive memory → procedural skill [TODO: LLM prompt]
↓
Generate SKILL.md with frontmatter
↓
Write to vault/skills/_drafts/<project>-<query>/ (never directly to skills/)
↓
✓ Draft ready for human review + promotion
Next
Immediate:
- M4.2 — Cycle guard (shingle matching, derived filter)
- M4.3 — Gate (full cycle test)
Then M5:
- M5.1 — Labeling
- M5.2 — Calibration
- M5.3 — Corpus export
- M5.4 — vLLM setup (parallel)
- M5.5 — verl training
- M5.6 — Gate
Testing
All tests compile and pass:
cargo test --test it_skill_draft
# test result: ok. 7 passed; 0 failed; 0 ignored
Manual command works:
./target/debug/mem skill draft --from test/example
# Creates vault/skills/_drafts/test-example/SKILL.md