Skip to content

find-learnings

find-learnings

findwriteshands-on

Use this when: you just solved something worth remembering

Problem it solves — Solved problems evaporate unless captured. This surfaces the non-obvious lessons from the work just done — footguns, root causes, emerging conventions — and saves only the ones you confirm to durable memory, so the next task starts ahead instead of rediscovering them.

Used in workflows: QA PR & Learn · Health Check · Debug & Learn

Find learnings

The compounding step: turn solved problems into recallable memory so they pay forward. Like find-untracked-work does for backlog gaps, this skill surfaces candidates and lets you choose — it never writes unprompted. Saving a learning is your call, the same way filing an issue is.

Store and format live in docs/learnings/README.md. Read it before proposing. When a learning (or a rule it graduates into) names a harness concept, use the term as docs/agents/glossary.md pins it — and if the work surfaced a genuinely new, recurring harness term, propose adding it to the glossary and the flat index in CLAUDE.md — so memory and rules stay consistent with the skills.

What counts as a learning

A candidate is worth surfacing when the work taught something the code alone won't tell the next reader:

  • a bug whose root cause was non-obvious (an off-by-one, an inverted mapping, a race, a framework footgun);
  • a fix that looks wrong but is right (a workaround and the constraint it dodges);
  • a convention that emerged from a decision made under pressure;
  • a dead end worth signposting so it isn't re-explored.
  • a harness drift / inconsistency noticed in passing — a skill missing a section, a gate that wasn't enforced, an eval that should exist — captured so find-harness-improvements can promote it into a harness:check check or a qa-harness lens.

Don't surface routine CRUD, cosmetic changes, or anything a good name/test already carries. A thin store that's all signal beats a fat one nobody trusts — it's fine to find nothing and say so.

Workflow — surface, then save

  1. Scan the work for candidates against the bar above. Be selective.
  2. Vet each candidate before surfacing it — so you only present vetted recommendations. Run each through vet's two questions: Worth — is it already covered by a rule / skill / existing learning (→ skip), and is the claim actually true? (verify a factual claim before it can enter durable memory — a wrong "learning" is worse than none). Placement — does it belong in docs/learnings/, or graduate straight into a rule / skill body? (a standing process rule isn't a tactical learning). Judge inline for clear cases; for a consequential or uncertain candidate, blind-vet it (subagent_type: Explore, idea + standards only) so author-bias doesn't wave it through. Drop the already-covered / false ones; tag each survivor with its verdict (save-as-learning / graduate-to-rule / verify-first).
  3. Present the survivors for decision — save nothing yet. Per candidate, give just enough to judge:
    • a one-line title (the trap, not the feature);
    • the root cause in a sentence;
    • the guard that would stop a regression (a Pest test, a .claude/rules/ line, a casts()/DTO change);
    • its vet verdict (save-as-learning / graduate-to-rule).
  4. Ask which to save with AskUserQuestion (multi-select). Never save unprompted. If nothing clears the bar, say so and stop.
  5. Write only the confirmed ones to docs/learnings/YYYY-MM-DD-slug.md in the README format (symptom → root cause → fix with file:line/SHA → guard) — or, for a graduate-to-rule verdict, edit the rule / skill body directly instead.
  6. Pin the guard. Every saved learning names what now stops the regression. If no guard exists yet, add one or flag that it's needed — a learning with no guard is a story, not a lesson.
  7. Update the index in docs/learnings/README.md — prepend a one-line link under "Index" (newest first), replacing the "No learnings captured yet." placeholder on first use.
  8. Report the paths saved and the one-line lesson each carries.

Keep entries short. If it's longer than the diff that fixed it, you're narrating the hunt — cut to root cause + guard.

--refresh (graduate / archive)

Sweep the store for entries that have outgrown it — and here too, propose, then confirm before moving anything:

  1. Graduate — an entry that has recurred, or now describes a standing rule, belongs in .claude/rules/<area>.md or CLAUDE.md. Surface the candidates; on your confirm, promote the line there (or confirm it's already there), then verify the graduated_to target actually contains it before flipping status — don't trust an asserted "it's already in X" (same truth-check as the capture path). Set the entry's status: graduated and graduated_to: path. Graduation is the point of the store, not deletion.
  2. Archive — if the code an entry describes is gone, propose status: archived (don't delete — it's provenance).
  3. Sync the index — every docs/learnings/*.md has a line under the README "Index" and every index line points at a file that exists; every graduated_to: target file exists and actually contains the promoted line. Fix drift as part of the same confirm.
  4. Report what moved.

Relationship to the rules system

Learnings are the on-ramp to .claude/rules/. A rule is a learning that earned its place by recurring. This skill feeds that pipeline; it does not replace the always-on code-quality.md or the path-scoped rules.

How this gets triggered

A PostToolUse hook nudges after a PR is raised (gh pr create / create_pull_request). You can also invoke it directly any time a fix taught you something. The hook only reminds — and even then this skill surfaces candidates for you to pick, never auto-saving.