Summary
Triggered weekly or when substrate quality degrades. Reads all four substrate indexes
and entry bodies eagerly. Runs four passes in order: promote (anti-patterns → reviewers),
merge (overlapping ADRs → consolidated entry), prune (stale solutions and superseded ADRs
→ stale markers), retag (scope globs for moved files → versioned entries). Every write
goes through substrate-write; no entry file is ever deleted or modified in place.
Procedure
Step 1 — Load all substrate indexes and entry bodies
Read the following indexes in full:
.substrate/anti-pattern/INDEX.md.substrate/adr/INDEX.md.substrate/solution/INDEX.md.substrate/reviewers/INDEX.md
For each entry listed in every index, open and read the full entry file (frontmatter
- body). This skill is eager — all four types are fully loaded before any pass runs.
Set the promotion threshold N from the promotion_threshold input if provided;
otherwise default to 5.
Set the observation window to the last 8 workflows (harvest history) and last 8 weeks (git log for retag).
Record:
anti_pattern_entries: list of all anti-pattern entries (id, scope, rule, match counts from harvest history)adr_entries: list of all ADR entries (id, status, decision body, retrieval count)solution_entries: list of all solution entries (id, scope, tags, retrieval count)reviewer_entries: list of all reviewer entries (id, predicate, category)file_moves: list of (old_path_glob, new_path_glob) pairs from git history (Step 5)
After loading, proceed through Passes A–D in order. Do not interleave passes.
Step 2 — Pass A: Promote recurring anti-patterns to reviewer entries
For each anti-pattern entry in anti_pattern_entries:
Check threshold: look up the entry's match count in the harvest history. If the count is less than N, skip this entry.
Check scope: if the entry's
scopearray is["**"](universal scope — applies everywhere regardless of path), skip promotion. A universal-scope anti-pattern already applies on every workflow; promoting it would produce analways: truereviewer that fires on every diff, which is low-signal and crowds out targeted reviewers.Check for existing reviewer: scan
reviewer_entriesfor any reviewer whose predicate paths overlap the anti-pattern's scope. If a reviewer already covers this scope for this category, skip promotion to avoid duplicates.Derive the reviewer entry:
id:<anti-pattern-id>-reviewer(kebab-case, truncated to keep under 50 chars if needed)type:reviewerdescription: derived from the anti-pattern'sdescriptionfield — rephrase as "Checks that [anti-pattern rule negation] in [scope short description]."created: today's date (YYYY-MM-DD)predicate.any.paths: the anti-pattern'sscopearray (verbatim)category:code-quality(default for promoted reviewers; use a more specific category if the anti-pattern's description clearly implies one, e.g.securityfor SQL injection)priority_floor:P2(default for promoted reviewers)- Body
## Summary: ≤5 lines — state what the reviewer checks, which scope triggers it, and that it was promoted from harvest history with the match count. - Body
## Review checklist: derive 2–4 checklist items from the anti-pattern's## Ruleand## Positive examplesections.
Write via substrate-write: call
substrate-writewith the derived entry. Ifsubstrate-writerejects the entry, log the rejection reason and skip this anti-pattern (do not retry with a modified entry — fix the derivation logic instead).Do not modify or delete the source anti-pattern entry.
After all anti-patterns are evaluated, collect the list of promoted reviewer IDs.
Step 3 — Pass B: Merge overlapping ADRs
For each pair of ADR entries in adr_entries whose status is accepted:
Detect overlap: compare the
## Decisionsections of both entries. Entries overlap if they record the same architectural decision — same outcome, same affected components, same constraints — even if worded differently. Do not merge ADRs that share a theme but make distinct decisions (e.g., "use Redis" vs. "use Redis Cluster" are sequential, not duplicate).Overlap indicators:
- Both decisions name the same component/layer (e.g., repository, session store).
- Both decisions prohibit or require the same thing (e.g., no direct ORM imports).
- One decision body explicitly references or restates the other.
Non-overlap indicators:
- The decisions differ in outcome (one accepts A, the other accepts B).
- The decisions affect different components.
- The newer decision explicitly supersedes or extends the older one in a meaningful way (new constraint or changed implementation).
Merge: if overlap is detected, construct a consolidated ADR entry:
id: derive a new id that captures the merged intent in kebab-case.type:adrstatus:accepteddescription: a single-sentence summary of the canonical decision, ≤200 chars.created: today's date.supersedes: array containing both overlapping entry ids.- Body: synthesize a single well-formed ADR body with:
## Summary(≤5 lines): state what the canonical decision is and which entries it merges.## Context: combine the context from both entries; credit the original dates.## Decision: the authoritative decision statement (union of both decisions).## Alternatives considered: union of alternatives from both entries.## Consequences: union of consequences from both entries.
Write via substrate-write: call
substrate-writewithsupersedesset to both overlapping ids. Thesubstrate-writeskill will update the ADR index to mark both original rows assuperseded.Do not modify or delete the original ADR files. The
substrate-writestep handles the index row update.Skip non-overlapping ADRs: if no overlap is detected with any other entry, leave the entry unchanged.
After all pairs are evaluated, mark the merged entries in adr_entries so the prune
pass (Step 4) can identify them as now-superseded.
Step 4 — Pass C: Prune stale entries
Stale solution detection:
For each solution entry in solution_entries:
- Look up the retrieval count from the harvest history observation window.
- If the retrieval count is 0 (zero retrievals in the window), the entry is stale.
- Write a stale-marker entry via
substrate-write:id:<solution-id>-staletype:solutiondescription:[STALE]+ original description +— no retrievals in last N workflows. May be outdated.created: today's datesupersedes:[<original-id>]scope: same as originaltags: original tags +[stale]- Body
## Summary(≤5 lines): state that this is a stale marker, give the original id and zero-retrieval count, note the original file is preserved. - Body
## Original description: copy the original entry's description line.
- Do not delete the original solution file.
Stale ADR detection:
For each ADR entry in adr_entries that is now superseded (either from the initial
index load or as a result of Pass B merges in Step 3):
The substrate-write supersession step already updated the ADR index row to superseded.
No additional write is required by the prune pass for ADRs — the index row update from
Pass B is sufficient to make staleness visible at the index layer.
If an ADR's status was superseded in the original index load (i.e., it was superseded
before this consolidate run), verify it has a superseded status in the index row. If
the row was missed (status still shows accepted), write a corrective note but do not
attempt an in-place index edit — flag this for manual review.
Step 5 — Pass D: Retag scope globs for moved files
Detect file moves:
From the git_log input (git history for the observation window), extract pairs of
(old_path, new_path) where files or directories were moved or renamed. Normalize each
pair into glob form:
- If a directory was renamed (
src/handlers/→src/http/), produce (src/handlers/**,src/http/**). - If a single file was moved, produce exact path pairs.
Scan entries for stale globs:
For each anti-pattern entry in anti_pattern_entries and each solution entry in
solution_entries:
- Check every glob in the entry's
scopearray against the detected file-move pairs. - A scope glob is stale if it matches an old path and the new path is distinct and no longer covered by the same glob.
- Broad glob exception: if a scope glob is broad enough to cover both the old
and new paths (e.g.,
src/**covers bothsrc/handlers/**andsrc/http/**), the glob is still valid — do not retag.
Write retagged entries:
For each entry with at least one stale scope glob:
Construct a new entry:
id:<original-id>-v2(append-v3,-v4etc. if-v2already exists)- All frontmatter fields carried over from the original, except:
id: the new versioned idcreated: today's datescope: the updated scope array (old glob replaced by new glob; other globs unchanged)supersedes:[<original-id>]
- Body: copy the original body, then append a one-line note at the end of the
## Summaryblock:Scope updated: <old-glob> renamed to <new-glob>.
Write via
substrate-write.Do not modify or delete the original entry file.
Do not retag reviewers in this pass unless the reviewer was created in Pass A of this same consolidate run (the promoted reviewer's predicate paths came directly from the anti-pattern's scope, so if the anti-pattern is retagged, the promoted reviewer's predicate should reflect the new paths). In that case, write a corrected reviewer entry superseding the one created in Pass A, using the updated scope globs.
Step 6 — Report
After all four passes complete, output a consolidate report:
Consolidate complete — <date>
Pass A (Promote): <N> reviewer(s) promoted
+ <reviewer-id> ← <anti-pattern-id> (match count: <M>)
Pass B (Merge): <N> ADR(s) merged
+ <merged-adr-id> ← [<adr-id-1>, <adr-id-2>]
Pass C (Prune): <N> stale marker(s) written
+ <stale-id> ← <original-id> (0 retrievals)
Pass D (Retag): <N> retagged entry/entries written
+ <new-id> ← <original-id> (src/handlers/** → src/http/**)
Nothing deleted. All writes append-only via substrate-write.
If a pass produced zero changes, report 0 for that pass.
If any substrate-write call was rejected during the run, list each rejection at the
end of the report under Skipped (substrate-write rejected):.
Constraints
- Never delete any substrate entry file. Prune and merge operations mark entries stale or superseded — they do not remove files from disk.
- Never modify any existing substrate entry file in place. All changes are expressed
as new entries via
substrate-writewithsupersedeslinks. - All writes go through
substrate-write. Direct file creation bypassing the skill is forbidden; frontmatter validation and index updates aresubstrate-write's responsibility. - Passes run in order A → B → C → D. Pass B uses the output of Pass A (newly promoted reviewers are visible before the prune pass). Pass C uses the output of Pass B (merged ADRs are marked superseded before the prune pass checks ADR status). Pass D uses the output of Passes A and B (retag updates reviewer predicates if they were promoted in Pass A).
- Universal-scope anti-patterns (
["**"]) are not promoted in Pass A. They produce always-firing reviewers that crowd out targeted ones. - Non-overlapping ADRs are not merged in Pass B. Sequential decisions (A supersedes B) are not the same as duplicate decisions (A and B say the same thing). Do not merge decisions that differ in outcome, component, or constraint.
- Stale threshold is zero retrievals in the observation window (default 8 workflows). An entry retrieved even once is not pruned.
- Broad scope globs are not retagged in Pass D unless the glob specifically names the old path in a way that no longer matches the new location.
- Do not mention any specific harness in entry bodies or the report. Skills compose via shared artifact paths and substrate, not direct calls.
- One consolidate run at a time. If a previous consolidate run left partial state (e.g., a stale-marker entry exists for an entry that is also a retag candidate), process the retag against the current state and do not double-prune.