Skip to content

feat(ci): no-growth gates for legacy public surfaces (SD-3176)#3357

Merged
caio-pizzol merged 1 commit into
mainfrom
caio-pizzol/SD-3176-legacy-no-growth-gates
May 17, 2026
Merged

feat(ci): no-growth gates for legacy public surfaces (SD-3176)#3357
caio-pizzol merged 1 commit into
mainfrom
caio-pizzol/SD-3176-legacy-no-growth-gates

Conversation

@caio-pizzol
Copy link
Copy Markdown
Contributor

Phase 1 of SD-3175. Freeze the legacy public compatibility surface while the path-as-contract facade is being built.

Pure additive CI. No runtime, package, or types change. Customers' imports today work identically tomorrow.

What the gates lock

Two snapshot scripts under tests/consumer-typecheck/:

  • Snapshot Asnapshot-super-editor-package-exports.mjs reads packages/super-editor/package.json#exports keys (21 today) and locks them. New subpath in the exports map fails CI.
  • Snapshot Bsnapshot-superdoc-legacy-exports.mjs runs against the packed-and-installed fixture. Uses the TypeScript compiler API to enumerate resolved named exports through the four legacy superdoc/* subpaths (resolves export * chains). Locks 203 names for superdoc/super-editor + 1 each for superdoc/converter / superdoc/docx-zipper / superdoc/file-zipper. When an entry advertises both types.import and types.require, both declaration files must enumerate the same names (guards against ensure-types.cjs regressing the CJS shim).

CI step Legacy public no-growth gates (SD-3176) wired into PR CI plus both release lanes, placed after the matrix step so the fixture is fresh.

When the gate fails

Default response: reject the change. These paths are legacy compatibility surface per docs/architecture/package-boundaries.md Decision 1; they are not supposed to grow. The tests/consumer-typecheck/snapshots/README.md documents when regeneration is justified (rare; requires linking the PR to SD-3175 or a child for reviewer sign-off).

Known limit (called out in the README)

This phase does not enumerate every file reachable through existing wildcard export-map keys (e.g. "./*", "./converter/internal/*"). Snapshot A locks the key set; Snapshot B locks the resolved superdoc/super-editor named export surface. A new file added under an existing wildcard that a consumer reaches via deep import (@superdoc/super-editor/something-new) passes both gates. Wildcard removal or shrinkage belongs to the later compat/major phases of SD-3175.

Verified

  • Clean run: both gates exit 0 (203 + 1 + 1 + 1 resolved names; 21 export-map keys)
  • Snapshot A rejects a fake ./fake-test-entry export-map key (exit 1)
  • Snapshot B rejects a fake resolved export through superdoc/super-editor (exit 1)
  • CJS parity rejects a name added to super-editor.d.cts only (exit 1)

Related

  • SD-3175 (umbrella) - the architectural plan these gates stabilize for
  • SD-3177 (Phase 2) - declaration emit spike, independent and parallel-safe
  • SD-2966 - policy framework (input, not blocker)

Phase 1 of SD-3175. Freeze the legacy public compatibility surface
while the path-as-contract facade is built. Pure additive CI; no
runtime, package, or types change.

Two snapshot scripts under tests/consumer-typecheck/:

- snapshot-super-editor-package-exports.mjs reads
  packages/super-editor/package.json#exports keys (21 today) and locks
  them. New subpath in the exports map fails CI.

- snapshot-superdoc-legacy-exports.mjs runs against the packed-and-
  installed fixture and enumerates resolved named exports through the
  four legacy superdoc subpaths via the TypeScript compiler API
  (resolves `export *` chains). Locks 203 names for super-editor + 1
  each for converter / docx-zipper / file-zipper. When an entry has
  both types.import and types.require, both .d.ts and .d.cts must
  enumerate the same names (guards against ensure-types.cjs regressing
  the CJS shim).

Snapshots in tests/consumer-typecheck/snapshots/ plus a README that
documents when to regenerate vs reject, and explicitly notes the
gate's known limit: it does not enumerate files reachable through
existing wildcard export-map keys (./* etc.), since wildcard removal
belongs to a later phase of SD-3175.

CI step "Legacy public no-growth gates (SD-3176)" wired into
ci-superdoc, release-superdoc, and release-stable, placed after the
matrix step so the fixture is fresh.

Empirically verified:
- both gates pass clean (exit 0)
- adding a fake export-map key fails Snapshot A (exit 1)
- adding a fake resolved export fails Snapshot B (exit 1)
- diverging the .d.cts from .d.ts fails the parity check (exit 1)
@caio-pizzol caio-pizzol requested a review from a team as a code owner May 17, 2026 15:14
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 17, 2026

SD-3176

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@caio-pizzol caio-pizzol merged commit d804415 into main May 17, 2026
17 checks passed
@caio-pizzol caio-pizzol deleted the caio-pizzol/SD-3176-legacy-no-growth-gates branch May 17, 2026 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants