feat(skill-tree): learned procedural memory the maestro grows and retrieves (#458)#462
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rieves (#458) Wakes forge-loop's dormant procedural-memory substrate into a living "skill tree": the loop distils a reusable "how to do X in this repo" card from each critic-clean merge, retrieves the relevant ones into the next worker's brief, and curates them over time — so workers stop re-deriving repo conventions cold. Tree structure - area-path tags (`area:<path>`) give each card its address; `area_ancestors` walks most-specific-leaf -> ancestor nodes (memory/models.py). - leaves = concrete procedure cards; internal nodes = generalised patterns (`area-node` tag) distilled once enough sibling leaves accrue. Lifecycle - Harvest: a one-shot "librarian" (skill_librarian.py, LLM behind an injected seam) distils diff+acceptance -> SkillCard; harvest_skills_from_merge records it with the merged commit SHA as provenance. Wired best-effort into the post-merge hook (runner/tick.py), gated by `misc.skill_tree_harvest`. - Retrieve+inject: area-weighted deterministic ranking (memory/skills.py) feeds render_skill_section into make_brief + make_repair_brief; emits skill_injected for measurement. (Semantic/Lumen retrieval is a documented fast-follow behind the same seam.) - Curate: expire_stale_skills retires cards whose proof SHA aged out of history; promote_internal_nodes generalises sibling leaves. Events: skill_harvested / injected / promoted / expired. Extends the existing SqliteMemoryStore + record_procedural_skill (now carries area tags + evidence refs + confidence) — no parallel store. Fully TDD'd with adversarial tests (remove harvest/inject/expiry and a test goes red); retrieval excludes non-matches and expired cards. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the skill tree epic (#458): a living, evolving memory of how to do X in this repo that the loop writes from its own critic-clean merges and reads back into the next worker's brief — so workers stop re-deriving repo conventions cold.
It wakes forge-loop's dormant procedural-memory substrate (the
SqliteMemoryStore+record_procedural_skill) rather than adding a parallel system.The tree
Each card carries an
area:<path>tag — its address in the tree.area_ancestorswalks most-specific-leaf → ancestor node.area-node) = generalised patterns distilled once enough sibling leaves accrue.Lifecycle
skill_librarian.py, LLM behind an injected seam) distils diff + acceptance →SkillCard;harvest_skills_from_mergerecords it with SHA provenance. Wired best-effort into the post-merge hook (runner/tick.py), gated bymisc.skill_tree_harvest(FORGE_SKILL_TREE_HARVEST, on by default).memory/skills.py) feedsrender_skill_sectionintomake_brief+make_repair_brief; emitsskill_injectedfor measurement. Retrieval is cheap + local so it's always on.expire_stale_skillsretires cards whose proof SHA aged out of history;promote_internal_nodesgeneralises sibling leaves. Events:skill_harvested / injected / promoted / expired.Design traps engineered around
Tests (TDD, adversarial)
New:
test_skill_area_tags,test_skill_librarian,test_skill_harvest,test_skill_events,test_skill_retrieval,test_skill_curation,test_worker_brief_skills— each behavior has a test that goes red if the harvest/inject/expiry is removed. Full suite green except pre-existingtest_runner_retry.pycases that require a GitHub token (they fail identically on cleantrunkin a token-less shell). Lint + format clean.Out of scope (fast-follow)
Semantic/Lumen retrieval (seam only); a UI surface; cross-repo skill sharing.
Spec:
docs/design/81-skill-tree.md.🤖 Generated with Claude Code