Iterate mode

This workflow defines PM orchestration, state, draft selection, and reporting for Iterate runs. Specialist workflows own research, writing, and review;...

This workflow defines PM orchestration, state, draft selection, and reporting for Iterate runs. Specialist workflows own research, writing, and review; Output layout owns generated paths.

Core terms

TermMeaning
IterationOne writer draft or revision followed by mechanical validation and one independent review.
Best draftThe eligible draft that preserves verified guidance and resolves the most consequential supported findings.
Iteration budgetA ceiling of 1, 2, or 3 iterations for this run; it is never a target to spend.
Review contextOptional approved context frozen for the run under Review context.
Preservation ledgerThe continuing record of verified source decisions for an existing page. New pages do not use one.

Manifest contract

The run manifest is drafts/run-manifest.json in the cache document root, .authoring-kit-cache/documents/<source-directory>/<document-key>/. Drafts, draft review reports, frozen review contexts, the preservation-ledger working copy and reviewer scratch sit beside it in drafts/; none of it is committed. The PM never writes the manifest: update-manifest.mjs creates and updates it (the subcommands are in the pipeline sequence below), validates the whole manifest before writing, and writes nothing on ok: false. Its exact version 1 contract is iterate-manifest.schema.json. Do not read the schema or another manifest to learn the format.

Rules the script enforces:

  • A fresh history is schema version 1; each batch appends one runs entry, and each reviewed draft one iterations entry. Earlier runs and iterations are never rewritten.
  • The draft hash is recomputed after review and must equal the snapshot’s sourceHash, so a draft changed after review is refused.
  • substantiveFindings is the list of finding IDs in that report, for resuming and loop control; it is not a count or a quality metric.
  • The writer and reviewer never read the manifest.
  • The cache is not committed and npm run clean removes it. A lost cache (or a new clone) loses a half-finished run: the Iterate run restarts.

Stale draft checks

Before reusing a recorded review, run node authoring-kit/scripts/check-fresh.mjs --mode=iterate --manifest=<run-manifest> --context-hash=<current frozen hash or null>. For each iteration it reports fresh and any failed checks:

  1. The draft’s recomputed hash equals contentHash.
  2. The recorded rubric version is the current one in review/config/content-quality-rubric.config.json.
  3. The iteration run’s review-context hash equals the current run’s frozen hash, including null.
  4. The paired report still exists and contains a matching version 3 reviewer snapshot.

allFresh summarises. An ok: false result means the manifest is unreadable or inconsistent; correct it first. If any check fails, copy the candidate to the next numbered draft and obtain a fresh review. Never overwrite an earlier draft or attach a second context to it.

Resolve review context

Before review, combine the document backlog located by preflight (reviewContext) with any request-supplied context, normalise it as the review-context contract describes, validate it against the review-context schema, and reject unknown fields or duplicate IDs. Do not discover context in ledgers, reports, research, manifests, or writer notes.

When effective items exist, write one normalised snapshot to <cache document root>/drafts/review-contexts/<run-id>.json, hash it, and freeze both path and hash for the run. Otherwise record null for both. A context change during execution makes the run stale.

Pipeline sequence

Documents are processed sequentially, never in parallel.

  1. Parse the request. Record paths, focus areas, review context, and the iteration budget. If no budget is supplied, ask for 1, 2, or 3 and state that 1 is the default. Run node authoring-kit/scripts/preflight.mjs <source-path> for each document: it derives the document key, applies the output-layout collision check, and reports the research state, review-context paths, and routed rubric. Stop on ok: false. Then run node authoring-kit/scripts/context-files.mjs scaffold <source-path> to create any missing backlog.md or research-context.md placeholder; it never edits a file that exists. Report the files it created.

  2. Select the authoring method. Choose by path and record new or existing source state:

    PageMethodSource state
    Component MDX existsauthor-component-pageexisting
    Component MDX does not existauthor-component-pagenew
    Guideline MDX existsauthor-guideline-pageexisting
    Guideline MDX does not exist and approved first-party policy is suppliedauthor-guideline-pagenew

    Stop a new guideline run when no approved first-party policy exists. External research cannot establish MDS policy.

  3. Set the run. Run node authoring-kit/scripts/update-manifest.mjs start-iterate --source=<source-path> --workflow=<author-component-page|author-guideline-page> --source-state=<new|existing> --budget=<1|2|3> [--research=<research-path>] [--preservation-ledger=<cache-ledger-path>] [--context=<frozen-context-path> --context-hash=<hash>]. It creates the manifest or appends a run to the existing one (a resume), takes the run ID from the UTC clock, and returns it with the next draft number, the cache draft path and reviewerScratchPaths, the two scratch report paths for that draft’s review. Omit --preservation-ledger for a new page; otherwise it is <cache document root>/drafts/preservation-ledger.md. The research file and ledger do not exist yet; only their paths are recorded.

  4. Research. Run for component pages unless the user says otherwise. For any other page, ask the user whether they want research on the topic before drafting, and run it only on a yes; with an existing research.md, ask whether to reuse it, extend it, or skip it. With no research.md, delegate a create. Otherwise reuse the file as it is, and never replace it. If the user asked for targeted research (for example keyboard navigation), run an extend on that topic before drafting. If preflight reports the research stale (research-context.md is newer than research.md), tell the user and offer an extend with no topic before continuing. Delegate under the researcher brief, wait for its returned handoff, and record _ak/<document-key>/research.md. If the handoff lists contested points, give the user the ready-to-paste text at the end of the research step, or straight away when a draft depends on the claim; the writer treats a contested claim as unverified. Offer each as an Open questions entry and say you will add them to research-context.md if they ask (Context files); add nothing otherwise, and never offer a [decision] placeholder.

  5. Extract component API. For a component page, run node authoring-kit/scripts/extract-component-api.mjs <slug> before every writer brief. Pass the output or its unavailable result to the writer. A page can document several packages (Tabs is tab-bar and tab; Select is select and option): the script reads component-packages.json beside it and prints a section for each, so pass all of it. When it reports a part as not covered, or exits 1 for a compound page that is not listed, tell the user the part is unverified rather than guessing; the fix is a map entry, which is a human edit.

  6. Iterate. Delegate to the writer under the writer brief, wait for the draft, run the mechanical gate, hash the exact bytes, then delegate one fresh reviewer under the reviewer brief, passing the routed rubric path, a snapshot timestamp (run date -u +%Y-%m-%dT%H:%M:%SZ once, just before dispatch, and reuse the value for a correction), and the first of the draft’s reviewerScratchPaths from start-iterate or the previous add-iteration. Accept the report at the returned path with node authoring-kit/scripts/update-manifest.mjs add-iteration --source=<source-path> --run-id=<runId> --draft=<draft-path> --scratch=<assigned-scratch-path> --timestamp=<review-timestamp>, which copies it to draft-<nnn>-review-report.md, records the iteration, derives the finding IDs, and validates. Apply Loop control. A correction uses the second scratch path. Iterate never invokes the synthesiser.

  7. Finalise. Select the best draft, assess Coverage, and run the deterministic finaliser below.

  8. Report. Use the final-report contract below.

Mechanical validation gate

After every writer step and before review:

  1. Run node authoring-kit/scripts/check-page-quality.mjs <draft-path>.
  2. Errors block review; notes do not. Send exact errors to the writer for a corrective edit on the same file. A corrective edit does not spend another iteration.
  3. Allow at most two corrective passes. If errors remain, stop and report them.
  4. After a clean gate, hash the draft and pass the validation result plus hash to the reviewer.
  5. Accept only a report, at the returned scratch path, with one matching version 3 reviewer snapshot, including model, and complete evidence fields. Run check-review-report.mjs on it with --started-at=<review-timestamp> and --role=reviewer; its warnings are advisory, as in Review-only. add-iteration recomputes the draft’s hash after the reviewer returns and refuses a draft that changed after review.

Loop control

Apply the first matching condition after each review:

ConditionDecision
No supported substantive finding remains (known items do not count)Stop.
Every remaining substantive finding needs a human decision or unavailable evidenceStop and list what is needed.
The iteration budget is exhaustedStop and report unresolved findings.
A substantive finding can be fixed from available evidence and budget remainsContinue from the best draft with that evidence.

Do not stop or continue because a rating changed or because of the number of findings. A known item never drives another loop and never blocks readiness, unless the reviewer marked it not applied and counted it as a finding.

Best-draft selection

An existing-page draft that drops a verified rule or decision cannot displace one that preserves it without explicit user approval. Use the preservation ledger. For a new page, compare the approved brief, research, and immutable draft history.

Among eligible drafts, compare the actual passages behind substantive findings. Prefer the draft that resolves consequential problems without introducing comparable problems or unsupported guidance. A missing finding in a later report is not proof of resolution. If no supported improvement separates drafts, retain the earlier one. Record the passages and findings that determined the choice; never choose by rating or finding total alone.

Coverage and readiness

The PM assesses Coverage from the research file and selected draft:

  • complete: cite the passage addressing every relevant Decision topic (a deliberate statement that MDS publishes no rule counts; see the rubric’s Coverage table);
  • gaps: list every relevant topic with no passage found;
  • unassessed: explain why no usable research file exists.

Readiness follows this order:

ConditionRecommendation
Mechanical errors, unapproved guidance loss, or substantive findings (not known items) remainNeeds revision.
Coverage has gapsNeeds coverage work.
A consequential question is unresolved or Coverage is unassessedNeeds human verification.
Checks pass, guidance is preserved, no substantive finding remains, and Coverage is completeReady for manual review and promotion consideration.

Promotion remains a human step. Never offer to promote the file.

Finalise

Run:

--draft and --report are the cache draft and its paired cache report. The script verifies the reviewed bytes and snapshot, applies only the documented path-depth changes, and writes the best-draft directory ak-<document-key>-best-draft/: <source-filename>, its score-free content-quality.json, review-report.md (the paired report, its heading path rewritten to the best-draft file) and, for an existing page, preservation-ledger.md. A re-finalise replaces the whole directory. The snapshot’s sourcePath is the best-draft file, because that file is what the recorded hash covers; a promoted draft is reviewed again as the live page. Its reviewProvenance points at review-report.md with reviewCount: 1. It never writes the live source and commits nothing on failure. Treat a non-zero exit as a failed finalise.

After a successful finalise, record the outcome with node authoring-kit/scripts/update-manifest.mjs finish-iterate --source=<source-path> --best=<iteration> --best-reason=<text> --stop-reason=<text> [--unresolved=<F1,F2>] [--final-draft=<selected-cache-draft-path>]. It sets bestDraft, stopReason, unresolvedFindings (finding IDs, no commas inside an ID) and finalDraftPath, validates, and writes only on success.

Runs and resuming

A fresh history starts at draft-001. A resumed run requires a valid schema version 1 manifest with at least one iteration, appends a new run ID, continues numbering, and carries the best draft forward. Apply the stale checks before trusting any earlier review. The user must explicitly request every additional batch.

Final report

Include:

  • File, display rating, reason, lens assessments, readiness, next action, and report link.
  • The committed best-draft directory, and the cache paths of the working drafts and run manifest for local inspection (not committed).
  • Supported improvements and remaining substantive findings, with passages and report IDs.
  • Strengths and optional polish.
  • Best-draft reasoning and links to every iteration report.
  • Every review-context ID and disposition, the known items excluded from the rating, and any ready-to-paste backlog.md entries you propose. Add them only if the user then asks (Context files); a person decides.
  • Coverage status with topic citations or the reason it is unassessed.
  • One research line from preflight’s research.bytes and the file, with no threshold or gate, e.g. “Research: 14.2KB, created 2026-10-07, 3 updates, 6 Decision topics, 1 contested, last full check 2026-10-07”, plus any contested points as ready-to-paste Open questions entries for research-context.md.
  • Proposed business examples and implementation proposals; for existing pages, preservation-ledger changes and any approved omissions.
  • Iteration budget and usage, reviewer model, and rubric version.
  • Manual next steps for promotion and deliberate ledger replacement or append, which the user runs by hand (README).
  • Last, a numbered Decisions I need from you list. One item per decision, each saying what you ask, your evidence-backed suggestion when you have one (labelled unconfirmed), and what you would add and to which file if they answer or ask. Cover, in this order: an open finding that needs an owner decision; each contested point; each proposal not in the draft, to approve or drop; each open question for confirmation. Say that answers can be given in one reply, that you will add entries only on request, and that a further iteration can follow. Do not repeat an item the report already lists; point to it. Omit the list when nothing needs a decision.

Never commit, push, publish, promote a draft, edit live page content, or clean generated history.

See also