Curate Workmap
Implementation note (added later, verified against
src/commands/read/curate.ts): much of the "Preferred direction" / "Next Fix Candidates" work below has already shipped.curateSearchResultsnow selects viaselectCuratedStashHits(score-first ranking throughannotateCurateHit/compareCurateHits/passesCurateScoreFloor, not "take the first hit per type"),collapseCurateFamilies/preferBroadRootRepresentative/getCurateFamilyimplement the asset-family root/child collapsing this document recommends,shouldRunCurateFallbacktriggers fallback on a weak result set (not only on zero hits, reversing the "Fallback Search Behavior" section below), andappendCurateSupportRef/mergeCurateSupportRefsattach graph-derived support refs (the "Graph Leverage" recommendation). TheorderCuratedTypesfunction this document's "Execution Path" section names no longer exists — regex-based type reordering was replaced by the scoring pipeline above. The "Current Behavior" / "Current Curate Contract" sections below were accurate at the time they were written but are now describing the PRE-fix state in several places; re-verify against the functions above before trusting any specific "current behavior" claim in this document. Not fully re-audited line by line — this note flags the drift rather than rewriting the analysis.
When To Read This
Read this before changing akm curate ranking, fallback, follow-up generation, or agent-facing output.
This page is the shortest path to understanding:
- how
akm curatecurrently works - which tests pin that behavior
- where the current implementation diverges from intended product behavior
- what fix direction has the strongest support from recent review
Debate Outcome
Recent multi-agent review converged on the same conclusion:
curateshould be relevance-first, not diversity-first- search ranking should remain the backbone of the shortlist
- type diversity should be a soft preference for later slots, not a hard override
- fallback search should run when the initial result set is weak or noisy, not only when it is empty
followUpshould become more action-aware over time, but ranking/fallback correctness comes first
Recommended fix order:
- Make curate selection score-first and diversity-second.
- Relax fallback suppression so one weak phrase hit does not block token fallback.
- Revisit follow-up generation after ranking quality improves.
Additional debate outcome:
- simple type-aware reranking is useful only as a thin post-search correction layer
- root-vs-derived asset families should usually be collapsed to one representative in the top-level shortlist
- graph data is better suited for attached support refs or navigation hints than for primary reranking in the first iteration
Current Curate Contract
- CLI entry lives in
src/commands/read/search-cli.ts. - Public entry point is
akmCurate()insrc/commands/read/curate.ts. - Default curated limit is
4. - Default search source is
stash. - Curate fetches more search hits than it returns:
limit * 4, minimum12. --type <type>bypasses diversification and returns top hits of that type.- Default multi-type curate currently keeps one best hit per type, then reorders types using regex heuristics.
- Registry hits only fill leftover slots and are capped at
2. - Bundle items are enriched via
akmShowUnified()best-effort. - Bundle
followUpis alwaysakm show <ref>today. - Curate logs both a summary event and per-item retrieval rows for bundle refs.
Execution Path
Read these first:
src/commands/read/search-cli.tssrc/commands/read/curate.tssrc/output/shapes/curate.tssrc/output/text/helpers.tssrc/commands/read/search.tssrc/commands/read/show.ts
Key functions in src/commands/read/curate.ts (current names; orderCuratedTypes()
no longer exists — see the implementation note above):
akmCurate()searchForCuration()deriveCurateFallbackQueries()mergeCurateSearchResponses()curateSearchResults()selectCuratedStashHits()/annotateCurateHit()/compareCurateHits()/passesCurateScoreFloor()collapseCurateFamilies()/preferBroadRootRepresentative()/getCurateFamily()shouldRunCurateFallback()appendCurateSupportRef()/mergeCurateSupportRefs()enrichCuratedStashHit()
Ranking And Selection Rules
Current behavior:
- Search returns scored, ordered hits.
- Curate then discards most of that ordering by taking the first hit per type.
- Those per-type winners are reordered using query regex boosts such as
deploy,review,guide,agent, andmemory. - This can promote obviously lower-score items above much stronger hits.
Why this is a problem:
- search already has strong ranking tests and should remain the primary relevance signal
- current curate can surface irrelevant filler to satisfy type variety
- users experience curate as a flagship shortlist, so wrong top results damage trust more than low variety does
Preferred direction:
- preserve top-ranked overall hits first
- allow diversity only when alternatives are close in score and plausibly relevant
- keep explicit
--typebehavior unchanged
Small type-aware corrections that are considered in-bounds:
- prefer runnable
script/ concretecommandover similarly scoredmemoryfor execution-heavy queries - prefer
workflow/skillover adjacent explanation docs for multi-step task queries - include
agentmainly for explicit delegation / persona / prompt-building queries - keep
memoryfor recall/context queries, not as generic filler
Corrections that are currently considered too risky:
- hard one-per-type quotas
- large hand-authored type matrices
- LLM reranking
- blanket demotion of
memoryoragentas types
Asset Families
Curate should think in terms of asset families, not just isolated types.
Practical examples in this repo:
skills/docker-homelabknowledge/skills/docker-homelab/references/compose
Desired behavior:
- broad query like
docker homelab-> prefer the root asset - narrow query like
docker compose reference-> prefer the child reference page - if both are useful, attach the weaker sibling as support instead of spending two top-level slots by default
This should start as an explicit structural heuristic, not semantic lineage inference.
Fallback Search Behavior
Current behavior:
searchForCuration()only runs fallback token searches when the initial query returns zero hits- if the initial query returns even one weak or irrelevant hit, fallback does not run
- fallback token extraction removes filler words, dedupes tokens, drops tokens shorter than 3 chars, and caps the set at 6
- fallback is also skipped when normalization leaves only one usable token
Why this is a problem:
- one weak phrase hit can block much better token hits
- prompt-style queries like
the dockerdo not get the obvious one-token fallback - meaningful short tokens such as
ai,ci,cd,go,js, ortsare lost today
Preferred direction:
- suppress fallback only when the initial result set is actually strong enough
- allow one-token fallback when that token is clearly the meaningful residue of a prompt-style query
- preserve a narrow allowlist of meaningful short tokens
Enrichment And Follow-Up Fields
Current behavior:
- curate enriches bundle hits by calling
akmShowUnified({ ref }) - if show fails, enrichment silently degrades to raw search-hit data
- bundle follow-up remains
akm show <ref>even for runnable scripts with a concreterun - registry follow-up uses the registry action, usually
akm bundle add ...
Product implication:
- output is inspect-first, not act-first
- this is acceptable for now, but becomes more visible once result quality improves
For agent consumers, the desired optimization order is:
- actionability
- relevance
- low duplication / root-asset preference
- navigability
- type diversity
Output Shape And Formatting
Read:
src/output/shapes/curate.tssrc/output/text/helpers.ts
Important details:
curatehas a dedicated output shaper nowbriefstill keepsfollowUpandreason--shape agenttrims fields down for agent use--shape summaryis rejected oncurate- text output prints fixed
Next steps:guidance that assumesakm show <ref>is the next action
Telemetry And Retrieval Signal
Read:
src/commands/read/curate.tstests/integration/get-retrieval-counts.test.ts
Important detail:
- curate writes per-item
usage_eventsrows for bundle refs so curated items count as retrieval signal
This means ranking changes do not just affect UX. They also affect downstream improvement-loop evidence.
Graph Leverage
Retired (0.9.17-alpha.9): the LLM entity graph this section recommends leveraging is gone —
graph-extraction,graph_meta/graph_files/graph_file_entities/graph_file_relations, andakm show'srelatedblock it fed are all deleted. It was already superseded before that: #935 (0.9.17-alpha.8) added the first-class asset->asset edge table this section says doesn't exist (asset_links, declared links), and curate's support refs (buildCurateSupportRefsinsrc/commands/read/curate.ts) come from declared links now, not graph data — the implementation note at the top of this document already flags that rename. Kept below for historical context only; do not implement against it.
Existing graph signal:
- there is no first-class asset->asset edge table
- asset relatedness is already derivable via shared-entity overlap
listRelatedPathsForFile()insrc/indexer/graph/graph-boost.tsreturns related assets withref,type,sharedEntities, andrelationCountakm showalready exposes a lightweightrelatedblock using that signal
Limits:
- graph coverage depends on graph extraction having run
- graph is thin or absent on cold bundles
- graph quality is uneven and generic entities can over-connect assets
- graph coverage is strongest for
knowledge/memoryand should not be assumed for every asset family
Recommended first graph-aware use in curate:
- do not use graph as a primary reranker yet
- use graph to attach 1-2 support refs or navigation hints to a top-level curated result
- prefer hints like
see also,related, orinspect nextover full graph payloads - keep full graph exploration in
akm show'srelatedblock
What not to do yet:
- no graph-only reranking
- no graph-required curate path
- no full graph dumps in curate output
- no semantic asset-lineage inference from sparse graph data
Tests That Pin Behavior
Start with these:
tests/integration/curate-command.test.tstests/curate-logic.test.tstests/integration/curate-search-for-curation.test.ts
What they cover:
- CLI JSON/text output
- shape/detail behavior
- usage logging
- fallback token derivation
- merge semantics
- type ordering
- diversification logic
- registry filler cap
- blank query rejection
- default limit
- phrase-hit fallback suppression
- current quality baselines showing irrelevant filler
Search-ranking baselines that curate should respect:
tests/integration/db-scoring.test.ts(notests/commands/search.test.tsexists in the current tree; this is the closest surviving search-scoring baseline, not a confirmed direct successor)tests/integration/ranking-regression.test.ts
Known Gaps / Mismatches
docs/guides/discover-and-load.mdcurrently says curate prefers one strong match per type; that wording is too strong if curate becomes relevance-first.docs/reference/cli.mddocuments--type,--limit, and--source, but does not currently explain the effective--detailand--shapebehavior alongside curate.- Some historical AKM refs about curate output shaping are stale because curate now has a dedicated shape implementation.
Safe Edit Checklist
Before editing curate:
- Read the three curate-focused test files.
- Read
src/commands/read/curate.tstop to bottom. - Confirm whether you are changing:
- post-search selection
- fallback triggering
- fallback token extraction
- output contract
- telemetry side effects
- Keep CLI surface and output-shape tests passing unless you intentionally change the public contract.
- If you improve ranking quality, convert current characterization tests that encode bad behavior into regression tests for the new intended behavior.
Useful AKM Queries And Refs
Queries:
akm search "curate rerank"
akm search "curate output shape"
akm search "search discovery curate"
akm search "curate telemetry usage_events"
akm search "curate fallback query"
akm search "curate quality baseline"
Historical context refs:
memories/curate-weak-for-ui-test-audit.derivedknowledge/curate-command-flags-inert
Note: knowledge/curate-command-flags-inert is historical context only. It describes an older output-shaping limitation that is no longer current now that src/output/shapes/curate.ts exists.
Next Fix Candidates
Highest-value next changes:
- Replace hard one-per-type selection with score-first shortlist selection plus optional soft diversity.
- Replace empty-only fallback triggering with weak-result fallback triggering.
- Add simple family-aware root/child collapsing for obvious structural bundles.
- Add regression tests asserting that docker-specific curate queries stop surfacing unrelated
commands/release-managerfiller. - Attach lightweight related-asset hints using existing graph data after ranking quality is fixed.
- Revisit
followUpgeneration after ranking quality is fixed.