prior-art
A structured scan answering two questions about any repo: is anyone ahead of us (the novelty verdict) and what are others doing that's worth porting in (the steal list). Both payoffs are first-class — a scan that only answers one is half done.
1. Distill the pillars (from the repo, not the user)
Read README / project instructions / core docs. Name 2-4 pillars — the properties that make the project distinctive. Rules:
- The unit of novelty is the combination, not any single pillar. Every pillar probably exists somewhere; the question is whether anyone holds all of them.
- Pillars are mechanisms, not adjectives ("human-verdict log driving promote/retire over named concepts", not "quality feedback").
- State the pillars to the user before sweeping (one line each). A wrong pillar wastes the whole sweep; a 10-second correction here is the cheapest fix in the pipeline.
2. Sweep — in a stranger's vocabulary
The searches must use the words outsiders would use for the mechanism and the problem — never the repo's own coined terms (nobody else uses your project's internal names; they say "mental model library", "agent memory", "context engineering"). Write 3-5 vocabulary translations per pillar first.
Run three lenses:
- sota-scan — what's the closest cluster of projects, per pillar.
- disconfirm — actively hunt the single repo/paper that refutes novelty. Budget real effort here; the sweep's credibility is this lens.
- cross-domain — adjacent fields with the same structural shape. This lens feeds the steal list even when it can't refute novelty.
Avenues: GitHub search, arXiv, general web. If a deep-research skill or tool is available in the session, delegate the sweep to it (pass the pillars and lenses in the question) rather than hand-rolling search fan-out — verified claims beat raw hits. Otherwise run WebSearch/WebFetch directly.
3. Probe — code, not READMEs
READMEs over-claim; search agents repeatedly over-attribute capabilities from marketing text. For the top 2-3 candidates (always including the disconfirm lens's strongest), read the actual file tree: does the claimed mechanism exist in code? Quote the file paths that prove or refute each pillar.
4. The pillar table
One table: candidates (rows, with stars/date) × pillars (columns), ✅/❌/partial, with your own repo as the last row. Every ✅ needs a receipt (file path, verbatim quote, or verified feature) — a table cell without evidence is a guess.
5. Verdict + steal list + watch list
- Verdict — novelty holds / refuted / sharpened. If it holds, name the moat as the specific combination and write the one-sentence positioning claim that survives scrutiny (the pattern: "X exists; Y exists; nobody closes the loop between them").
- Steal list — concrete mechanisms from the candidates worth porting in, each with the source repo and where it would land in this codebase. This is half the value of the scan; never skip it.
- Watch list — repos one change away from closing the gap, with the specific change that would do it, and a re-run trigger ("re-run if X ships graph retrieval, or in ~6 months").
6. Caveats — say what the scan can't know
Every novelty verdict is an absence claim over a finite survey. Name the blind spots explicitly: closed-source products, non-GitHub / non-English ecosystems, and how fast the space moves. No "we are definitively novel" without the finite-survey qualifier.
7. File it — with the machine block
Write the report to docs/prior-art-YYYY-MM-DD.md in the target repo (sections: pillars, table,
verdict, steal list, watch list, caveats).
Always end the report with a fenced json block — the machine-readable contract that lets a
future agent (or a scheduled poller) act on the scan without re-reading prose:
{
"scanned": "YYYY-MM-DD",
"repo": "<target repo>",
"pillars": [{"id": "a", "name": "...", "vocab": ["outsider term 1", "..."]}],
"verdict": {"status": "holds|refuted|sharpened", "moat": "...", "positioning": "one sentence"},
"candidates": [{"repo": "owner/name", "stars": 0, "pillars": {"a": true, "b": false}, "probed": true}],
"steal": [{"mechanism": "...", "source": "owner/name", "lands_in": "path or subsystem", "effort": "S|M|L"}],
"watch": [{"repo": "owner/name", "trigger": "what change closes the gap", "check": "cheap way to test it (release notes, path exists, grep)", "closes": ["a"]}],
"rerun_after": "YYYY-MM-DD",
"blind_spots": ["closed-source products", "..."]
}
watch[].check and rerun_after are the automation hooks: a cheap cron can poll the checks and
fire a full re-scan only when a trigger hits or the date passes — never re-scan on a bare interval.
End the chat message with the verdict in one line, the top steal, and the re-run trigger.