Spec Retrieval (Prior Work)
When you scaffold a new spec, Monday Morning automatically surfaces the most-similar prior completed specs as “Prior Work” — a structured artifact of accumulated knowledge, surfaced at the moment you most need it. The completed work in your .mm/ folder compounds: each shipped spec becomes a retrievable artifact that primes future related specs.
You don’t have to do anything to make it happen. The system is part of the spec lifecycle.
What you see
Section titled “What you see”In the desktop app, a spec’s entity detail view includes a Prior Work section below the spec body:
- Match cards — title, similarity score, tags, and a short goal preview
- Navigation — open any match to jump to that prior spec’s detail view
- Refresh — regenerate matches against the current
spec.md(idempotent — re-runs produce a byte-stable file) - Stale hint — a soft “may be stale — refresh?” hint appears when files in the spec folder have been modified since the matches were generated
In agent sessions, the spec-writer and tasks-list-creator agents read prior-work.md automatically when authoring a new spec, so prior patterns and verification lessons inform the spec itself, not just the human reading it after.
What’s automatic
Section titled “What’s automatic”Three events drive the system end-to-end without any manual step:
| Event | What happens |
|---|---|
Spec completed (mm_complete finishes the last task) | The spec is added to .mm/index/specs.json with extracted goal, requirements, verify-spec convergence, and severity data. |
Spec scaffolded (/mm:spec) | Retrieval runs against the new spec’s content; the top matches are written to prior-work.md in the new spec folder. |
| Spec authored (spec-writer / tasks-list-creator subagents) | The agents read prior-work.md so the spec they draft inherits patterns and avoids prior pitfalls. |
You don’t run anything. The system maintains the index, generates the artifact, and consumes it. Your job is simply to read what’s surfaced.
When you might take action
Section titled “When you might take action”Most of the time, the artifact is fresh and accurate. Two cases call for a manual step:
- The stale hint appears — files in the spec folder were modified after
prior-work.mdwas generated. Use Refresh to regenerate. - You created a spec outside
/mm:spec— directmm_create(entity: "spec") calls don’t include the mid-authoring refresh that the slash command does, so the matches were computed against a stub. Refresh in the panel, or run/mm:retrieve-prior-work {spec-folder}from a session.
Both produce a byte-stable file when content hasn’t changed; safe to re-run.
How matches are computed
Section titled “How matches are computed”Retrieval runs locally, with two scorers:
Semantic scoring (preferred). When the local embedding model and the ledger index are available, candidates are scored by embedding cosine similarity against the new spec’s content. Matches must clear semantic_similarity_threshold (default 0.35 — cosine scores don’t live on the same scale as keyword overlap, so it’s a separate knob).
Keyword fallback. When the semantic index is unavailable, scoring falls back to Jaccard token overlap on goal (weight 0.4), requirements (0.4), and title (0.2) — tokens lowercased, split on non-alphanumeric, stopword-filtered — gated by similarity_threshold (default 0.15).
Boost layer (applied on top of either scorer):
- +0.10 per shared tag, capped at +0.20
- +0.05 when requirement counts are within ±2 of each other
- +0.05 when the candidate spec’s verify-spec convergence is
converged
The final score is clamped to 1.0, and the top N matches above the threshold are returned, sorted descending. Either way the pipeline never blocks spec creation: a missing model or index degrades to the fallback, never an error.
The ledger index and mm_index
Section titled “The ledger index and mm_index”The embedding side is powered by the ledger index at .mm/index/ledger/ — chunked embeddings of your specs, issues, notes, and standards. It’s the same index that gives mm_search its hybrid mode: lexical + semantic fusion, so semantically-similar-but-differently-worded entries surface even when the literal query string doesn’t match (and it degrades to lexical-only results when the index or model is unavailable).
The mm_index tool maintains it, with two modes:
rebuild— a full re-embed of the ledger, self-healing any chunk an incremental update missed.health— reports embedding-model availability, index staleness (indexed chunks whose source sections have changed), orphaned entries (indexed but the source file no longer exists), and any legacy.mm/index/amem*directories left behind by the removed semantic-memory feature. Legacy directories are only ever reported — never deleted automatically; clean them up on request.
Both modes are fail-soft: an unavailable embedding model reports as unavailable rather than throwing.
Configuration
Section titled “Configuration”Three knobs in .mm/config.json:
{ "spec_retrieval": { "similarity_threshold": 0.15, "semantic_similarity_threshold": 0.35, "top_n": 3 }}| Key | Default | What it does |
|---|---|---|
similarity_threshold | 0.15 | Minimum score to surface under the keyword (Jaccard) fallback scorer. |
semantic_similarity_threshold | 0.35 | Minimum cosine score to surface under the semantic (embedding) scorer. |
top_n | 3 | Maximum matches per prior-work.md. |
Missing keys, missing file, or malformed JSON all degrade silently to defaults — retrieval will not block spec creation under any circumstance.
Files and locations
Section titled “Files and locations”| Path | Purpose |
|---|---|
.mm/index/specs.json | The completed-spec index. Auto-generated. Don’t edit manually. |
.mm/index/ledger/ | The ledger embedding index behind semantic retrieval and hybrid search. Maintained by mm_index. |
.mm/specs/{slug}/prior-work.md | The surfaced matches for a given spec. Auto-generated. Read selectively — these are pointers, not requirements. |
.mm/config.json (spec_retrieval block) | Threshold and top-N tuning. |
Empty states
Section titled “Empty states”When prior-work.md exists but has zero matches, the panel renders an explanatory state keyed off the reason:
no_completed_specs— The workspace has no fully-completed specs yet. As specs ship, they’ll be indexed and surface here.below_threshold— Specs exist in the index but none scored above your threshold. Lower it to widen the net.index_missing— The index could not be built (parse errors, etc.). Run/mm:retrieve-prior-workto diagnose.
The empty state is intentional — its presence vs. absence is unambiguous. An empty prior-work.md means “we ran retrieval and found nothing” rather than “retrieval didn’t run.”
Why structured fields, not LLM distillation?
Section titled “Why structured fields, not LLM distillation?”A common alternative is to have an LLM read each completed spec and write abstract “skills” or “lessons learned.” Monday Morning explicitly does not do this. Reasons:
- The spec is the distillation. Goal, requirements, verify-spec convergence — these are already structured artifacts. Re-distilling them with an LLM adds cost without adding signal.
- Skills decay. Abstract lessons drift as the underlying code changes; the originating spec doesn’t.
- Retrievable provenance. Every match links back to the spec that produced it, so you can verify the context, not just trust a summary.
The keyword approach surfaces overlapping vocabulary; the ledger embedding index adds overlapping concepts on top. The structured-field foundation stays intentionally simple and explainable, and the semantic layer degrades back to it whenever the model isn’t available.
Related
Section titled “Related”- Your First Workflow — covers the
/mm:speclifecycle end-to-end - The .mm/ Data Model — where
prior-work.mdand the indexes live - MCP Tools Reference —
mm_retrieve_prior_work,mm_index, andmm_search