Handle $ARGUMENTS.
Research is a resumable evidence system, not chat browsing:
pick -> question -> registry -> queries -> leads -> read log -> score -> promote
It discovers and synthesizes. It does not run measured packets (benchmark), close an issue corpus row by row (issue-harvester, which also owns issue-by-issue closure after harvest --issues) or patch product code. best-api decides call shapes and the Plan playbook plans adoption. Discovery never escalates into audit or harvest on its own.
Modes
| Arguments | Does |
|---|---|
<feature or question> |
Picks the most valuable open research question for it, then runs a discovery run. |
full <area> |
Ingests and compiles every relevant corpus into docs/research (see Compiled layer below). |
maintain <area> |
Cleans an existing research lane: contradictions, freshness, backlinks, synthesis (see Compiled layer below). |
audit [--target <surface|full>] <repo>... |
Compares external editor architectures with Slate and Plate through a complete source inventory and explicit extraction decisions (editor audit; full, all, exhaustive or multi-repository audits also read its Strict source-to-contract matrix section). |
audit sync [all|<audit-id>|<artifact-path>]... |
Refreshes existing audits against new commits (editor audit). |
harvest <repo> [--since <commit>] [--issues ...] [--apply] [<filter>] |
Harvests portable behavior evidence from an external editor (test harvest). |
harvest plan <slate|plate> <report-or-repo-key>, or harvest <report> --lane <lane> |
Prepares a lane-specific adoption plan from a harvest (test harvest). |
audit and harvest run only when typed or explicitly requested; read the named reference in full before starting. When the token after audit or harvest does not resolve to a repository, owner/repo, audit id or report, treat the arguments as a question.
Pick what to research
- Layer. Pick it from the architecture reference's Pick the layer (
.agents/playbooks/references/architecture.md). - What is known. Read the matching compiled pages under
docs/research/decisions/anddocs/research/sources/, the earlier runs underdocs/research/runs/for prior reads, leads and rejections, and the area's category indocs/solutions/, which holds lessons already diagnosed. - The gap. Choose the one question most likely to change a decision, in this order: an open question or
deferlimit on the decision page; a candidate editor or library not yet compared for this feature; a rejected lead whose reopen condition is now met; evidence whose source changed since it was read. - State the pick, its layer and why it beats the next candidate, then start the run.
Reuse a matching read or lead instead of repeating it. Compare the question, source revision, dependencies and reopening condition first; a new source can support an existing lead without creating another. Unknown historical provenance needs inspection before reuse. A lookup never advances Editor Audit's architecture, test-harvest or issue-refresh cursors.
Discovery run
Record the question and scope, stop rule, artifact path, expected promotion owner, current local evidence gap and explicit exclusions before the first search.
Search the web and GitHub (code search, issues, PRs, discussions, examples, benchmark harnesses, browser test fixtures, commit history). Go beyond the usual three editors when relevant: ProseMirror, Lexical, Tiptap, CodeMirror, Milkdown, Remirror, Monaco, Quill, document editors, browser editor test suites, pagination and virtualization libraries, and TypeScript-heavy runtimes. Use ProseKit for headless extension composition, framework adapters, autocomplete and editor UI prior art, and Meowdown for hybrid Markdown, hidden-syntax caret and selection behavior, touch input, IME and WebKit proof ideas. Separate what those projects own from what they inherit through ProseMirror; Meowdown's desktop WebKit and touch-emulation tests are scoped browser evidence, not iOS proof.
Web and GitHub hits are leads only. Inspect the real source locally before any code-level claim, and never patch from snippets, titles, READMEs or discussions. Extract invariants, test cases, API shape, benchmark technique, architecture pressure and browser proof strategy; write Plate- or Slate-native code, never copied code. External editors are pressure sources, not architecture to clone: translate each lesson into Slate or Plate model, change, selection, DOM, browser and package-owner proof vocabulary before it can change a decision.
Artifacts
Each run lives in docs/research/runs/<date>-<topic>/, for either layer:
README.md # question, scope, stop rule, current verdict
repo-registry.tsv # repo_key, url, host, license, stars_or_signal, last_activity, topic_tags, local_path, status, score, notes
query-ledger.tsv # query_key, surface, query, filters, result_count, sampled_count, new_repo_keys, new_lead_keys, next_query
lead-ledger.tsv # lead_key, repo_key, source_ref, topic, claim, evidence_grade, novelty, applicability, proof_owner, next_action, status
read-log.tsv # source_ref, repo_key, kind, path_or_url, lines_or_id, read_reason, takeaway, lead_key
rejected-ledger.tsv # dedupe_key, repo_key, lead_key, reason, reopen_condition
promoted-ledger.tsv # lead_key, packet_id, owner, test_or_benchmark, verification_command, decision
shards/NNN-<theme>.md # one bounded batch summary each
sources/ # tiny excerpts and metadata, not dumps
New lead, read and promotion rows also record source_revision, source_fingerprint and checked_at, with unknown for unavailable provenance. Historical headers and rows stay as they are. Cloned repositories and bulk corpora live in ../raw; small raw notes a run cites go in docs/research/raw/<date>-<topic>/. A search's output over another project's code stays in ../raw and never enters the repository; the run records its pattern, hit counts and revision in query-ledger.tsv. Never stream bulk results into chat: the ledgers are the state, and a run resumes from query-ledger.tsv and lead-ledger.tsv.
Keys: repo_key is the normalized lowercase host/owner/repo without .git; query_key is a slug of surface plus normalized query; lead_key is <topic>:<normalized invariant>:<proof family>, independent of repo; dedupe_key is the normalized problem signature, such as selection:projected-native-double-highlight:visual-oracle. Before reading a repo deeply, check the registry for its repo_key and the lead ledger for the same lead_key or dedupe_key; add support to an existing lead, read a rejected lead's reopen_condition first, and reuse an existing clone.
Shards
Work in batches of about 10-20 repos, 20-40 issues or PRs, or one theme, whichever is smaller. Each shard gets a summary with its scope, sources sampled, top, rejected and duplicate leads, score changes and next query. Update the ledgers after every shard, and stop a shard early when it yields a concrete proof packet.
Grades and scores
A: local source inspected, plus a runnable test or benchmark idea or exact source behavior.B: an upstream issue, PR or test discussion detailed enough to map an invariant.C: docs, a blog or an example that suggests a pattern needing local validation.D: a search result, README claim or vague discussion; it only chooses the next source.
Score leads, not repos, on impact, novelty, applicability, proofability and risk, each 0-3. Promote when impact + novelty + applicability + proofability - risk >= 7, or when a lower-scoring lead matches a current user-reported bug. The score ranks investigation only; it never justifies machinery or scores a target architecture. Prefer test, oracle and benchmark-method leads over runtime rewrites unless the runtime owner is already proven.
Promotion
A lead becomes exactly one of:
test-packet: a native unit, Playwright or Browser oracle with its verification command;benchmark-packet: a metric or harness repair with a target and before/after command;plan-packet: abest-apiverdict on the call shape, plus a decision-ledger row (.agents/playbooks/references/architecture.md) when runtime or adoption ownership is unclear;docs-packet: an accepted research note or current-state decision;no-code-decision: rejected or quarantined with its reason and reopen condition.
A likely fix becomes a Bug fix, Benchmark, oracle or plan packet with its baseline, proof gate and keep, revert or quarantine decision. A clean negative result keeps its artifact with the rejected leads and the next search angle. A material Stop, Pursue or Defer assessment is written as a review page's verdict through verdict; the compiled decision links that page and the raw run instead of copying rows.
The handoff counts repos searched and read, issues and PRs read, leads kept, merged and rejected, and packets promoted; lists the top promoted leads with lead_key, grade, owner and proof command, and the rejections that prevent repeated work; and names the next shard or none with a reason.
Compiled layer (full and maintain)
Read docs/research/schema.md and the matching pages under docs/research/decisions/ and docs/research/sources/ first; drop to ../raw, broader repository search or external sources only to verify, resolve a conflict or deepen evidence. docs/research is the compiled layer and ../raw the evidence layer; keep raw evidence, source summaries, decisions and open questions distinct, never treat a compiled summary as stronger than its primary source, and update the layer itself, not only the chat answer.
Acquire raw evidence from the strongest stable source: an official git clone, then an official export or local cache, and a page capture only when neither exists. Each raw source family records its canonical URL or repository, local raw path, snapshot date and revision (a commit hash, or a fetch timestamp for a cache or export). Refresh a raw source only when its area is active, its drift matters to the decision or it has likely changed since the last ingest; creating or refreshing a raw source family appends ../raw/log.md, and a refresh also updates that metadata and refreshes the compiled pages it changes. Never edit ../raw while compiling conclusions unless the task curates raw evidence.
Compiled pages stay derived: paraphrased summaries and cross-source synthesis, never raw third-party pages, vendor screenshots, one-to-one source cards or quote-heavy mirrors. Promote an editor's findings to an area page of its home under sources/, a lesson to docs/solutions/, an explicit conclusion to decisions/ and unresolved ambiguity to an open question on the decision or area page it blocks. Keep one research layer with stable paths and one page-type system; do not split it into goal-specific silos such as editor-behavior/. Keep one concept per file, never a giant mixed essay; point every durable claim outward to its evidence in ../raw, repository files, source-of-truth docs or plans; and promote only knowledge that is reusable, likely to matter again and stable enough to keep, such as durable architecture conclusions and vocabulary, leaving temporary exploration in docs/analysis or docs/plans.
A full pass scopes every relevant corpus, runs an official-source discovery step per corpus (its official docs, repository and release-note entrypoints), reads the strongest local raw hits before calling anything missing, and closes each corpus in a per-corpus ledger: pages and raw paths inspected, files read, official entrypoints checked, strongest evidence, a disposition (evidenced, raw gap, compile gap, synthesis gap, freshness gap, evidence gap, contradiction gap or structure gap) and the next action. A raw gap means ../raw holds no relevant evidence after the discovery step; a compile gap, raw evidence with no source summary; a synthesis gap, source summaries with no decision page for their conclusion; a freshness gap, a compiled page that newer evidence likely changed; an evidence gap, a question the strongest local raw hits leave open after they were read; a contradiction gap, compiled pages that disagree; a structure gap, duplicated, orphaned or mis-split pages. No corpus ends silent; thin or contradictory evidence becomes an open question on the decision or area page it blocks, naming its owner and the evidence that would close it, never fake law. A full pass that spot-checked one corpus of several is not full.
Broad grep is routing, not evidence: read every hit that obviously matches the question before classifying a corpus, keep raw paths searched separate from raw files actually read, and say why a promising hit was skipped.
maintain with no area runs a broad upkeep pass across the layer. maintain checks the area for stale pages and claims, contradictions, orphan, duplicated and overgrown pages, dead terminology, weakly sourced claims, raw evidence with no compiled summary, source summaries that imply a missing decision, and open questions that now have answers. It is aggressive about structure and conservative about claims: it fixes what existing evidence supports, never invents a decision, claims coverage from one weak source or silently resolves a contradiction, leaves an open question on the page the gap blocks, naming its owner and the evidence that would close it, for each gap it cannot fill, and reports what it fixed, what is still missing, whether the area needs full and, for editor-behavior evidence, whether the spec or current-evidence.md needs reconciling under AGENTS.md's editor-behavior rule.
Retiring internal docs compiles their still-true lessons into a home a workflow reads before anything is deleted; the owner prefers compressing to deleting (2026-10-06).
When a task depends on a domain bigger than the visible compiled pages, run maintain on it, or full when raw coverage is missing, before relying on those pages; run one before and after major research or migration work.
For backlog or closure status, follow Reading research ledgers.
Reading research ledgers
Read the existing corpus ledger before interpreting backlog or closure.
-
when closing a
docs/research/runs/**lead, read that artifact'slead-ledger.tsv,promoted-ledger.tsv, andread-log.tsvfirst. Use exact source refs and owner files from those ledgers before any repo-widerg. Broad current-tree or OSS scans are allowed only after the recorded anchors are missing, stale, or insufficient for the proof command; -
when parsing ledgers, match exact column names before fuzzy fallbacks. Prefer a literal
statuscolumn overdecision,action, or regex matches. Never infer backlog/open state from adecisioncolumn when astatuscolumn exists in the same TSV; -
when scanning research backlog/open status, parse work ledgers only:
lead-ledger.tsv,promoted-ledger.tsv, issue closure ledgers, or an explicitly named action matrix. Do not countrepo-registry.tsv,read-log.tsv, source registries, or other provenance metadata as open work just because they contain astatus-like column; -
when classifying research status values, separate actionable backlog from accepted deferral.
promote-*,promoted-pending,queued-*,open,todo,candidate,needs-*, and untriaged rows can be actionable. Statuses likepromoted-kept,promoted-existing,kept-*,covered,covered-existing,supporting,supporting-only,invalid-skip,rejected, andclosedare closed. Statuses starting withdeferred-*or legacydeferare queued stopping checkpoints, not work to "fix" during a timed run unless the active packet deliberately takes that owner; -
before writing one-off reducers over generated benchmark, ledger, or proof artifacts, inspect the artifact schema first: print the TSV header or JSON top-level keys, then parse the real field names. Do not guess columns such as
checkedwhen the ledger usescheck, and do not guess benchmark summary keys before reading the artifact shape;