research-stack · research.devclusterai.com
MVP · records to 2026-09-23 · every number is from the project's records, listed at the end
referenceon mainread 2026-09-23

What it does today.

Not a story and not a plan. Every row below is a thing that is merged and runs, with the file it is read from beside it. What is not built is on the roadmap, not here.

seq 1Kernelthe record

Thirteen ledgers, one append-only table.

One events table. The ledger a row belongs to fixes its class: sequenced under one writer, mergeable between machines, or scarce — coordinated, because it is money.

ledgerclasswhat it holds
QuestionsequencedWhat was asked, its premises, a restatement, a proposed reframe, and the locked charter with its coverage contract.
ArgumentsequencedClaims and the quote each is anchored to; the edges between them; verdicts, gaps, hypotheses, the synthesis and the article.
RunsequencedThe run itself: its lease, every state entered, every guard evaluated, tasks created, claimed, done or failed, retrievals, knowledge hits, the finish.
UnitsequencedEvery model call: what was sent, the raw response committed before any validation, and whether it was admitted, rejected or repaired.
PlansequencedThe statechart's bytes, by hash — an edit is a different plan.
DoctrinesequencedThe doctrine and every payload schema, by hash; and which (plan, doctrine) pair is the default.
BudgetscarceCaps, price snapshots, and reserve → settle or release. Money is integer micro-USD.
PolicysequencedThe rules in force and the version id every fresh fetch row carries; a user's quota and each refusal.
DecisionsequencedThe owner's appends alone: decisions with a scope and an expiry, feedback on a run, identity escalations.
EvalmergeableBench results, the owner's labels, judge scores, computed scores — one row per measurement.
FetchmergeableEvery search and fetch: the result set, the stored body's hashes, the engines registered.
MemorysequencedA campaign's core memory — at most 32 live items, edited by the owner, cited by the auditor.
KnowledgemergeableThe cross-run graph: doc versions, chunks, resolved entities, linked claims and the one edge table.

Eleven are the POC's; Memory arrived with B6 and Knowledge with S2a, each a new member of the events.ledger CHECK. Counted from the enum, not recalled.Ledger::ALL in crates/kernel-events/src/event.rs (13) · Ledger::POC (11) · docs/SPEC-kernel.md §1–§2

seq 2Kerneladmission

Fifty-three rules a row is admitted by.

Nothing is stored because a model produced it. Admission runs the registry over every draft; the first failure names the code and the path, and the attempt becomes an admission.rejected row with its evidence.

codesledgerwhat a row must satisfy
A1ArgumentEvery anchor resolves and is re-read byte for byte inside the transaction — a quote not in the stored body is refused at commit.
A2ArgumentA verdict cites a search that actually ran; refuted or contested needs a resolved disconfirming anchor; the edges are derived, not declared.
A3 A5ArgumentA synthesis cites live, non-refuted claims of this run, at least one of them observed.
A4ArgumentA claim's confidence never exceeds the weakest claim it rests on, unless an owner decision says so.
A7ArgumentThe synthesis and article gate: no cited claim the verifier called unsupported, and every paragraph cites a claim it lists.
F1 – F3FetchA fetch row's hashes match the body in the store; a search row's cache key is the derivation; ok, empty and failed each have their shape.
F4 – F7FetchThe engine is one the plan lists; provenance is the payload, so refs = []; every fresh row carries the policy version it ran under.
Q1 – Q3QuestionA reframe cites evidence; a charter refs the question asked; the coverage contract is kept — canonical queries, entities, dimensions, facets.
R1 – R4RunA task is claimed once per attempt; every state entered names its one cause; run.started refs question, plan, doctrine and prices by hash; a task id is derived, not chosen.
U1 U2UnitThe call's doctrine hash is the run's and its prompt windows fall on character boundaries; a unit writes only the ledgers its manifest lists.
B1 B4BudgetThe scope vocabulary and integer money; a release targets a live reservation.
P1 D1 D2Plan · DoctrineA plan version is the blake3 of its bytes and a doctrine version the hash over every schema; a promotion must pass the score gate.
Dec1DecisionOnly the owner writes a decision, feedback or an escalation. The kernel cannot.
Pol1 – Pol3PolicyOnly the kernel writes a policy row, and a version, quota or refusal quotes exactly the row it derives from.
E1 – E4EvalA measurement's refs and hashes resolve, its recomputed field is recomputed, its ranges are closed, and only the kernel or rs writes one.
M1 – M4MemoryAn edit names the live head of an item of that campaign; only the owner edits and only a unit cites; at most 32 live items.
Kn1 – Kn4 · En1Knowledge · FetchKnowledge and engine records are computed, never model-written; every id a payload names is in its refs.
KH1RunA knowledge hit is the kernel's, about a task of its own run, naming the rule it ran under.
P13 P14every ledgerA row above rung 0 references its live, scope-matching decision; no row carries anything credential-shaped.

53 codes in the closed list, 47 of them a closure in the registry. The other six are properties enforced elsewhere: A6 the fold's determinism, R5 the writer's lease check, B2 the cap arithmetic, B3 a kernel error, E5 a CHECK in the schema, Kn5 hash-equality on rsk rebuild.INVARIANT_CODES in crates/kernel-events/src/reason.rs, counted; k1_ids.rs asserts 53 and k2_invariants.rs::registry_complete the 47 · the closures are crates/kernel/src/invariants/ · docs/SPEC-kernel.md §2

seq 3Planaudit-first

Ten states, and one loop that reads again.

audit-first · plan v2 auditor audit scout orient recharter recharter investigator + verifier investigate coverer cover synthesist synthesise writer write done up to 3 addenda · a pass that adds no claim ends the loop side states: gap (a task the run needed failed) · halted (budget exhausted, payment, auth, the kill switch) source: plans/audit-first.v2.toml · cover is DEPTH-1, write is NARR-1 · plan v1 is still the default
stateunitretrievalleaves when
auditauditornonethe question has premises on the record
orientscoutorienta hypothesis is live
recharterrecharternonea charter is locked
investigateinvestigator · verifierinvestigate · verifyno line and no claim is left, or every task of this entry has finished
covercoverernoneevery cell holds its claims — or the rounds ran out, or the addendum sends the run back
synthesisesynthesistnonethe answer is admitted
writewriternonethe article is on the record (scout depth skips it)
done · gap · haltedterminal: finished, a task the run needed failed, or stopped by budget, payment, auth or the kill switch

The default plan is still v1 — audit, orient, recharter, investigate, synthesise. v2 adds cover and write, and it becomes the default only when E4 promotes it by score: one complete score of the pair on the current gold set that no comparable variant outscores, which invariant D2 checks inside the transaction. No promotion has been made.plans/audit-first.v2.toml (states, guards, depth table) · plans/audit-first.v1.toml · DEFAULT_PLAN_FILE in crates/kernel/src/cli/mod.rs · docs/DEPTH-1-NOTES.md · docs/GATE-MVP.md (E4: no version.promoted in the gate ledger)

seq 4Unitmanifests

Eight units, each with one job and its own cap.

unitwhat it is asked to dowritesseat · cap
auditorInterrogates the question before anything is searched: premises, what would change the answer, the sources an expert would read.Question · MemoryPro · $0.20
scoutThe reconnaissance pass — not to answer, but to correct the map before the real work starts.ArgumentFlash · $0.06
recharterTurns the audit into the charter: the lines to investigate, the claims to verify, the coverage contract.QuestionPro · $0.20
investigatorOne line of inquiry: reads the pages and asserts claims, each anchored to a quote in a page it opened.ArgumentFlash · $0.06
verifierAdversarial: tries to refute one claim, with a supporting and a counter search, then returns a verdict.ArgumentFlash · $0.06
covererReads the coverage contract against the claims counted and writes an addendum for every thin cell (plan v2).QuestionFlash · $0.06
synthesistThe answer, over the run's accepted claims alone.ArgumentPro · $0.30
writerThe reader's report, every paragraph citing the claims it lists (plan v2).ArgumentPro · $0.15

Eight directories; units::UNITS counts seven (the doctrine's six and the coverer) and the writer is NARR-1's. Every seat has a fallback binding with a cap of its own, and a unit may write only the ledgers its manifest lists — never Eval, Run or Knowledge. rsk units lint holds each one to three layers: the manifest and templates statically, its input SQL prepared on a hardened reader, then executed against a real task and required to return exactly one row.units/*/manifest.toml · units/*/user.md · units/README.md · invariant.U2 in crates/kernel/src/invariants/unit.rs

seq 5Interfacethree ways in

Ten tools, twenty-four verbs, five screens.

All three read one file. Nothing renders from a cache of its own.

the MCP server — rsk mcp

toolwhat it does
audit_questionInterrogates a question without searching: hidden assumptions, candidate reframings, sub-questions, the vocabulary to search with.
deep_research_startStarts a run in the background and returns a job id. Depth: scout, standard, deep, exhaustive.
deep_research_statusThe phase, the recent events and the elapsed time of a job.
deep_research_resultThe report — markdown, or the full structured run. Partial results while it is still running.
deep_researchRuns and waits, up to wait_seconds; hands back the job id if the wait elapses first.
list_research_jobsRecent jobs with their status.
research_doctrineThe six laws and the six phases, to apply the method yourself.
ledger_queryOne read-only SQL statement over the ledger and its derived views.
run_nextDriven mode: pulls the next unit call — the prompt and the schema — for you to answer as the unit.
run_submitDriven mode: answers that offer. The kernel admits or rejects it exactly as it would a model's.

Ten tools and one prompt, research. rsk opencode and rsk claude-code write a project that wires this server up.crates/kernel/src/mcp/mod.rs · docs/SPEC-kernel.md §7

the CLI — rsk

  • run itresearch (start · status · result · replay · jobs · audit) · console a run, resumed from its last admitted event; replay re-executes with the network refused
  • reproducerebuild · fixtures (record · replay) replay the events into a fresh file, compare every view hash, then swap
  • read itpolicy · engines · memory · models readers: no lease is taken, nothing is written
  • the ownerdecide · feedback · escalate · quota · key the only writes a person makes; each one an event, with a scope and an expiry
  • evidencebench · gate · eval every published number is one of these rows, re-rendered from the ledger
  • healthdoctor · units lint · plan lint · sync sync exports and merges the mergeable class between machines
  • frontendsmcp · skill · opencode · claude-code the server, and the projects that drive it

Twenty-four verbs in a release build; a twenty-fifth, fault, exists only in a test build.enum Cmd in crates/kernel/src/cli/mod.rs, counted · docs/SPEC-kernel.md §7

the console — rsk console serve

screenroutewhat it reads
ASK/askThe caps the run will start under, the user's quota, the campaigns — before anything is spent.
THE RUN/run/<id>The run's own streams, its retrievals joined to the pages fetched, its budget rows. Live over SSE.
THE REPORT/report/<id>The same renderer the CLI writes, its anchors, and the Eval rows about that run.
RUNS/runs, /compareEvery run with its question, campaign, state, money and wall time; two runs side by side.
DECISIONS/decisionsThe decisions in force, the quotas, the engines by campaign — and the four the owner can append.
THE PAGE/page/<fetch_ref>The stored body, verified against its hash on read, with the quoted byte range marked exactly as A1 checked it.

Five screens, and the page behind any anchor. Each is a pure function of a ledger, read through the same hardened pool ledger_query runs under, and each has a ?json twin so an agent reads what a person sees. Worst p95 53.9 ms over the 53-run gate ledger, against a 500 ms bound.docs/CONSOLE.md (the five screens, the render times, the ledger they were measured over) · crates/rs-console

read-only SQL — ledger_query

  • one statementDML, DDL, PRAGMA, ATTACH and BEGIN are refused with the class forbidden. The connection is opened read-only, with an authorizer and query_only.
  • bounded1,000 rows by default, 10,000 at most, 1 MiB per statement; a result that hit the cap says truncated rather than lying about the rest.
  • honest typesA blob comes back base64, at most 4 KiB of it, with its true length; a non-finite REAL is null; hlc is the packed integer it is stored as.
  • same poolThe guards in a plan, the units' input SQL and the console's screens all run under these rules. There is one read path.
seq 6Guardthe product

What it refuses.

This is the part worth paying for. Each of these is a refusal a research tool normally cannot make, because it has no record to check against.

five gates on one run · each refuses before the cost is paid question report P13 row refused blocked_source no request sent B2 cap no call made A1 claim refused A7 gap, not prose each refusal is itself a row: what was asked for, which rule said no, and the evidence beside it source: crates/kernel/src/invariants/ · crates/kernel/src/retrieval/blocked.rs · docs/SPEC-kernel.md §2
  • a quote that does not resolveEvery anchor is rewritten from the model's url, quote to a byte range in a page this run actually fetched, and re-read inside the transaction: the body is decompressed, re-hashed, and body[start..end] compared with the quote byte for byte. A stale read or a poisoned frame is refused at commit. invariant.A1 · at the POC gate 498 anchors, 490 resolved, 0 failing the re-read, 0 at a fetch that was not ok
  • a call that would cross a capMoney is reserved before the HTTP call and settled after it. A reserve that would pass the run's cap, the unit's cap or the UTC-day cap is refused class.scarce_cap, and the run ends halted · budget_exhausted — never a surprise bill. invariant.B1–B4 · bench G-2: 0 over-cap admits of 400, 30 refusals · the MVP gate: 0 refused, 0 halted over 53 runs
  • a blocked sourceA source the task forbids is checked before the request on its canonical URL and on the spelling that cited it, and again after on the URL a redirect ended at and on the page's own title. A hit is fetch.done · failed · blocked_source with no network at all, and a body already stored is replaced by the refusal so nothing can anchor to it. crates/kernel/src/retrieval/blocked.rs (BLOCK-1, finding #1330 — four of ten runs had read the forbidden survey when the prompt was the only thing carrying the ban)
  • a lapsed decisionAny row carrying identity provenance above rung 0 must reference a live, scope-matching owner decision. Expired, wrong-scope or absent, and the row is not admitted — so "never silent across the legal boundary" is a property of the ledger rather than a convention of whoever wrote the fetcher. invariant.P13 · and P14: no row, and no evidence of a refused row, carries anything credential-shaped
  • an article that cannot citeEvery paragraph of the report must cite at least one claim, every cited claim must be listed and live, and none may be one the verifier called unsupported. A writer that cannot meet it after its repairs ends the run gap with the synthesis on the record, rather than shipping prose. invariant.A7 · three of the ten plan-v2 runs ended exactly this way

and it also refuses

whatrulewhy it exists
A unit writing outside its manifestinvariant.U2A model's output can only land in the ledgers that unit declared — never Eval, Run or Knowledge.
A model writing knowledge or an engine recordKn1 · En1Those are computed from what was fetched; a model asserting them would be the map drawing itself.
A search engine the plan does not nameinvariant.F4The run's retrieval is the plan's, not the model's.
A charter line whose query names no canonical sourceinvariant.Q3The coverage contract is kept at admission, not merely requested in a prompt.
A 33rd live item in a campaign's memoryinvariant.M4The core memory stays core; the owner merges or deletes first.
A promotion no score supportsinvariant.D2A plan becomes the default by measurement, inside the transaction that records it.
Anything but a read from a model's SQLforbiddenModel-controlled SQL runs on a read-only pool under an authorizer.
A second writer on a live runclass.sequenced_writerThe lease is exclusive: two processes cannot interleave into one run's streams.

A refusal is not an error log. It is a row — what was asked for, which rule said no, at which path, with the attempt's evidence beside it — so the things this tool would not do are as readable as the things it did.crates/kernel/src/invariants/ · docs/SPEC-kernel.md §1 (the closed reason list) §2 (the registry) · docs/GATE-POC.md checks 4 and 5 · docs/GATE-MVP.md (G1, G2) · docs/BENCH-POC.md G-2

seq 7Budgetmeasured

What it costs.

runmeasuredcapwhat that bought
standard · plan v1$0.26$0.4013.6 model calls, 91.5 retrieval targets, 14.6 claims — the mean of ten DeepResearch Bench II tasks
deep · plan v2$0.40$0.6023.4 calls, 191.7 targets, 24.8 claims, 2.4 cover rounds — the same ten tasks, the plan the only difference
the MVP gate$8.271496$20.00 / UTC day53 questions in 20 campaigns (51 standard, 1 deep, 1 scout): 531 paid calls, 5 memo hits, p50 93.6 s
replaying a recorded run$0.0079 of 79 model calls served from the ledger, 0 calls and 0 reserves — the report comes back identical
a question, at the gate's mix$0.156$8.271496 settled over 53 runs

The per-question figure is that division and nothing more. Money is integer micro-USD, reserved before a call and settled after it from the response's own usage, so the ledger's total is what was spent rather than what was estimated. No reserve was refused and no run was halted over the 53.docs/DEPTH-1-NOTES.md (the ten-task table, mean 0.26 → 0.40) · bench/sets/gold-8/caps.toml (the caps) · docs/GATE-MVP.md (53 runs, $8.271496, 531 paid calls, 5 memo hits, p50 93.6 s) · docs/GATE-POC.md check 3 (replay 79 / 79 at $0)

next: how it works — the same machine as a drawing — or the MVP, where these parts are measured against other people's rubrics.