Wiki Merge — Collapse an Overlap Cluster
Folds one or more concept slugs into a single canonical entry. Preserves provenance, rewrites incoming wikilinks across atlas / books / concepts / project knowledge folders, deletes the losers, and denylists them so the Saturday
wiki-growcron doesn't re-promote.
When to Use
- Right after
wiki-curateflags an overlap cluster in Section A and you've decided which slug should be canonical. - Manual cleanup when you notice two concepts that should be one.
When NOT to Use
- For trivial renames — keep both files and add an alias.
- For tag normalisation — that's edit-in-place, not a merge.
- When the "overlap" turns out to be a genuine sub-concept relation
— keep both, add a
[[wikilink]]reference between them instead.
What it does
uv run python scripts/wiki-merge.py <winner> <loser1> [<loser2> ...]
uv run python scripts/wiki-merge.py --apply <winner> <loser1> [<loser2> ...]
Steps performed (in order, only on --apply):
- Read winner + every loser concept file under
~/vault/concepts/. - Build merged body — winner's body verbatim, then each loser's
body under a
## From <loser-slug>section. Each section includes a small admonition naming the source project + promotion date for traceability. Sub-headings in loser bodies are demoted by one level (##→###) so they don't compete with the new section delimiter. - Build merged frontmatter — winner's fields preserved; tags
becomes the union of winner ∪ loser tags; a new
fold_in_sources:block records each loser's slug + source_project + promoted_on date;last_merged:is set to today. - Write merged content back to the winner's file.
- Rewrite wikilinks — every
[[<loser-slug>]](with or without alias suffix) across atlas topics, book chapters, other concepts, and project knowledge folders gets rewritten to[[<winner-slug>|<original-display-text>]]. The alias keeps the original display label visible so the change isn't jarring on pages that referenced the loser by name. - Delete loser files from
~/vault/concepts/. - Append to denylist — each loser slug is added to
~/vault/concepts/.denylistwith a comment noting the merge date. This stops the Saturdaywiki-growcron from re-promoting the loser slug if a project knowledge article with that slug still exists.
Dry-run output
Default invocation (no --apply) prints a plan:
Merge plan (dry-run):
Winner: goodharts-law (concepts/goodharts-law.md)
Fold in: goodhart-taxonomy, goodhart-resistance
Merged file size: 11666 chars (winner was 3516)
Wikilink rewrites: 12 file(s)
concepts/strategic-classification.md: 1 occurrence(s)
.../knowledge/goodhart-resistance.md: 1 occurrence(s)
...
Denylist additions: goodhart-taxonomy, goodhart-resistance
Files to delete: concepts/goodhart-taxonomy.md, concepts/goodhart-resistance.md
(dry-run — pass --apply to perform the merge)
Inspect the file count and the rewrite targets. If anything looks wrong (e.g. a loser slug is wildly overrepresented across the corpus suggesting it's actually a distinct concept), abort and reconsider.
Apply
uv run python scripts/wiki-merge.py --apply goodharts-law goodhart-taxonomy goodhart-resistance
Performs all six steps. After the run:
~/vault/concepts/goodharts-law.mdcontains the merged content with fold-in provenance in frontmatter.goodhart-taxonomy.mdandgoodhart-resistance.mdare deleted.- All atlas/books/concepts/project-knowledge files that wikilinked to the loser slugs now wikilink to the winner with the original display label preserved as the alias.
~/vault/concepts/.denylisthas two new lines.
Verify with wiki-curate — the goodhart cluster should be gone
on the next run.
Safety properties
- Dry-run is default. Forgetting
--applypreviews only. - Loser frontmatter preserved in
fold_in_sources:— even though the loser file is deleted, the merged file records source_project + promoted_on for each fold-in, so the provenance is recoverable. - Wikilinks preserve display labels — rewrite produces
[[winner|Original Display]]form, so a topic page that wrote[[Goodhart Taxonomy]]will still render "Goodhart Taxonomy" after the merge, just pointing atgoodharts-lawnow. - Denylist prevents re-promotion — if a project still has
<loser-slug>.mdin its knowledge folder, the next Saturday cron won't re-promote it.
Anti-patterns
- Don't merge a curated concept INTO an auto-generated one. If you must, swap winner/loser. Curated content should be the canonical surface.
- Don't merge concepts from different domains just because slugs
share a token (e.g.
modeltoken inlanguage-modelandlinear-model). Use judgement. - Don't merge without dry-running first. The dry-run output is the only confirmation step.
Cross-References
| Skill | Relationship |
|---|---|
wiki-curate |
Identifies the clusters this skill collapses. |
wiki-grow |
Writer of auto-promoted concepts; denylist entries from wiki-merge prevent it from re-promoting losers. |
compile-knowledge |
Source of project knowledge articles that get promoted to concepts. |