Copilot + Mulch self-learning hook pack
This folder is a minimal hook pack you can copy into an existing repository to add a Mulch-backed GitHub Copilot self-learning loop without modifying Mulch itself.
- primes Mulch context at
sessionStart - refreshes published context when the user prompt changes
- publishes session-scoped context artifacts and resolves them through stable metadata
- captures prompt and tool breadcrumbs during the session
- records a tactical session summary into the
copilotMulch domain atsessionEnd - promotes strong
copilotinbox records into real domains with a dedicated helper
.github/hooks/mulch-copilot.json- Copilot hook configuration.github/hooks/mulch-self-learning.mjs- hook runner and manual prime refresher.github/hooks/mulch-eval.mjs- asynchronous evaluator forcopilotinbox records.github/hooks/mulch-promote.mjs- promotion helper forcopilotinbox records.github/hooks/mulch-close-loop.mjs- background runner that evaluates then promotes in sequenceAGENTS.md- tells Copilot to resolve the latest session-scoped Mulch context artifact
Before copying these files into a target repository, the user needs to:
- Install Mulch in the target repo, for example with
npm install -D @os-eco/mulch-cli. - Initialize Mulch with
./node_modules/.bin/ml init. - Add a dedicated tactical inbox domain with
./node_modules/.bin/ml add copilot. - Add any real project domains you want to learn into, such as
api,frontend, ortesting. - Ensure Node is available because the hook runner is executed with
node. - Commit
.github/hooks/mulch-copilot.jsonto the default branch so Copilot loads it.
After bootstrap, copy the five files in .github/hooks/ plus AGENTS.md into the target repository.
- The hook runner looks for Mulch at
./node_modules/.bin/mlfirst, then falls back tomlormulchonPATH. - The
copilotdomain is used as an inbox for hook-generated session summaries. - The stable handoff point is
.github/hooks/.runtime/prime.meta.json, which points to the latest session-scoped published artifact viaartifactPath. - The assembled published artifact includes a per-session Mulch export plus
ml ready,ml status, and prompt-matchedml searchoutput. - The hook keeps raw
ml prime --exportoutput separate from the published artifact so same-worktree sessions do not compete for one sharedprime.txtpath. mulch-promote.mjscan review or apply promotions formulch-evalrecords that scored aspromote.mulch-close-loop.mjsis launched automatically in the background fromsessionEnd, so evaluation and promotion stay out of the synchronous hook path while still running in order.
sessionStartruns prompt-awareml prime --exclude-domain copilot --format plain --export .github/hooks/.runtime/prime-raw-<session>.txt, plusml ready --limit 5andml status, then publishes an assembled context artifact to.github/hooks/.runtime/prime-<session>.txtsessionStartwrites.github/hooks/.runtime/prime.meta.json, which points to the latest published artifactuserPromptSubmittedlogs the prompt, refreshes metadata and the session-scoped published artifact, and adds prompt-matchedml searchoutput when availablepostToolUseanderrorOccurredlog tool results and failuressessionEndrunsml learn --jsonand writes a session summary withml record copilot --stdinsessionEndbackground-spawnsmulch-close-loop.mjs, which runsmulch-eval.mjs --record-outcomesand thenmulch-promote.mjs --applyin sequencemulch-promote.mjscan also be run manually to preview or apply promotions for promote-worthy inbox records
By default, the hook pack launches the evaluator in the background at sessionEnd. You can also run it manually or from CI:
node .github/hooks/mulch-eval.mjs
node .github/hooks/mulch-eval.mjs --json
node .github/hooks/mulch-eval.mjs --record-outcomesThe evaluator uses a deterministic rubric:
- groundedness: changed files and evidence
- reusability: domain mapping and breadth of touched files
- specificity: prompt/context richness
- validation signal: tool execution and existing session outcome data
Recommendations:
promote- strong candidate to mine into real Mulch domainsreview- useful, but still tactical or incompletediscard- low-signal session summary
When --record-outcomes is used, the script appends a mulch-eval outcome to each unevaluated record using stock ml outcome.
Use the promotion helper to close the loop on strong session summaries:
node .github/hooks/mulch-promote.mjs --json
node .github/hooks/mulch-promote.mjs --apply
node .github/hooks/mulch-promote.mjs --record <copilot-record-id> --applyBy default, the script filters to copilot records where the latest mulch-eval outcome recommends promote and where at least one suggested domain is available. With --apply, it writes reference records into each pending target domain and appends mulch-promote outcomes back to the source copilot record.
The copilot domain remains a tactical inbox for session summaries. It is excluded from priming so operational breadcrumbs do not get fed back into model context.
Hooks can prepare context, but they cannot directly inject it into Copilot's live prompt.
This pack closes the loop by combining:
sessionStartanduserPromptSubmittedhooks: refresh.github/hooks/.runtime/prime.meta.jsonand the latest session-scoped context artifactAGENTS.md: instructs Copilot to resolve that metadata file and read the current artifactsessionEndhook: records new tactical learnings and launches ordered async evaluation and promotionmulch-promote.mjs: lets humans or automation promote strongcopilotinbox records into real domains
That gives you a practical cycle of:
Mulch domains -> session-scoped context artifact -> prime.meta.json -> Copilot reads via AGENTS.md -> work happens -> hooks capture/evaluate/promote -> durable learnings land in real Mulch domains