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;...

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

RequestCount
Explicit positive whole numberUse it.
Light reviewOne independent review.
Thorough reviewThree independent reviews followed by synthesis.
Missing, conflicting, zero, negative, or fractional countAsk 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:

  1. 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.
  2. 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.
  3. Skip finished work. Before each document, run node authoring-kit/scripts/check-fresh.mjs --mode=review-only --source=<document> --count=<n>. Its decision is skip when the newest committed run folder under reviewsDirectory (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 as skipped in the batch summary. Review it again only when the user explicitly asks for a fresh review. A review decision (changed source, too few reviews, no completed run) is reviewed normally. The script’s rubricCurrent: false and a sharedInputDrift of changed (unknown when the cache holds no run manifest) are advisory and do not change the decision; mention them in the summary. ok: false means a committed snapshot is unreadable or invalid: record the document as incomplete and continue.
  4. Share one batchId. Use the first reviewed document’s run ID as the batchId for every run in the request, so the runs stay grouped.
  5. 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.
  6. Continue past failures. A document that fails is recorded as incomplete or stale and 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

  1. Run node authoring-kit/scripts/preflight.mjs <document> [--context=<context-file>]. Stop on ok: false (missing source or a document-key collision under Output layout). Run node 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 returns startedAt, runId, batchId, runDirectory, reviewIds, reviewerScratchPaths (two paths per review ID), and synthesiserScratchPaths, 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 place start-run accepts.
  2. Use the rubric path and version preflight reported. For MDX, run check-page-quality.mjs and record the result. A mechanical error is reported separately but does not prevent a content review of a live page. For general copy, record not-applicable. Then run node 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 the running entry, hashes the source and the shared inputs, writes the version 1 run manifest, and validates both. Do not dispatch until it prints ok: true.
  3. Use the reviewIds init-review-run.mjs assigned (R1 through Rn); they are all known before dispatch. Give every fresh reviewer the same frozen inputs and brief apart from its ID. Supply startedAt as the snapshot timestamp; the reviewer echoes it rather than estimating the time. Assign each reviewer only the first of its own reviewerScratchPaths; it writes the full report there and returns only that path. Never fork the PM conversation, reuse a reviewer context, or share sibling results.
  4. 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: its warnings are 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’s reviewerScratchPaths (review-<n>-attempt-2.md), never the first again. Accept a report under the reviewer brief with node 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 as stale), and a snapshot whose hash, timestamp or rubric version differs from the run’s. It copies the report to reviewer-report-<n>.md, appends the review’s score-free record (including the reported model), 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.
  5. 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 startedAt as its snapshot timestamp. Assign the first of the synthesiserScratchPaths that init-review-run.mjs reported (<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. Run check-review-report.mjs on it with --role=synthesiser (same warn-only handling as reviewer reports, adding --context when 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 echoing startedAt and 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 the synthesiserScratchPaths (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.
  6. For MDX, assess Coverage when a usable _ak/<document-key>/research.md exists; otherwise record unassessed. Omit Coverage for general copy. Coverage appears in the final report, not the snapshot or ledger.
  7. 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, --synthesis must be one of the assigned scratch paths, whose snapshot must echo startedAt and 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 ## Coverage section, unchanged. For a long assessment, write it to a file under <runDirectory>/scratch/ and pass --coverage-file instead. Do not change the synthesiser’s findings, rating, or snapshot. The script rechecks the source hash, then writes the committed run folder: reviewer-report.md and the snapshot content-quality.json (adding the PM-owned sourcePath and reviewProvenance, pointing at the committed report and validated against content-quality.schema.json). It marks the cache run manifest complete and validates both manifests. On ok: false it has committed nothing. It refuses a run whose committed folder exists. The scratch files stay disposable.
  8. 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.md entries 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.

See also