diff --git a/.github/package-impact-map.md b/.github/package-impact-map.md new file mode 100644 index 0000000000..303c8f330b --- /dev/null +++ b/.github/package-impact-map.md @@ -0,0 +1,66 @@ +# Package impact map + +Source of truth for which repo paths should trigger CI and release workflows for each published surface. + +## Principle + +**Test broad, release narrow.** + +- **CI gates compatibility.** A change to SuperDoc core should run the CI of every dependent package — that's how breakage in `@superdoc-dev/react` or `@superdoc-dev/sdk` gets caught before it ships. CI paths follow *compatibility* impact. +- **Release gates artifact changes.** A package should only publish a new version when its own published artifact actually changes. Release paths follow *artifact* impact. + +These two are not the same. `template-builder` and `esign` externalize `superdoc` in their builds and declare it as a `peerDependency`, so a core change doesn't change their tarballs → CI broad, release narrow. CLI bundles core into platform binaries, so a core change does change the CLI tarball → both broad. + +## Surfaces + +| Surface | Purpose | Release impact | CI impact | +|---|---|---|---| +| `superdoc` | Main browser DOCX editor/runtime | core | core | +| `@superdoc-dev/react` | React wrapper around superdoc | react + core (see note below) | react + core | +| `@superdoc-dev/template-builder` | React SDT/template authoring UI | `packages/template-builder/**` only | template-builder + core | +| `@superdoc-dev/esign` | React signing workflow | `packages/esign/**` only | esign + core | +| `@superdoc-dev/cli` | Native Document API CLI | cli + doc-api + core | same | +| `@superdoc-dev/sdk` | JS/Python SDK packaging CLI binaries | sdk + cli + doc-api + core | same | +| `@superdoc-dev/mcp` | MCP server over SDK/document engine | mcp + sdk + cli + doc-api + core | same | +| `superdoc-vscode-ext` | VS Code DOCX editor | vscode-ext + core | same | +| `@superdoc-dev/create` | Project scaffolder | `apps/create/**` only | own changes only | +| `@superdoc-dev/superdoc-yjs-collaboration` | Standalone Yjs server (no SuperDoc dep) | `packages/collaboration-yjs/**` only | own changes + collaboration examples | +| `@superdoc/docs` (private) | Documentation site | N/A (not published) | docs + public API / doc generation | +| demos, examples (private) | Compatibility samples | N/A (not published) | own paths + relevant upstream runtime | + +## Path expansions + +**core** expands to: +- `packages/superdoc/**` +- `packages/super-editor/**` +- `packages/layout-engine/**` +- `packages/word-layout/**` +- `packages/preset-geometry/**` +- `shared/**` +- `pnpm-workspace.yaml` + +**doc-api** is `packages/document-api/**`. + +**cli** is `apps/cli/**`. + +**sdk** is `packages/sdk/**`. + +**mcp**, **vscode-ext**, **create** are their respective `apps/*/**` or `packages/*/**` paths. + +## Why each classification + +- **`template-builder` and `esign`** externalize `superdoc` in their Vite build (`rollupOptions.external`) and declare it as a `peerDependency`. A SuperDoc core change does not change the wrapper's published bundle — consumers receive the new core through their own `npm install`. Release-on-core is pure version noise; CI-on-core remains necessary to catch breaking API changes. +- **`react`** externalizes `superdoc` in its Vite build the same way, and declares `superdoc` in **both** `dependencies` and `peerDependencies`. The `dependencies` entry preserves auto-install for every consumer (zero-break regardless of package manager); the `peerDependencies` entry signals the singleton contract and aligns the manifest with template-builder/esign. Because the `dependencies` entry still pins via lockfiles, existing consumers only pick up a new core version when react republishes, so release-on-core stays correct *today*. The unlock for release-narrow is to remove `superdoc` from `dependencies` entirely — that is a breaking change and tracked as a separate decision. +- **CLI / SDK** bundle engine behavior into platform-specific native binaries (see `apps/cli/.releaserc.cjs` and `packages/sdk/.releaserc.cjs` — both use `patch-commit-filter.cjs` to expand release analysis into core paths). The published artifact genuinely changes when core changes. +- **MCP** depends on SDK via `workspace:*` and imports engine/session code directly. Its current release trigger (`apps/mcp/**` only) causes it to lag SDK releases. Expand to match SDK's release paths. +- **VS Code extension** packages SuperDoc into the extension VSIX. Treated like CLI/SDK. +- **collaboration-yjs** has no SuperDoc dependency. It's a standalone Yjs server. Release and CI both narrow. +- **create** is a scaffolder with no dependencies on SuperDoc runtime. Release and CI both narrow. +- **docs, demos, examples** are not published. They get CI on changes to anything they render to catch visual or behavior regressions. + +## Notes + +- `packages/ai/**` has been removed from all release and CI triggers. `@superdoc-dev/ai` is being deprecated; npm-side deprecation is a separate operational step. +- When SuperDoc core ships a breaking API change, `template-builder` and `esign` must be manually updated and released. Their `peerDependencies` version bump is the signal; semantic-release won't auto-trigger on upstream changes for them. +- `@superdoc-dev/react` declares `superdoc` in both `dependencies` and `peerDependencies` to preserve zero-break install semantics while still signaling the singleton contract. Removing `superdoc` from `dependencies` is the unlock for release-narrow and is tracked as a separate decision. +- When editing a release or CI workflow, its `paths:` filter must match the corresponding row in this map. Workflow-lint rules should enforce this. diff --git a/.github/workflows/ci-behavior.yml b/.github/workflows/ci-behavior.yml index 612d45956b..b8d15c5499 100644 --- a/.github/workflows/ci-behavior.yml +++ b/.github/workflows/ci-behavior.yml @@ -10,7 +10,6 @@ on: - 'packages/superdoc/**' - 'packages/layout-engine/**' - 'packages/super-editor/**' - - 'packages/ai/**' - 'packages/word-layout/**' - 'packages/preset-geometry/**' - 'tests/behavior/**' diff --git a/.github/workflows/ci-superdoc.yml b/.github/workflows/ci-superdoc.yml index f33149ea68..f7015852c0 100644 --- a/.github/workflows/ci-superdoc.yml +++ b/.github/workflows/ci-superdoc.yml @@ -16,6 +16,7 @@ on: - 'packages/sdk/**' - 'packages/template-builder/**' - 'packages/esign/**' + - 'packages/ai/**' - 'evals/**' - '**/*.md' merge_group: diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 7e59bd1144..c8a6afd527 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -14,7 +14,6 @@ on: - 'packages/superdoc/**' - 'packages/super-editor/**' - 'packages/layout-engine/**' - - 'packages/ai/**' - 'packages/word-layout/**' - 'packages/preset-geometry/**' - 'shared/**' diff --git a/.github/workflows/release-esign.yml b/.github/workflows/release-esign.yml index 8431abc0ae..62ab1dceed 100644 --- a/.github/workflows/release-esign.yml +++ b/.github/workflows/release-esign.yml @@ -8,13 +8,6 @@ on: - main paths: - 'packages/esign/**' - - 'packages/superdoc/**' - - 'packages/layout-engine/**' - - 'packages/super-editor/**' - - 'packages/ai/**' - - 'packages/word-layout/**' - - 'packages/preset-geometry/**' - - 'shared/**' - 'pnpm-workspace.yaml' - '!**/*.md' workflow_dispatch: diff --git a/.github/workflows/release-mcp.yml b/.github/workflows/release-mcp.yml index a8f5f281e7..e6b1c79459 100644 --- a/.github/workflows/release-mcp.yml +++ b/.github/workflows/release-mcp.yml @@ -7,7 +7,19 @@ on: branches: - main paths: + # MCP depends on SDK (workspace:*) and imports engine/session code directly. + # Keep in sync with apps/mcp/.releaserc.cjs include list and + # .github/package-impact-map.md. - 'apps/mcp/**' + - 'packages/sdk/**' + - 'apps/cli/**' + - 'packages/document-api/**' + - 'packages/superdoc/**' + - 'packages/super-editor/**' + - 'packages/layout-engine/**' + - 'packages/word-layout/**' + - 'packages/preset-geometry/**' + - 'shared/**' - 'pnpm-workspace.yaml' - '!**/*.md' workflow_dispatch: diff --git a/.github/workflows/release-react.yml b/.github/workflows/release-react.yml index 30bedd8fdf..6f541c507e 100644 --- a/.github/workflows/release-react.yml +++ b/.github/workflows/release-react.yml @@ -7,11 +7,14 @@ on: branches: - main paths: + # React declares `superdoc` in dependencies (not peerDependencies), so + # existing consumers with lockfiles won't pick up a new core version + # until react republishes. Keep release broad until the peer-dep + # migration lands (tracked separately). See .github/package-impact-map.md. - 'packages/react/**' - 'packages/superdoc/**' - 'packages/layout-engine/**' - 'packages/super-editor/**' - - 'packages/ai/**' - 'packages/word-layout/**' - 'packages/preset-geometry/**' - 'shared/**' diff --git a/.github/workflows/release-sdk.yml b/.github/workflows/release-sdk.yml index 103bf688de..119b7fda5f 100644 --- a/.github/workflows/release-sdk.yml +++ b/.github/workflows/release-sdk.yml @@ -15,7 +15,6 @@ on: - 'packages/superdoc/**' - 'packages/super-editor/**' - 'packages/layout-engine/**' - - 'packages/ai/**' - 'packages/word-layout/**' - 'packages/preset-geometry/**' - 'shared/**' diff --git a/.github/workflows/release-superdoc.yml b/.github/workflows/release-superdoc.yml index c3f781da39..9ba85fbaa9 100644 --- a/.github/workflows/release-superdoc.yml +++ b/.github/workflows/release-superdoc.yml @@ -11,7 +11,6 @@ on: - 'packages/superdoc/**' - 'packages/layout-engine/**' - 'packages/super-editor/**' - - 'packages/ai/**' - 'packages/word-layout/**' - 'packages/preset-geometry/**' - 'shared/**' diff --git a/.github/workflows/release-template-builder.yml b/.github/workflows/release-template-builder.yml index a4d4561ca7..0f95aa59ee 100644 --- a/.github/workflows/release-template-builder.yml +++ b/.github/workflows/release-template-builder.yml @@ -8,13 +8,6 @@ on: - main paths: - 'packages/template-builder/**' - - 'packages/superdoc/**' - - 'packages/layout-engine/**' - - 'packages/super-editor/**' - - 'packages/ai/**' - - 'packages/word-layout/**' - - 'packages/preset-geometry/**' - - 'shared/**' - 'pnpm-workspace.yaml' - '!**/*.md' workflow_dispatch: diff --git a/.github/workflows/release-vscode-ext.yml b/.github/workflows/release-vscode-ext.yml index 6e8baecaaa..8a149188ab 100644 --- a/.github/workflows/release-vscode-ext.yml +++ b/.github/workflows/release-vscode-ext.yml @@ -11,7 +11,6 @@ on: - 'packages/superdoc/**' - 'packages/layout-engine/**' - 'packages/super-editor/**' - - 'packages/ai/**' - 'packages/word-layout/**' - 'packages/preset-geometry/**' - 'shared/**' diff --git a/.github/workflows/visual-test.yml b/.github/workflows/visual-test.yml index c47c121713..4c86af2b48 100644 --- a/.github/workflows/visual-test.yml +++ b/.github/workflows/visual-test.yml @@ -11,7 +11,6 @@ on: - 'packages/superdoc/**' - 'packages/layout-engine/**' - 'packages/super-editor/**' - - 'packages/ai/**' - 'packages/word-layout/**' - 'packages/preset-geometry/**' - 'tests/visual/**' diff --git a/apps/cli/.releaserc.cjs b/apps/cli/.releaserc.cjs index 950fe38849..ca0b8e3cd2 100644 --- a/apps/cli/.releaserc.cjs +++ b/apps/cli/.releaserc.cjs @@ -13,7 +13,6 @@ require('../../scripts/semantic-release/patch-commit-filter.cjs')([ 'packages/superdoc', 'packages/super-editor', 'packages/layout-engine', - 'packages/ai', 'packages/word-layout', 'packages/preset-geometry', 'shared', diff --git a/apps/mcp/.releaserc.cjs b/apps/mcp/.releaserc.cjs index 5fd7f91913..a7d22596d6 100644 --- a/apps/mcp/.releaserc.cjs +++ b/apps/mcp/.releaserc.cjs @@ -1,4 +1,28 @@ /* eslint-env node */ +/* + * Commit filter: MCP depends on SDK (workspace:*) and imports engine/session + * code directly. Git log must include commits touching those paths so MCP + * picks up SDK/core fixes. This shared helper patches git-log-parser to + * expand path coverage. It REPLACES semantic-release-commit-filter — do not + * use both (the filter restricts to CWD, which undoes the expansion). + * + * Keep in sync with .github/workflows/release-mcp.yml paths and + * .github/package-impact-map.md. + */ +require('../../scripts/semantic-release/patch-commit-filter.cjs')([ + 'apps/mcp', + 'packages/sdk', + 'apps/cli', + 'packages/document-api', + 'packages/superdoc', + 'packages/super-editor', + 'packages/layout-engine', + 'packages/word-layout', + 'packages/preset-geometry', + 'shared', + 'pnpm-workspace.yaml', +]); + const branch = process.env.GITHUB_REF_NAME || process.env.CI_COMMIT_BRANCH; const branches = [ @@ -17,7 +41,6 @@ const config = { branches, tagFormat: 'mcp-v${version}', plugins: [ - 'semantic-release-commit-filter', '@semantic-release/commit-analyzer', notesPlugin, ['@semantic-release/npm'], diff --git a/apps/vscode-ext/.releaserc.cjs b/apps/vscode-ext/.releaserc.cjs index 214a88ceae..971762aea1 100644 --- a/apps/vscode-ext/.releaserc.cjs +++ b/apps/vscode-ext/.releaserc.cjs @@ -13,7 +13,6 @@ require('../../scripts/semantic-release/patch-commit-filter.cjs')([ 'packages/superdoc', 'packages/super-editor', 'packages/layout-engine', - 'packages/ai', 'packages/word-layout', 'packages/preset-geometry', 'shared', diff --git a/packages/esign/.releaserc.cjs b/packages/esign/.releaserc.cjs index f4a177a602..0f314e7cd9 100644 --- a/packages/esign/.releaserc.cjs +++ b/packages/esign/.releaserc.cjs @@ -1,24 +1,11 @@ /* eslint-env node */ /* - * Commit filter: esign depends on superdoc, so git log must include - * commits touching superdoc's sub-packages. This shared helper patches - * git-log-parser to expand path coverage. It REPLACES - * semantic-release-commit-filter — do not use both (the filter restricts - * to CWD, which undoes the expansion). - * - * Keep in sync with .github/workflows/release-esign.yml paths: trigger. + * Release narrow: esign externalizes `superdoc` in its build, so a core + * change does not alter the published esign tarball (consumers get the new + * core via their own peerDependencies install). Only commits touching + * packages/esign/** should trigger a release. See + * .github/package-impact-map.md. */ -require('../../scripts/semantic-release/patch-commit-filter.cjs')([ - 'packages/esign', - 'packages/superdoc', - 'packages/super-editor', - 'packages/layout-engine', - 'packages/ai', - 'packages/word-layout', - 'packages/preset-geometry', - 'shared', - 'pnpm-workspace.yaml', -]); const branch = process.env.GITHUB_REF_NAME || process.env.CI_COMMIT_BRANCH; @@ -40,21 +27,8 @@ const config = { branches, tagFormat: 'esign-v${version}', plugins: [ - [ - '@semantic-release/commit-analyzer', - { - // Cap at minor — esign depends on superdoc, so upstream breaking - // changes don't break esign's own public API. - // Prevents accidental major bumps from superdoc feat!/BREAKING CHANGE commits. - releaseRules: [ - { breaking: true, release: 'minor' }, - { type: 'feat', release: 'minor' }, - { type: 'fix', release: 'patch' }, - { type: 'perf', release: 'patch' }, - { type: 'revert', release: 'patch' }, - ], - }, - ], + 'semantic-release-commit-filter', + '@semantic-release/commit-analyzer', notesPlugin, ['@semantic-release/npm', { npmPublish: true }], ], diff --git a/packages/react/.releaserc.cjs b/packages/react/.releaserc.cjs index 2a427aab25..3571721b49 100644 --- a/packages/react/.releaserc.cjs +++ b/packages/react/.releaserc.cjs @@ -1,19 +1,18 @@ /* eslint-env node */ /* - * Commit filter: react wraps superdoc, so git log must include - * commits touching superdoc's sub-packages. This shared helper patches - * git-log-parser to expand path coverage. It REPLACES - * semantic-release-commit-filter — do not use both (the filter restricts - * to CWD, which undoes the expansion). + * Commit filter: react declares `superdoc` in dependencies (not + * peerDependencies), so existing consumers with lockfiles won't pick up a + * new core version until react republishes. Expand commit analysis into + * core paths so semantic-release triggers a react release on core changes. * - * Keep in sync with .github/workflows/release-react.yml paths: trigger. + * When react migrates `superdoc` to peerDependencies, narrow this to + * packages/react only. See .github/package-impact-map.md. */ require('../../scripts/semantic-release/patch-commit-filter.cjs')([ 'packages/react', 'packages/superdoc', 'packages/super-editor', 'packages/layout-engine', - 'packages/ai', 'packages/word-layout', 'packages/preset-geometry', 'shared', @@ -43,8 +42,8 @@ const config = { [ '@semantic-release/commit-analyzer', { - // Cap at minor — react wraps superdoc, so upstream breaking - // changes don't break react's own public API. + // Cap at minor — react declares superdoc in dependencies, so + // upstream breaking changes don't break react's own public API. // Prevents accidental major bumps from superdoc feat!/BREAKING CHANGE commits. releaseRules: [ { breaking: true, release: 'minor' }, diff --git a/packages/react/package.json b/packages/react/package.json index b1263315ef..0c141cc074 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -40,7 +40,8 @@ }, "peerDependencies": { "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "react-dom": ">=16.8.0", + "superdoc": ">=1.0.0" }, "devDependencies": { "@testing-library/react": "catalog:", diff --git a/packages/sdk/.releaserc.cjs b/packages/sdk/.releaserc.cjs index bf9c50fca5..ea2f22e2f1 100644 --- a/packages/sdk/.releaserc.cjs +++ b/packages/sdk/.releaserc.cjs @@ -13,7 +13,6 @@ require('../../scripts/semantic-release/patch-commit-filter.cjs')([ 'packages/superdoc', 'packages/super-editor', 'packages/layout-engine', - 'packages/ai', 'packages/word-layout', 'packages/preset-geometry', 'shared', diff --git a/packages/superdoc/.releaserc.cjs b/packages/superdoc/.releaserc.cjs index 3d2f9de69b..e0d55b3570 100644 --- a/packages/superdoc/.releaserc.cjs +++ b/packages/superdoc/.releaserc.cjs @@ -10,7 +10,6 @@ const SUPERDOC_PACKAGES = [ 'packages/superdoc', 'packages/super-editor', 'packages/layout-engine', - 'packages/ai', 'packages/word-layout', 'packages/preset-geometry', 'shared', diff --git a/packages/template-builder/.releaserc.cjs b/packages/template-builder/.releaserc.cjs index 1b624a4de0..8104a5a966 100644 --- a/packages/template-builder/.releaserc.cjs +++ b/packages/template-builder/.releaserc.cjs @@ -1,24 +1,11 @@ /* eslint-env node */ /* - * Commit filter: template-builder depends on superdoc, so git log must include - * commits touching superdoc's sub-packages. This shared helper patches - * git-log-parser to expand path coverage. It REPLACES - * semantic-release-commit-filter — do not use both (the filter restricts - * to CWD, which undoes the expansion). - * - * Keep in sync with .github/workflows/release-template-builder.yml paths: trigger. + * Release narrow: template-builder externalizes `superdoc` in its build, so a + * core change does not alter the published template-builder tarball + * (consumers get the new core via their own peerDependencies install). Only + * commits touching packages/template-builder/** should trigger a release. + * See .github/package-impact-map.md. */ -require('../../scripts/semantic-release/patch-commit-filter.cjs')([ - 'packages/template-builder', - 'packages/superdoc', - 'packages/super-editor', - 'packages/layout-engine', - 'packages/ai', - 'packages/word-layout', - 'packages/preset-geometry', - 'shared', - 'pnpm-workspace.yaml', -]); const branch = process.env.GITHUB_REF_NAME || process.env.CI_COMMIT_BRANCH; @@ -40,21 +27,8 @@ const config = { branches, tagFormat: 'template-builder-v${version}', plugins: [ - [ - '@semantic-release/commit-analyzer', - { - // Cap at minor — template-builder depends on superdoc, so upstream breaking - // changes don't break template-builder's own public API. - // Prevents accidental major bumps from superdoc feat!/BREAKING CHANGE commits. - releaseRules: [ - { breaking: true, release: 'minor' }, - { type: 'feat', release: 'minor' }, - { type: 'fix', release: 'patch' }, - { type: 'perf', release: 'patch' }, - { type: 'revert', release: 'patch' }, - ], - }, - ], + 'semantic-release-commit-filter', + '@semantic-release/commit-analyzer', notesPlugin, ['@semantic-release/npm', { npmPublish: true }], ],