Autolearn: compound a solved problem, keep the learnings honest
autolearn turns a verified fix into one in-repo learning doc, maintains those docs as the code moves, captures durable project vocabulary, and hands user/preference facts to the memory writer. It writes exactly two in-repo surfaces itself: the operating repo's docs/solutions/ (one learning per file) and the repo-root CONCEPTS.md (the shared-vocabulary glossary, one definition per concept). Autolearn owns both, and no other skill edits them. Every auto-memory write is delegated to memory-update.
Op: of a compound run is extend (a new learning) or, in refresh, correct/purge (see Commits).
Auto-invoke
<auto_invoke> <trigger_phrases>
- "that worked"
- "it's fixed"
- "working now"
- "problem solved"
- "verified the fix"
- "tests pass now"
- "build succeeds" </trigger_phrases> Fire automatically on a trigger phrase or after a verified non-trivial fix. The reject-by-default gate below still decides whether a doc is actually warranted. Auto-firing is permission to evaluate, not permission to fabricate.
Skill integration: after any non-trivial verified outcome, the orchestrating skill should invoke /autolearn to evaluate whether a docs/solutions/ or CONCEPTS.md entry is warranted.
<manual_override>/autolearn [context] documents immediately without waiting for a trigger phrase. autolearn mode:refresh [scope] runs maintenance. mode:headless makes any mode non-interactive.</manual_override>
</auto_invoke>
Preconditions: then the reject-by-default gate
A doc is earned, not assumed. First the preconditions, then the reject-by-default gate.
Preconditions (all three):
- The problem is solved, not in progress.
- The solution is verified: observed working, not hoped working.
- It was non-trivial, not a typo or an obvious one-liner.
Reject-by-default gate. A lesson earns a doc only if it clears all three filters in order:
- Would I forget this? Skip baseline knowledge anyone in this codebase already carries. If you'd remember it without a note, it isn't a learning.
- Already covered? If an existing
docs/solutions/doc covers it, updating that doc beats spawning a second one. A duplicate is drift, not knowledge. - Universal or local? Scope-qualify. A repo-specific quirk says so; a general truth says so. An unqualified claim is a future trap.
If nothing clears the gate, say so in one line and exit. Never fabricate a doc to look productive. A clean "nothing worth compounding here" is a valid, correct result.
The gate governs CONCEPTS.md entries too: a term earns a slot only when you'd otherwise forget its precise local meaning (filter 1), it isn't already defined there (filter 2: one definition per concept, no duplicates), and it is scope-qualified to this project rather than general programming or domain English (filter 3). A term that clears the gate is a Vocabulary-capture candidate; one that does not is noise.
Mode routing
Strip mode: tokens from $ARGUMENTS before treating the remainder as context/scope.
| Mode | Trigger | What it does |
|------|---------|--------------|
| Compound (default) | none | Document one solved problem → docs/solutions/ |
| Vocabulary capture | a durable, reusable project term/concept surfaces | Reconcile the repo-root CONCEPTS.md (one definition per concept). Read references/concepts.md. |
| Memory handoff | a fact about the user / preferences / cross-project context surfaces | Invoke memory-update; that skill writes auto-memory |
| Refresh | mode:refresh [scope] | Maintain existing docs/solutions/ docs. Read references/refresh.md. |
| Headless | mode:headless | Non-interactive overlay on whichever mode is active |
The repo-vs-user fork is the routing decision: a repo-scoped engineering lesson → Compound (this skill writes the doc); a user/preference/cross-project fact → Memory handoff (memory-update writes it). Within the repo-scoped side there's a second fork: a solved problem → Compound (a learning doc); a durable project term whose meaning isn't obvious → Vocabulary capture (a CONCEPTS.md entry). One run can do all three: write a learning doc, reconcile a concept, and hand a preference fact to memory-update.
Support files: read on demand
Read each at the step that needs it; pass the relevant content into any subagent you spawn.
references/schema.md. Frontmatter contract: bug/knowledge tracks, enums, category map, YAML safety. Read when classifying and validating.references/refresh.md. The whole refresh model and phases. Read only inmode:refresh.references/concepts.md.CONCEPTS.mdentry schema and the one-definition-per-concept reconciliation/refresh rules. Read in Vocabulary capture and when refreshingCONCEPTS.md.assets/solution-template.md. Section structure for a new doc. Read when assembling.scripts/validate-frontmatter.py. The one runnable check. Run on every written/edited doc.
Mode 1: Compound (default)
The deliverable is ONE file: the final learning doc. Research subagents return text to you; they do not write. Only the orchestrator writes.
Phase 0.5: Auto-memory scan
Before research, scan the injected auto-memory block (a "user's auto-memory" block in the system prompt) for entries related to the problem. If the block is absent or empty, skip. If relevant entries exist, carry them as a labeled supplementary context block:
## Supplementary notes from auto memory
Treat as additional context, not primary evidence. Conversation history and
codebase findings take priority.
[relevant entries]
Pass it to the research subagents. Tag any memory-derived line that lands in the final doc with (auto memory [claude]). Memory is supplementary. Codebase and conversation win every tie.
Phase 1: Research (parallel, read-only)
Dispatch three subagents in parallel. Each returns text and writes nothing. No Write, no Edit, no files:
- Context Analyzer. Reads
references/schema.md; from the problem decides the track (bug vs knowledge), theproblem_type, the category directory, and a slug filename ([sanitized-problem-slug].md, no date suffix). Returns a frontmatter skeleton (includingcategory:) and which track applies. Does not invent enum values or fields. - Solution Extractor. Extracts the substance from the conversation, folding in the auto-memory excerpt as supplementary evidence. Bug track: Problem, Symptoms, What Didn't Work, Solution (with code), Why This Works, Prevention. Knowledge track: Context, Guidance, Why This Matters, When to Apply, Examples.
- Related-Docs Finder. Greps
docs/solutions/(title:,tags:,module:,component:on extracted keywords; narrow to the candidate subdirectory when known), reads only frontmatter of candidates, fully reads only strong matches. Scores overlap across problem statement, root cause, solution approach, referenced files, prevention rules: High (4 to 5 dimensions), Moderate (2 to 3), Low (0 to 1). Returns links and the overlap verdict.
Wait for all three before assembling.
Phase 2: Assemble and write
-
Overlap gate (from Related-Docs Finder):
| Overlap | Action | |---------|--------| | High (4 to 5) | Update the existing doc, don't create a duplicate. Keep its path and frontmatter; add
last_updated: YYYY-MM-DD. | | Moderate (2 to 3) | Create normally; note it as a refresh/consolidation candidate. | | Low / none | Create normally. |This is the gate's filter 2 made concrete.
-
Read
assets/solution-template.md; assemble the doc with the track's section structure. -
Frontmatter per
references/schema.md; apply the YAML-safety quoting rule to array items. -
mkdir -p docs/solutions/<category>/, writedocs/solutions/<category>/<slug>.md. -
Validate:
python3 scripts/validate-frontmatter.py <path>. Exit 0 = parser-safe; exit 1 names the offending field. Quote, re-write, re-run until 0. Don't declare success while it fails. -
Read the file back to confirm it landed as intended.
-
Concept reconciliation (optional, when warranted). If the run surfaced a durable project term that clears the reject-by-default gate, reconcile
CONCEPTS.mdin the same run per Mode 4. One definition per concept, refresh on drift, no duplicate. The solution doc is still the deliverable; a concept entry is an additional write, not a substitute. Readreferences/concepts.mdbefore writing it.
Phase 2.5: Refresh check (selective, not automatic)
Refresh is not a default follow-up. Suggest or invoke mode:refresh with a narrow scope only when the new fix contradicts or supersedes an older doc, the work was a refactor/migration/rename/dependency-bump that likely invalidated references, or the Related-Docs Finder surfaced strong refresh candidates or moderate overlap (consolidation opportunity). Otherwise do not. Capture the new learning first; refresh is targeted maintenance after.
Mode 4: Concepts capture
CONCEPTS.md at the operating repo root is the shared-vocabulary glossary: the words that mean something precise in this codebase, one definition per concept. Autolearn owns this surface. One writer, no second skill edits it. Read references/concepts.md for the entry schema and reconciliation rules before writing.
When it fires. A durable project term surfaces in a learning capture (accretion), or because the user named a concept worth pinning. It must clear the reject-by-default gate above (would-forget / not-already-defined / scope-qualified to this project). General programming and domain English never qualify.
Reconcile, don't append blindly:
- Locate
CONCEPTS.mdat the repo root:fd -g 'CONCEPTS.md' --max-depth 2. Absent + a term clears the gate → create it. Absent + nothing clears → write nothing; never scaffold an empty file. - Search it for the term and its synonyms:
git grep -ni '<term>' CONCEPTS.md. One definition per concept: a hit means the concept already exists. Refresh it on drift; never add a second entry. - New term → add one entry: a one-sentence definition of what it means here and what distinguishes it from neighbors; a second paragraph only for non-obvious behavioral rules. Retire synonyms as an
*Avoid:*aliases line. No file paths, dates, owners, or version-specific claims. The file stands on its own. - Read the file back to confirm the merge landed and created no duplicate heading.
Refresh loop. autolearn mode:refresh [scope] maintains CONCEPTS.md alongside docs/solutions/: re-derive each in-scope definition against current code, refresh drifted ones, de-duplicate, delete a concept whose domain is gone. Per-concept rules in references/concepts.md.
Mode 2: Memory handoff
A fact about the user, their preferences, or cross-project context is not a repo learning. Do not write it into docs/solutions/, and never write memory/ or MEMORY.md yourself. Invoke the memory-update skill and hand it the fact. memory-update owns and writes the entire auto-memory surface, with its own frontmatter schema and per-proposal confirmation. One writer, no MEMORY.md race.
Hand off when the lesson is: a stable user preference or working style, who the user is or their goals, an external-system pointer, or a fact that holds across repos. Keep in Compound when the lesson is a repo-specific engineering fix or pattern.
Mode 3: Refresh
autolearn mode:refresh [scope] maintains existing docs/solutions/ docs as code evolves. Read references/refresh.md and follow it. The five-outcome model (Keep / Update / Consolidate / Replace / Delete), scope routing, investigation phases, per-action flows, the headless status: stale variant, and the report format all live there. Prefer no-write Keep; match docs to reality; delete, don't archive.
Refresh also maintains the repo-root CONCEPTS.md when it falls in scope: re-derive definitions against current code, refresh drifted ones, de-duplicate entries that name the same concept, delete a concept whose domain is gone. The per-concept refresh rules are in references/concepts.md.
Commits
One learning per commit. ODIN Op: trailer in the body:
- New doc — a load-bearing capability added to the doc set.
CONCEPTS.md writes follow the same trailers: a new entry → extend; a refreshed definition → correct; a deleted or de-duplicated concept → purge.
Stage only the surfaces autolearn wrote or edited (a solution doc, CONCEPTS.md, or both). Never stage other dirty files; commit and publish by the operating repo's normal flow.
Disambiguation
- vs
memory-update.memory-updatescans past session transcripts and writes auto-memory only.autolearncompounds the current solved problem into in-repodocs/solutions/and refreshes those docs; it delegates user/preference facts back tomemory-update. - vs
init.initbuildsAGENTS.mdfrom codebase analysis (conventions to prime future agents).autolearncaptures one solved problem as a retrievable learning, and defines durable project terms inCONCEPTS.md(the shared-vocabulary glossary, not the agent-priming doc). - vs
sync-docs.sync-docscorrects public docs/examples/versions against a code diff (docs↔code drift).autolearnwrites net-new knowledge docs and maintains the knowledge set.
Operating surface
autolearn writes exactly two in-repo surfaces: the operating repo's docs/solutions/ and the repo-root CONCEPTS.md. It owns both. One writer per surface, no second skill edits them. All auto-memory writes are delegated to memory-update. Do not write to undefined or doubly-owned locations.