Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 15 additions & 19 deletions .github/workflows/ci-superdoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,26 +113,22 @@ jobs:
- name: Typecheck
run: pnpm run type-check

- name: Public-contract checkJs (SD-2863)
# Gated subset of public-contract files run with `// @ts-check`. The
# script greps tsc output for errors in the curated file list and
# ignores the wider 1500+ errors from the broader super-editor source
# tree (those are tracked under SD-2863 follow-up tickets).
run: pnpm --filter superdoc run check:jsdoc

- name: SuperDoc public interface check
# Single wrapper covering all SuperDoc public-surface gates:
# - typecheck-matrix.mjs (packs superdoc, runs every scenario)
# - deep-type-audit.mjs --strict-supported-root
# - package-shape-gate.mjs (publint + attw)
# - snapshot.mjs --all --check (super-editor / legacy / root)
# - check-root-classification-closure.mjs (SD-3212 A1b)
# All stages run from the same packed-and-installed fixture, so
# ordering matters: matrix produces the install; the rest reuse
# it. --skip-build because the Build step above already ran
# `pnpm run build` (which includes build:superdoc).
# Local equivalent: `pnpm check:public:superdoc` (with the build
# stage included).
# Single wrapper covering all SuperDoc public-surface gates,
# ordered cheap-to-expensive:
# - contract-tiers-test (pure validator unit tests)
# - contract-tiers (package.json#exports vs publicContract)
# - jsdoc-ratchet (checkJs gate + per-file ratchet)
# - build (skipped here; the Build step above already ran it)
# - consumer-typecheck-matrix (packs superdoc, runs every scenario)
# - deep-type-audit-supported-root (any-leak gate)
# - package-shape (publint + attw)
# - export-snapshots (super-editor / legacy / root no-growth)
# - root-classification-closure (SD-3212 A1b)
# Stages 5-9 share one packed-and-installed fixture; stage 5
# produces it, the rest reuse it. --skip-build skips stage 4
# because the Build step above already ran `pnpm run build`.
# Local equivalent: `pnpm check:public:superdoc` (with build).
run: pnpm check:public:superdoc --skip-build

unit-tests:
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ Do not hand-edit `COMMAND_CATALOG`, `OPERATION_MEMBER_PATH_MAP`, `OPERATION_REFE
- `pnpm test` - unit tests
- `pnpm dev` - dev server from `examples/`
- `pnpm check:types` - raw TS compile across all referenced projects (`tsc -b tsconfig.references.json`). Does NOT run the public-interface chain. Legacy alias: `pnpm run type-check`.
- `pnpm check:public` - **canonical pre-merge command for typed public surfaces.** Validates both `superdoc` (tier discipline + vite build + postbuild chain + consumer typecheck matrix + deep-type audit + package-shape + snapshots + classification closure) and Document API (contract parity + output staleness + examples + overview). ~5 min. Non-mutating. Combines `check:public:superdoc` + `check:public:docapi`.
- `pnpm check:public:superdoc` - SuperDoc public package surface only. Wraps eight stages: tier-discipline:test + tier-discipline (fast-fail), build, matrix, deep-type audit, package-shape, snapshots, closure. Legacy alias: `pnpm run check:public-contract`.
- `pnpm check:public` - **canonical pre-merge command for typed public surfaces.** Validates both `superdoc` (tier discipline + jsdoc ratchet + vite build + postbuild chain + consumer typecheck matrix + deep-type audit + package-shape + snapshots + classification closure) and Document API (contract parity + output staleness + examples + overview). ~5 min. Non-mutating. Combines `check:public:superdoc` + `check:public:docapi`.
- `pnpm check:public:superdoc` - SuperDoc public package surface only. Wraps nine stages in cheap-to-expensive order: `contract-tiers-test`, `contract-tiers`, `jsdoc-ratchet`, `build`, `consumer-typecheck-matrix`, `deep-type-audit-supported-root`, `package-shape`, `export-snapshots`, `root-classification-closure`. Legacy alias: `pnpm run check:public-contract`.
- `pnpm check:public:docapi` - Document API public surface only. Clean-checkout safe: gitignored generated artifacts are built in memory; tracked outputs (reference docs, overview block) are compared byte-for-byte. No mutation. Legacy alias: `pnpm run docapi:check`.
- `pnpm generate:docapi` - regenerate Document API outputs after editing the contract (alias of `docapi:sync`). Writes gitignored Document API generated artifacts. Run only when you need the artifacts materialized locally (SDK builds, publishing); `check:public:docapi` does not require it.
- `pnpm generate:all` - regenerate schemas, SDK clients, tool catalogs, reference docs.
- `pnpm report:public:superdoc` - print public-contract tier metadata (supported / legacy / legacy-raw / asset / deprecated). Read-only, not a gate. Use `check:public:superdoc` (or its `tier-discipline` stage) to enforce. Source of truth: `packages/superdoc/scripts/type-surface.config.cjs`.
- `pnpm report:public:superdoc` - print public-contract tier metadata (supported / legacy / legacy-raw / asset / deprecated). Read-only, not a gate. Use `check:public:superdoc` (or its `contract-tiers` stage) to enforce. Source of truth: `packages/superdoc/scripts/type-surface.config.cjs`.

Full system reference (script catalog, dataflow, CI vs local): `packages/superdoc/scripts/README.md`.

Expand Down
41 changes: 24 additions & 17 deletions packages/superdoc/scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,17 @@ it stopped running.
| `check-export-coverage.cjs` | postbuild | Every `package.json#exports` subpath carries a `types` field or is on the runtime-only allowlist. | `TS7016` returns for consumers on runtime-only subpaths. |
| `verify-public-facade-emit.cjs` | postbuild | Per-facade expected symbol set + ESM/CJS parity + legacy command-signature compat. Has a hand-maintained `expectedNames` allowlist per facade (consolidation tracked separately). | Symbol set drift ships silently; CJS shims diverge from ESM. |
| `report-declaration-reachability.cjs` | postbuild | Instrumentation (not a gate): per-bucket reachability ratio of emitted declarations. | Loses visibility into unreachable emit (the SD-2952 trim target). |
| `check-jsdoc.cjs` | CI step | Per-file checkJs gate for files in a hand-curated `CHECKED_FILES` allowlist. Currently 6 files. **Note**: `SuperDoc.js` now has `// @ts-check` but is gated by `check:types`, not this script. The 6-file list is a historical ratchet from before the broader enablement; consolidating with `check:types` is tracked separately. | A targeted regression on one of the 6 ratcheted files ships silently. |
| `check-jsdoc.cjs` | wrapper stage 3 (`jsdoc-ratchet`) | Two gates: (a) per-file checkJs on the hand-curated `CHECKED_FILES` (currently 6 files; each must carry `// @ts-check` and stay clean against tsc); (b) ratchet over the public-reachable .js JSDoc surface — every file must be in `CHECKED_FILES`, carry `// @ts-check`, be on `jsdoc-allowlist.cjs` with a reason, or be in `jsdoc-debt-snapshot.json` as known pre-existing debt. New public JSDoc files that aren't accounted for fail with a clear "add @ts-check or allowlist" message. Stale snapshot entries (file gone, gained @ts-check, moved out of public surface) also fail. The allowlist contract is enforced too: every entry must carry a non-empty reason, point at an existing file, and still resolve to a public-reachable JSDoc file. Refresh the snapshot with `pnpm --filter superdoc run check:jsdoc -- --write`. Runs as stage 3 of `check:public:superdoc`. | New public-reachable JSDoc files could land without type coverage; existing ones could lose their `// @ts-check` directive without surfacing as a regression; the allowlist could grow silent / typo-shaped exemptions. |

The repo also has a top-level tier-discipline gate. One script,
The repo also has a top-level public-contract tier gate. One script,
`scripts/report-public-contract.mjs`, with two modes:

- default (read-only report) - what `pnpm report:public:superdoc` runs.
Prints the tiers + a validator status block. Exit 0 always.
- `--check` (gate) - runs as stage 2 of `check:public:superdoc` after
the validator's unit tests. Fails the build on any invariant
violation.
Prints the tiers + a validator status block. Report mode does not
fail on contract drift; load/runtime errors can still exit non-zero.
- `--check` (gate) - runs as stage `contract-tiers` of
`check:public:superdoc` after the validator's unit tests
(`contract-tiers-test`). Fails the build on any invariant violation.

Both modes share the pure `validatePublicContract` exported from the
same file (unit-tested in `scripts/report-public-contract.test.mjs`).
Expand Down Expand Up @@ -144,17 +145,23 @@ what an actual consumer would see — not the workspace source.
| `package-shape-gate.mjs` | External package-shape linters (publint + attw) against the packed tarball. | Catches condition ordering, masquerading exports, missing field declarations. |
| `check-root-classification-closure.mjs` | Asserts no `supported-root` or `legacy-root` export references an `internal-candidate` symbol in its public declared type. | Closure rule from SD-3212. |

`check:public:superdoc` runs all six in order (after the cheap
tier-discipline stage at the top of the wrapper). `typecheck-matrix` packs
`superdoc.tgz` and installs it into the consumer fixture. The rest
reuse what matrix produced: `deep-type-audit`, `snapshot --all
--check`, and `check-root-classification-closure` read from the
installed fixture in `node_modules/superdoc/`; `package-shape-gate`
runs `publint` / `attw` against the packed tarball at
`packages/superdoc/superdoc.tgz` directly. CI (`ci-superdoc.yml`) and
release workflows (`release-superdoc.yml`, `release-stable.yml`) call
`pnpm check:public:superdoc --skip-build` directly — no duplicated step
lists.
Of these, five run as wrapper stages of `check:public:superdoc`
after the cheap policy gates (`contract-tiers-test`,
`contract-tiers`, `jsdoc-ratchet`) and `build`:
`consumer-typecheck-matrix`, `deep-type-audit-supported-root`,
`package-shape`, `export-snapshots`, `root-classification-closure`.
`consumer-typecheck-matrix` packs `superdoc.tgz` and installs it into
the consumer fixture. The rest reuse what matrix produced:
`deep-type-audit-supported-root`, `export-snapshots`, and
`root-classification-closure` read from the installed fixture in
`node_modules/superdoc/`; `package-shape` runs `publint` / `attw`
against the packed tarball at `packages/superdoc/superdoc.tgz`
directly. `check-all-public-types-fixture.mjs` is a fixture-build
helper, not a wrapper stage.

CI (`ci-superdoc.yml`) and release workflows (`release-superdoc.yml`,
`release-stable.yml`) call `pnpm check:public:superdoc --skip-build`
directly - no duplicated step lists.

---

Expand Down
Loading
Loading