Mulch Expertise Management System
repository·main·Indexed 43 days ago
https://github.com/jayminwest/mulchA structured expertise management system for AI agent workflows that allows agents to record, query, and prime themselves with accumulated project knowledge. Mulch stores expertise as typed JSONL records in git-trackable files, enabling learnings to compound across sessions and teammates. It includes a CLI (@os-eco/mulch-cli) for managing domains, recording insights (such as conventions, failures, and decisions), and generating AI-optimized context via the `ml prime` command.
What's inside Mulch
- Mulch is a structured expertise management system designed for AI agents. It allows you to store, query, and inject project learnings across different sessions using git-tracked JSONL files. This ensures that knowledge gained during one interaction is preserved and available for future tasks.
Use field aliases to handle legacy data
mainThe
aliasesfield in acustom_typesdefinition allows you to map canonical field names to legacy names. When Mulch reads a record containing a legacy field name, it automatically rewrites it to the canonical name. This enables seamless schema evolution without requiring manual migration scripts.custom_types: incident: extends: failure required: [severity, pager_link] aliases: pager_link: [pagerduty_url, page_url] # Accepts legacy names on readThe Mulch Soft-Archive Contract
mainMulch uses a soft-archive mechanism to manage record decay. Archived records are moved to
.mulch/archive/<domain>.jsonland include a# ARCHIVEDbanner, astatus: "archived"field, and anarchived_attimestamp.To reverse an archival, use the following command:
ml restore <id>Understand the record decay and auto-archive model
mainRecords in Mulch have a
freshness_scorethat determines their relevance. As a record ages or receives challenges, its score drops. When the score falls below a threshold, the record is flagged for archiving.Decay Logic: Score is calculated based on:
(confirmations_in_window × type_weight) + recency_bonus − (challenges × challenge_weight) − staleness_penalty.Decay Rates by Type:
failure,decision,reference: Decay slowly (high importance).convention,pattern: Decay normally.note: Decays fastest (intended for short-lived scratch).guide: Barely decays (long-form documentation).
Cleanup Operations:
ml prime --maybe-prune: Performs a cadence-based cleanup (using a.mulch/.last-prunestamp file) to archive stale records.ml doctor: Flags records that are candidates for archiving.ml restore: Recovers any records that were auto-archived.- Note on Deletion: Auto-archive is a 'soft-archive'. Hard deletion is only performed if the
--hardflag is explicitly used.
Configuration:
prime.auto_prune: Set toweeklyoroffto control the automatic cleanup cadence.
Understand base record fields in Mulch
mainEvery record in Mulch, regardless of its type, contains a set of standard fields. While many are managed automatically by Mulch (like
id,recorded_at, andstatus), others are provided by the user during theml recordcommand.User-provided fields
type: The registered type (e.g.,convention,decision).classification: The trust tier:foundational,tactical, orobservational. Defaults totactical.tags: A list of searchable strings.relates_to: A list ofmx-idsfor related records.supersedes: A list ofmx-idsthis record replaces (triggers decay onml prune).owner: An opaque string for organizational use.
System-managed fields
id: A stable, human-readable ID stem combined with a date.status: The lifecycle state:draft,active,deprecated, orarchived.evidence: An object containing metadata likecommit,date,issue,file, etc. Git information often auto-populates this.
Understand the Mulch storage architecture
mainMulch stores expertise as typed JSONL records in the
.mulch/directory. This structure ensures that expertise is git-trackable and easily shared across teams.Directory Structure:
.mulch/expertise/<domain>.jsonl: One file per domain containing typed, structured records (one per line)..mulch/mulch.config.yaml: Configuration for domains and governance settings.
Record Model:
- Six Record Types:
convention,pattern,failure,decision,reference,guide. - Three Classification Tiers:
foundational,tactical,observational(these govern shelf life and pruning). - Concurrency: Uses advisory file locks and atomic writes to ensure safe concurrent access from multiple agents.
Configure record ownership and review workflows
mainMulch supports an ownership model to resolve conflicts and manage stale records. Ownership is resolved using the following priority chain:
- An explicit
--owner @handleflag provided during record creation. - A lookup in the project's
CODEOWNERSfile based on the record'sfile_anchors. - A
default_ownerspecified per-domain inmulch.config.yaml. - The Git author of the commit that recorded the information.
You can use
ml reviewto list records owned by your current user that require attention.# List records owned by the current user that need review ml review- An explicit
Multi-Agent Safety and Concurrency
mainMulch is designed for environments where multiple agents might access the expertise store simultaneously. It employs several safety mechanisms:
- Advisory File Locking: Uses
O_CREAT|O_EXCLlock files with a 50ms retry interval and a 5s timeout. Stale locks are detected after 30s. Write commands (record,edit,delete,compact,prune,doctor --fix) all utilize this locking. - Atomic Writes: Uses a temporary file + rename strategy to prevent partial or corrupt JSONL writes.
- Git Integration: Uses a
merge=unionstrategy in.gitattributesto ensure that during git conflicts, all unique lines from both sides are preserved, preventing loss of expertise. - Read-Only Safety: Commands like
prime,query,search,status, andvalidatedo not require locking and can run concurrently without interference.
- Advisory File Locking: Uses
Concurrency and Multi-Agent Safety in Mulch
mainMulch is designed for multi-agent workflows where several agents record expertise concurrently. It ensures data integrity through three primary mechanisms:
- Advisory file locking: Write commands acquire a
.lockfile before modifying JSONL files. It retries every 50ms for up to 5 seconds. Stale locks (>30s) are automatically removed. - Atomic writes: Mutations are written to a temporary file first and then atomically renamed into place to prevent corruption during crashes.
- Git merge strategy:
ml initconfigures.gitattributeswithmerge=union, allowing parallel branches to append-merge JSONL lines without conflicts.
Command Safety Levels
Safety level Commands Notes Fully safe (read-only) prime,query,search,rank,status,validate,learn,readyNo file writes. Safe for any number of agents at any time. Safe (locked writes) record,edit,delete,delete-domain,compact,prune,archive,restore,doctorAcquires per-file locks. Multiple agents can target the same domain; locks serialize access. Serialize (setup ops) init,add,onboard,setupModifies config or external files. Run once during setup, not during parallel agent work. - Advisory file locking: Write commands acquire a
Understand the `.mulch/` directory layout
mainMulch uses a specific directory structure within your repository to manage configuration, records, and recipes. Understanding these paths is critical for manual maintenance and automation.
Path Purpose Written by Read by .mulch/mulch.config.yamlConfiguration you / ml initevery command .mulch/expertise/<domain>.jsonlLive records ml record,ml edit,ml compact,ml restore,ml doctor --fixml prime,ml search,ml query,ml rank,ml status,ml validate,ml learn,ml ready,ml sync.mulch/archive/<domain>.jsonlSoft-archived records ml pruneml search --archived,ml restore.mulch/recipes/<name>.tsTypeScript provider recipe you ml setup,ml setup --list.mulch/recipes/<name>.shShell provider recipe you ml setup,ml setup --list.mulch/hooks/*.shLifecycle hook scripts you ml record,ml prime,ml prune.mulch/README.mdAuto-generated layout doc ml inithumans .gitattributesmerge=unionrulesyou git Mulch Record Schema and Types
mainMulch enforces strict schemas for 6 specific record types using Ajv. When creating records, ensure you include the required fields:
Type Required Fields Optional Fields conventioncontent- patternname,descriptionfilesfailuredescription,resolution- decisiontitle,rationale- referencename,descriptionfilesguidename,description- Classifications & Shelf Life: Records are categorized to manage their lifecycle:
foundational: Permanent records.tactical: Automatically pruned after 14 days.observational: Automatically pruned after 30 days.
Linking & Metadata:
- Evidence: Use
--evidence-commitor--evidence-beadflags when recording. - Linking: Use
relates_toandsupersedes(string arrays) to connect records. - Outcomes: Records can contain an array of outcomes including
status,duration,test_results, andagent.
Attach records to files or directories
mainYou can anchor records to specific locations in your repository to ensure they are surfaced during context-aware operations like
ml prime --files <path>orml prime --context.files[]: A list of repo-relative file paths. Use this when a record is about specific files or lines. It is auto-populated from the current git context if omitted. Note that records usingfiles[]are invalidated if the file is renamed or moved.dir_anchors[]: A list of repo-relative directory paths. Use this when wisdom applies to a whole module or folder. This is more resilient to file churn within the directory. You can set this explicitly using--dir-anchor <path>(repeatable).
Matching Logic: A record matches a file path if the path is explicitly listed in
files[]OR if any entry indir_anchors[]is an ancestor of that path.