| name | promote |
| tier | essential |
| description | Graduate a hardened learning into a project-context doc - operator-approved merge of a proven standard into the right doc, with a derived_from lineage breadcrumb (one-fact-one-source). |
| disable-model-invocation | false |
| allowed-tools | ["Read","Write","Edit","Glob","Bash","mcp__igris-brain__igris_memory_recall","mcp__igris-brain__igris_memory_search","mcp__igris-brain__igris_memory_get","mcp__igris-brain__igris_memory_dashboard","mcp__igris-brain__igris_edge_create","mcp__igris-brain__igris_memory_mark_promoted"] |
| triggers | ["PROMOTE","promote","graduate standard","promote learning"] |
PROMOTE โ MemoryโDoc Promotion Skill
/promote โ the memoryโdoc promotion pass (FR-196 one-fact-one-source).
A learning earns promotion once it has proven itself โ it is recalled often,
high-confidence, and a stable standard rather than a fresh observation. Promotion
moves that standard out of the recall stream and into the project's authored
context doc, which then owns it. The learning row is never deleted: it
becomes a lineage stub (promoted_to_doc points readers at the doc), and recall
stops double-surfacing the raw content. The operator approves every promotion
โ the model proposes, never silently writes a doc.
Degradation โ promote CANNOT run with the brain absent. Unlike capture,
this pass requires the brain: it queries candidates, records a
derived_from lineage edge, and marks the source learning promoted โ none of
which has a local fallback. If the igris-brain MCP is unavailable, warn
and exit cleanly without touching any doc:
Note: /promote needs the brain MCP (to query candidates, record lineage, and mark the learning promoted) and it is unavailable โ exiting without changes. Re-run when the brain is reachable.
Never half-merge: do not write a standard into a doc if you cannot
immediately record the lineage edge AND mark the learning promoted โ a merge
without the marking re-introduces the exact double-surfacing this pass exists
to prevent (the doc owns it AND recall keeps surfacing the raw learning).
Determine the current project slug + absolute path up front (promotion targets
that project's ~/.igris/projects/{slug}/context/ docs).
P1 โ Surface hardened candidates
Find learnings that have earned a doc home. Use igris_memory_recall (or
igris_memory_search for an FTS pass) scoped to the project, and prefer rows
exhibiting the "this lesson has proven itself" signals:
- high
confidence (battle-tested, near 1.0),
- high
access_count (recalled frequently โ the recall composite already
surfaces these higher),
category IN (decision, pattern) โ the kinds that become standards
(a one-off discovery or a mistake usually is not a doc-worthy standard),
scope = 'global' โ already cross-project-proven (the brain's internal
scope-promotion lifted it because it recurred across projects); a strong
doc-promotion candidate.
igris_memory_dashboard (project = slug, summary_only: true) gives a quick
sizing of the memory footprint (by_review_status, by_category) to frame how
many candidates exist.
Two hard filters on the candidate set:
review_status = 'approved' only โ never promote a pending_review row
(a perception-channel candidate a human has not yet vetted). The default
recall/search filter already hides pending rows, so a candidate surfaced via
igris_memory_recall/_search is already approved โ but state it and do not
reach around the filter.
- Exclude rows already promoted โ
igris_memory_get a candidate and skip
it if its recall output shows a Promoted: โ <doc> pointer (it already lives
in a doc; re-promoting would duplicate it).
Present the shortlist to the operator with, for each: title, category,
confidence, access_count, scope, and the proposed target doc (next step).
P2 โ Propose a target doc per candidate
Map each candidate to the right authored doc under
~/.igris/projects/{slug}/context/ by reading the doc-type catalog โ the
self-describing source of truth for which doc-type owns which kind of standard
(do NOT hardcode the mapping):
- Glob
~/.igris/core/context-doc-types/*.md and Read each definition.
Each declares its target (the on-disk doc name), its applies_when, and a
kind_affinity (the candidate kinds it owns โ e.g. decision, pattern โ
coding_guidelines.md; structural โ architecture_map.md; UI, design โ
design_system.md; API โ api_pattern.md; test โ test_standards.md).
- Match the candidate's
category/topic to the best-fit definition's
kind_affinity, and propose that definition's target as the doc.
Read whatever target docs already exist (Glob the context dir). If the matched
doc-type is absent on disk, offer the operator to create it โ hand off to
/ground <type>, which authors a new, well-headed doc from that type's
catalog skeleton โ or to skip this candidate. Do not force a standard into a
mismatched doc.
P3 โ Operator approves each promotion
For each candidate, present the proposal and get an explicit decision โ
approve / skip / change-target. Never promote silently. A "no" leaves the
learning exactly as-is (still in memory, still surfaced by recall).
P4 โ Merge the standard into the doc (read โ dedup โ merge โ write)
For each approved candidate:
- Read the target doc fully (
Read).
- Dedup against existing content โ if the doc already documents this
standard (a heading or paragraph covering the same rule), do not append a
second copy. Offer to refine the existing section (fold in any new detail
from the learning) instead, or skip the merge if the doc already says it
well. Appending a standard the doc already carries is the exact duplication
this pass must avoid.
- Merge the learning's standard under a stable heading โ either an
existing topical section it belongs under, or a clear new
## <heading> (a
## Promoted Standards section is a reasonable home when there is no
topical fit). Write the standard (the rule + the why + when-to-apply),
distilled from the learning's content โ not a verbatim dump of the row.
- Write the doc back (
Edit for a surgical section insert, or Write for
a doc you are creating). Never overwrite the whole file with unrelated
content โ a context doc is operator-authored; merge into it, do not clobber
it. Note the heading anchor you merged under (you need it for P5/P6).
P5 โ Record the lineage breadcrumb (a derived_from edge)
Lineage is a graph edge, not a copy of the content (FR-196: lineage is "a
different kind, not a duplicate"). After the merge, record where the standard
came from:
igris_edge_create({
from_type: "learning",
from_id: "<learning id>",
to_type: "concept",
to_id: "<slug>:context/<doc>#<anchor>", # e.g. "igris-ai:context/coding_guidelines.md#error-handling"
edge_type: "derived_from",
provenance: "user", # operator-approved, not observed/inferred
metadata: { "promoted_at": "<ISO timestamp>", "target_doc": "<doc>", "target_anchor": "<anchor>", "approved_by": "operator" }
})
(to_type: "concept" is the free-standing-node type for "a doc section" โ it is
not itself a DB entity. The edge is idempotent on its tuple, so a re-run is
safe.)
P6 โ Mark the source learning promoted
Set the recall pointer so the doc becomes the single source going forward:
igris_memory_mark_promoted({
id: <learning id>,
doc_path: "<slug>:context/<doc>", # same path used in the edge's to_id (without the #anchor)
doc_anchor: "<anchor>" # the heading slug you merged under; a leading '#' is stripped
})
After this, igris_memory_recall surfaces Promoted: โ <doc>#<anchor> for that
learning instead of its raw content โ the standard now lives in exactly one
place (the doc), with a recall breadcrumb pointing there.
P7 โ Promote summary
Report what was promoted:
## Promote complete โ <slug>
- Candidates reviewed: <N>
- Promoted: <P>
- <title> [<category>, conf <x>] โ <doc>#<anchor>
- ...
- Skipped: <k> (already-promoted / operator-declined / dedup โ doc already covered it)
- Lineage edges recorded: <P> (derived_from: learning โ concept)
Constraints
- GUIDED, never automatic โ the operator approves every promotion. The
model proposes; it never silently writes a standard into a doc.
- DEDUP before writing โ read the target doc and dedup the standard against
existing content before merging (offer refine-existing/skip). This is the
load-bearing guard against duplicate-knowledge drift.
- Curate, don't dump โ promote moves only hardened standards (approved,
high-confidence/recall, decision|pattern).
- Graceful degradation โ brain absent โ warn and exit without touching
any doc (no local fallback; never half-merge a standard you cannot mark +
lineage).
- One-fact-one-source โ after a promotion the doc owns the standard; mark
the learning promoted so recall points to the doc. Never merge a standard
into a doc without then recording lineage AND marking the learning promoted.
- NEVER clobber an authored doc โ read-then-merge under a stable heading;
never overwrite a whole context doc.
- NEVER modify source code โ promote merges standards into context docs; it
does not edit the project's application code.