Skip to content

Commit 9700b46

Browse files
committed
chore(footnote): resolve PresentationEditor merge with main (SD-2656)
2 parents 9d2b213 + 3728071 commit 9700b46

195 files changed

Lines changed: 9894 additions & 2582 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-behavior.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
# detect gate above. When the suite does run, exercise all 3 browsers
6767
# so cross-browser regressions are caught at PR time.
6868
browser: [chromium, firefox, webkit]
69-
shard: [1, 2, 3, 4, 5]
69+
shard: [1, 2, 3, 4, 5, 6]
7070
steps:
7171
- uses: actions/checkout@v6
7272

@@ -105,8 +105,8 @@ jobs:
105105
run: pnpm exec playwright install-deps ${{ matrix.browser }}
106106
working-directory: tests/behavior
107107

108-
- name: Run behavior tests (${{ matrix.browser }} shard ${{ matrix.shard }}/5)
109-
run: pnpm exec playwright test --project=${{ matrix.browser }} --shard=${{ matrix.shard }}/5
108+
- name: Run behavior tests (${{ matrix.browser }} shard ${{ matrix.shard }}/6)
109+
run: pnpm exec playwright test --project=${{ matrix.browser }} --shard=${{ matrix.shard }}/6
110110
working-directory: tests/behavior
111111

112112
validate:

.github/workflows/ci-examples.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
strategy:
5858
fail-fast: false
5959
matrix:
60-
example: [react, vue, vanilla, cdn, angular, nuxt, laravel]
60+
example: [react, vue, vanilla, cdn, angular, nuxt, laravel, solid]
6161
steps:
6262
- name: Restore workspace
6363
uses: actions/cache/restore@v4

.github/workflows/ci-superdoc.yml

Lines changed: 17 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -113,61 +113,23 @@ jobs:
113113
- name: Typecheck
114114
run: pnpm run type-check
115115

116-
- name: Public-contract checkJs (SD-2863)
117-
# Gated subset of public-contract files run with `// @ts-check`. The
118-
# script greps tsc output for errors in the curated file list and
119-
# ignores the wider 1500+ errors from the broader super-editor source
120-
# tree (those are tracked under SD-2863 follow-up tickets).
121-
run: pnpm --filter superdoc run check:jsdoc
122-
123-
- name: Consumer typecheck (matrix)
124-
# The matrix script owns the published-package validation path:
125-
# it packs superdoc, installs the tarball into the standalone
126-
# fixture (`pnpm install --ignore-workspace`), then runs every
127-
# scenario under its declared resolution mode and strictness
128-
# settings. Replaces the pre-SD-2831 bare `tsc --noEmit` step
129-
# so the new pack-and-install scenarios are actually exercised
130-
# in CI, not just locally.
131-
run: |
132-
cd tests/consumer-typecheck
133-
node typecheck-matrix.mjs
134-
135-
- name: Deep public-type audit (supported-root strict, SD-3213e)
136-
# Single invocation does both: (1) prints the broad inventory
137-
# (tier counts, top files, entry/root-bucket attribution) for
138-
# visibility, and (2) gates on the supported-root subset against
139-
# `deep-type-audit.supported-root-allowlist.json`. Fails on any
140-
# new `any` finding reachable from root `.` via an export
141-
# classified as `supported-root`, AND on stale entries (a drain
142-
# landed but the allowlist wasn't shrunk). The broad audit
143-
# remains report-only because it includes legacy/raw reach.
144-
run: node tests/consumer-typecheck/deep-type-audit.mjs --strict-supported-root
145-
146-
- name: Package shape gates
147-
# External package-shape linters (publint + attw) running against
148-
# the packed tarball. Catches manifest issues that the in-repo
149-
# consumer matrix does not see: condition ordering, masquerading
150-
# ESM, missing CDN files, unpublished `source` paths.
151-
run: node tests/consumer-typecheck/package-shape-gate.mjs
152-
153-
- name: Public surface no-growth snapshots (SD-3176, SD-3212)
154-
# Unified entry point for the three snapshot families:
155-
# - super-editor-package: @superdoc/super-editor package.json#exports keys
156-
# - legacy: resolved exports for superdoc/* legacy subpaths
157-
# - root: 4-source inventory (types.import, types.require, import,
158-
# require) for the superdoc root entry. Cross-source mismatches
159-
# are reported in the companion .md but are not blockers on their
160-
# own.
161-
# Runs after the matrix step so the packed-and-installed fixture is
162-
# available. See tests/consumer-typecheck/snapshots/README.md.
163-
run: node tests/consumer-typecheck/snapshot.mjs --all --check
164-
165-
- name: Root classification closure gate (SD-3212 PR A1b)
166-
# Asserts the dependency-closure rule from the A1 classification:
167-
# no supported-root or legacy-root exported root symbol may reference
168-
# an internal-candidate root symbol in its public declared type.
169-
# Catches the failure class behind Phase 4a's 31-failure dry-run.
170-
run: node tests/consumer-typecheck/check-root-classification-closure.mjs
116+
- name: SuperDoc public interface check
117+
# Single wrapper covering all SuperDoc public-surface gates,
118+
# ordered cheap-to-expensive:
119+
# - contract-tiers-test (pure validator unit tests)
120+
# - contract-tiers (package.json#exports vs publicContract)
121+
# - jsdoc-ratchet (checkJs gate + per-file ratchet)
122+
# - build (skipped here; the Build step above already ran it)
123+
# - consumer-typecheck-matrix (packs superdoc, runs every scenario)
124+
# - deep-type-audit-supported-root (any-leak gate)
125+
# - package-shape (publint + attw)
126+
# - export-snapshots (super-editor / legacy / root no-growth)
127+
# - root-classification-closure (SD-3212 A1b)
128+
# Stages 5-9 share one packed-and-installed fixture; stage 5
129+
# produces it, the rest reuse it. --skip-build skips stage 4
130+
# because the Build step above already ran `pnpm run build`.
131+
# Local equivalent: `pnpm check:public:superdoc` (with build).
132+
run: pnpm check:public:superdoc --skip-build
171133

172134
unit-tests:
173135
needs: build

.github/workflows/release-stable.yml

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -114,26 +114,15 @@ jobs:
114114
# `latest` tag, so a regression that bypassed PR CI would otherwise
115115
# ship to every consumer pinned to `^1` or `latest`. Run identical
116116
# checks here so the stable lane cannot silently relax the gate.
117-
- name: Consumer typecheck (matrix)
118-
run: |
119-
cd tests/consumer-typecheck
120-
node typecheck-matrix.mjs
121-
122-
- name: Deep public-type audit (supported-root strict, SD-3213e)
123-
# Single invocation: broad inventory + supported-root strict gate.
124-
# Same gate as PR CI. Catches releases that bypass PR CI.
125-
run: node tests/consumer-typecheck/deep-type-audit.mjs --strict-supported-root
126-
127-
- name: Package shape gates
128-
run: node tests/consumer-typecheck/package-shape-gate.mjs
129-
130-
- name: Public surface no-growth snapshots (SD-3176, SD-3212)
131-
# Unified entry point for all three snapshot families
132-
# (super-editor-package, legacy, root). Same gate as PR CI.
133-
run: node tests/consumer-typecheck/snapshot.mjs --all --check
134-
135-
- name: Root classification closure gate (SD-3212 PR A1b)
136-
run: node tests/consumer-typecheck/check-root-classification-closure.mjs
117+
- name: SuperDoc public interface check
118+
# Wraps the nine wrapper stages: contract-tiers-test,
119+
# contract-tiers, jsdoc-ratchet, build (skipped here),
120+
# consumer-typecheck-matrix, deep-type-audit-supported-root,
121+
# package-shape, export-snapshots, root-classification-closure.
122+
# Same coverage as PR CI; runs before stable release so any
123+
# bypass path (manual republish, hotfix) still catches
124+
# regressions. --skip-build because Build above already ran.
125+
run: pnpm check:public:superdoc --skip-build
137126

138127
- name: Release stable packages (orchestrator)
139128
id: stable_release

.github/workflows/release-superdoc.yml

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -128,34 +128,17 @@ jobs:
128128
- name: Build packages
129129
run: pnpm run build
130130

131-
# Public-type contract gates: same gates as PR CI (ci-superdoc.yml).
131+
# Public-type contract gate: same coverage as PR CI (ci-superdoc.yml).
132132
# Runs before publishing so a release cannot ship a regression that
133133
# bypassed PR CI (manual republish, hotfix branch, recovery flow).
134-
- name: Consumer typecheck (matrix)
135-
run: |
136-
cd tests/consumer-typecheck
137-
node typecheck-matrix.mjs
138-
139-
- name: Deep public-type audit (supported-root strict, SD-3213e)
140-
# Same gate as PR CI. One invocation prints the broad inventory
141-
# AND runs the supported-root strict gate against the committed
142-
# allowlist. Catches releases that bypass PR CI.
143-
run: node tests/consumer-typecheck/deep-type-audit.mjs --strict-supported-root
144-
145-
- name: Package shape gates
146-
# External package-shape linters (publint + attw) running against
147-
# the packed tarball. Same step as PR CI.
148-
run: node tests/consumer-typecheck/package-shape-gate.mjs
149-
150-
- name: Public surface no-growth snapshots (SD-3176, SD-3212)
151-
# Same gate as PR CI. Catches releases that bypass PR CI.
152-
# Runs the unified entry point for all three snapshot families
153-
# (super-editor-package, legacy, root).
154-
run: node tests/consumer-typecheck/snapshot.mjs --all --check
155-
156-
- name: Root classification closure gate (SD-3212 PR A1b)
157-
# Same gate as PR CI. Catches releases that bypass PR CI.
158-
run: node tests/consumer-typecheck/check-root-classification-closure.mjs
134+
- name: SuperDoc public interface check
135+
# Wraps the nine wrapper stages: contract-tiers-test,
136+
# contract-tiers, jsdoc-ratchet, build (skipped here),
137+
# consumer-typecheck-matrix, deep-type-audit-supported-root,
138+
# package-shape, export-snapshots, root-classification-closure.
139+
# --skip-build because the Build step above already ran
140+
# `pnpm run build` (which includes build:superdoc).
141+
run: pnpm check:public:superdoc --skip-build
159142

160143
# PR preview: publish with pr-<number> dist-tag
161144
- name: Publish PR preview

AGENTS.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,17 @@ Do not hand-edit `COMMAND_CATALOG`, `OPERATION_MEMBER_PATH_MAP`, `OPERATION_REFE
7171
- `pnpm build` - build all packages
7272
- `pnpm test` - unit tests
7373
- `pnpm dev` - dev server from `examples/`
74-
- `pnpm run generate:all` - regenerate schemas, SDK clients, tool catalogs, reference docs
74+
- `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`.
75+
- `pnpm check:public` - **canonical pre-merge command for typed public surfaces.** Validates both `superdoc` (tier discipline + jsdoc ratchet + public-method fixture coverage + 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`.
76+
- `pnpm check:public:superdoc` - SuperDoc public package surface only. Wraps ten stages in cheap-to-expensive order: `contract-tiers-test`, `contract-tiers`, `jsdoc-ratchet`, `public-method-coverage`, `build`, `consumer-typecheck-matrix`, `deep-type-audit-supported-root`, `package-shape`, `export-snapshots`, `root-classification-closure`. Legacy alias: `pnpm run check:public-contract`.
77+
- `pnpm check:public:docapi` - Document API public surface only. Wraps four stages: `contract-parity`, `contract-outputs`, `examples`, `overview-alignment`. 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`.
78+
- `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.
79+
- `pnpm generate:all` - regenerate schemas, SDK clients, tool catalogs, reference docs.
80+
- `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`.
81+
82+
Full system reference (script catalog, dataflow, CI vs local): `packages/superdoc/scripts/README.md`.
83+
84+
Naming convention: `check:*` = non-mutating, safe in CI. `generate:*` = mutates files. `report:*` = read-only information, not a gate. Older command names (`check:public-contract`, `docapi:sync`, `report:public-contract`, etc.) remain as aliases.
7585

7686
## Testing
7787

CONTRIBUTING.md

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -228,18 +228,43 @@ pnpm run format # Run Prettier
228228

229229
### Adding a public API
230230

231-
If your PR adds a new public export from `superdoc` (a new entry in `packages/superdoc/src/public/index.ts`, a new value re-exported from a public subpath, or a new subpath in `package.json` `exports`), it must ship with a type test that exercises the new surface under strict mode.
231+
Any change that grows the public surface ships with explicit assertions for the shape consumers will see. The gates below catch missing surface but **do not catch wrong-but-explicit types** — a misannotated signature can compile, pass the consumer matrix, and still break consumer TypeScript builds. Be deliberate about what you assert.
232232

233-
The canonical root contract is `packages/superdoc/src/public/index.ts` (per the SD-3175 path-as-contract umbrella, finalized in SD-3212 PR C). Several automated gates enforce consistency on every PR:
233+
Three kinds of public surface change, and what each requires:
234234

235-
- **`verify-public-facade-emit.cjs`** -- verifies the curated `src/public/**` facade matches the emitted `.d.ts` for symbol set, ESM/CJS parity, leak grep, and command-signature compatibility. Adding a new export updates the corresponding `expectedNames` array in this script in the same PR.
236-
- **`snapshot.mjs --all --check`** -- unified entry point for the three snapshot families. The `root` family locks the root export inventory across the four `package.json#exports` sources (`types.import`, `types.require`, `import`, `require`); the `legacy` family locks `superdoc/*` subpath resolved exports; the `super-editor-package` family locks `@superdoc/super-editor`'s `package.json#exports` keys. Drift fails CI; run `snapshot.mjs --family <name> --write` to regenerate one family after an intentional change.
237-
- **`check-root-classification-closure.mjs`** -- enforces the dependency-closure rule: no `supported-root` or `legacy-root` export may reference an `internal-candidate` type in its declared public type. New exports require an entry in `tests/consumer-typecheck/snapshots/superdoc-root-classification.json`.
238-
- **`typecheck-matrix.mjs`** -- every typed public subpath has at least one matrix scenario. If you add a new subpath, add a fixture under `tests/consumer-typecheck/src/` and a corresponding entry in the matrix, and update the inventory in `docs/architecture/package-boundaries.md`.
239-
- **`check-all-public-types-fixture.mjs`** -- derives the expected type-only root export list from `superdoc-root-classification.json` (rows with `inDts && !inEsm && !inCjs`) and fails if `src/all-public-types.ts` is missing assertions or has stale ones. Runs before the matrix to catch fixture drift early.
240-
- **`src/all-public-types.ts`** -- the fixture exercised by the SD-2842 matrix scenarios to catch any-collapses on customer-facing types. When you add a new type-only root export, add a corresponding `import { X } from 'superdoc';` plus `const _real_X: AssertNotAny<X> = true;` line. The `check-all-public-types-fixture.mjs` gate fails CI if you forget.
235+
**A. New public method on `SuperDoc` / `DocumentApi` / a UI handle.** Add a consumer fixture under `tests/consumer-typecheck/src/` that asserts BOTH the parameter shape and the return shape. The pattern (see `search-match.ts` for a real example):
241236

242-
The point of these gates is to keep customer TypeScript builds working. A new export that ships without a type test can collapse to `any` (or fail to resolve) for consumers without the team noticing.
237+
```ts
238+
declare const sd: SuperDoc;
239+
const _paramOk: AssertEqual<Parameters<SuperDoc['myMethod']>[0], MyParam> = true;
240+
const _returnOk: AssertEqual<ReturnType<SuperDoc['myMethod']>, MyReturn> = true;
241+
sd.myMethod(realRuntimeValue); // exercises the call site
242+
```
243+
244+
Why both: a migration narrowed `SuperDoc.search` from `string | RegExp` to `string` and slipped past every existing gate because the return-type fixture was there but the parameter-type fixture was not.
245+
246+
**B. New event in `SuperDocEventMap` or new `Config.on*` callback.** Add a consumer fixture that asserts the payload type:
247+
248+
```ts
249+
sd.on('my-event', (payload) => {
250+
const _payloadOk: AssertEqual<typeof payload, MyEventPayload> = true;
251+
});
252+
// @ts-expect-error: unknown event names must be rejected
253+
sd.on('my-evnt', () => {});
254+
```
255+
256+
When the event fires from SuperDoc itself (not bridged from upstream), also add a runtime test in `SuperDoc.test.js` that registers a handler and asserts the emitted payload matches. Types prove consumer usability; runtime tests prove the value the runtime actually emits. They are not the same gate.
257+
258+
**C. New public export from `superdoc` (a new entry in `packages/superdoc/src/public/index.ts`, a new value re-exported from a public subpath, or a new subpath in `package.json` `exports`).** The facade source IS the contract (SD-3175 path-as-contract, finalized in SD-3212 PR C). Gates enforce consistency on every PR:
259+
260+
- **`verify-public-facade-emit.cjs`** -- parses each `src/public/**` facade source file directly and asserts the emitted `.d.ts` matches. No `expectedNames` allowlist to update; adding a named export to the facade source is the only action needed.
261+
- **`snapshot.mjs --all --check`** -- locks the three snapshot families. `root` covers the four `package.json#exports` sources (`types.import`, `types.require`, `import`, `require`); `legacy` covers `superdoc/*` subpath resolved exports; `super-editor-package` covers `@superdoc/super-editor`'s `package.json#exports` keys. Drift fails CI; run `snapshot.mjs --family <name> --write` to regenerate one family after an intentional change.
262+
- **`check-root-classification-closure.mjs`** -- no `supported-root` or `legacy-root` export may reference an `internal-candidate` type in its declared public type. New exports require an entry in `tests/consumer-typecheck/snapshots/superdoc-root-classification.json`.
263+
- **`typecheck-matrix.mjs`** -- every typed public subpath has at least one matrix scenario. New subpath = new fixture under `tests/consumer-typecheck/src/` + corresponding matrix entry + inventory line in `docs/architecture/package-boundaries.md`.
264+
- **`check-all-public-types-fixture.mjs`** -- derives the expected type-only root export list from `superdoc-root-classification.json` and fails if `src/all-public-types.ts` is missing assertions or has stale ones.
265+
- **`src/all-public-types.ts`** -- exercised by the SD-2842 matrix scenarios to catch any-collapses on customer-facing types. New type-only root export = add `import { X } from 'superdoc';` plus `const _real_X: AssertNotAny<X> = true;`.
266+
267+
The point of these gates is to keep customer TypeScript builds working. A new public surface that ships without an explicit fixture can collapse to `any`, narrow silently, or fail to resolve for consumers without the team noticing until upgrade.
243268

244269
### Branch Naming
245270

@@ -288,7 +313,7 @@ When you open a PR, the following checks run automatically:
288313
- [ ] Code is formatted (`pnpm run format:check`)
289314
- [ ] Commit messages follow conventional commits
290315
- [ ] PR description links to related issue
291-
- [ ] If you added a public API, the consumer-typecheck gates pass (see [Adding a public API](#adding-a-public-api))
316+
- [ ] If you added a public API: appropriate fixture from [Adding a public API](#adding-a-public-api) — public method (Parameters + ReturnType), public event/callback (payload type + runtime assertion where practical), or public export (the gate lists). `pnpm check:public` passes.
292317

293318
## Release Process
294319

apps/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@superdoc-dev/cli",
3-
"version": "0.11.1",
3+
"version": "0.12.0",
44
"type": "module",
55
"bin": {
66
"superdoc": "./dist/index.js"

apps/cli/platforms/cli-darwin-arm64/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@superdoc-dev/cli-darwin-arm64",
3-
"version": "0.11.1",
3+
"version": "0.12.0",
44
"os": [
55
"darwin"
66
],

0 commit comments

Comments
 (0)