Dedupe Against Corpus
Table of Contents
Related skills: Called by ingest-inbox-item step 4. Queried ad-hoc by search-corpus. Backlinks into matched seeds (the one place this skill writes outside new seeds).
Three tiers of match
- Tier 1 — Exact fingerprint: sha256 of body matches an existing seed's fingerprint. →
SKIPPED. - Tier 2 — Title similarity: normalized Jaccard on title tokens ≥ 0.7. →
LINKcandidate. - Tier 3 — Content similarity: for seeds sharing ≥2 topic tags, first-200-word Jaccard ≥ 0.5. →
LINKcandidate.
Tier 2 and 3 candidates are unioned (up to 3 total LINK targets).
Workflow
Dedupe one candidate seed:
- [ ] Step 1: Grep all corpus/**/*.md frontmatter for fingerprint match
- [ ] Step 2: If exact match, return SKIPPED
- [ ] Step 3: Normalized title Jaccard against all existing seeds
- [ ] Step 4: For seeds sharing ≥2 topic tags, first-200-word Jaccard
- [ ] Step 5: Union tier-2 and tier-3 candidates, cap at 3
- [ ] Step 6: If any LINK candidates, return LINK with related_seeds list; else CREATE
- [ ] Step 7: For LINK, Edit matched seeds' related_seeds to add this candidate's id
Step 7: Backlink safely
The matched seeds get their related_seeds field extended (append, never replace) ONLY IF:
manual_edits: falseon the matched seed, OR- The edit is strictly additive (appending an id to a list is always safe).
Do not touch any other field on the matched seed.
Worked example
Candidate: new seed about "dropout as ensemble" with topics [regularization, ensembling, dropout], first 200 words describing thinned-network averaging.
Existing corpus:
2026-03-11-l2-as-gaussian-prior— topics[regularization, bayesian]. Title Jaccard = 0.1 (different). Shared tags: 1. Skip content-similarity check.2026-02-08-bagging-in-deep-nets— topics[regularization, ensembling]. Shared tags: 2. First-200-word Jaccard: 0.51 → LINK candidate.
Output: {action: LINK, related_seeds: [2026-02-08-bagging-in-deep-nets]}.
Side effect: corpus/seeds/2026-02-08-bagging-in-deep-nets.md gets its related_seeds appended with the new seed's id.
Guardrails
- Never merge, rewrite, or delete. Only link. Merging is the writer's call.
- Never alter an existing seed's body. Only its
links.related_seedsfield. - Never cross-link into
corpus/dead/— dead ideas stay dead. - Fingerprint is over the body only (not frontmatter). Retagging must not change fingerprint.
- The 3-link cap prevents unbounded link chains.
- Never propose LINK across
status: publishedtostatus: seed— published posts are immutable except for typo fixes.
Quick reference
- Returns one of:
SKIPPED,LINK,CREATE. - LINK can carry up to 3 related-seed ids.
- Side effect: backlinks into matched seeds (additive).