Review system architecture (commonplace.review + commonplace.cli.review)
Type: kb/types/note.md
The review subsystem is deterministic coordination around externally dispatched
judgment. Commonplace selects (note, criterion) pairs, snapshots their inputs,
creates jobs and prompts, validates worker output, and persists completion and
freshness. The parent agent or harness launches workers; Commonplace does not
launch reviewer models. The persisted generic assay field remains named
criterion_path.
For operation, see the review-system guide and
run review batches. Exact behavior
belongs to the executing commonplace.review and commonplace.cli.review
source.
Execution and ownership
target selector -> selector JSON
job creation -> queued job + pair rows + captured prompt
external worker -> job-owned output file
finalization -> parsed results + completion + freshness baselines
Selector JSON is the only job-creation input. A job groups pairs by note or by criterion for prompt sharing, but every pair remains an independent unit of output and freshness, and every job uses one persisted result kind.
The parent owns dispatch and concurrency. Each review worker starts without the parent's task conversation, reads one generated prompt path, and writes only the job-owned output named there. It does not mutate notes, criteria, manifests, or the store. ADR 067 owns that worker boundary; the generated prompt is its executable instance.
Canonical state and artifacts
SQLite is canonical for job and pair protocol state, execution provenance, and
freshness. Storage architecture places that state
among Commonplace's other storage roles; live schema, location, and query
behavior remain in commonplace.store and commonplace.review.review_db.
Review artifacts have narrower roles:
- the prompt is generated job input carrying the captured review task;
job-output.mdis the worker-to-finalizer transport;- per-pair result files retain the review body, which is evidence not stored in SQLite; and
MANIFEST.jsonis a reconstructable inspection surface.
Artifact paths are derived from store state rather than persisted as another
authority. MANIFEST.json is never pipeline state. A worker's optional
self-reported model remains a labelled artifact claim; it does not become
harness provenance or freshness identity. Review identity is
(note_path, criterion_path, model_partition); missing runner telemetry is
normal.
The output transport also carries one soft, per-pair report of which pre-resolved linked artifacts the worker opened and whether budget or evidential sufficiency stopped inspection. Finalization removes that bookkeeping from the retained review body and joins it with code-generated available cost in job telemetry. Missing, partial, malformed, or unpriced bookkeeping remains measurement state; it cannot change a result, completion, freshness, or review identity.
Finalization boundary
Finalization accepts only queued jobs and is all-or-nothing across every pair in the job. It validates provenance, output structure, pair coverage, and each pair's persisted result contract before advancing state. Success completes all pairs, creates or replaces their freshness baselines, and prunes superseded evidence. Failure completes none and advances no baseline. ADR 035 owns this transaction boundary.
The artifact failure policy follows the state boundary. A per-pair result-file write failure prevents DB completion because that file carries review evidence. A later manifest refresh failure is only a warning because the manifest is reconstructable from completed state.
Freshness hash boundary
A review baseline pins exactly two source files: the note and the persisted
criterion. The criterion may be a catalog gate, type spec, collection contract,
or critique instruction. Selector applicability and missing-baseline
discovery remain review-specific; registered-target status belongs to
freshness architecture.
Prompt scaffolding is deliberately outside the freshness hash. This includes the worker instructions, output protocol, reading scope, prompt assembly, and the mechanical wrappers that present type specs or collection contracts as criteria. Therefore judgment-bearing particulars must live in the hashed note or criterion files. A wrapper may say how to apply a dependency document, never supply the case-specific judgment itself. A scaffolding change that shifts judgments is a system upgrade requiring deliberate corpus-wide re-review or acknowledgement rather than ordinary file-triggered staleness.
The live comments in
freshness.py and
protocol/prompt.py place
this rule in both change loops. ADRs 038
and 041
apply it to type and collection criteria.
Semantic gates may follow the target note's pre-resolved links. The linked
files are reading context, not freshness inputs. In particular,
semantic/grounding-alignment reads an ingest's append-only Quotes or an exact
snapshot declared by the link text. ADR 073
owns that source-specific mutation and availability boundary; it does not
widen the review pair.
Maintenance scope
Review this page when execution ownership, canonical-state roles, the finalization transaction, or the two-file freshness boundary changes. Module additions, function signatures, table columns, command arguments, and protocol fields do not by themselves require an edit; their live owners remain source, schema, or command help.