Review-only mode
Review-only assesses live pages, drafts, or non-MDX files without rewriting them. Documents run sequentially. The reviews of one document run in parallel; more than one review requires synthesis.
Choose the review count
| Request | Count |
|---|---|
| Explicit positive whole number | Use it. |
| Light review | One independent review. |
| Thorough review | Three independent reviews followed by synthesis. |
| Missing, conflicting, zero, negative, or fractional count | Ask for light, thorough, or another positive whole number. |
Run the reviews of one document in parallel: dispatch every reviewer together, then wait for all of them. Never ask the user how to schedule them. Run them one after another only when the user’s request says so. Do not ask for a single review.
State total reviewer and synthesis calls. Never silently cap a custom count. Iterate and Research-update stay sequential.
Several documents
When a request covers more than one document (for example “all components”), resolve and confirm the scope before any review:
- Resolve the list. Expand the request to workspace paths of live source documents only,
excluding
_ak/output,_components/, and other non-page files. Show the full list. - State the cost. Give the document count and the total reviewer and synthesis calls across the whole request, not per document, then wait for the user’s confirmation.
- Skip finished work. Before each document, run
node authoring-kit/scripts/check-fresh.mjs --mode=review-only --source=<document> --count=<n>. Itsdecisionisskipwhen the newest committed run folder underreviewsDirectory(the latest completed run) holds a snapshot whose source hash matches the live document’s current hash and whose review count is at least the requested count. Record a skipped document asskippedin the batch summary. Review it again only when the user explicitly asks for a fresh review. Areviewdecision (changed source, too few reviews, no completed run) is reviewed normally. The script’srubricCurrent: falseand asharedInputDriftofchanged(unknownwhen the cache holds no run manifest) are advisory and do not change the decision; mention them in the summary.ok: falsemeans a committed snapshot is unreadable or invalid: record the document asincompleteand continue. - Share one
batchId. Use the first reviewed document’s run ID as thebatchIdfor every run in the request, so the runs stay grouped. - Keep context lean. After a document completes, keep only its path, run ID, rating, and outcome. Do not carry its reports forward or re-read them for later documents.
- Continue past failures. A document that fails is recorded as
incompleteorstaleand the next document starts; a failure never stops the batch or changes another document’s history.
When the batch ends, run
node authoring-kit/scripts/summarise-batch.mjs --rows=<source>=<outcome>[,<source>=<outcome>...]
with each document’s outcome (reviewed, skipped, incomplete, or stale) and report its table
as printed: a row per document with path, outcome, rating, and run ID, then the totals and the
statement that the live ledgers were not updated and that the user records them by hand
(README).
Run state and committed output
A run’s working state lives in the cache document root,
.authoring-kit-cache/documents/<source-directory>/<document-key>/reviews/<run-id>/: the history
manifest (reviews/manifest.json), the run’s review-manifest.json, the frozen review context, the raw
reviewer-report-<n>.md copies and the scratch reports. None of it is committed. Only complete-run
writes the committed run folder _ak/<document-key>/reviews/<run-id>/, and only these two files:
reviewer-report.md and content-quality.json. An incomplete or stale run commits nothing. The latest
completed run is the newest committed run folder with a valid snapshot; no pointer file records it. A
committed run folder is never reused or overwritten.
For every new run, init-review-run.mjs captures startedAt from the UTC clock, derives the run ID
from it as YYYYMMDD-HHmmss, creates the cache run directory atomically, and assigns the reviewer IDs.
Reuse startedAt in every reviewer snapshot and the final snapshot. The run directory uses the run ID
exactly; on a collision, in the cache or among committed run folders, the script appends the first
available collision suffix starting with -02, then -03, and so on.
Do not add a source slug, review count, mode label, or sequence name: the document workspace already
supplies that context. Keep existing run IDs and directories unchanged.
Every path recorded in a manifest or snapshot is relative to the project root; see
Paths. A snapshot, like every committed file, names only committed paths
(for example src/pages/components/badge/_ak/index/reviews/<run-id>/reviewer-report.md), never a cache
path. The checkers reject file-system paths and paths relative to the document workspace.
Both use schemaVersion: 1; their separate schemas describe different documents, not
successive generations of one manifest. The exact contracts are
review-history-manifest.schema.json
and review-run-manifest.schema.json. The PM never
writes either manifest: update-manifest.mjs (see Execute and persist) builds each one, validates it with
the checks in check-authoring-kit-manifest.mjs, and writes only on success. Do not read a schema or an
earlier run’s manifest to learn the format. A run record is never rewritten except by the script’s own
transitions (running to complete, incomplete or stale).
No manifest field contains a score, criterion value, complexity label, or issue count.
Execute and persist
- Run
node authoring-kit/scripts/preflight.mjs <document> [--context=<context-file>]. Stop onok: false(missing source or a document-key collision under Output layout). Runnode authoring-kit/scripts/init-review-run.mjs --source=<document> --count=<n>, adding--batch-id=<first run's ID>for the second and later documents of a batch. It returnsstartedAt,runId,batchId,runDirectory,reviewIds,reviewerScratchPaths(two paths per review ID), andsynthesiserScratchPaths, all cache paths. Resolve and freeze review context under Review context, using the context paths preflight reported; write the frozen file to<runDirectory>/review-context.json, the only placestart-runaccepts. - Use the rubric path and version preflight reported. For MDX, run
check-page-quality.mjsand record the result. A mechanical error is reported separately but does not prevent a content review of a live page. For general copy, recordnot-applicable. Then runnode authoring-kit/scripts/update-manifest.mjs start-run --source=<document> --run-id=<runId> --batch-id=<batchId> --count=<n> --started-at=<startedAt> --mechanical=<passed|failed|not-applicable> [--mechanical-note=<text>] [--context=<frozen-context-path> --context-hash=<hash>]. It creates the cache history manifest when missing, appends therunningentry, hashes the source and the shared inputs, writes the version 1 run manifest, and validates both. Do not dispatch until it printsok: true. - Use the
reviewIdsinit-review-run.mjsassigned (R1throughRn); they are all known before dispatch. Give every fresh reviewer the same frozen inputs and brief apart from its ID. SupplystartedAtas the snapshot timestamp; the reviewer echoes it rather than estimating the time. Assign each reviewer only the first of its ownreviewerScratchPaths; it writes the full report there and returns only that path. Never fork the PM conversation, reuse a reviewer context, or share sibling results. - Await each reviewer’s returned path, which must equal its assigned path. Match
results to their assigned IDs, not arrival order. Never share sibling results with reviewers,
including during correction.
Run
node authoring-kit/scripts/check-review-report.mjs --report=<report> --source=<document> --started-at=<startedAt> --role=reviewer [--context=<frozen-context-path>]on every scratch report before accepting it. It is warn-only for now: itswarningsare not blocking, but verify each one against the report, request a correction for any that is real, and list the unresolved ones in the final report. A correction request is a continuation of the PM’s delegated review, with the same review ID and inputs; it assigns the second of that review’sreviewerScratchPaths(review-<n>-attempt-2.md), never the first again. Accept a report under the reviewer brief withnode authoring-kit/scripts/update-manifest.mjs add-review --source=<document> --run-id=<runId> --id=<R1> --scratch=<assigned-scratch-path>. It refuses any path but that review’s assigned scratch path, a source that changed since the run started (close the run asstale), and a snapshot whose hash, timestamp or rubric version differs from the run’s. It copies the report toreviewer-report-<n>.md, appends the review’s score-free record (including the reportedmodel), and validates; its printed result is the confirmation, so do not re-read the manifest to check it. Never retype or copy a report yourself. Await all requested reviews and accept every report before starting synthesis. - With one review, there is no synthesis: go to step 6. With more than one, supply all
accepted records (project-root-relative paths) to the review synthesiser with
startedAtas its snapshot timestamp. Assign the first of thesynthesiserScratchPathsthatinit-review-run.mjsreported (<runDirectory>/scratch/synthesis-attempt-1.md); the run directory is new, so neither path exists. The synthesiser writes the complete report there and returns only the path. Require the returned path to match the assigned path exactly. Read only that assigned path after a successful handoff. Runcheck-review-report.mjson it with--role=synthesiser(same warn-only handling as reviewer reports, adding--contextwhen review context is frozen). Accept the report only when it exists, is complete under the review synthesiser and Review reporting contracts, and contains one valid assessment-only version 3 snapshot echoingstartedAtand the source hash. The synthesiser records no model: that belongs to the reviewers. A correction request is a continuation of the PM’s synthesis delegation, not a direct user invocation. Use the second of thesynthesiserScratchPaths(synthesis-attempt-2.md) for the one correction attempt; never reuse an earlier scratch file. The PM never adjudicates findings or reconstructs a missing synthesis from reviewer reports. - For MDX, assess Coverage when a usable
_ak/<document-key>/research.mdexists; otherwise recordunassessed. Omit Coverage for general copy. Coverage appears in the final report, not the snapshot or ledger. - Run
node authoring-kit/scripts/update-manifest.mjs complete-run --source=<document> --run-id=<runId> [--synthesis=<assigned-synthesis-scratch-path>] [--coverage=<complete|gaps|unassessed>:<text>]. With one review it takes no--synthesis, and the final report is a copy of that review’s report. With more than one,--synthesismust be one of the assigned scratch paths, whose snapshot must echostartedAtand the source hash. Pass the Coverage assessment from step 6 (when it applies) as--coverage=<status>:<text>: the script appends it to the report as a## Coveragesection, unchanged. For a long assessment, write it to a file under<runDirectory>/scratch/and pass--coverage-fileinstead. Do not change the synthesiser’s findings, rating, or snapshot. The script rechecks the source hash, then writes the committed run folder:reviewer-report.mdand the snapshotcontent-quality.json(adding the PM-ownedsourcePathandreviewProvenance, pointing at the committed report and validated againstcontent-quality.schema.json). It marks the cache run manifest complete and validates both manifests. Onok: falseit has committed nothing. It refuses a run whose committed folder exists. The scratch files stay disposable. - Report rating, reason, lens assessments, substantive findings, strengths, next action, review
count, Coverage, context dispositions, known items excluded from the rating, any ready-to-paste
backlog.mdentries you propose (add them only if the user then asks, per Context files), and final report link. State what was committed (the run folder) and that the working state is in the cache, and that the live ledger was not updated and that the user records it by hand (README).
Interrupted or invalid runs
If a review fails, an input changes, or correction fails, run
node authoring-kit/scripts/update-manifest.mjs close-run --source=<document> --run-id=<runId> --status=<incomplete|stale>,
record why in the diagnostics, and stop that document. Keep diagnostics under distinct incomplete-<n>.md names. Cancel
outstanding work where supported and ignore late results. When the host could not run the reviewers
in parallel, tell the user the run is incomplete and that they can ask for the reviews “one after
another”. A late completion
must not reopen a failed run or trigger synthesis. Do not synthesise fewer reviews, publish a
partial snapshot, or commit anything. An unreadable, missing, or mismatched synthesis
handoff is a failed synthesis, even if the scratch file later appears. Never replace it with a
PM-authored report or mark the run complete.
A retry gets a new run ID. Never mix reports from different runs or add reviews to obtain a preferred rating.