@williamthorsen/release-kit 11.0.0 โ†’ 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/.meta/changelog.json +274 -2
  2. package/.readyup/kits/default.js +18 -33
  3. package/.readyup/kits/npm-auto-publish.js +24 -23
  4. package/.readyup/manifest.json +16 -11
  5. package/CHANGELOG.md +98 -0
  6. package/README.md +57 -69
  7. package/bin/release-kit.js +1 -1
  8. package/dist/esm/assertCleanWorkingTree.d.ts +1 -5
  9. package/dist/esm/assertTaggedBaseline.d.ts +29 -0
  10. package/dist/esm/assertTaggedBaseline.js +41 -0
  11. package/dist/esm/attachChangelogDiagnostics.d.ts +4 -0
  12. package/dist/esm/attachChangelogDiagnostics.js +14 -0
  13. package/dist/esm/bin/release-kit.js +88 -24
  14. package/dist/esm/buildChangelogEntries.d.ts +69 -17
  15. package/dist/esm/buildChangelogEntries.js +222 -120
  16. package/dist/esm/buildDependencyGraph.d.ts +6 -6
  17. package/dist/esm/buildEmptyReleaseEntry.d.ts +1 -8
  18. package/dist/esm/buildReleaseSummary.d.ts +2 -8
  19. package/dist/esm/buildReleaseSummary.js +2 -2
  20. package/dist/esm/buildSyntheticChangelogEntry.d.ts +3 -5
  21. package/dist/esm/buildSyntheticChangelogEntry.js +2 -2
  22. package/dist/esm/bumpVersion.d.ts +1 -8
  23. package/dist/esm/changelogJsonFile.d.ts +5 -7
  24. package/dist/esm/changelogJsonFile.js +2 -17
  25. package/dist/esm/changelogJsonUtils.d.ts +7 -10
  26. package/dist/esm/changelogOverrides.d.ts +79 -100
  27. package/dist/esm/changelogOverrides.js +138 -58
  28. package/dist/esm/classifyChangelogCommit.d.ts +36 -0
  29. package/dist/esm/classifyChangelogCommit.js +34 -0
  30. package/dist/esm/commitCommand.d.ts +2 -4
  31. package/dist/esm/compareVersions.d.ts +10 -4
  32. package/dist/esm/compareVersions.js +16 -0
  33. package/dist/esm/configFlagSchema.d.ts +1 -1
  34. package/dist/esm/createGithubRelease.d.ts +7 -19
  35. package/dist/esm/createGithubReleaseCommand.d.ts +5 -5
  36. package/dist/esm/createGithubReleaseCommand.js +9 -9
  37. package/dist/esm/createTags.d.ts +2 -3
  38. package/dist/esm/decideRelease.d.ts +11 -41
  39. package/dist/esm/decideRelease.js +5 -27
  40. package/dist/esm/defaults.d.ts +5 -24
  41. package/dist/esm/defaults.js +7 -5
  42. package/dist/esm/defineConfig.d.ts +1 -1
  43. package/dist/esm/deleteFileIfExists.d.ts +1 -1
  44. package/dist/esm/deriveReleaseNotesConfig.d.ts +20 -0
  45. package/dist/esm/deriveReleaseNotesConfig.js +21 -0
  46. package/dist/esm/deriveWorkspaceConfig.d.ts +3 -5
  47. package/dist/esm/detectPackageManager.d.ts +2 -4
  48. package/dist/esm/detectUndeclaredTagPrefixes.d.ts +4 -6
  49. package/dist/esm/detectUndeclaredTagPrefixes.js +1 -1
  50. package/dist/esm/determineBumpType.d.ts +11 -11
  51. package/dist/esm/determineBumpType.js +6 -7
  52. package/dist/esm/discoverWorkspaces.d.ts +14 -15
  53. package/dist/esm/discoverWorkspaces.js +12 -12
  54. package/dist/esm/enterRepoRoot.d.ts +12 -0
  55. package/dist/esm/enterRepoRoot.js +16 -0
  56. package/dist/esm/enumerateReleaseWindows.d.ts +50 -0
  57. package/dist/esm/enumerateReleaseWindows.js +124 -0
  58. package/dist/esm/extractMigration.d.ts +6 -8
  59. package/dist/esm/findUnroutedEntryScopes.d.ts +16 -0
  60. package/dist/esm/findUnroutedEntryScopes.js +57 -0
  61. package/dist/esm/formatExcludedSkip.d.ts +3 -0
  62. package/dist/esm/formatExcludedSkip.js +3 -0
  63. package/dist/esm/formatPrivateSkip.d.ts +1 -6
  64. package/dist/esm/generateChangelogs.d.ts +13 -26
  65. package/dist/esm/generateChangelogs.js +0 -14
  66. package/dist/esm/glyphs.d.ts +2 -2
  67. package/dist/esm/help/prepareHelp.d.ts +3 -4
  68. package/dist/esm/help/prepareHelp.js +7 -8
  69. package/dist/esm/index.d.ts +1 -1
  70. package/dist/esm/init/checks.d.ts +3 -3
  71. package/dist/esm/init/checks.js +4 -1
  72. package/dist/esm/init/detectRepoType.d.ts +2 -3
  73. package/dist/esm/init/hasProvenance.d.ts +2 -0
  74. package/dist/esm/init/hasProvenance.js +3 -0
  75. package/dist/esm/init/initCommand.d.ts +3 -6
  76. package/dist/esm/init/initCommand.js +11 -11
  77. package/dist/esm/init/parseJsonRecord.d.ts +1 -4
  78. package/dist/esm/init/scaffold.d.ts +1 -3
  79. package/dist/esm/init/scaffold.js +2 -30
  80. package/dist/esm/init/templates.d.ts +9 -11
  81. package/dist/esm/init/templates.js +12 -11
  82. package/dist/esm/init/updateTemplatesCommand.d.ts +13 -0
  83. package/dist/esm/init/updateTemplatesCommand.js +64 -0
  84. package/dist/esm/injectReleaseNotesIntoReadme.d.ts +12 -17
  85. package/dist/esm/injectSection.d.ts +3 -3
  86. package/dist/esm/loadConfig.d.ts +16 -14
  87. package/dist/esm/loadConfig.js +2 -5
  88. package/dist/esm/loadValidatedConfig.d.ts +16 -19
  89. package/dist/esm/loadValidatedConfig.js +6 -1
  90. package/dist/esm/packsPath.d.ts +9 -9
  91. package/dist/esm/parseChangeRecordBlock.d.ts +37 -0
  92. package/dist/esm/parseChangeRecordBlock.js +134 -0
  93. package/dist/esm/parseCommitMessage.d.ts +42 -32
  94. package/dist/esm/parseCommitMessage.js +33 -41
  95. package/dist/esm/parseRequestedTags.d.ts +3 -3
  96. package/dist/esm/planReleaseNotesPreviews.d.ts +6 -6
  97. package/dist/esm/planVersionBump.d.ts +5 -3
  98. package/dist/esm/planVersionBump.js +3 -0
  99. package/dist/esm/prepareCommand.d.ts +4 -7
  100. package/dist/esm/prepareCommand.js +17 -18
  101. package/dist/esm/previewTagPrefixes.d.ts +8 -10
  102. package/dist/esm/propagateBumps.d.ts +6 -7
  103. package/dist/esm/publish.d.ts +1 -1
  104. package/dist/esm/publishCommand.d.ts +4 -3
  105. package/dist/esm/publishCommand.js +8 -8
  106. package/dist/esm/pushCommand.d.ts +4 -3
  107. package/dist/esm/pushCommand.js +8 -2
  108. package/dist/esm/pushRelease.d.ts +2 -2
  109. package/dist/esm/readChangelogSections.d.ts +33 -0
  110. package/dist/esm/readChangelogSections.js +80 -0
  111. package/dist/esm/releaseFiles.d.ts +5 -7
  112. package/dist/esm/releasePlan.d.ts +11 -13
  113. package/dist/esm/releasePrepare.d.ts +25 -25
  114. package/dist/esm/releasePrepare.js +80 -80
  115. package/dist/esm/releasePrepareMono.d.ts +9 -7
  116. package/dist/esm/releasePrepareMono.js +114 -99
  117. package/dist/esm/releasePrepareProject.d.ts +19 -29
  118. package/dist/esm/releasePrepareProject.js +46 -45
  119. package/dist/esm/renderChangelogMarkdown.d.ts +10 -4
  120. package/dist/esm/renderChangelogMarkdown.js +27 -2
  121. package/dist/esm/renderReleaseNotes.d.ts +3 -11
  122. package/dist/esm/renderReleaseNotes.js +2 -6
  123. package/dist/esm/reportPrepare.d.ts +4 -5
  124. package/dist/esm/reportPrepare.js +67 -42
  125. package/dist/esm/resolveCommandTags.d.ts +15 -11
  126. package/dist/esm/resolveCommandTags.js +35 -5
  127. package/dist/esm/resolveConfigFlag.d.ts +7 -0
  128. package/dist/esm/resolveConfigFlag.js +4 -0
  129. package/dist/esm/resolveReleaseTags.d.ts +6 -8
  130. package/dist/esm/resolveReleaseTags.js +1 -1
  131. package/dist/esm/resolveStylesOrExit.d.ts +2 -2
  132. package/dist/esm/showTagPrefixesCommand.d.ts +7 -10
  133. package/dist/esm/showTagPrefixesCommand.js +4 -4
  134. package/dist/esm/stripEmojiPrefix.d.ts +1 -0
  135. package/dist/esm/stripScope.d.ts +2 -2
  136. package/dist/esm/stripScope.js +3 -3
  137. package/dist/esm/sync-labels/generateCommand.d.ts +11 -10
  138. package/dist/esm/sync-labels/generateCommand.js +11 -8
  139. package/dist/esm/sync-labels/initCommand.d.ts +6 -7
  140. package/dist/esm/sync-labels/initCommand.js +2 -2
  141. package/dist/esm/sync-labels/presets.d.ts +5 -4
  142. package/dist/esm/sync-labels/presets.js +9 -9
  143. package/dist/esm/sync-labels/resolveLabels.d.ts +7 -7
  144. package/dist/esm/sync-labels/resolveLabels.js +1 -1
  145. package/dist/esm/sync-labels/retiredConfig.d.ts +4 -5
  146. package/dist/esm/sync-labels/syncCommand.d.ts +1 -4
  147. package/dist/esm/sync-labels/templates.d.ts +3 -3
  148. package/dist/esm/sync-labels/templates.js +3 -3
  149. package/dist/esm/sync-labels/typeLabels.d.ts +14 -0
  150. package/dist/esm/sync-labels/typeLabels.js +38 -0
  151. package/dist/esm/sync-labels/types.d.ts +1 -1
  152. package/dist/esm/tagCommand.d.ts +1 -1
  153. package/dist/esm/typeGuards.d.ts +2 -2
  154. package/dist/esm/types.d.ts +185 -116
  155. package/dist/esm/types.js +2 -2
  156. package/dist/esm/validateConfig.d.ts +2 -11
  157. package/dist/esm/validateConfig.js +5 -1
  158. package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +14 -12
  159. package/dist/esm/validateOverridesCommand.d.ts +19 -21
  160. package/dist/esm/validateOverridesCommand.js +16 -23
  161. package/docs/api.md +6 -6
  162. package/docs/changelogs.md +90 -28
  163. package/docs/configuration.md +30 -29
  164. package/docs/editorial-overrides.md +90 -31
  165. package/docs/labels.md +21 -19
  166. package/docs/project-releases.md +14 -14
  167. package/docs/publishing.md +5 -5
  168. package/docs/readiness-checks.md +3 -3
  169. package/docs/releasing.md +54 -24
  170. package/docs/work-types.md +46 -58
  171. package/package.json +7 -7
  172. package/presets/labels/common.yaml +1 -41
  173. package/schemas/changelog-overrides.json +39 -0
  174. package/cliff.toml.template +0 -65
  175. package/dist/esm/collectPolicyViolations.d.ts +0 -15
  176. package/dist/esm/collectPolicyViolations.js +0 -12
  177. package/dist/esm/determineBumpFromCommits.d.ts +0 -17
  178. package/dist/esm/determineBumpFromCommits.js +0 -28
  179. package/dist/esm/getCommitsSinceTarget.d.ts +0 -21
  180. package/dist/esm/getCommitsSinceTarget.js +0 -66
  181. package/dist/esm/resolveCliffConfigPath.d.ts +0 -11
  182. package/dist/esm/resolveCliffConfigPath.js +0 -20
  183. package/dist/esm/resolveReleaseNotesConfig.d.ts +0 -26
  184. package/dist/esm/resolveReleaseNotesConfig.js +0 -29
  185. package/dist/esm/runGitCliff.d.ts +0 -38
  186. package/dist/esm/runGitCliff.js +0 -25
  187. package/dist/esm/workTypesData.d.ts +0 -50
  188. package/dist/esm/workTypesData.js +0 -145
  189. package/schemas/label-map.json +0 -24
package/docs/releasing.md CHANGED
@@ -1,43 +1,59 @@
1
1
  # Releasing
2
2
 
3
- How to scaffold the release workflows, what `release-kit prepare` does with its flags, and how the release workflow runs a release.
3
+ How to scaffold the release workflows and keep them up to date, what `release-kit prepare` does with its flags, and how the release workflow runs a release.
4
4
 
5
5
  The [README](../README.md#quick-start) shows the first run.
6
6
 
7
7
  ## `release-kit init`
8
8
 
9
- Initialize release-kit in the current repository. By default, scaffolds only the GitHub Actions workflow files. Use `--with-config` to also scaffold configuration files.
9
+ Initializes release-kit in the current repository. By default, scaffolds only the GitHub Actions workflow files. Use `--with-config` to also scaffold configuration files.
10
10
 
11
11
  Scaffolded files:
12
12
 
13
- - `.github/workflows/create-github-release.yaml` โ€” workflow that creates a GitHub Release on tag push, independent of npm publish
14
- - `.github/workflows/publish.yaml` โ€” workflow that delegates to a reusable publish workflow
15
- - `.github/workflows/release.yaml` โ€” workflow that delegates to a reusable release workflow
16
- - `.config/release-kit.config.ts` โ€” starter config with commented-out customization examples (with `--with-config`)
17
- - `.config/git-cliff.toml` โ€” copied from the bundled template (with `--with-config`)
13
+ - `.github/workflows/create-github-release.yaml`: Workflow that creates a GitHub Release on tag push, independent of npm publish
14
+ - `.github/workflows/publish.yaml`: Workflow that delegates to a reusable publish workflow
15
+ - `.github/workflows/release.yaml`: Workflow that delegates to a reusable release workflow
16
+ - `.config/release-kit.config.ts`: Starter config with commented-out customization examples (with `--with-config`)
17
+
18
+ ## `release-kit update-templates`
19
+
20
+ Updates the scaffolded workflows to the templates of the installed release-kit version, and prints what changed in each file. Run it after upgrading release-kit; `--dry-run` previews the changes without writing them.
21
+
22
+ The workflows are managed files: release-kit renders them, and a change made by hand is overwritten on the next update. The config files are the repository's own, and the command never reads or writes them.
23
+
24
+ - It creates a missing workflow that `init` would create.
25
+ - It refreshes `.github/workflows/sync-labels.yaml` only when the file exists, because `sync-labels init` scaffolds it on request.
26
+ - It keeps `publish.yaml`'s provenance setting: When the file does not set `provenance: true`, as in a private repository, the updated file does not either.
18
27
 
19
28
  ## `release-kit prepare`
20
29
 
21
- Run release preparation with automatic workspace discovery.
30
+ Runs release preparation with automatic workspace discovery.
22
31
 
23
32
  Workspace names for `--only` match the package directory name (e.g., `arrays`, `release-kit`).
24
33
 
25
- `--bump` and `--force` are orthogonal: `--bump` is purely a level chooser; `--force` is purely a release trigger. Examples:
34
+ `prepare` reads each target's history once and builds the changelog items of its unreleased commits. The bump is the highest level that those items call for, under [`versionPatterns`](configuration.md#versionpatterns), so the bump and the changelog describe the same release: A `feat` entry in a [change-record block](changelogs.md#change-record-blocks) bumps minor under a `docs:` title, and a breaking item bumps major.
35
+
36
+ - A commit that doesn't yield an item doesn't bump anything: one without a ticket-ID prefix, one of a type excluded from the changelog (such as `fmt`), and one whose change-record entries are all undeclared or excluded.
37
+ - A `BREAKING CHANGE:` footer doesn't raise a major bump. Only a subject's `!` and an entry's `breaking: true` mark an item breaking; on a type whose policy forbids `!`, the footer is reported as a [policy violation](work-types.md#policy-enforcement).
38
+ - A target whose commits don't yield an item is skipped. The prepare report lists the commits that could not be parsed and the change-record diagnostics, skipped targets included.
39
+
40
+ `--bump` and `--force` are orthogonal in every mode, single-package included: `--bump` is purely a level chooser; `--force` is purely a release trigger. Examples:
26
41
 
27
42
  ```sh
28
43
  # Release every target at its natural bump level (no flags).
29
44
  release-kit prepare
30
45
 
31
- # Force a release even when no bump-worthy commits exist; defaults to patch
32
- # per target, with each target keeping its natural bump if one is derivable.
46
+ # Force a release even when the commits don't yield any changelog item;
47
+ # defaults to patch per target, with each target keeping its natural bump
48
+ # if it has one.
33
49
  release-kit prepare --force
34
50
 
35
51
  # Force a release at a uniform level across every releasing target.
36
52
  release-kit prepare --force --bump=minor
37
53
 
38
- # --bump=X alone is a level chooser, NOT a trigger. If a target has no
39
- # bump-worthy commits, it skips with a "Pass --force..." reason. If it has
40
- # bump-worthy commits, the override applies.
54
+ # --bump=X alone is a level chooser, NOT a trigger. If a target's commits
55
+ # don't yield any changelog item, it skips with a "Pass --force..." reason.
56
+ # Otherwise the override applies.
41
57
  release-kit prepare --bump=minor
42
58
  ```
43
59
 
@@ -45,10 +61,10 @@ release-kit prepare --bump=minor
45
61
 
46
62
  `--with-release-notes` writes two versioned files per workspace after each workspace's `changelog.json` is produced:
47
63
 
48
- - `<workspacePath>/docs/README.v<version>.md` โ€” the workspace `README.md` with release notes injected at the `<!-- section:release-notes -->` marker.
49
- - `<workspacePath>/docs/RELEASE_NOTES.v<version>.md` โ€” the standalone release notes for this version.
64
+ - `<workspacePath>/docs/README.v<version>.md`: The workspace `README.md` with release notes injected at the `<!-- section:release-notes -->` marker.
65
+ - `<workspacePath>/docs/RELEASE_NOTES.v<version>.md`: The standalone release notes for this version.
50
66
 
51
- The publish-time inject-and-revert lifecycle is unchanged; previews are additive, deterministic, and safe to regenerate. When `changelogJson.enabled` is `false`, prepare reports a warning and skips preview generation. In dry-run mode, planned writes are logged and no files are created.
67
+ The publish-time inject-and-revert lifecycle is unchanged; previews are additive, deterministic, and safe to regenerate. When `changelogJson.enabled` is `false`, prepare reports a warning and skips preview generation. In dry-run mode, prepare logs the planned writes and doesn't create any files.
52
68
 
53
69
  Because preview filenames are versioned, committing them will accumulate files over time. The recommended `.gitignore` entry for monorepos is:
54
70
 
@@ -64,7 +80,7 @@ docs/*.v*.md
64
80
 
65
81
  ### Setting an explicit version with `--set-version`
66
82
 
67
- The `--set-version` flag is a first-class escape hatch for the cases where commit-derived bump logic produces the wrong version โ€” most notably, promoting a pre-1.0 package to 1.0.0. Pre-1.0 packages collapse a `feat!` breaking change to a minor bump (matching semantic-release's `initialMajor: false` and release-please's `bump-minor-pre-major`), so a deliberate promotion to 1.0.0 must be requested explicitly.
83
+ The `--set-version` flag is a first-class escape hatch for the cases in which the derived bump produces the wrong version, most notably when promoting a pre-1.0 package to 1.0.0. Pre-1.0 packages collapse a `feat!` breaking change to a minor bump (matching semantic-release's `initialMajor: false` and release-please's `bump-minor-pre-major`), so a deliberate promotion to 1.0.0 must be requested explicitly.
68
84
 
69
85
  The flag validates that:
70
86
 
@@ -80,17 +96,31 @@ Promoting a pre-1.0 package to 1.0.0 in a monorepo:
80
96
  release-kit prepare --only arrays --set-version 1.0.0
81
97
  ```
82
98
 
83
- An empty changelog section is expected for a bare promotion, because the changelog is generated from commits since the last tag. To include a narrative entry, land a descriptive release commit (e.g., a `feat!` describing the stable API) before running `prepare`.
99
+ An empty changelog section is expected for a bare promotion, because the changelog is generated from commits since the last tag. To include a narrative entry, merge a descriptive release commit (e.g., a `feat!` describing the stable API) before running `prepare`.
100
+
101
+ ### Adopting release-kit in a repo with untagged releases
102
+
103
+ `prepare` finds a target's previous release by its tag. When a target's current version was released and recorded in its `CHANGELOG.md` or `changelog.json` but never tagged, the unreleased window would extend back to the start of history: The new version would absorb every earlier commit, and its bump would be derived from all of them. `prepare` stops before writing anything instead, under `--force` and `--set-version` too, and names each target, its version, and the tag to create:
104
+
105
+ ```text
106
+ The current version is recorded in the changelog, but its tag is not the previous tag reachable from HEAD:
107
+ - workspace 'api': 1.2.0 (create tag api-v1.2.0)
108
+ Tag the commit that released each version, then run prepare again.
109
+ ```
110
+
111
+ Tag each named version at the commit that released it, then run `prepare` again. In a monorepo, `prepare` checks the project only after every workspace passes, so a second run can name the project's tag. The check skips a first release, whose version isn't recorded in any changelog, and a workspace that releases only through propagation.
112
+
113
+ Each new tag closes a release window. When that window's commits yield items, `prepare` renders the tagged version from them, in place of its hand-written section; it keeps every other hand-written version as [Existing `CHANGELOG.md` sections](changelogs.md#existing-changelogmd-sections) describes.
84
114
 
85
115
  ## GitHub Actions workflow
86
116
 
87
117
  The `init` command scaffolds a release workflow at `.github/workflows/release.yaml` that delegates to a reusable release workflow. The scaffolded workflow accepts these inputs:
88
118
 
89
- | Input | Type | Description |
90
- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------- |
91
- | `only` | string | Workspaces to release (comma-separated, leave empty for all) |
92
- | `bump` | choice | Override bump type: `patch`, `minor`, `major` (empty = auto-detect) |
93
- | `force` | boolean | Release even when no commits or no bump-worthy commits exist (defaults to patch; combine with `bump` for a different level) |
119
+ | Input | Type | Description |
120
+ | ------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
121
+ | `only` | string | Workspaces to release (comma-separated, leave empty for all) |
122
+ | `bump` | choice | Bump type: `auto` (default, detects it from commits), `patch`, `minor`, or `major` |
123
+ | `force` | boolean | Release even when the window doesn't have any commits or any bump-worthy commits (defaults to patch; combine with `bump` for a different level) |
94
124
 
95
125
  For repos that need a self-contained workflow instead of the reusable one, the scaffolded file can be expanded. The key steps are: checkout with full history (`fetch-depth: 0`), run `release-kit prepare` with optional `--only`, `--bump`, and `--force` flags, check for changes, read tags from `tmp/.release-tags`, then commit, tag, and push.
96
126
 
@@ -1,60 +1,63 @@
1
1
  # Work types and tiers
2
2
 
3
- The taxonomy against which release-kit parses commits: its tiers, the breaking-change policy, section markers, customization, and the maintainer scripts that keep release-kit's copy level with its upstream.
4
-
5
- release-kit bundles a copy of the codeassembly canonical taxonomy in `packages/release-kit/src/work-types.json`, kept level by the [maintainer scripts](#maintaining-the-bundled-taxonomy). The taxonomy is split into three tiers that drive section rendering and audience classification.
6
-
7
- | Tier | Key | Header | Aliases | `!` policy |
8
- | -------- | ----------- | ------------------------- | ------------- | ------------ |
9
- | public | `feat` | ๐ŸŽ‰ Features | `feature` | optional |
10
- | public | `drop` | ๐Ÿชฆ Removed | | **required** |
11
- | public | `deprecate` | ๐Ÿ—‘๏ธ Deprecated | | forbidden |
12
- | public | `fix` | ๐Ÿ› Bug fixes | `bugfix` | optional |
13
- | public | `sec` | ๐Ÿ”’ Security | `security` | optional |
14
- | public | `perf` | โšก Performance | `performance` | optional |
15
- | internal | `internal` | ๐Ÿ—๏ธ Internal features | `utility` | forbidden |
16
- | internal | `refactor` | โ™ป๏ธ Refactoring | | forbidden |
17
- | internal | `tests` | ๐Ÿงช Tests | `test` | forbidden |
18
- | process | `tooling` | โš™๏ธ Tooling | | forbidden |
19
- | process | `ci` | ๐Ÿ‘ท CI | | forbidden |
20
- | process | `deps` | ๐Ÿ“ฆ Dependencies | `dep` | forbidden |
21
- | process | `ai` | ๐Ÿค– Agentic support | | forbidden |
22
- | process | `docs` | ๐Ÿ“š Documentation | `doc` | forbidden |
23
- | process | `fmt` | (excluded from changelog) | | forbidden |
3
+ The taxonomy against which release-kit parses commits: its tiers, the breaking-change policy, section markers, and customization.
4
+
5
+ release-kit reads the taxonomy from `CANONICAL_TAXONOMY` in [`@williamthorsen/change-grammar`](https://github.com/williamthorsen/node-monorepo-tools/tree/main/packages/change-grammar#readme), which also parses commit subjects. The taxonomy is split into three tiers that determine section rendering and audience classification.
6
+
7
+ | Tier | Key | Header | Aliases | `!` policy |
8
+ | -------- | ----------- | ------------------------- | ------------- | ---------- |
9
+ | public | `feat` | ๐ŸŽ‰ Features | `feature` | optional |
10
+ | public | `drop` | ๐Ÿชฆ Removed | | optional |
11
+ | public | `deprecate` | ๐Ÿ—‘๏ธ Deprecated | | forbidden |
12
+ | public | `fix` | ๐Ÿ› Bug fixes | `bugfix` | optional |
13
+ | public | `sec` | ๐Ÿ”’ Security | `security` | optional |
14
+ | public | `perf` | โšก Performance | `performance` | optional |
15
+ | internal | `internal` | ๐Ÿ—๏ธ Internal features | `utility` | forbidden |
16
+ | internal | `refactor` | โ™ป๏ธ Refactoring | | forbidden |
17
+ | internal | `tests` | ๐Ÿงช Tests | `test` | forbidden |
18
+ | process | `tooling` | โš™๏ธ Tooling | | forbidden |
19
+ | process | `ci` | ๐Ÿ‘ท CI | | forbidden |
20
+ | process | `deps` | ๐Ÿ“ฆ Dependencies | `dep` | forbidden |
21
+ | process | `ai` | ๐Ÿค– Agentic support | | forbidden |
22
+ | process | `docs` | ๐Ÿ“š Documentation | `doc` | forbidden |
23
+ | process | `fmt` | (excluded from changelog) | | forbidden |
24
24
 
25
25
  ## Tier semantics
26
26
 
27
- - **`public`** โ€” visible to all audiences. `public`-tier sections appear in both public release notes and dev changelogs.
28
- - **`internal`** โ€” dev-only. `internal`-tier sections appear in dev changelogs but not in public-facing release notes.
29
- - **`process`** โ€” dev-only. Same audience treatment as `internal`.
27
+ - **`public`**: Visible to all audiences. `public`-tier sections appear in both public release notes and dev changelogs.
28
+ - **`internal`**: Dev-only. `internal`-tier sections appear in dev changelogs but not in public-facing release notes.
29
+ - **`process`**: Dev-only. Same audience treatment as `internal`.
30
30
 
31
- Section render order is **tier order (`public` โ†’ `internal` โ†’ `process`), then row order within tier**. The bundled `cliff.toml.template` encodes this order via hidden `<!-- NN -->` HTML-comment prefixes on each parser's `group` value; tera's `group_by` filter sorts groups lexicographically (now monotonic by row number), and the body template's `striptags` filter erases the prefix from rendered headings.
31
+ Section render order is **tier order (`public` โ†’ `internal` โ†’ `process`), then row order within tier**. It comes from the declaration order of `CANONICAL_TAXONOMY`: `CANONICAL_SECTION_ORDER` in `buildChangelogEntries.ts` indexes each header by its row, and `transformReleases` sorts a release's sections by that index whatever order the commits arrived in.
32
+
33
+ ## Subject forms
34
+
35
+ `classifyChangelogCommit` resolves a commit's type through `parseCommitMessage`, so a subject maps to its section under any form that the parser accepts: `type:`, `scope|type:`, and the conventional-commit `type(scope):`, each followed by a space and a title. A subject combining both scope forms, such as `web|feat(api):`, does not parse. The type is matched case-insensitively: `Feat:` and `FEAT:` resolve like `feat:`. The ticket-ID prefix is still required, and an alias resolves before the section is chosen. A commit whose [change-record block](changelogs.md#change-record-blocks) records entries takes its sections from the entries' types instead of from its subject.
32
36
 
33
37
  ## `utility` alias
34
38
 
35
- `utility:` is a backward-compat alias for `internal:`. Both forms parse to the same canonical type, route to the same `๐Ÿ—๏ธ Internal features` section, and are subject to the same `!` policy.
39
+ `utility:` is a backward-compat alias for `internal:`. Both forms parse to the same canonical type, appear under the same `๐Ÿ—๏ธ Internal features` section, and are subject to the same `!` policy.
36
40
 
37
41
  ## `!` (breaking change) policy
38
42
 
39
- Each work-type carries a `breakingPolicy` value:
43
+ Each work-type has a `breakingPolicy` value:
40
44
 
41
- - `optional` (`feat`, `fix`, `sec`, `perf`): `!` is allowed; both `type:` and `type!:` parse cleanly. Any of these can break consumers, and the marker records when one does: A fix can break consumers who relied on the defective behavior, and a performance change can break a contract to achieve its gain.
45
+ - `optional` (`feat`, `drop`, `fix`, `sec`, `perf`): `!` is allowed; both `type:` and `type!:` parse cleanly. Any of these can break consumers, and the marker records when one does: A removal breaks consumers only when the removed surface was published, a fix can break consumers who relied on the defective behavior, and a performance change can break a contract to achieve its gain.
42
46
  - `forbidden` (`deprecate` and every `internal`- and `process`-tier type): `!` is a policy violation. Deprecating a surface keeps it working, and removing it is a `drop`. Internal- and process-tier work does not face consumers; a change that breaks consumers faces them and therefore takes a public-tier type.
43
- - `required` (`drop`): Bare `drop:` is a policy violation; only `drop!:` is accepted. Removing a public surface always breaks consumers, and the `!` form makes that explicit.
44
47
 
45
48
  ### Policy enforcement
46
49
 
47
- `parseCommitMessage` enforces the `!` policy at release time and treats a violation as a warning. Commits already in the log cannot be rewritten, so a policy-violating commit is parsed using its canonical type with `breaking: false` (the `!` is dropped from the parse) and an `onPolicyViolation` callback fires. Callers (`decideRelease` etc.) can collect these warnings and surface them in the release report. A single legacy `internal!` in a year-old log does not block releases.
50
+ `parseCommitMessage` enforces the `!` policy at release time and treats a violation as a warning. Commits already in the log cannot be rewritten, so a policy-violating commit is parsed using its canonical type with `breaking: false` (the `!` is dropped from the parse) and an `onPolicyViolation` callback fires. `readReleaseHistory` collects these warnings while it builds the items of the unreleased window, and the release report lists them. A single legacy `internal!` in a year-old log does not block releases.
48
51
 
49
- A `BREAKING CHANGE:` body footer on a `forbidden`-policy type triggers the same warning path as the prefix `!` does: A type that cannot be breaking is parsed as non-breaking whichever surface carries the signal.
52
+ A `BREAKING CHANGE:` body footer on a `forbidden`-policy type triggers the same warning path as the prefix `!` does: A type that cannot be breaking is parsed as non-breaking whichever surface has the signal. The warning is all that a footer triggers; it doesn't raise a bump (see [`๐Ÿšจ **Breaking:**` bullet marker](#-breaking-bullet-marker)).
50
53
 
51
- The release-prepare orchestrators (`releasePrepare`, `releasePrepareMono`, `releasePrepareProject`) apply `DEFAULT_BREAKING_POLICIES` automatically. Violations encountered while parsing each workspace's or project's commit window are collected onto the corresponding result's `policyViolations` field and rendered under the section in the prepare report:
54
+ The release-prepare orchestrators (`releasePrepare`, `releasePrepareMono`, `releasePrepareProject`) apply `DEFAULT_BREAKING_POLICIES` automatically. Violations in the titles and change-record entries of each workspace's or project's unreleased window are collected onto the corresponding result's `policyViolations` field, on a skipped result as on a released one, and rendered under the section in the prepare report:
52
55
 
53
56
  ```
54
57
  arrays
55
58
  Found 1 commits since arrays-v1.0.0
56
59
  ๐ŸŸ  1 policy violation:
57
- ยท def5678 'internal!: refactor cache' โ€” type 'internal' at prefix surface
60
+ ยท def5678 'internal!: refactor cache': type 'internal' at prefix surface
58
61
  Bumping versions (patch)...
59
62
  ๐Ÿ“ฆ 1.0.0 โ†’ 1.0.1 (patch)
60
63
  ```
@@ -63,7 +66,7 @@ To customize, set `breakingPolicies` in `release-kit.config.ts`. The map replace
63
66
 
64
67
  ## `๐Ÿšจ **Breaking:**` bullet marker
65
68
 
66
- Items whose commit subject carries the `!` prefix (e.g. `feat!`, `drop!`, `feat(api)!`) on a type whose policy permits it are rendered with a `๐Ÿšจ **Breaking:** ` prefix on the bullet:
69
+ Items whose commit subject has the `!` prefix (e.g. `feat!`, `drop!`, `feat(api)!`) on a type whose policy permits it are rendered with a `๐Ÿšจ **Breaking:** ` prefix on the bullet:
67
70
 
68
71
  ```markdown
69
72
  - ๐Ÿšจ **Breaking:** Drop legacy /v1 endpoint
@@ -71,17 +74,17 @@ Items whose commit subject carries the `!` prefix (e.g. `feat!`, `drop!`, `feat(
71
74
 
72
75
  The marker agrees with the version bump:
73
76
 
74
- - A `forbidden`-policy type carrying `!`, such as `refactor!`, gets no marker, just as its `!` raises no bump; the prepare report lists it as a policy violation. An [editorial override](editorial-overrides.md) that sets `breaking: true` restores the marker for one entry.
77
+ - A `forbidden`-policy type with `!`, such as `refactor!`, doesn't get a marker, just as its `!` doesn't raise a bump; the prepare report lists it as a policy violation. An [editorial override](editorial-overrides.md) that sets `breaking: true` restores the marker for one entry.
75
78
  - The configured `breakingPolicies` map, `{}` included, decides which types permit the marker.
76
- - A commit whose type the parser cannot resolve has no policy, so its `!` prefix alone decides.
79
+ - A commit whose type the parser cannot resolve doesn't appear in any changelog, so the question of a marker doesn't arise.
77
80
 
78
- A `BREAKING CHANGE:` body footer on its own does **not** retroactively mark a changelog item as breaking, even on a type whose policy permits `!`; the changelog signal is tied to the commit prefix. This avoids surprise breaking-marker appearances for older commits written under earlier conventions.
81
+ A `BREAKING CHANGE:` body footer on its own does **not** retroactively mark a changelog item as breaking, even on a type whose policy permits `!`; the changelog signal is tied to the commit prefix. This avoids surprise breaking-marker appearances for older commits written under earlier conventions. Because the bump follows the items, a footer doesn't raise a major bump either: A consumer that marks breaking changes with the footer alone gets the bump of the commit's type.
79
82
 
80
- The emoji and label of this marker are sourced from the `markers.breaking` entry in `work-types.json` (see [Section markers](#section-markers)) so consumers that render their own breaking-changes section draw from the same SSOT.
83
+ The emoji and label of this marker come from the `markers.breaking` entry of `CANONICAL_TAXONOMY` (see [Section markers](#section-markers)), which is also the source for consumers that render their own breaking-changes section.
81
84
 
82
85
  ## Section markers
83
86
 
84
- Alongside `tiers` and `types`, `work-types.json` exposes a top-level `markers` object for cross-cutting section markers โ€” visual indicators that aren't tied to a specific work type. Today the canonical entry is `breaking`; additional keys (e.g., security advisories, migration notices) can be added without a schema change.
87
+ Alongside `tiers` and `types`, `CANONICAL_TAXONOMY` declares a top-level `markers` object for cross-cutting section markers: visual indicators that aren't tied to a specific work type. Today its only entry is `breaking`.
85
88
 
86
89
  ```jsonc
87
90
  {
@@ -91,29 +94,14 @@ Alongside `tiers` and `types`, `work-types.json` exposes a top-level `markers` o
91
94
  }
92
95
  ```
93
96
 
94
- Entries store plain text only โ€” the SSOT is format-agnostic, so consumers apply their own emphasis (Markdown bold, ANSI escape, HTML `<strong>`) when constructing the rendered form. release-kit's own renderer constructs the per-bullet prefix as `${emoji} **${label}:** ` from this entry.
97
+ Entries store plain text only, so that the taxonomy stays format-agnostic: Consumers apply their own emphasis (Markdown bold, ANSI escape, HTML `<strong>`) when constructing the rendered form. release-kit's own renderer constructs the per-bullet prefix as `${emoji} **${label}:** ` from this entry.
95
98
 
96
99
  ## `fmt`
97
100
 
98
- `fmt:` commits are recognized by `parseCommitMessage` (they contribute to a patch bump) but `fmt` carries `excludedFromChangelog: true`. The bundled `cliff.toml.template` skips `fmt:` commits at the parser level, so they never appear in `CHANGELOG.md`, `changelog.json`, or release notes. The label and emoji are present in `work-types.json` for schema parity with the codeassembly upstream but never render.
101
+ `fmt:` commits are recognized by `parseCommitMessage`, but `fmt` sets `excludedFromChangelog: true`, which `DEFAULT_WORK_TYPES` copies onto its `WorkTypeConfig`. `classifyChangelogCommit` excludes a commit whose type sets the flag, so a `fmt:` commit never appears in `CHANGELOG.md`, `changelog.json`, or release notes. Because it doesn't yield an item, it doesn't raise a bump, and the release report does not list it as unparseable. The taxonomy declares a label and emoji for `fmt` like any other type, but they never render.
99
102
 
100
103
  ## Custom work types
101
104
 
102
- Work types from your config are merged with these defaults by key โ€” your entries override or extend, they don't replace the full set. Release-notes sections are rendered in the declaration order of the merged work-types record, with any unknown titles trailing the known ones.
103
-
104
- The default `devOnlySections` (excluded from public release notes but still written to `CHANGELOG.md`) are derived from the `internal` and `process` tiers (excluding `fmt`). Override via `changelogJson.devOnlySections` in your config; matching is decorator-tolerant, so a bare-name override like `['Internal features']` keeps working against the emoji-prefixed and prefix-decorated default titles.
105
-
106
- ## Maintaining the bundled taxonomy
107
-
108
- `src/workTypesData.ts` mirrors `src/work-types.json` for runtime use. Two maintainer scripts of the release-kit package compare that JSON with its codeassembly upstream and update it. They exist only in a checkout of this repository and are not part of the published `release-kit` CLI.
109
-
110
- - `nmr work-types:check` compares the content of `src/work-types.json` with the upstream, ignoring the local `$schema` hint.
111
- - `nmr work-types:sync` overwrites `src/work-types.json` with the upstream when their content differs.
112
-
113
- Both run from `packages/release-kit`, or from anywhere in the repository as `nmr -F @williamthorsen/release-kit work-types:check` and `nmr -F @williamthorsen/release-kit work-types:sync`. After `sync` writes the file, update `src/workTypesData.ts` to match; `workTypesData.unit.test.ts` fails until the two agree.
114
-
115
- `check` exits 0 on a match, 1 on drift, 2 when the upstream fetch fails, and 3 when either file is not valid JSON or the upstream fails the shape check. When the upstream URL returns 404, `check` exits 0 with a warning.
116
-
117
- ### Authenticated fetches
105
+ Work types from a config are merged with these defaults by key: A consumer entry overrides or extends, it does not replace the full set. `classifyChangelogCommit` reads the merged record, so an added type appears in the changelog under the `header` that it declares, and an entry setting `excludedFromChangelog: true` keeps its commits out of the changelog and the bump. Release-notes sections are rendered in the declaration order of the merged work-types record, with any unknown titles trailing the known ones.
118
106
 
119
- The upstream codeassembly repo is public, so `check` and `sync` need no token. When `GITHUB_TOKEN` is set in the environment, both scripts send it as `Authorization: Bearer <token>`.
107
+ The default `devOnlySections` (excluded from public release notes but still written to `CHANGELOG.md`) are derived from the `internal` and `process` tiers (excluding `fmt`). Override via `changelogJson.devOnlySections`; matching is decorator-tolerant: A bare-name override like `['Internal features']` keeps working against the emoji-prefixed default titles.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/release-kit",
3
- "version": "11.0.0",
3
+ "version": "13.0.0",
4
4
  "description": "Version-bumping and changelog-generation toolkit for release workflows",
5
5
  "keywords": [
6
6
  "changelog",
@@ -43,7 +43,6 @@
43
43
  ".readyup/manifest.json",
44
44
  "CHANGELOG.md",
45
45
  "bin",
46
- "cliff.toml.template",
47
46
  "dist/*",
48
47
  "docs",
49
48
  "!docs/*.v*.md",
@@ -51,7 +50,8 @@
51
50
  "schemas/**"
52
51
  ],
53
52
  "dependencies": {
54
- "@williamthorsen/nmr-core": "0.13.0",
53
+ "@williamthorsen/change-grammar": "0.1.0",
54
+ "@williamthorsen/nmr-core": "0.13.1",
55
55
  "@williamthorsen/toolbelt.errors": "0.8.1",
56
56
  "json-stringify-pretty-compact": "4.0.0",
57
57
  "semver": "7.8.5",
@@ -63,8 +63,10 @@
63
63
  "@williamthorsen/toolbelt.filesystem": "0.9.1",
64
64
  "@williamthorsen/toolbelt.testing": "0.6.1",
65
65
  "@williamthorsen/toolbelt.vitest": "0.10.1",
66
+ "actionlint": "2.0.6",
67
+ "esbuild": "0.28.2",
66
68
  "readyup": "0.38.0",
67
- "smol-toml": "1.8.0",
69
+ "smol-toml": "1.9.0",
68
70
  "vitest": "4.1.11"
69
71
  },
70
72
  "engines": {
@@ -76,8 +78,6 @@
76
78
  },
77
79
  "scripts": {
78
80
  "build:post": "rdy compile",
79
- "build:pre": "rdy verify",
80
- "work-types:check": "node scripts/check-work-types.ts",
81
- "work-types:sync": "node scripts/sync-work-types.ts"
81
+ "build:pre": "rdy verify"
82
82
  }
83
83
  }
@@ -1,37 +1,17 @@
1
1
  # Common label definitions for GitHub repositories.
2
2
  # Compatible with EndBug/label-sync format.
3
+ # Work-type labels are built from change-grammar's taxonomy in src/sync-labels/typeLabels.ts.
3
4
 
4
5
  # Main categories
5
- - name: ai
6
- color: a2eeef
7
- description: Guidance on working in this repo, such as its AGENTS.md or a repo-local skill, or its agent config
8
6
  - name: breaking
9
7
  color: b60205
10
8
  description: Breaking API change or removal of functionality
11
9
  - name: bug
12
10
  color: d73a4a
13
11
  description: "Something isn't working"
14
- - name: deprecation
15
- color: fbca04
16
- description: Marks functionality for future removal
17
- - name: documentation
18
- color: a2eeef
19
- description: Documentation for human readers, such as a README, a guide, or a code comment
20
- - name: feature
21
- color: '0075ca'
22
- description: Added or improved external functionality
23
- - name: fix
24
- color: d73a4a
25
- description: Fixes a bug
26
12
  - name: operational
27
13
  color: '000000'
28
14
  description: Actions outside the codebase
29
- - name: performance
30
- color: '0075ca'
31
- description: Improves performance without changing behavior
32
- - name: security
33
- color: b60205
34
- description: Security vulnerability or hardening
35
15
  - name: spike
36
16
  color: '000000'
37
17
  description: Investigation
@@ -47,26 +27,6 @@
47
27
  color: fbca04
48
28
  description: Further information is needed
49
29
 
50
- # Refactoring
51
- - name: ci
52
- color: edc287
53
- description: CI/CD tooling & configuration
54
- - name: dependencies
55
- color: edc287
56
- description: Change to dependencies
57
- - name: internal
58
- color: 1d76db
59
- description: Internal change without external impact
60
- - name: refactoring
61
- color: edc287
62
- description: Improvement to code without change in functionality
63
- - name: tests
64
- color: edc287
65
- description: Tests
66
- - name: tooling
67
- color: edc287
68
- description: Development tools
69
-
70
30
  # Priority
71
31
  - name: 'priority:critical'
72
32
  color: b60205
@@ -0,0 +1,39 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "changelog-overrides",
4
+ "description": "Editorial overrides that release-kit applies to generated changelog items. Each key is a lowercase hex commit hash or prefix, which targets every item of the commit, optionally followed by `:<n>`, which targets the item derived from the commit's `n`th change-record entry.",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "$schema": {
9
+ "type": "string",
10
+ "description": "JSON Schema reference for editor support."
11
+ }
12
+ },
13
+ "patternProperties": {
14
+ "^[0-9a-f]+(:[1-9][0-9]*)?$": {
15
+ "type": "object",
16
+ "description": "Override for the items that the key targets. At least one field must be set.",
17
+ "additionalProperties": false,
18
+ "minProperties": 1,
19
+ "properties": {
20
+ "audience": {
21
+ "enum": ["all", "dev", "skip"],
22
+ "description": "`skip` removes the items. `all` and `dev` are reserved and not yet supported."
23
+ },
24
+ "description": {
25
+ "type": "string",
26
+ "description": "Replaces the item's headline."
27
+ },
28
+ "body": {
29
+ "type": "string",
30
+ "description": "Replaces the item's body."
31
+ },
32
+ "breaking": {
33
+ "type": "boolean",
34
+ "description": "Sets whether the item is marked as breaking."
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
@@ -1,65 +0,0 @@
1
- # git-cliff configuration
2
- # Generates changelogs from conventional-ish commit messages.
3
- #
4
- # Commit format: [ticket-prefix ]scope|type[!]: description [#PR]
5
- # Examples:
6
- # #19 rdy|feat: Add utility functions for common check patterns (#26)
7
- # AFG-42 panel|fix: Fix button layout (#73)
8
- # ## feat: Quick utility added during interactive session
9
- #
10
- # Only ticketed commits (leading #NN, PROJ-NN, or ##) are included.
11
- # Unticketed maintenance commits (deps upgrades, tooling tweaks) are skipped.
12
- # Use ## as a synthetic ticket prefix for ad-hoc commits that belong in the changelog.
13
- #
14
- # Section order: each `group` value carries a hidden `<!-- NN -->` HTML-comment
15
- # prefix encoding the canonical row position. tera's `group_by` filter sorts
16
- # groups lexicographically by string, and the body template's `striptags`
17
- # filter erases the comment from the rendered heading. Numbering is per
18
- # unique group (not per parser entry) โ€” all parsers routing to the same group
19
- # share the same prefix.
20
-
21
- # Markdown rendering is handled in-process by `renderChangelogMarkdown.ts`. cliff is invoked
22
- # only for `--context` JSON output (see `buildChangelogEntries.ts`), so no `[changelog]` block
23
- # is needed. The `[git].commit_parsers` section below remains load-bearing for group
24
- # assignment in the `--context` payload.
25
-
26
- [git]
27
- conventional_commits = false
28
- filter_unconventional = false
29
- split_commits = false
30
- commit_preprocessors = []
31
- # Require a ticket-ID prefix for inclusion.
32
- # Supported prefixes: "#123 ", "#123-1 ", "#123.1 ", "TOOL-123 ", "## "
33
- commit_parsers = [
34
- { message = "^release:", skip = true },
35
- { message = "^Merge", skip = true },
36
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?feat(!)?:", group = "<!-- 01 -->๐ŸŽ‰ Features" },
37
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?feature(!)?:", group = "<!-- 01 -->๐ŸŽ‰ Features" },
38
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?drop(!)?:", group = "<!-- 02 -->๐Ÿชฆ Removed" },
39
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?deprecate(!)?:", group = "<!-- 03 -->๐Ÿ—‘๏ธ Deprecated" },
40
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?fix(!)?:", group = "<!-- 04 -->๐Ÿ› Bug fixes" },
41
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?bugfix(!)?:", group = "<!-- 04 -->๐Ÿ› Bug fixes" },
42
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?sec(!)?:", group = "<!-- 05 -->๐Ÿ”’ Security" },
43
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?security(!)?:", group = "<!-- 05 -->๐Ÿ”’ Security" },
44
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?perf(!)?:", group = "<!-- 06 -->โšก Performance" },
45
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?performance(!)?:", group = "<!-- 06 -->โšก Performance" },
46
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?internal(!)?:", group = "<!-- 07 -->๐Ÿ—๏ธ Internal features" },
47
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?utility(!)?:", group = "<!-- 07 -->๐Ÿ—๏ธ Internal features" },
48
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?refactor(!)?:", group = "<!-- 08 -->โ™ป๏ธ Refactoring" },
49
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?tests?(!)?:", group = "<!-- 09 -->๐Ÿงช Tests" },
50
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?tooling(!)?:", group = "<!-- 10 -->โš™๏ธ Tooling" },
51
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?ci(!)?:", group = "<!-- 11 -->๐Ÿ‘ท CI" },
52
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?deps?(!)?:", group = "<!-- 12 -->๐Ÿ“ฆ Dependencies" },
53
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?ai(!)?:", group = "<!-- 13 -->๐Ÿค– Agentic support" },
54
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?docs?(!)?:", group = "<!-- 14 -->๐Ÿ“š Documentation" },
55
- { message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([^|]+\\|)?fmt(!)?:", skip = true },
56
- # Skip unticketed commits (maintenance, deps, initial scaffolding, etc.)
57
- { message = ".*", skip = true },
58
- ]
59
- protect_breaking_commits = false
60
- filter_commits = true
61
- tag_pattern = "v[0-9].*"
62
- skip_tags = ""
63
- ignore_tags = ""
64
- topo_order = false
65
- sort_commits = "oldest"
@@ -1,15 +0,0 @@
1
- import type { PolicyViolationHandler } from './parseCommitMessage.js';
2
- import type { PolicyViolation } from './types.js';
3
- /**
4
- * Build a fresh `policyViolations` accumulator paired with the `onPolicyViolation` callback
5
- * that pushes structured entries into it.
6
- *
7
- * Used by all three release-prepare orchestrators (`releasePrepare`, `releasePrepareMono`,
8
- * `releasePrepareProject`) to collect parser-side `!`-policy violations into a result-attachable
9
- * array. Centralizing the callback shape keeps the `commitSubject` extraction rule (`firstLine
10
- * post-split`) consistent across orchestrators.
11
- */
12
- export declare function createPolicyViolationCollector(): {
13
- violations: PolicyViolation[];
14
- onPolicyViolation: PolicyViolationHandler;
15
- };
@@ -1,12 +0,0 @@
1
- export function createPolicyViolationCollector() {
2
- const violations = [];
3
- const onPolicyViolation = (commit, type, surface) => {
4
- violations.push({
5
- commitHash: commit.hash,
6
- commitSubject: commit.message.split('\n', 1)[0] ?? '',
7
- type,
8
- surface,
9
- });
10
- };
11
- return { violations, onPolicyViolation };
12
- }
@@ -1,17 +0,0 @@
1
- import { type PolicyViolationHandler } from './parseCommitMessage.js';
2
- import type { Commit, ReleaseType, VersionPatterns, WorkTypeConfig } from './types.js';
3
- /** Aggregate result of parsing commits and determining the bump type. */
4
- export interface BumpDetermination {
5
- releaseType: ReleaseType | undefined;
6
- parsedCommitCount: number;
7
- unparseableCommits: Commit[] | undefined;
8
- }
9
- /** Optional configuration for parser-policy plumbing. */
10
- export interface DetermineBumpOptions {
11
- /** Per-canonical-type breaking-policy lookup (drives `!` policy enforcement). */
12
- breakingPolicies?: Record<string, 'forbidden' | 'optional' | 'required'>;
13
- /** Receives policy-violation notifications from `parseCommitMessage`. */
14
- onPolicyViolation?: PolicyViolationHandler;
15
- }
16
- /** Parse commits, determine bump type, and apply patch floor when commits exist but none parsed. */
17
- export declare function determineBumpFromCommits(commits: Commit[], workTypes: Record<string, WorkTypeConfig>, versionPatterns: VersionPatterns, scopeAliases: Record<string, string> | undefined, options?: DetermineBumpOptions): BumpDetermination;
@@ -1,28 +0,0 @@
1
- import { determineBumpType } from "./determineBumpType.js";
2
- import { parseCommitMessage, } from "./parseCommitMessage.js";
3
- export function determineBumpFromCommits(commits, workTypes, versionPatterns, scopeAliases, options) {
4
- const parseOptions = {
5
- ...(options?.breakingPolicies !== undefined && { breakingPolicies: options.breakingPolicies }),
6
- ...(options?.onPolicyViolation !== undefined && { onPolicyViolation: options.onPolicyViolation }),
7
- };
8
- const parsedCommits = [];
9
- const unparseable = [];
10
- for (const commit of commits) {
11
- const parsed = parseCommitMessage(commit.message, commit.hash, workTypes, scopeAliases, parseOptions);
12
- if (parsed === undefined) {
13
- unparseable.push(commit);
14
- }
15
- else {
16
- parsedCommits.push(parsed);
17
- }
18
- }
19
- let releaseType = determineBumpType(parsedCommits, workTypes, versionPatterns);
20
- if (releaseType === undefined && commits.length > 0) {
21
- releaseType = 'patch';
22
- }
23
- return {
24
- releaseType,
25
- parsedCommitCount: parsedCommits.length,
26
- unparseableCommits: unparseable.length > 0 ? unparseable : undefined,
27
- };
28
- }