lessons-learned
Lessons Learned
Use this skill to maintain a lightweight project memory loop.
Treat this file as the single source of truth for lesson-memory behavior:
trigger rules, recall flow, capture flow, limits, and validation.
README.md, references/, and phase-entry commands must not override those
rules.
Trigger Contract
Invoke this skill in these moments:
- Task start: Run recall before implementation.
- During task: Run capture when the user corrects your approach.
- Task end: Evaluate capture criteria and auto-capture qualifying lessons.
Do not trigger for:
- One-off factual Q&A with no reusable process.
- Pure concept explanation without actionable guidance.
- Formatting-only or administrative edits with no technical lesson.
- Non-reproducible context with no stable prevention rule.
Minimal Execution Guardrails
When this skill is the primary process skill in a session:
- For non-trivial work (3+ steps), create a task tracker before implementation.
- Before claiming completion, run relevant verification commands and report evidence.
- Do not replace verification with assumptions or partial checks.
Storage
Store all lesson artifacts under docs/lessons/ at the project root:
docs/lessons/
├── _index.md
├── api-timeout-retry-pattern.md
├── db-migration-run-order.md
└── null-check-before-save.md
Each lesson card is one atomic Zettelkasten note. Keep one reusable lesson per card.
Canonical Limits
Apply these limits everywhere in the skill package:
- Load 1-3 primary cards during recall.
- Load up to 2 related cards.
- Load at most 5 cards total.
- Use 0-2
relatedlinks per card. - Use 3-6 tags per card.
- Keep
confidencein the inclusive range0.0-0.9.
If another file conflicts with these limits, this file wins.
Recall Phase
Run this phase before writing code.
- Extract task keywords (technology, failure mode, domain terms).
- Determine whether lesson storage exists:
- If
docs/lessons/does not exist, treat this as first-run state and skip recall. - If
docs/lessons/exists but_index.mddoes not, rebuild_index.mdfrom existing card frontmatter before recall.
- If
- Determine working scope from the task context:
projectfor cross-cutting or repo-wide concernsmodulefor package/directory-level concernsfeaturefor a specific flow or component
- Read
docs/lessons/_index.md. - Rank candidates with this order:
tag match -> scope match -> confidence (desc) -> date (desc).- Legacy fallback: if a card has no
confidence, derive it fromsource(user-correction=0.7,bug-fix=0.5,retrospective=0.3). If both are missing, use0.3.
- Legacy fallback: if a card has no
- Load 1-3 primary cards.
- Expand with
relatedlinks from primary cards, loading up to 2 additional cards. - Enforce the hard cap: primary plus related cards must not exceed 5 total.
- Apply loaded lessons as constraints for current work and mention loaded card IDs briefly.
If no cards match, continue work without lesson constraints.
Recall Warnings
Treat these as non-blocking and continue:
docs/lessons/is missing on first run._index.mdhad to be rebuilt.- A loaded card is missing
confidenceand needs legacy fallback. - A
relatedtarget is missing.
Capture Phase
Run this phase when any of these conditions are met:
- The user corrected your approach
- The user asks for capture
- A bug fix revealed a reusable pattern
- A task completion surfaced a non-obvious reusable insight
Step 1 — Decide whether to capture
Ask: "Will this lesson save time next time a similar task appears?"
Only capture non-obvious insights. Prioritize lessons such as:
- Hidden relationships between files/modules.
- Execution paths that differ from what the code structure suggests.
- Non-obvious config, env vars, flags, or ordering constraints.
- Breakthroughs where error messages were misleading.
- Tool/API quirks and required workarounds.
- Build/test commands or operational prerequisites that are not documented nearby.
- Files that must be changed together for correctness.
Capture if:
- ✅ Reusable pattern or decision rule
- ✅ Costly mistake with a clear prevention strategy
- ✅ Key parameter, config, or precondition that is easy to forget
- ✅ Multi-attempt solution (include failure reasons + success conditions)
Skip if:
- ❌ One-off Q&A with no reusable process
- ❌ Pure concept explanation without actionable guidance
- ❌ Non-reproducible, context-specific conclusion
- ❌ Obvious framework/language behavior with no hidden constraint
- ❌ Session-specific notes that are unlikely to repeat
Step 2 — Write the Zettel card
Generate a semantic kebab-case ID that describes the lesson (e.g., api-timeout-retry-pattern).
Before writing a new card, check for a semantically similar existing card and make the decision explicit:
decision=createwhen no similar card exists.decision=updatewhen a similar card already covers the same lesson.
Surface this decision in the capture output. Do not jump straight to card content without stating whether you are creating or updating.
Assign a scope before writing the card:
projectfor repo-wide constraintsmodulefor package/directory-level constraintsfeaturefor one flow/component
Assign initial confidence by source:
user-correction:0.7bug-fix:0.5retrospective:0.3
If the user confirms a lesson was useful, increase confidence by +0.1
(max 0.9).
Write the card to docs/lessons/<id>.md using the template in
references/card-template.md.
Before creating a new card, check semantic duplication:
- If an existing card is semantically similar, update that card instead of creating a duplicate.
- Preserve existing card ID when updating.
Minimal correction-capture example:
Lessons capture report: decision=update, updated=1 (
db-migration-run-order), skipped=0
Card fields:
| Field | Purpose |
|---|---|
id |
Semantic kebab-case slug, also the filename |
date |
ISO date when the lesson was captured |
scope |
project / module / feature applicability |
tags |
3–6 lowercase tags for recall matching |
source |
user-correction / bug-fix / retrospective |
confidence |
Numeric confidence score used for recall ranking |
related |
0–2 high-relevance lesson references using [[card-id]] |
| Title | One-line summary of the lesson |
| Context | What was happening when the mistake occurred |
| Mistake | What went wrong |
| Lesson | Extracted rule or best practice |
| When to Apply | Future situations where this lesson matters |
Task-end behavior:
- If capture criteria are met, auto-capture without asking for permission first.
- After capture, report what was created or updated.
- For normal user-facing output, prefer a short capture summary.
- Do not reproduce the full card body unless the user asks to inspect it.
Step 3 — Update the index
Upsert one row in docs/lessons/_index.md per card ID.
If _index.md does not exist, create it with this structure:
# Lessons Index
> Auto-generated by lessons-learned skill. Do not edit manually.
| Card | Scope | Tags | Date |
|---|---|---|---|
Then keep rows sorted by Date descending (newest first).
Step 4 — Confirm with user
Tell the user what was captured using a compact report, e.g.:
Lessons capture report: created=1 (
api-timeout-retry-pattern), updated=1 (db-migration-run-order), skipped=1 (obvious behavior)
If capture occurred, include the create-vs-update decision in the report when it
helps explain the outcome, for example decision=create or decision=update.
Keep this confirmation short. Prefer the decision, the affected card ID, and a one-line rule summary. Avoid dumping the full markdown card or index contents in normal output.
Linking Rule
Use related links for high-value cards only.
Create related links when at least 2 of 4 conditions are true:
- Reusable across different tasks.
- Represents a high-cost mistake (multiple attempts or significant time loss).
- Depends on critical parameter/config/decision details.
- Connects naturally to at least two existing lesson cards.
Linking constraints:
- Add 0–2 related links per card, only when relevance is strong.
- Use deterministic ranking from
references/linking-heuristics.md. - Do not add weak or speculative links.
Broken related targets are non-blocking:
- If a related target is missing, ignore it and warn.
- Continue recall/capture flow.
Anti-patterns
- Capturing obvious language/framework behavior with no hidden constraint.
- Capturing session-only notes (temporary logs, ad-hoc local paths, one-off environment noise).
- Writing verbose narrative cards without actionable prevention rules.
- Creating near-duplicate cards when an update to an existing card is enough.
- Recording broad advice without a concrete trigger in
When to Apply.
Validation
Apply these checks during capture or update. These are blocking failures unless explicitly listed as warnings elsewhere.
- Card filename equals
idslug. dateformat is ISOYYYY-MM-DD.scopeis one ofproject,module,feature.tagscount is 3–6.sourceis valid enum.confidenceis numeric and in range0.0-0.9.relatedcount is 0–2 and every target resolves to an existing card.- Index row exists and matches card metadata, including
scope. _index.mdrows are ordered byDatedescending (newest first).- Recall limits are respected: 1–3 primary + up to 2 related, max 5 total.
Integration Guide
When used with other skills in the same session, follow the Trigger Contract as the single source of truth:
- task start -> recall
- user correction during work -> capture
- task end -> capture evaluation
This is a non-replaceable step — lesson capture cannot be substituted by todo trackers, progress files, or other skill artifacts.