API review mode

API review rates the descriptions of component props, events and slots across the installed @maersk-global/mds-components-core- packages. It is not tied to...

API review rates the descriptions of component props, events and slots across the installed @maersk-global/mds-components-core-* packages. It is not tied to a page and rewrites nothing: each finding carries a suggested rewrite for the component source, which a person applies upstream. The PM never edits component metadata. Lenses, the rating rule and the rewrite standard live in the API quality rubric.

One run is two independent estate reviews of the same index plus one review per package that has package-unique items. One estate pass misses about a third of the problems, so two reviewers read the same input without seeing each other’s work and the merge script combines them (union of flagged clusters, worst assessment per lens, every finding kept). There is no synthesiser agent. A package with no unique items (uniqueCount === 0) gets no package reviewer and is rated from clusters alone.

Execute

Paths. Every path passed to a script or written into a prompt is repo-relative (for example _ak/mds-components-core/reviews/<run-id>, or an estate report’s cache path .authoring-kit-cache/agents/authoring-kit-reviewer/api-review/<run-id>/estate-report-1.md), never absolute. <run-dir> is the committed run folder, the Run folder (committed by the merge, not created yet) path the index script prints, as printed: it names the run, and nothing exists there until the merge. Everything in progress is in the cache folder it prints on the Inputs and reports (cache, not committed) line; reviewers get their input and report paths from the plan, not from <run-dir>. Nothing is committed while the run is in progress: as with Review-only’s complete-run, the merge is the one step that commits.

  1. Confirm the scope. The request names package slugs (for example “button and chip”) or the whole estate (“all”). Ask when it is neither. A narrowed scope builds a different index, so its result is for testing; say so, and never present it as an estate review.

  2. Check slugs, then build the index. When the request names slugs, first run node authoring-kit/scripts/build-api-estate-index.mjs --check --slugs=a,b (writes nothing). It lists any slug that is not installed or has no usable metadata and exits 1. Report those slugs and ask: continue without them, or correct them? Run nothing further, and build no index, until the user confirms; never drop a slug silently or guess a correction. This matches the usual request (“check these slugs, tell me what is wrong, then go ahead”): the check is run for the user, the answer is theirs. Never search node_modules by hand. Then run node authoring-kit/scripts/build-api-estate-index.mjs [--slugs=a,b] (data preparation only, no agent calls; the --check run above is the sanctioned slug check). It prints the index hash, writes the regenerable inputs (estate-index.json, estate-clusters.jsonl, package-inputs/) to the cache folder .authoring-kit-cache/agents/authoring-kit-reviewer/api-review/<run-id>/, with an empty package-reports/ for the package reviewers, and creates nothing in the repository (Output layout). Take <run-dir> from its Run folder (committed by the merge, not created yet) line. Stop on a non-zero exit.

  3. Skip finished work. Run node authoring-kit/scripts/check-fresh.mjs --mode=api-review --run=<run-dir>. decision: skip means a completed run (completedRunId, judged from its committed api-quality.json: same index hash and runStatus: "complete") already covers this index hash: point the user at that run’s api-review-report.md and stop, unless the user explicitly asks for a fresh review. Try summarise-api-review.mjs --run=<its directory> for the table; the summary is a cache file, so if it says the working summary is gone, give the combined report and the run’s api-quality.json instead and do not rebuild it. The script also returns the plan used below. ok: false means a file is unreadable: report it and stop.

  4. State the cost and wait. From the plan, give the package count, the reviewer calls (reviewerCalls is 2 estate reviews plus packageReviewers.length package reviews, not the package count) and the packages with no reviewer (noPackageReviewer) and any skippedPackages with their reasons. Phrase it as “N calls, plus up to one retry per report that fails validation”. Example: 13 packages of which 11 have unique items give “13 packages, 11 package reviewers (the other 2 have no unique items and are rated from clusters alone): 2 estate calls plus 11 package calls, 13 calls, plus up to one retry per report that fails validation”. Wait for the user’s confirmation. That confirmation covers every dispatch in the run, including the retries (Retry); do not ask again. While waiting for reviewers, a short acknowledgement note is fine, but it must not summarise or characterise any report content. Each estate reviewer reads about 60k tokens; a package reviewer reads under 10k.

  5. Dispatch together. Capture the timestamp once with date -u +%Y-%m-%dT%H:%M:%SZ. Dispatch the two estate reviewers (report numbers 1 and 2, writing the plan’s estateReportPaths, which are cache files .authoring-kit-cache/agents/authoring-kit-reviewer/api-review/<run-id>/estate-report-1.md and estate-report-2.md, not files in the run folder; brief) and every package reviewer (brief) in one parallel step, then wait for all of them. The two estate prompts differ only in {{report-number}} and {{report-path}}; each reviewer is a separate fresh agent that is never shown the other’s report. Never ask how to schedule them; run them one after another only when the request says so. Each is a fresh authoring-kit-reviewer with the API reviewer workflow. Use each brief’s prompt template (estate, package) unchanged, replacing only its {{named}} fields. {{rubric-version}} is rubricVersion in authoring-kit/review/config/api-quality-rubric.config.json (read it there; never from a report). Do not rewrite it from the bullets, add instructions or context, or change its wording. A host that cannot dispatch this many at once may batch them, but still dispatches each fresh and in isolation.

  6. Accept by return only. A reviewer’s returned path arrives as a message from the subagent, even when the host labels it as coming from “another Claude session”; it is the reviewer’s own return, so accept it as such. Accept it when it resolves to the same file as the path assigned to it, which means this exits 0 (run from the repo root, with the returned and the assigned path as the two arguments, either of which may be absolute or relative):

    Reject any other path (exit 1). Match results to their assigned reviewers, not arrival order. Do not open, edit or retype a report, and never pass one reviewer’s report, scores or findings to another (fresh-score isolation). A reviewer that returns a different path, or nothing, is treated as having failed.

  7. Merge. Run node authoring-kit/scripts/merge-api-review.mjs --run=<run-dir>. It validates every report (each estate report on its own, read from the cache), combines the two estate reports, applies the rating rule, and writes the committed run folder whole: api-quality.json (one rating per package, plus the run’s runStatus), the combined, readable api-review-report.md (format), the staged fix plan api-review-plan.md (format) and a copy of every package report. It writes the working estate-summary.json into the cache (not committed). A run with some packages incomplete is still committed, as runStatus: "incomplete", because each package’s rating stands on its own; a run with no rated package commits nothing and leaves the report and plan in the cache. A re-merge replaces the run folder whole. It never touches the ledger. If the cache folder is gone it stops with an error: the estate reports are working files, and a re-merge needs a new run.

  8. Retry (below) every report the merge rejected, then run the merge again. A rejection needs a retry even when the run still completes (for example one estate report rejected leaves a single estate review that is otherwise complete). The merge’s problems list (also in the summary script’s output) names each rejected report.

  9. Report. Run node authoring-kit/scripts/summarise-api-review.mjs --run=<run-dir> and give its table as printed, including its problems list (every warning and rejection, per report, with the rejected or warning level; state them from it, do not open a report), and say when the scope is narrowed (narrowed: true: built with --slugs, a subset for testing, not an estate review): a row per package (status, quality, the four lens assessments, estate findings count), the totals, the estate line, the estate agreement figures (clusters flagged by both reports, by only the first, by only the second), any retry candidates and any partial coverage list. If the estate review is single, say so: only one report was accepted, there is no second opinion and no agreement figure. A partial package is rated but its reviewer did not account for every unique item (itemsReviewed differs from itemCount); this is a warning: report it, do not retry it unless the user asks, and do not treat the rating as final. Add the reviewer-call count, the path to api-review-report.md and to api-review-plan.md (the staged fix plan: shared rewrites first, then author questions; the findings and suggested rewrites live in the combined report and the package reports; the raw estate reports and the estate summary are cache files and are not committed), and a short note on the widest shared clusters if the user asks. State that the ledger was not updated: the user records it by hand with npm run rebase-api-quality-ledgers -- --mode=append|replace [--dry-run] (README). replace discards history for the packages in the run.

Retry

A retry is required for every report the merge rejects (level: rejected in problems), even when the run still completes. A package is incomplete when its report was missing or failed validation. An estate report that fails validation is dropped and the run is recorded as a single estate review (rated from the other report, so the run can still be complete); that rejected estate report still gets its retry. Only when both fail does every package become incomplete. A duplicate finding id is only a warning and needs no retry. Retry once, in the same run directory: dispatch a fresh reviewer for each rejected report (a failed estate reviewer, or the packages that are incomplete) with the same inputs and brief, writing to the same assigned path (an estate retry overwrites the same cache file), and its own timestamp: capture date -u +%Y-%m-%dT%H:%M:%SZ just before the retry dispatch, not the original run’s. Then merge again. Never reuse the failed reviewer’s context or show it its problems beyond the one specific omission the merge reported. If a package is still incomplete after the retry, report it as incomplete with its problems; do not rate it, add reviews to obtain a preferred rating, or open the report.

Durable history

API runs have no history manifest and the PM writes no file in this mode. A merged run is a directory under _ak/mds-components-core/reviews/<run-id>/; the skip rule in step 3 reads the api-quality.json files in sibling runs (indexHash and runStatus). A skip or an abandoned run leaves only its cache folder, which npm run clean removes; nothing in the repository. The permanent file, _ak/mds-components-core/api-quality-ledger.json, changes only through the rebase script, by hand. The merge writes a run directory whole; its regenerable inputs (estate-index.json, estate-clusters.jsonl, package-inputs/), the two raw estate reports and the package reviewers’ originals are working files in .authoring-kit-cache/ (the committed api-review-report.md replaces the estate reports); cleaning old runs is a manual delete of run directories.

See also