API Doc Signature Sync
The **Type:** / **类型:** blocks in website/docs/{en,zh}/api/** are
hand-written, curated copies of real exported types — there is no
generation and no compiler check behind them, so they can be wrong the moment
they are authored, not only when the type later changes. This skill catches
both: it grounds every documented signature in the actual source type and the
tsc oracle instead of trusting the prose.
Core rule — verify, never recall. Read the type from
packages/core/src/types/*.ts or packages/core/src/api/types.ts (and, when
built, the emitted .d.ts) and let tsc decide. Never judge a signature from
memory or from the doc's own prose.
When to run
- A public type in
packages/core/src/types/ (e.g. api.ts, config.ts,
mock.ts, runner.ts) or packages/core/src/api/types.ts changed.
- A
**Type:** / **类型:** block, or the prose describing a type's fields,
was edited in website/docs/**/api/**.
- Reviewing a PR that touches either side.
Scope: every page with a **Type:** block — api/runtime-api/** and
api/javascript-api/**, both en and zh.
Procedure
1. en/zh parity (deterministic — run the script first)
node .agents/skills/api-doc-sync/scripts/check-type-blocks.mjs
The en and zh pages must declare structurally identical signatures (only
the label and translated // comments may differ). The script enforces this
and exits non-zero on any mismatch, missing counterpart, or block-count
difference. Fix every reported drift before moving on. Use --json for a
machine-readable inventory of all blocks.
2. Source fidelity (per changed symbol — let tsc judge)
For each documented symbol whose page changed (or whose type changed):
Find the source of truth. Locate the exported type in
packages/core/src/types/ (start from types/index.ts re-exports) or
packages/core/src/api/types.ts. Read its real shape: every overload,
parameter order, optionality, generics, and union members. Prefer the built
dist/**/*.d.ts when available — it is the exact surface users consume;
build with pnpm --filter @rstest/core build if needed.
Turn the doc into compile assertions. Write a throwaway .ts file
inside the repo (e.g. the repo root or packages/core/, with a temp name
like __doc-probe.ts) that imports the real type and exercises every call
form the docs show as a positive case, plus a // @ts-expect-error for
every form the docs say is invalid (e.g. "the options object cannot be the
third argument"). It must live in the repo, not the external scratchpad: tsc
resolves node_modules upward from the file's own directory, so only an
in-workspace file can resolve @rstest/core. Run it, then delete it:
npx tsc --noEmit --strict --skipLibCheck <scratch>.ts
- A positive form that fails to compile → the docs show a call that does not
exist. Drift.
- An unused
@ts-expect-error → a form the docs claim is rejected is
actually accepted (or vice-versa). Drift.
Check for under-documentation. Enumerate the overloads / fields that the
source type actually has and confirm each is represented in the doc
signature or prose. The bug this skill exists for was a missing overload
(the (name, fn, timeout?) shorthand was dropped from the **Type:**
line) — a positive-only check will not catch that, so explicitly diff the
source's overload set against the documented one.
Check field-level claims. When the prose lists option fields
(timeout, retry, …), confirm each exists on the type with the stated
optionality and meaning, and that no real field is omitted.
Check entrypoint exports. For every named type in a **Type:** /
**类型:** block, confirm it is exported from the package entrypoint that
the page documents. A type that exists only in source or another entrypoint
is not available to readers of that page.
Check named-type linkability. A signature that names another type
(TestContext, TestOptions, RstestUtilities, …) can be a bare, unlinked
black box. For each named type a signature references, confirm the page
either links it to its canonical definition or documents it inline. Only add
a link when both hold:
- (a) the type has a canonical anchor to point at — a real heading
(
### TestContext → #testcontext), not a loose bullet in a list (a
bullet generates no anchor); and
- (b) the type is foreign to the page — a data structure the reader must
navigate elsewhere to understand, not a fluent/chaining return type that
names the very object the current page documents.
When both hold (e.g. TestContext at
/api/runtime-api/test-api/test#testcontext), add a short prose link after
the signature — do not re-inline the type's members, which creates a
second copy that drifts. The link goes in an adjacent sentence, since a
markdown link cannot live inside the backticked **Type:** code span.
When either test fails, treat the type as already inline-documented and skip
it — no link noise. RstestUtilities is the canonical skip: no heading anchor
(only a bullet gloss in types.mdx), and => RstestUtilities is a fluent
self-reference to the rs/rstest object these pages already document.
3. Fix drift at the doc layer
Apply fixes to the .mdx directly. For each fix:
- Update both
en and zh; keep the signature blocks structurally
identical (re-run the script in step 1 to confirm).
- Preserve the curated style — friendly names like
TestOptions, omitted
internal generics (ExtraContext) — as long as the omission is a faithful
simplification, not a missing overload or wrong arg order.
- When a brand-new API/field is documented, set
<ApiMeta addedVersion="…" />
per the convention in website/AGENTS.md.
4. Re-verify
Re-run step 1 (parity) and step 2 (compile assertions) until both are clean,
then pnpm prettier --check the touched .mdx files.
Notes
- The parity script is safe to wire into CI / pre-push as a hard gate — it is
fully deterministic. The source-fidelity pass (step 2) is the judgement half
and runs here, on demand.
- This skill does not generate signatures from source. Generation would
make drift impossible but discards the curated/simplified style the docs use
on purpose; that trade-off is intentionally out of scope.
1---2name: api-doc-sync3description: Verify hand-written API doc signatures match the exported types. Use after changing a public type in packages/core/src/types/ or packages/core/src/api/types.ts, editing a `**Type:**`/`**类型:**` block in website/docs, or reviewing signature drift.4---56# API Doc Signature Sync78The `**Type:**` / `**类型:**` blocks in `website/docs/{en,zh}/api/**` are9**hand-written, curated copies** of real exported types — there is no10generation and no compiler check behind them, so they can be wrong the moment11they are authored, not only when the type later changes. This skill catches12both: it grounds every documented signature in the actual source type and the13`tsc` oracle instead of trusting the prose.1415> **Core rule — verify, never recall.** Read the type from16> `packages/core/src/types/*.ts` or `packages/core/src/api/types.ts` (and, when17> built, the emitted `.d.ts`) and let `tsc` decide. Never judge a signature from18> memory or from the doc's own prose.1920## When to run2122- A public type in `packages/core/src/types/` (e.g. `api.ts`, `config.ts`,23 `mock.ts`, `runner.ts`) or `packages/core/src/api/types.ts` changed.24- A `**Type:**` / `**类型:**` block, or the prose describing a type's fields,25 was edited in `website/docs/**/api/**`.26- Reviewing a PR that touches either side.2728Scope: every page with a `**Type:**` block — `api/runtime-api/**` and29`api/javascript-api/**`, both `en` and `zh`.3031## Procedure3233### 1. en/zh parity (deterministic — run the script first)3435```bash36node .agents/skills/api-doc-sync/scripts/check-type-blocks.mjs37```3839The en and zh pages must declare **structurally identical** signatures (only40the label and translated `//` comments may differ). The script enforces this41and exits non-zero on any mismatch, missing counterpart, or block-count42difference. Fix every reported drift before moving on. Use `--json` for a43machine-readable inventory of all blocks.4445### 2. Source fidelity (per changed symbol — let `tsc` judge)4647For each documented symbol whose page changed (or whose type changed):48491. **Find the source of truth.** Locate the exported type in50 `packages/core/src/types/` (start from `types/index.ts` re-exports) or51 `packages/core/src/api/types.ts`. Read its real shape: every overload,52 parameter order, optionality, generics, and union members. Prefer the built53 `dist/**/*.d.ts` when available — it is the exact surface users consume;54 build with `pnpm --filter @rstest/core build` if needed.55562. **Turn the doc into compile assertions.** Write a throwaway `.ts` file57 **inside the repo** (e.g. the repo root or `packages/core/`, with a temp name58 like `__doc-probe.ts`) that imports the real type and exercises **every call59 form the docs show** as a positive case, plus a `// @ts-expect-error` for60 **every form the docs say is invalid** (e.g. "the options object cannot be the61 third argument"). It must live in the repo, not the external scratchpad: `tsc`62 resolves `node_modules` upward from the file's own directory, so only an63 in-workspace file can resolve `@rstest/core`. Run it, then delete it:6465 ```bash66 npx tsc --noEmit --strict --skipLibCheck <scratch>.ts67 ```6869 - A positive form that fails to compile → the docs show a call that does not70 exist. **Drift.**71 - An unused `@ts-expect-error` → a form the docs claim is rejected is72 actually accepted (or vice-versa). **Drift.**73743. **Check for under-documentation.** Enumerate the overloads / fields that the75 source type actually has and confirm each is represented in the doc76 signature or prose. The bug this skill exists for was a _missing overload_77 (the `(name, fn, timeout?)` shorthand was dropped from the `**Type:**`78 line) — a positive-only check will not catch that, so explicitly diff the79 source's overload set against the documented one.80814. **Check field-level claims.** When the prose lists option fields82 (`timeout`, `retry`, …), confirm each exists on the type with the stated83 optionality and meaning, and that no real field is omitted.84855. **Check entrypoint exports.** For every named type in a `**Type:**` /86 `**类型:**` block, confirm it is exported from the package entrypoint that87 the page documents. A type that exists only in source or another entrypoint88 is not available to readers of that page.89906. **Check named-type linkability.** A signature that names another type91 (`TestContext`, `TestOptions`, `RstestUtilities`, …) can be a bare, unlinked92 black box. For each named type a signature references, confirm the page93 either links it to its canonical definition or documents it inline. Only add94 a link when **both** hold:9596 - (a) the type has a **canonical anchor** to point at — a real heading97 (`### TestContext` → `#testcontext`), not a loose bullet in a list (a98 bullet generates no anchor); and99 - (b) the type is **foreign** to the page — a data structure the reader must100 navigate elsewhere to understand, _not_ a fluent/chaining return type that101 names the very object the current page documents.102103 When both hold (e.g. `TestContext` at104 `/api/runtime-api/test-api/test#testcontext`), add a short prose link after105 the signature — do **not** re-inline the type's members, which creates a106 second copy that drifts. The link goes in an adjacent sentence, since a107 markdown link cannot live inside the backticked `**Type:**` code span.108109 When either test fails, treat the type as already inline-documented and skip110 it — no link noise. `RstestUtilities` is the canonical skip: no heading anchor111 (only a bullet gloss in `types.mdx`), and `=> RstestUtilities` is a fluent112 self-reference to the `rs`/`rstest` object these pages already document.113114### 3. Fix drift at the doc layer115116Apply fixes to the `.mdx` directly. For each fix:117118- Update **both** `en` and `zh`; keep the signature blocks structurally119 identical (re-run the script in step 1 to confirm).120- Preserve the curated style — friendly names like `TestOptions`, omitted121 internal generics (`ExtraContext`) — as long as the omission is a faithful122 simplification, not a missing overload or wrong arg order.123- When a brand-new API/field is documented, set `<ApiMeta addedVersion="…" />`124 per the convention in `website/AGENTS.md`.125126### 4. Re-verify127128Re-run step 1 (parity) and step 2 (compile assertions) until both are clean,129then `pnpm prettier --check` the touched `.mdx` files.130131## Notes132133- The parity script is safe to wire into CI / pre-push as a hard gate — it is134 fully deterministic. The source-fidelity pass (step 2) is the judgement half135 and runs here, on demand.136- This skill does **not** generate signatures from source. Generation would137 make drift impossible but discards the curated/simplified style the docs use138 on purpose; that trade-off is intentionally out of scope.