@williamthorsen/release-kit 12.0.0 โ†’ 13.1.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 (168) hide show
  1. package/.meta/changelog.json +229 -0
  2. package/.readyup/kits/default.js +18 -17
  3. package/.readyup/kits/npm-auto-publish.js +24 -23
  4. package/.readyup/manifest.json +16 -11
  5. package/CHANGELOG.md +64 -0
  6. package/README.md +27 -51
  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 +1 -1
  12. package/dist/esm/attachChangelogDiagnostics.js +3 -0
  13. package/dist/esm/bin/release-kit.js +85 -22
  14. package/dist/esm/buildChangelogEntries.d.ts +23 -13
  15. package/dist/esm/buildChangelogEntries.js +36 -17
  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/buildSyntheticChangelogEntry.d.ts +3 -5
  20. package/dist/esm/buildSyntheticChangelogEntry.js +2 -2
  21. package/dist/esm/bumpVersion.d.ts +1 -8
  22. package/dist/esm/changelogJsonFile.d.ts +5 -7
  23. package/dist/esm/changelogJsonFile.js +2 -17
  24. package/dist/esm/changelogJsonUtils.d.ts +7 -10
  25. package/dist/esm/changelogOverrides.d.ts +59 -98
  26. package/dist/esm/classifyChangelogCommit.d.ts +7 -9
  27. package/dist/esm/classifyChangelogCommit.js +3 -2
  28. package/dist/esm/commitCommand.d.ts +2 -4
  29. package/dist/esm/compareVersions.d.ts +10 -4
  30. package/dist/esm/compareVersions.js +16 -0
  31. package/dist/esm/configFlagSchema.d.ts +1 -1
  32. package/dist/esm/createGithubRelease.d.ts +7 -19
  33. package/dist/esm/createGithubReleaseCommand.d.ts +5 -5
  34. package/dist/esm/createGithubReleaseCommand.js +9 -9
  35. package/dist/esm/createTags.d.ts +2 -3
  36. package/dist/esm/decideRelease.d.ts +2 -6
  37. package/dist/esm/defaults.d.ts +5 -24
  38. package/dist/esm/defaults.js +4 -5
  39. package/dist/esm/defineConfig.d.ts +1 -1
  40. package/dist/esm/deleteFileIfExists.d.ts +1 -1
  41. package/dist/esm/deriveReleaseNotesConfig.d.ts +20 -0
  42. package/dist/esm/deriveReleaseNotesConfig.js +21 -0
  43. package/dist/esm/deriveWorkspaceConfig.d.ts +3 -5
  44. package/dist/esm/detectPackageManager.d.ts +2 -4
  45. package/dist/esm/detectUndeclaredTagPrefixes.d.ts +4 -6
  46. package/dist/esm/detectUndeclaredTagPrefixes.js +1 -1
  47. package/dist/esm/determineBumpType.d.ts +1 -1
  48. package/dist/esm/discoverWorkspaces.d.ts +14 -15
  49. package/dist/esm/discoverWorkspaces.js +12 -12
  50. package/dist/esm/enterRepoRoot.d.ts +12 -0
  51. package/dist/esm/enterRepoRoot.js +16 -0
  52. package/dist/esm/enumerateReleaseWindows.d.ts +8 -8
  53. package/dist/esm/extractMigration.d.ts +6 -8
  54. package/dist/esm/findUnroutedEntryScopes.d.ts +16 -0
  55. package/dist/esm/findUnroutedEntryScopes.js +57 -0
  56. package/dist/esm/formatExcludedSkip.d.ts +3 -0
  57. package/dist/esm/formatExcludedSkip.js +3 -0
  58. package/dist/esm/formatPrivateSkip.d.ts +1 -6
  59. package/dist/esm/generateChangelogs.d.ts +10 -5
  60. package/dist/esm/glyphs.d.ts +1 -1
  61. package/dist/esm/help/prepareHelp.d.ts +3 -4
  62. package/dist/esm/help/prepareHelp.js +4 -3
  63. package/dist/esm/init/checks.d.ts +3 -3
  64. package/dist/esm/init/checks.js +4 -1
  65. package/dist/esm/init/detectRepoType.d.ts +2 -3
  66. package/dist/esm/init/hasProvenance.d.ts +2 -0
  67. package/dist/esm/init/hasProvenance.js +3 -0
  68. package/dist/esm/init/initCommand.d.ts +3 -6
  69. package/dist/esm/init/initCommand.js +10 -10
  70. package/dist/esm/init/parseJsonRecord.d.ts +1 -4
  71. package/dist/esm/init/scaffold.d.ts +1 -1
  72. package/dist/esm/init/templates.d.ts +9 -11
  73. package/dist/esm/init/templates.js +12 -11
  74. package/dist/esm/init/updateTemplatesCommand.d.ts +13 -0
  75. package/dist/esm/init/updateTemplatesCommand.js +64 -0
  76. package/dist/esm/injectReleaseNotesIntoReadme.d.ts +12 -17
  77. package/dist/esm/injectSection.d.ts +3 -3
  78. package/dist/esm/loadConfig.d.ts +16 -14
  79. package/dist/esm/loadConfig.js +2 -2
  80. package/dist/esm/loadValidatedConfig.d.ts +16 -19
  81. package/dist/esm/loadValidatedConfig.js +6 -1
  82. package/dist/esm/packsPath.d.ts +9 -9
  83. package/dist/esm/parseChangeRecordBlock.d.ts +2 -2
  84. package/dist/esm/parseCommitMessage.d.ts +17 -32
  85. package/dist/esm/parseCommitMessage.js +28 -37
  86. package/dist/esm/parseRequestedTags.d.ts +3 -3
  87. package/dist/esm/planReleaseNotesPreviews.d.ts +6 -6
  88. package/dist/esm/planVersionBump.d.ts +5 -3
  89. package/dist/esm/planVersionBump.js +3 -0
  90. package/dist/esm/prepareCommand.d.ts +4 -7
  91. package/dist/esm/prepareCommand.js +13 -6
  92. package/dist/esm/previewTagPrefixes.d.ts +8 -10
  93. package/dist/esm/propagateBumps.d.ts +6 -7
  94. package/dist/esm/publish.d.ts +1 -1
  95. package/dist/esm/publishCommand.d.ts +4 -3
  96. package/dist/esm/publishCommand.js +8 -8
  97. package/dist/esm/pushCommand.d.ts +4 -3
  98. package/dist/esm/pushCommand.js +8 -2
  99. package/dist/esm/pushRelease.d.ts +2 -2
  100. package/dist/esm/readChangelogSections.d.ts +33 -0
  101. package/dist/esm/readChangelogSections.js +80 -0
  102. package/dist/esm/releaseFiles.d.ts +5 -7
  103. package/dist/esm/releasePlan.d.ts +11 -13
  104. package/dist/esm/releasePrepare.d.ts +23 -22
  105. package/dist/esm/releasePrepare.js +31 -11
  106. package/dist/esm/releasePrepareMono.d.ts +9 -7
  107. package/dist/esm/releasePrepareMono.js +85 -33
  108. package/dist/esm/releasePrepareProject.d.ts +19 -29
  109. package/dist/esm/releasePrepareProject.js +31 -12
  110. package/dist/esm/renderChangelogMarkdown.d.ts +10 -4
  111. package/dist/esm/renderChangelogMarkdown.js +27 -2
  112. package/dist/esm/renderReleaseNotes.d.ts +3 -11
  113. package/dist/esm/renderReleaseNotes.js +2 -6
  114. package/dist/esm/reportPrepare.d.ts +4 -5
  115. package/dist/esm/reportPrepare.js +33 -19
  116. package/dist/esm/resolveCommandTags.d.ts +15 -11
  117. package/dist/esm/resolveCommandTags.js +35 -5
  118. package/dist/esm/resolveConfigFlag.d.ts +7 -0
  119. package/dist/esm/resolveConfigFlag.js +4 -0
  120. package/dist/esm/resolveReleaseTags.d.ts +6 -8
  121. package/dist/esm/resolveReleaseTags.js +1 -1
  122. package/dist/esm/resolveStylesOrExit.d.ts +2 -2
  123. package/dist/esm/showTagPrefixesCommand.d.ts +7 -10
  124. package/dist/esm/showTagPrefixesCommand.js +4 -4
  125. package/dist/esm/stripEmojiPrefix.d.ts +1 -0
  126. package/dist/esm/stripScope.d.ts +2 -2
  127. package/dist/esm/stripScope.js +3 -3
  128. package/dist/esm/sync-labels/generateCommand.d.ts +11 -10
  129. package/dist/esm/sync-labels/generateCommand.js +17 -9
  130. package/dist/esm/sync-labels/initCommand.d.ts +6 -7
  131. package/dist/esm/sync-labels/initCommand.js +2 -2
  132. package/dist/esm/sync-labels/presets.d.ts +5 -4
  133. package/dist/esm/sync-labels/presets.js +9 -9
  134. package/dist/esm/sync-labels/resolveLabels.d.ts +7 -7
  135. package/dist/esm/sync-labels/resolveLabels.js +2 -1
  136. package/dist/esm/sync-labels/retiredConfig.d.ts +4 -5
  137. package/dist/esm/sync-labels/syncCommand.d.ts +1 -4
  138. package/dist/esm/sync-labels/templates.d.ts +3 -3
  139. package/dist/esm/sync-labels/templates.js +3 -3
  140. package/dist/esm/sync-labels/typeLabels.d.ts +14 -0
  141. package/dist/esm/sync-labels/typeLabels.js +38 -0
  142. package/dist/esm/sync-labels/types.d.ts +4 -2
  143. package/dist/esm/tagCommand.d.ts +1 -1
  144. package/dist/esm/typeGuards.d.ts +2 -2
  145. package/dist/esm/types.d.ts +122 -93
  146. package/dist/esm/types.js +2 -1
  147. package/dist/esm/validateConfig.d.ts +2 -11
  148. package/dist/esm/validateConfig.js +2 -2
  149. package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +14 -12
  150. package/dist/esm/validateOverridesCommand.d.ts +17 -20
  151. package/dist/esm/validateOverridesCommand.js +1 -1
  152. package/docs/api.md +6 -6
  153. package/docs/changelogs.md +63 -40
  154. package/docs/configuration.md +29 -27
  155. package/docs/editorial-overrides.md +23 -23
  156. package/docs/labels.md +37 -19
  157. package/docs/project-releases.md +13 -13
  158. package/docs/publishing.md +5 -5
  159. package/docs/readiness-checks.md +3 -3
  160. package/docs/releasing.md +50 -25
  161. package/docs/work-types.md +41 -57
  162. package/package.json +7 -6
  163. package/presets/labels/common.yaml +1 -41
  164. package/dist/esm/resolveReleaseNotesConfig.d.ts +0 -26
  165. package/dist/esm/resolveReleaseNotesConfig.js +0 -29
  166. package/dist/esm/workTypesData.d.ts +0 -50
  167. package/dist/esm/workTypesData.js +0 -145
  168. package/schemas/label-map.json +0 -24
@@ -1,56 +1,55 @@
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**. It comes from the declaration order of `work-types.json`: `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.
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
32
 
33
33
  ## Subject forms
34
34
 
35
- `classifyChangelogCommit` resolves a commit's type through `parseCommitMessage`, so a subject reaches its section under any form that parser accepts: `type:`, `scope|type:`, and the conventional-commit `type(scope):`. The type is matched case-insensitively, so `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.
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.
36
36
 
37
37
  ## `utility` alias
38
38
 
39
- `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.
40
40
 
41
41
  ## `!` (breaking change) policy
42
42
 
43
- Each work-type carries a `breakingPolicy` value:
43
+ Each work-type has a `breakingPolicy` value:
44
44
 
45
- - `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.
46
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.
47
- - `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.
48
47
 
49
48
  ### Policy enforcement
50
49
 
51
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.
52
51
 
53
- 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. The warning is all that a footer triggers; it raises no bump (see [`๐Ÿšจ **Breaking:**` bullet marker](#-breaking-bullet-marker)).
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)).
54
53
 
55
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:
56
55
 
@@ -58,7 +57,7 @@ The release-prepare orchestrators (`releasePrepare`, `releasePrepareMono`, `rele
58
57
  arrays
59
58
  Found 1 commits since arrays-v1.0.0
60
59
  ๐ŸŸ  1 policy violation:
61
- ยท def5678 'internal!: refactor cache' โ€” type 'internal' at prefix surface
60
+ ยท def5678 'internal!: refactor cache': type 'internal' at prefix surface
62
61
  Bumping versions (patch)...
63
62
  ๐Ÿ“ฆ 1.0.0 โ†’ 1.0.1 (patch)
64
63
  ```
@@ -67,7 +66,7 @@ To customize, set `breakingPolicies` in `release-kit.config.ts`. The map replace
67
66
 
68
67
  ## `๐Ÿšจ **Breaking:**` bullet marker
69
68
 
70
- 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:
71
70
 
72
71
  ```markdown
73
72
  - ๐Ÿšจ **Breaking:** Drop legacy /v1 endpoint
@@ -75,17 +74,17 @@ Items whose commit subject carries the `!` prefix (e.g. `feat!`, `drop!`, `feat(
75
74
 
76
75
  The marker agrees with the version bump:
77
76
 
78
- - 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.
79
78
  - The configured `breakingPolicies` map, `{}` included, decides which types permit the marker.
80
- - A commit whose type the parser cannot resolve reaches no changelog at all, so no marker question arises.
79
+ - A commit whose type the parser cannot resolve doesn't appear in any changelog, so the question of a marker doesn't arise.
81
80
 
82
- 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. The bump follows the items, so a footer raises no major bump either: A consumer that marks breaking changes with the footer alone gets the bump of the commit's type.
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.
83
82
 
84
- 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.
85
84
 
86
85
  ## Section markers
87
86
 
88
- 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`.
89
88
 
90
89
  ```jsonc
91
90
  {
@@ -95,29 +94,14 @@ Alongside `tiers` and `types`, `work-types.json` exposes a top-level `markers` o
95
94
  }
96
95
  ```
97
96
 
98
- 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.
99
98
 
100
99
  ## `fmt`
101
100
 
102
- `fmt:` commits are recognized by `parseCommitMessage`, but `fmt` carries `excludedFromChangelog: true`, which `DEFAULT_WORK_TYPES` carries 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. It yields no item, so it raises no bump, and the release report does not list it as unparseable. 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.
103
102
 
104
103
  ## Custom work types
105
104
 
106
- 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 reaches the changelog under the `header` 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.
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.
107
106
 
108
- 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, so a bare-name override like `['Internal features']` keeps working against the emoji-prefixed default titles.
109
-
110
- ## Maintaining the bundled taxonomy
111
-
112
- `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.
113
-
114
- - `nmr work-types:check` compares the content of `src/work-types.json` with the upstream, ignoring the local `$schema` hint.
115
- - `nmr work-types:sync` overwrites `src/work-types.json` with the upstream when their content differs.
116
-
117
- 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.
118
-
119
- `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.
120
-
121
- ### Authenticated fetches
122
-
123
- 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": "12.0.0",
3
+ "version": "13.1.0",
4
4
  "description": "Version-bumping and changelog-generation toolkit for release workflows",
5
5
  "keywords": [
6
6
  "changelog",
@@ -50,7 +50,8 @@
50
50
  "schemas/**"
51
51
  ],
52
52
  "dependencies": {
53
- "@williamthorsen/nmr-core": "0.13.0",
53
+ "@williamthorsen/change-grammar": "0.1.0",
54
+ "@williamthorsen/nmr-core": "0.13.1",
54
55
  "@williamthorsen/toolbelt.errors": "0.8.1",
55
56
  "json-stringify-pretty-compact": "4.0.0",
56
57
  "semver": "7.8.5",
@@ -62,8 +63,10 @@
62
63
  "@williamthorsen/toolbelt.filesystem": "0.9.1",
63
64
  "@williamthorsen/toolbelt.testing": "0.6.1",
64
65
  "@williamthorsen/toolbelt.vitest": "0.10.1",
66
+ "actionlint": "2.0.6",
67
+ "esbuild": "0.28.2",
65
68
  "readyup": "0.38.0",
66
- "smol-toml": "1.8.0",
69
+ "smol-toml": "1.9.0",
67
70
  "vitest": "4.1.11"
68
71
  },
69
72
  "engines": {
@@ -75,8 +78,6 @@
75
78
  },
76
79
  "scripts": {
77
80
  "build:post": "rdy compile",
78
- "build:pre": "rdy verify",
79
- "work-types:check": "node scripts/check-work-types.ts",
80
- "work-types:sync": "node scripts/sync-work-types.ts"
81
+ "build:pre": "rdy verify"
81
82
  }
82
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
@@ -1,26 +0,0 @@
1
- import type { OutputStyle } from '@williamthorsen/nmr-core';
2
- import type { ReleaseNotesConfig } from './types.js';
3
- export interface ResolvedReleaseNotesConfig {
4
- releaseNotes: ReleaseNotesConfig;
5
- changelogJsonOutputPath: string;
6
- /** Section titles in priority order, derived from the merged workTypes record. */
7
- sectionOrder: string[];
8
- }
9
- export interface ResolveReleaseNotesConfigOptions {
10
- /** Config file to read, relative to the working directory. Defaults to `CONFIG_FILE_PATH`. */
11
- configPath?: string;
12
- }
13
- /**
14
- * Loads and validates the release-kit config, resolving the release-notes settings it carries.
15
- *
16
- * An unusable config reports to stderr and calls `process.exit(1)`, whether the file failed to load or failed
17
- * validation, and whether it was named by the caller or the default one. Both callers are CLI commands whose
18
- * whole behavior depends on the resolved config, so neither could proceed on derived defaults without silently
19
- * dropping a configured `releaseNotes.shouldInjectIntoReadme`, `changelogJson.outputPath`, or `workTypes`.
20
- * An absent default config is a supported state and resolves to the defaults.
21
- */
22
- export declare function resolveReleaseNotesConfig(stderrStyle: OutputStyle, options?: ResolveReleaseNotesConfigOptions): Promise<ResolvedReleaseNotesConfig>;
23
- /** Extract section headers in declaration order from a merged workTypes record. */
24
- export declare function deriveSectionOrder(workTypes: Record<string, {
25
- header: string;
26
- }>): string[];
@@ -1,29 +0,0 @@
1
- import { DEFAULT_CHANGELOG_JSON_CONFIG, DEFAULT_RELEASE_NOTES_CONFIG } from "./defaults.js";
2
- import { resolveWorkTypes } from "./loadConfig.js";
3
- import { loadValidatedConfig, reportConfigProblem, reportConfigWarnings } from "./loadValidatedConfig.js";
4
- export async function resolveReleaseNotesConfig(stderrStyle, options = {}) {
5
- const result = await loadValidatedConfig(options.configPath);
6
- if (result.status === 'invalid') {
7
- reportConfigProblem(result.problem, stderrStyle);
8
- process.exit(1);
9
- }
10
- if (result.status === 'missing') {
11
- return {
12
- releaseNotes: { ...DEFAULT_RELEASE_NOTES_CONFIG },
13
- changelogJsonOutputPath: DEFAULT_CHANGELOG_JSON_CONFIG.outputPath,
14
- sectionOrder: deriveSectionOrder(resolveWorkTypes()),
15
- };
16
- }
17
- reportConfigWarnings(result.warnings, stderrStyle);
18
- const { config } = result;
19
- return {
20
- releaseNotes: {
21
- shouldInjectIntoReadme: config.releaseNotes?.shouldInjectIntoReadme ?? DEFAULT_RELEASE_NOTES_CONFIG.shouldInjectIntoReadme,
22
- },
23
- changelogJsonOutputPath: config.changelogJson?.outputPath ?? DEFAULT_CHANGELOG_JSON_CONFIG.outputPath,
24
- sectionOrder: deriveSectionOrder(resolveWorkTypes(config.workTypes)),
25
- };
26
- }
27
- export function deriveSectionOrder(workTypes) {
28
- return Object.values(workTypes).map((entry) => entry.header);
29
- }
@@ -1,50 +0,0 @@
1
- /**
2
- * Canonical work-types data: the runtime mirror of `work-types.json`.
3
- *
4
- * `work-types.json` is release-kit's copy of the codeassembly canonical. This `.ts` mirror exists for
5
- * runtime consumption: The compiler baseline does not enable JSON module imports, and a TS constant keeps
6
- * `breakingPolicy` typed as its three-value union.
7
- *
8
- * `nmr work-types:sync` updates only the JSON, so copy its change here by hand. A drift test
9
- * (`workTypesData.unit.test.ts`) asserts that this constant deep-equals the parsed contents of
10
- * `work-types.json`.
11
- */
12
- /** Schema for a single entry. */
13
- export interface WorkTypeEntry {
14
- tier: string;
15
- key: string;
16
- aliases: string[];
17
- emoji: string;
18
- label: string;
19
- description: string;
20
- breakingPolicy: 'forbidden' | 'optional' | 'required';
21
- excludedFromChangelog?: boolean;
22
- }
23
- /**
24
- * Schema for an orthogonal section marker (e.g., breaking-changes indicator).
25
- *
26
- * Stored as plain text โ€” consumers add formatting (bold, prefix punctuation) when
27
- * constructing the rendered form. Keeps the SSOT format-agnostic across Markdown,
28
- * HTML, terminal, and plain-text consumers.
29
- */
30
- export interface MarkerEntry {
31
- emoji: string;
32
- label: string;
33
- }
34
- /** Schema for the full data. */
35
- export interface WorkTypesData {
36
- /** Semantic version of the data shape, as declared by the upstream canonical. */
37
- version: string;
38
- tiers: string[];
39
- types: WorkTypeEntry[];
40
- /**
41
- * Cross-cutting section markers keyed by marker name. The `breaking` marker is
42
- * canonical and required; additional keys are permitted for forward-compatibility.
43
- */
44
- markers: {
45
- [key: string]: MarkerEntry;
46
- breaking: MarkerEntry;
47
- };
48
- }
49
- /** Canonical work-types data, kept in lockstep with `work-types.json`. */
50
- export declare const WORK_TYPES_DATA: WorkTypesData;
@@ -1,145 +0,0 @@
1
- export const WORK_TYPES_DATA = {
2
- version: '1.1.0',
3
- tiers: ['public', 'internal', 'process'],
4
- types: [
5
- {
6
- tier: 'public',
7
- key: 'feat',
8
- aliases: ['feature'],
9
- emoji: '๐ŸŽ‰',
10
- label: 'Features',
11
- description: 'A change that gives consumers a new capability or extends an existing one.',
12
- breakingPolicy: 'optional',
13
- },
14
- {
15
- tier: 'public',
16
- key: 'drop',
17
- aliases: [],
18
- emoji: '๐Ÿชฆ',
19
- label: 'Removed',
20
- description: 'A change that removes a capability or surface on which consumers depend.',
21
- breakingPolicy: 'required',
22
- },
23
- {
24
- tier: 'public',
25
- key: 'deprecate',
26
- aliases: [],
27
- emoji: '๐Ÿ—‘๏ธ',
28
- label: 'Deprecated',
29
- description: 'A change that marks a capability or surface for removal while the capability or surface keeps working.',
30
- breakingPolicy: 'forbidden',
31
- },
32
- {
33
- tier: 'public',
34
- key: 'fix',
35
- aliases: ['bugfix'],
36
- emoji: '๐Ÿ›',
37
- label: 'Bug fixes',
38
- description: 'A change that corrects behavior that consumers meet and that differs from what was intended.',
39
- breakingPolicy: 'optional',
40
- },
41
- {
42
- tier: 'public',
43
- key: 'sec',
44
- aliases: ['security'],
45
- emoji: '๐Ÿ”’',
46
- label: 'Security',
47
- description: 'A change that closes a vulnerability or hardens a consumer-facing surface against attack.',
48
- breakingPolicy: 'optional',
49
- },
50
- {
51
- tier: 'public',
52
- key: 'perf',
53
- aliases: ['performance'],
54
- emoji: 'โšก',
55
- label: 'Performance',
56
- description: 'A change that reduces the time, memory, or other resources that consumer-facing work uses, without changing its result.',
57
- breakingPolicy: 'optional',
58
- },
59
- {
60
- tier: 'internal',
61
- key: 'internal',
62
- aliases: ['utility'],
63
- emoji: '๐Ÿ—๏ธ',
64
- label: 'Internal features',
65
- description: 'A change that adds or extends a capability that consumers do not use directly, such as a helper or an internal module.',
66
- breakingPolicy: 'forbidden',
67
- },
68
- {
69
- tier: 'internal',
70
- key: 'refactor',
71
- aliases: [],
72
- emoji: 'โ™ป๏ธ',
73
- label: 'Refactoring',
74
- description: 'A change that restructures existing code without changing its behavior.',
75
- breakingPolicy: 'forbidden',
76
- },
77
- {
78
- tier: 'internal',
79
- key: 'tests',
80
- aliases: ['test'],
81
- emoji: '๐Ÿงช',
82
- label: 'Tests',
83
- description: 'A change confined to tests, test fixtures, or test helpers, including one that unblocks a build or a type check.',
84
- breakingPolicy: 'forbidden',
85
- },
86
- {
87
- tier: 'process',
88
- key: 'tooling',
89
- aliases: [],
90
- emoji: 'โš™๏ธ',
91
- label: 'Tooling',
92
- description: 'A change to the tools used to develop the project: build, lint, formatting, and release configuration, and development scripts.',
93
- breakingPolicy: 'forbidden',
94
- },
95
- {
96
- tier: 'process',
97
- key: 'ci',
98
- aliases: [],
99
- emoji: '๐Ÿ‘ท',
100
- label: 'CI',
101
- description: 'A change to continuous-integration workflows and their configuration.',
102
- breakingPolicy: 'forbidden',
103
- },
104
- {
105
- tier: 'process',
106
- key: 'deps',
107
- aliases: ['dep'],
108
- emoji: '๐Ÿ“ฆ',
109
- label: 'Dependencies',
110
- description: 'A change that adds, removes, or upgrades a dependency, including its lockfile and version-catalog entries.',
111
- breakingPolicy: 'forbidden',
112
- },
113
- {
114
- tier: 'process',
115
- key: 'ai',
116
- aliases: [],
117
- emoji: '๐Ÿค–',
118
- label: 'Agentic support',
119
- description: "A change to guidance on working in the repository itself, such as its `AGENTS.md` or a repo-local skill, or to the repository's agent configuration.",
120
- breakingPolicy: 'forbidden',
121
- },
122
- {
123
- tier: 'process',
124
- key: 'docs',
125
- aliases: ['doc'],
126
- emoji: '๐Ÿ“š',
127
- label: 'Documentation',
128
- description: 'A change to documentation for human readers, such as a README, a guide, or a code comment.',
129
- breakingPolicy: 'forbidden',
130
- },
131
- {
132
- tier: 'process',
133
- key: 'fmt',
134
- aliases: [],
135
- emoji: '๐ŸŽจ',
136
- label: 'Formatting',
137
- description: 'A change to formatting alone, such as whitespace or line wrapping, that leaves the content unchanged.',
138
- breakingPolicy: 'forbidden',
139
- excludedFromChangelog: true,
140
- },
141
- ],
142
- markers: {
143
- breaking: { emoji: '๐Ÿšจ', label: 'Breaking' },
144
- },
145
- };
@@ -1,24 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "title": "label-map",
4
- "description": "Maps commit-prefix scopes and types to GitHub label names. Consumed by agent skills, CI tooling, and any script that needs to translate commit conventions into label operations.",
5
- "type": "object",
6
- "required": ["types", "scopes"],
7
- "additionalProperties": false,
8
- "properties": {
9
- "$schema": {
10
- "type": "string",
11
- "description": "JSON Schema reference for editor support."
12
- },
13
- "types": {
14
- "type": "object",
15
- "description": "Maps commit-type prefix (e.g., `feat`) to GitHub label name (e.g., `feature`).",
16
- "additionalProperties": { "type": "string" }
17
- },
18
- "scopes": {
19
- "type": "object",
20
- "description": "Maps commit-scope prefix (e.g., `audit`) to GitHub label name (e.g., `scope:audit`).",
21
- "additionalProperties": { "type": "string" }
22
- }
23
- }
24
- }