| name | learning |
| description | Two-tier learning system — Tier 1 fast capture via LEARNINGS.md, Tier 2 validated promotion to expertise.yaml |
Two-Tier Learning
Psi's self-improvement mechanism. Two speeds of learning, both injected into prompts.
Tier 1: LEARNINGS.md (Fast, Unvalidated)
Managed by src/psi/learning_tracker.py.
Format: --- delimited blocks in a markdown file.
# Learned Patterns
Rules extracted from experience. Apply relevant rules to avoid repeating mistakes.
---
Always use `type: "module"` in package.json when using ESM imports.
---
Filter all database queries by userId to prevent data leaks.
---
How it works:
- Claude appends rules during work (it writes directly to LEARNINGS.md)
- Orchestrator reads last 20 rules and injects them into the next iteration prompt
- Parser skips the header block (everything before first
---) and blocks < 10 chars
Key implementation detail: get_all() splits on ---, skips blocks[0] (header), normalizes whitespace.
Tier 2: expertise.yaml (Validated, Promoted)
Managed by src/psi/skill_sync.py. Runs between phases, not during.
Flow:
- Read all LEARNINGS.md entries
- Extract search terms from each (backtick code, quoted strings, significant words)
- Search codebase with ripgrep (excludes yaml, md, node_modules, .git, .psi)
- 3+ occurrences → promote to
.claude/skills/learned/resources/expertise.yaml
- Remove promoted entries from LEARNINGS.md
Confidence thresholds:
- High: 5+ file matches
- Medium: 3-4 file matches
- Low: <3 (stays in LEARNINGS.md only)
expertise.yaml schema (written via yaml.safe_dump()):
version: "0.2.0"
patterns:
- pattern: "Always extend tsconfig from @tsconfig/node20"
confidence: high
occurrences: 7
evidence: "tsconfig.json, packages/*/tsconfig.json"
learned_from: skill_sync
promoted_at: "2026-01-31T14:23:00"
evolution_log:
- date: "2026-01-31"
change: "Promoted 3 patterns from Tier 1"
patterns_added: 3
All YAML operations use yaml.safe_load()/yaml.safe_dump() per PyYAML best practices — prevents arbitrary object construction on load and restricts serialization to safe Python types on dump.
Prompt Injection Order
In prompt_generator.py:augment_with_learnings():
- Tier 2 patterns first (validated, higher priority), capped at 20
- Tier 1 learnings second (unvalidated, lower priority), capped at 20
- Separated by
--- from base prompt
Troubleshooting
No patterns promoted after skill sync
- Search terms may be too generic. Check
_extract_search_terms() output.
- ripgrep excludes yaml/md files — patterns about config won't match code files.
LEARNINGS.md entries duplicating
- Claude may write duplicate rules. No dedup currently — accepted limitation.
- Promoted entries are removed, which helps keep the file clean.
Related Files
src/psi/learning_tracker.py — Tier 1 read/write
src/psi/skill_sync.py — Tier 2 validation + promotion
src/psi/prompt_generator.py — Injection into prompts