@williamthorsen/release-kit 10.7.0 โ 10.8.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.
- package/.meta/changelog.json +28 -0
- package/.readyup/kits/default.js +1 -1
- package/.readyup/manifest.json +2 -2
- package/CHANGELOG.md +15 -0
- package/README.md +6 -16
- package/dist/esm/bin/release-kit.js +3 -3
- package/dist/esm/buildChangelogEntries.d.ts +1 -1
- package/dist/esm/buildChangelogEntries.js +14 -5
- package/dist/esm/checkWorkTypesDrift.d.ts +2 -3
- package/dist/esm/checkWorkTypesDrift.js +1 -1
- package/dist/esm/parseCommitMessage.d.ts +4 -5
- package/dist/esm/types.d.ts +8 -7
- package/dist/esm/work-types.json +68 -52
- package/dist/esm/work-types.schema.json +12 -2
- package/dist/esm/workTypesData.d.ts +10 -9
- package/dist/esm/workTypesData.js +97 -11
- package/docs/changelogs.md +8 -8
- package/docs/work-types.md +20 -25
- package/package.json +1 -1
package/.meta/changelog.json
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "10.8.0",
|
|
4
|
+
"date": "2026-09-15",
|
|
5
|
+
"sections": [
|
|
6
|
+
{
|
|
7
|
+
"title": "๐ Features",
|
|
8
|
+
"audience": "all",
|
|
9
|
+
"items": [
|
|
10
|
+
{
|
|
11
|
+
"description": "Allow the breaking marker on fix and perf commits (#818)",
|
|
12
|
+
"body": "- Makes `release-kit prepare` bump the major version for a `fix!` or `perf!` commit under the default breaking policies, instead of reporting a policy violation and bumping only the patch version while the changelog marked the entry breaking.\n- Corrects `docs/work-types.md` to state that a `breakingPolicies` map replaces the default policies rather than overriding individual types, and that release-kit treats every type omitted by the map as `optional`.",
|
|
13
|
+
"hash": "9d7bbe89deef6cdcedd999336e1cb8118bbf739f"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"title": "๐ Bug fixes",
|
|
19
|
+
"audience": "all",
|
|
20
|
+
"items": [
|
|
21
|
+
{
|
|
22
|
+
"description": "Omit the breaking marker from changelog entries whose type forbids it (#819)",
|
|
23
|
+
"body": "- Makes the configured `breakingPolicies` map decide whether the changelog marks a commit breaking, as it already decides the version bump.",
|
|
24
|
+
"hash": "6ff7414f6f826fc85ae3337c4ac6bd9e38fe6ef7"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
},
|
|
2
30
|
{
|
|
3
31
|
"version": "10.7.0",
|
|
4
32
|
"date": "2026-09-15",
|
package/.readyup/kits/default.js
CHANGED
|
@@ -98,7 +98,7 @@ function translateGlob(pattern) {
|
|
|
98
98
|
|
|
99
99
|
// .readyup/kits/default.ts
|
|
100
100
|
function getMinVersion() {
|
|
101
|
-
const picked = { "version": "10.
|
|
101
|
+
const picked = { "version": "10.8.0" };
|
|
102
102
|
if (typeof picked["version"] !== "string") {
|
|
103
103
|
throw new TypeError("release-kit/package.json: 'version' must be a string");
|
|
104
104
|
}
|
package/.readyup/manifest.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"path": "kits/default.ts"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
|
-
"hash": "
|
|
16
|
+
"hash": "a8611365",
|
|
17
17
|
"kind": "inline",
|
|
18
18
|
"path": "../package.json",
|
|
19
19
|
"paths": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"readyupVersion": "0.36.0",
|
|
47
47
|
"source": "kits/default.ts",
|
|
48
48
|
"sourceHash": "55ff5731",
|
|
49
|
-
"targetHash": "
|
|
49
|
+
"targetHash": "be5f29ad"
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
"checklists": [
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 10.8.0 โ 2026-09-15
|
|
6
|
+
|
|
7
|
+
### ๐ Features
|
|
8
|
+
|
|
9
|
+
- Allow the breaking marker on fix and perf commits (#818)
|
|
10
|
+
|
|
11
|
+
- Makes `release-kit prepare` bump the major version for a `fix!` or `perf!` commit under the default breaking policies, instead of reporting a policy violation and bumping only the patch version while the changelog marked the entry breaking.
|
|
12
|
+
- Corrects `docs/work-types.md` to state that a `breakingPolicies` map replaces the default policies rather than overriding individual types, and that release-kit treats every type omitted by the map as `optional`.
|
|
13
|
+
|
|
14
|
+
### ๐ Bug fixes
|
|
15
|
+
|
|
16
|
+
- Omit the breaking marker from changelog entries whose type forbids it (#819)
|
|
17
|
+
|
|
18
|
+
- Makes the configured `breakingPolicies` map decide whether the changelog marks a commit breaking, as it already decides the version bump.
|
|
19
|
+
|
|
5
20
|
## 10.7.0 โ 2026-09-15
|
|
6
21
|
|
|
7
22
|
### ๐ Features
|
package/README.md
CHANGED
|
@@ -7,30 +7,20 @@ Version-bumping and changelog-generation toolkit for release workflows.
|
|
|
7
7
|
Provides a self-contained CLI that auto-discovers workspaces from `pnpm-workspace.yaml`, parses conventional commits, determines version bumps, updates `package.json` files, and generates changelogs from `git-cliff --context` output rendered in-process (with optional [editorial overrides](docs/editorial-overrides.md)).
|
|
8
8
|
|
|
9
9
|
<!-- section:release-notes -->
|
|
10
|
-
## Release notes โ v10.
|
|
10
|
+
## Release notes โ v10.8.0 (2026-09-15)
|
|
11
11
|
|
|
12
12
|
### ๐ Features
|
|
13
13
|
|
|
14
|
-
-
|
|
14
|
+
- Allow the breaking marker on fix and perf commits (#818)
|
|
15
15
|
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
Migration: To reset `.config/v11y-check.config.json` to its defaults, delete the file and run `v11y init`, because `v11y init --force` now overwrites only `.github/workflows/audit.yaml`.
|
|
16
|
+
- Makes `release-kit prepare` bump the major version for a `fix!` or `perf!` commit under the default breaking policies, instead of reporting a policy violation and bumping only the patch version while the changelog marked the entry breaking.
|
|
17
|
+
- Corrects `docs/work-types.md` to state that a `breakingPolicies` map replaces the default policies rather than overriding individual types, and that release-kit treats every type omitted by the map as `optional`.
|
|
20
18
|
|
|
21
19
|
### ๐ Bug fixes
|
|
22
20
|
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
- Fixes the issue that the `npm-auto-publish` kit advised `npm trust github โฆ` for every package when the npm session lacked the two-factor authentication that trust queries need.
|
|
26
|
-
|
|
27
|
-
- Treat label names that differ only in case as one label (#808)
|
|
28
|
-
|
|
29
|
-
- Fixes the issue that `sync-labels generate` wrote a preset's `bug` and a local `Bug` to `.github/labels.yaml` as two labels, which made the first sync fail to create the second and every later sync rename the existing label back and forth.
|
|
30
|
-
- Lets a `labels` entry change a preset label's casing: `Bug` replaces a preset's `bug` and appears in the output as `Bug`, and `Bug: null` removes it.
|
|
31
|
-
- Makes `labels` keys that differ only in case a config error that names each group, such as `'bug' and 'Bug'`, since folding them would discard all but one without any sign in the output.
|
|
21
|
+
- Omit the breaking marker from changelog entries whose type forbids it (#819)
|
|
32
22
|
|
|
33
|
-
|
|
23
|
+
- Makes the configured `breakingPolicies` map decide whether the changelog marks a commit breaking, as it already decides the version bump.
|
|
34
24
|
<!-- /section:release-notes -->
|
|
35
25
|
|
|
36
26
|
## Installation
|
|
@@ -209,7 +209,7 @@ Subcommands:
|
|
|
209
209
|
sync Overwrite the local work-types.json with the upstream contents
|
|
210
210
|
|
|
211
211
|
Exit codes (check):
|
|
212
|
-
0 Match (or upstream
|
|
212
|
+
0 Match (or upstream not found, with a warning)
|
|
213
213
|
1 Drift detected
|
|
214
214
|
2 Network error
|
|
215
215
|
3 Schema mismatch
|
|
@@ -223,8 +223,8 @@ function showWorkTypesCheckHelp() {
|
|
|
223
223
|
Usage: release-kit work-types check
|
|
224
224
|
|
|
225
225
|
Compare the local work-types.json against the upstream codeassembly canonical and report
|
|
226
|
-
drift. Exit 0 on match, 1 on drift, 0 + warning when upstream is
|
|
227
|
-
|
|
226
|
+
drift. Exit 0 on match, 1 on drift, 0 + warning when upstream is not found, 2 on network
|
|
227
|
+
error, 3 on schema mismatch.
|
|
228
228
|
|
|
229
229
|
Options:
|
|
230
230
|
--help, -h Show this help message
|
|
@@ -23,4 +23,4 @@ export declare function stripGroupDecorations(group: string): string;
|
|
|
23
23
|
* not whether git-cliff runs). This means dry-run exercises the full git-cliff toolchain and surfaces missing-binary,
|
|
24
24
|
* malformed-config, and template-resolution failures earlier than before.
|
|
25
25
|
*/
|
|
26
|
-
export declare function buildChangelogEntries(config: Pick<ReleaseConfig, '
|
|
26
|
+
export declare function buildChangelogEntries(config: Pick<ReleaseConfig, 'breakingPolicies' | 'changelogJson' | 'cliffConfigPath' | 'workTypes'>, tag: string, options?: GenerateChangelogOptions): ChangelogEntry[];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { chainError } from '@williamthorsen/toolbelt.errors/candidate';
|
|
2
2
|
import { extractVersion } from "./changelogJsonUtils.js";
|
|
3
|
-
import { DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
3
|
+
import { DEFAULT_BREAKING_POLICIES, DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
4
4
|
import { extractMigration } from "./extractMigration.js";
|
|
5
|
-
import { COMMIT_PREPROCESSOR_PATTERNS, PIPE_SCOPE_SOURCE } from "./parseCommitMessage.js";
|
|
5
|
+
import { COMMIT_PREPROCESSOR_PATTERNS, parseCommitMessage, PIPE_SCOPE_SOURCE } from "./parseCommitMessage.js";
|
|
6
6
|
import { resolveCliffConfigPath } from "./resolveCliffConfigPath.js";
|
|
7
7
|
import { runGitCliff } from "./runGitCliff.js";
|
|
8
8
|
import { stripEmojiPrefix } from "./stripEmojiPrefix.js";
|
|
@@ -30,7 +30,9 @@ export function buildChangelogEntries(config, tag, options) {
|
|
|
30
30
|
const contextJson = runGitCliff(resolvedConfigPath, cliffArgs);
|
|
31
31
|
const releases = parseCliffContext(contextJson);
|
|
32
32
|
const devOnlySections = new Set(config.changelogJson.devOnlySections);
|
|
33
|
-
|
|
33
|
+
const workTypes = config.workTypes ?? DEFAULT_WORK_TYPES;
|
|
34
|
+
const breakingPolicies = config.breakingPolicies ?? DEFAULT_BREAKING_POLICIES;
|
|
35
|
+
return transformReleases(releases, devOnlySections, workTypes, breakingPolicies);
|
|
34
36
|
}
|
|
35
37
|
catch (error) {
|
|
36
38
|
throw chainError(`Failed to build changelog entries for tag ${tag}`, error);
|
|
@@ -74,7 +76,7 @@ function toCliffContextCommit(value) {
|
|
|
74
76
|
}
|
|
75
77
|
return commit;
|
|
76
78
|
}
|
|
77
|
-
function transformReleases(releases, devOnlySections) {
|
|
79
|
+
function transformReleases(releases, devOnlySections, workTypes, breakingPolicies) {
|
|
78
80
|
const entries = [];
|
|
79
81
|
const devOnlyNormalised = new Set([...devOnlySections].map(stripGroupDecorations));
|
|
80
82
|
for (const release of releases) {
|
|
@@ -89,7 +91,7 @@ function transformReleases(releases, devOnlySections) {
|
|
|
89
91
|
const group = stripCommentPrefix(commit.group ?? 'Other');
|
|
90
92
|
const description = extractDescription(commit.message);
|
|
91
93
|
const body = extractBody(commit.message);
|
|
92
|
-
const breaking =
|
|
94
|
+
const breaking = isBreakingUnderPolicy(commit, workTypes, breakingPolicies);
|
|
93
95
|
let items = sectionMap.get(group);
|
|
94
96
|
if (items === undefined) {
|
|
95
97
|
items = [];
|
|
@@ -132,6 +134,13 @@ function transformReleases(releases, devOnlySections) {
|
|
|
132
134
|
function stripCommentPrefix(group) {
|
|
133
135
|
return group.replace(HTML_COMMENT_PREFIX_PATTERN, '');
|
|
134
136
|
}
|
|
137
|
+
function isBreakingUnderPolicy(commit, workTypes, breakingPolicies) {
|
|
138
|
+
if (!subjectHasBreakingMarker(commit.message)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
const parsed = parseCommitMessage(commit.message, commit.id ?? '', workTypes, undefined, { breakingPolicies });
|
|
142
|
+
return parsed?.breaking ?? true;
|
|
143
|
+
}
|
|
135
144
|
const SUBJECT_BREAKING_MARKER_PATTERN = new RegExp(String.raw `^(?:${PIPE_SCOPE_SOURCE}\|)?\w+(?:\([^)]+\))?!:`);
|
|
136
145
|
function subjectHasBreakingMarker(message) {
|
|
137
146
|
let subject = message.split('\n', 1)[0] ?? '';
|
|
@@ -4,7 +4,7 @@ export declare const UPSTREAM_WORK_TYPES_URL = "https://raw.githubusercontent.co
|
|
|
4
4
|
export interface DriftCheckResult {
|
|
5
5
|
/**
|
|
6
6
|
* Process exit code semantics:
|
|
7
|
-
* - `0` โ match (or upstream
|
|
7
|
+
* - `0` โ match (or upstream not found, with a warning).
|
|
8
8
|
* - `1` โ drift detected.
|
|
9
9
|
* - `2` โ network error.
|
|
10
10
|
* - `3` โ schema mismatch (upstream JSON does not parse or fails the schema invariants).
|
|
@@ -27,8 +27,7 @@ export interface CheckWorkTypesDriftDependencies {
|
|
|
27
27
|
*
|
|
28
28
|
* Failure modes:
|
|
29
29
|
* - Network error โ exit 2 with a diagnostic.
|
|
30
|
-
* - Upstream 404 โ exit 0 with a
|
|
31
|
-
* JSON yet; the check is informational while migration is in flight).
|
|
30
|
+
* - Upstream 404 โ exit 0 with a warning.
|
|
32
31
|
* - Schema mismatch โ exit 3 with a diagnostic.
|
|
33
32
|
* - Drift โ exit 1 with a unified-diff-style message.
|
|
34
33
|
* - Match โ exit 0.
|
|
@@ -38,7 +38,7 @@ export async function checkWorkTypesDrift(dependencies = {}) {
|
|
|
38
38
|
if (response.status === 404) {
|
|
39
39
|
return {
|
|
40
40
|
exitCode: 0,
|
|
41
|
-
message: `Upstream work-types.json not
|
|
41
|
+
message: `Upstream work-types.json not found at ${url}; skipping drift check.`,
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
if (!response.ok) {
|
|
@@ -15,10 +15,9 @@ export type PolicyViolationSurface = 'prefix' | 'body';
|
|
|
15
15
|
/**
|
|
16
16
|
* Callback invoked when `parseCommitMessage` detects a `!`-policy violation.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* etc.) collect callback invocations and surface them in the release report.
|
|
18
|
+
* The parser warns and continues on a violation, so legacy log entries don't block releases.
|
|
19
|
+
* Callers (`decideRelease`, `releasePrepareMono`, etc.) collect callback invocations and
|
|
20
|
+
* surface them in the release report.
|
|
22
21
|
*/
|
|
23
22
|
export type PolicyViolationHandler = (commit: Commit, type: string, surface: PolicyViolationSurface) => void;
|
|
24
23
|
/** Optional configuration for `parseCommitMessage` beyond the core inputs. */
|
|
@@ -47,6 +46,6 @@ export interface ParseCommitMessageOptions {
|
|
|
47
46
|
* `!`-policy enforcement is **release-time tolerant**: when the resolved type's policy
|
|
48
47
|
* forbids `!`, the marker is dropped from the parse (`breaking: false`) and
|
|
49
48
|
* `onPolicyViolation` is invoked. When the policy requires `!`, a bare type triggers the
|
|
50
|
-
* same warning path.
|
|
49
|
+
* same warning path.
|
|
51
50
|
*/
|
|
52
51
|
export declare function parseCommitMessage(message: string, hash: string, workTypes: Record<string, WorkTypeConfig>, scopeAliases?: Record<string, string>, options?: ParseCommitMessageOptions): ParsedCommit | undefined;
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -11,19 +11,20 @@ export interface ChangelogItem {
|
|
|
11
11
|
/**
|
|
12
12
|
* Whether this item represents a breaking change.
|
|
13
13
|
*
|
|
14
|
-
* `true` when the commit subject carries the `!` prefix (e.g. `feat!:` or `drop(scope)!:`)
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* marker constructed from `WORK_TYPES_DATA.markers.breaking`
|
|
18
|
-
* with the canonical SSOT values) to surface them prominently
|
|
14
|
+
* `true` when the commit subject carries the `!` prefix (e.g. `feat!:` or `drop(scope)!:`) and
|
|
15
|
+
* the commit's work-type policy permits it, so the item agrees with the version bump.
|
|
16
|
+
* The `BREAKING CHANGE:` body footer is intentionally NOT considered here. Renderers prefix
|
|
17
|
+
* breaking-item bullets with the marker constructed from `WORK_TYPES_DATA.markers.breaking`
|
|
18
|
+
* (rendered as `๐จ **Breaking:** ` with the canonical SSOT values) to surface them prominently
|
|
19
|
+
* in release notes.
|
|
19
20
|
*/
|
|
20
21
|
breaking?: boolean;
|
|
21
22
|
/**
|
|
22
23
|
* Migration instruction for a consumer, taken from the `Migration:` paragraph of `body`.
|
|
23
24
|
*
|
|
24
25
|
* Derived from `body` wherever `body` is set, and absent where the body carries no labeled
|
|
25
|
-
* paragraph. Independent of `breaking`: a `
|
|
26
|
-
*
|
|
26
|
+
* paragraph. Independent of `breaking`: a `deprecate` commit cannot carry `!` under the default
|
|
27
|
+
* breaking policy and still calls for a migration. `body` keeps the paragraph, so
|
|
27
28
|
* `CHANGELOG.md` goes on rendering it in place.
|
|
28
29
|
*/
|
|
29
30
|
migration?: string;
|
package/dist/esm/work-types.json
CHANGED
|
@@ -1,133 +1,149 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./work-types.schema.json",
|
|
3
|
+
"markers": {
|
|
4
|
+
"breaking": {
|
|
5
|
+
"emoji": "๐จ",
|
|
6
|
+
"label": "Breaking"
|
|
7
|
+
}
|
|
8
|
+
},
|
|
3
9
|
"tiers": ["public", "internal", "process"],
|
|
4
10
|
"types": [
|
|
5
11
|
{
|
|
6
|
-
"tier": "public",
|
|
7
|
-
"key": "feat",
|
|
8
12
|
"aliases": ["feature"],
|
|
13
|
+
"breakingPolicy": "optional",
|
|
14
|
+
"description": "A change that gives consumers a new capability or extends an existing one.",
|
|
9
15
|
"emoji": "๐",
|
|
16
|
+
"key": "feat",
|
|
10
17
|
"label": "Features",
|
|
11
|
-
"
|
|
18
|
+
"tier": "public"
|
|
12
19
|
},
|
|
13
20
|
{
|
|
14
|
-
"tier": "public",
|
|
15
|
-
"key": "drop",
|
|
16
21
|
"aliases": [],
|
|
22
|
+
"breakingPolicy": "required",
|
|
23
|
+
"description": "A change that removes a capability or surface on which consumers depend.",
|
|
17
24
|
"emoji": "๐ชฆ",
|
|
25
|
+
"key": "drop",
|
|
18
26
|
"label": "Removed",
|
|
19
|
-
"
|
|
27
|
+
"tier": "public"
|
|
20
28
|
},
|
|
21
29
|
{
|
|
22
|
-
"tier": "public",
|
|
23
|
-
"key": "deprecate",
|
|
24
30
|
"aliases": [],
|
|
31
|
+
"breakingPolicy": "forbidden",
|
|
32
|
+
"description": "A change that marks a capability or surface for removal while the capability or surface keeps working.",
|
|
25
33
|
"emoji": "๐๏ธ",
|
|
34
|
+
"key": "deprecate",
|
|
26
35
|
"label": "Deprecated",
|
|
27
|
-
"
|
|
36
|
+
"tier": "public"
|
|
28
37
|
},
|
|
29
38
|
{
|
|
30
|
-
"tier": "public",
|
|
31
|
-
"key": "fix",
|
|
32
39
|
"aliases": ["bugfix"],
|
|
40
|
+
"breakingPolicy": "optional",
|
|
41
|
+
"description": "A change that corrects behavior that consumers meet and that differs from what was intended.",
|
|
33
42
|
"emoji": "๐",
|
|
43
|
+
"key": "fix",
|
|
34
44
|
"label": "Bug fixes",
|
|
35
|
-
"
|
|
45
|
+
"tier": "public"
|
|
36
46
|
},
|
|
37
47
|
{
|
|
38
|
-
"tier": "public",
|
|
39
|
-
"key": "sec",
|
|
40
48
|
"aliases": ["security"],
|
|
49
|
+
"breakingPolicy": "optional",
|
|
50
|
+
"description": "A change that closes a vulnerability or hardens a consumer-facing surface against attack.",
|
|
41
51
|
"emoji": "๐",
|
|
52
|
+
"key": "sec",
|
|
42
53
|
"label": "Security",
|
|
43
|
-
"
|
|
54
|
+
"tier": "public"
|
|
44
55
|
},
|
|
45
56
|
{
|
|
46
|
-
"tier": "public",
|
|
47
|
-
"key": "perf",
|
|
48
57
|
"aliases": ["performance"],
|
|
58
|
+
"breakingPolicy": "optional",
|
|
59
|
+
"description": "A change that reduces the time, memory, or other resources that consumer-facing work uses, without changing its result.",
|
|
49
60
|
"emoji": "โก",
|
|
61
|
+
"key": "perf",
|
|
50
62
|
"label": "Performance",
|
|
51
|
-
"
|
|
63
|
+
"tier": "public"
|
|
52
64
|
},
|
|
53
65
|
{
|
|
54
|
-
"tier": "internal",
|
|
55
|
-
"key": "internal",
|
|
56
66
|
"aliases": ["utility"],
|
|
67
|
+
"breakingPolicy": "forbidden",
|
|
68
|
+
"description": "A change that adds or extends a capability that consumers do not use directly, such as a helper or an internal module.",
|
|
57
69
|
"emoji": "๐๏ธ",
|
|
70
|
+
"key": "internal",
|
|
58
71
|
"label": "Internal features",
|
|
59
|
-
"
|
|
72
|
+
"tier": "internal"
|
|
60
73
|
},
|
|
61
74
|
{
|
|
62
|
-
"tier": "internal",
|
|
63
|
-
"key": "refactor",
|
|
64
75
|
"aliases": [],
|
|
76
|
+
"breakingPolicy": "forbidden",
|
|
77
|
+
"description": "A change that restructures existing code without changing its behavior.",
|
|
65
78
|
"emoji": "โป๏ธ",
|
|
79
|
+
"key": "refactor",
|
|
66
80
|
"label": "Refactoring",
|
|
67
|
-
"
|
|
81
|
+
"tier": "internal"
|
|
68
82
|
},
|
|
69
83
|
{
|
|
70
|
-
"tier": "internal",
|
|
71
|
-
"key": "tests",
|
|
72
84
|
"aliases": ["test"],
|
|
85
|
+
"breakingPolicy": "forbidden",
|
|
86
|
+
"description": "A change confined to tests, test fixtures, or test helpers, including one that unblocks a build or a type check.",
|
|
73
87
|
"emoji": "๐งช",
|
|
88
|
+
"key": "tests",
|
|
74
89
|
"label": "Tests",
|
|
75
|
-
"
|
|
90
|
+
"tier": "internal"
|
|
76
91
|
},
|
|
77
92
|
{
|
|
78
|
-
"tier": "process",
|
|
79
|
-
"key": "tooling",
|
|
80
93
|
"aliases": [],
|
|
94
|
+
"breakingPolicy": "forbidden",
|
|
95
|
+
"description": "A change to the tools used to develop the project: build, lint, formatting, and release configuration, and development scripts.",
|
|
81
96
|
"emoji": "โ๏ธ",
|
|
97
|
+
"key": "tooling",
|
|
82
98
|
"label": "Tooling",
|
|
83
|
-
"
|
|
99
|
+
"tier": "process"
|
|
84
100
|
},
|
|
85
101
|
{
|
|
86
|
-
"tier": "process",
|
|
87
|
-
"key": "ci",
|
|
88
102
|
"aliases": [],
|
|
103
|
+
"breakingPolicy": "forbidden",
|
|
104
|
+
"description": "A change to continuous-integration workflows and their configuration.",
|
|
89
105
|
"emoji": "๐ท",
|
|
106
|
+
"key": "ci",
|
|
90
107
|
"label": "CI",
|
|
91
|
-
"
|
|
108
|
+
"tier": "process"
|
|
92
109
|
},
|
|
93
110
|
{
|
|
94
|
-
"tier": "process",
|
|
95
|
-
"key": "deps",
|
|
96
111
|
"aliases": ["dep"],
|
|
112
|
+
"breakingPolicy": "forbidden",
|
|
113
|
+
"description": "A change that adds, removes, or upgrades a dependency, including its lockfile and version-catalog entries.",
|
|
97
114
|
"emoji": "๐ฆ",
|
|
115
|
+
"key": "deps",
|
|
98
116
|
"label": "Dependencies",
|
|
99
|
-
"
|
|
117
|
+
"tier": "process"
|
|
100
118
|
},
|
|
101
119
|
{
|
|
102
|
-
"tier": "process",
|
|
103
|
-
"key": "ai",
|
|
104
120
|
"aliases": [],
|
|
121
|
+
"breakingPolicy": "forbidden",
|
|
122
|
+
"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.",
|
|
105
123
|
"emoji": "๐ค",
|
|
124
|
+
"key": "ai",
|
|
106
125
|
"label": "Agentic support",
|
|
107
|
-
"
|
|
126
|
+
"tier": "process"
|
|
108
127
|
},
|
|
109
128
|
{
|
|
110
|
-
"tier": "process",
|
|
111
|
-
"key": "docs",
|
|
112
129
|
"aliases": ["doc"],
|
|
130
|
+
"breakingPolicy": "forbidden",
|
|
131
|
+
"description": "A change to documentation for human readers, such as a README, a guide, or a code comment.",
|
|
113
132
|
"emoji": "๐",
|
|
133
|
+
"key": "docs",
|
|
114
134
|
"label": "Documentation",
|
|
115
|
-
"
|
|
135
|
+
"tier": "process"
|
|
116
136
|
},
|
|
117
137
|
{
|
|
118
|
-
"tier": "process",
|
|
119
|
-
"key": "fmt",
|
|
120
138
|
"aliases": [],
|
|
139
|
+
"breakingPolicy": "forbidden",
|
|
140
|
+
"description": "A change to formatting alone, such as whitespace or line wrapping, that leaves the content unchanged.",
|
|
121
141
|
"emoji": "๐จ",
|
|
142
|
+
"excludedFromChangelog": true,
|
|
143
|
+
"key": "fmt",
|
|
122
144
|
"label": "Formatting",
|
|
123
|
-
"
|
|
124
|
-
"excludedFromChangelog": true
|
|
145
|
+
"tier": "process"
|
|
125
146
|
}
|
|
126
147
|
],
|
|
127
|
-
"
|
|
128
|
-
"breaking": {
|
|
129
|
-
"emoji": "๐จ",
|
|
130
|
-
"label": "Breaking"
|
|
131
|
-
}
|
|
132
|
-
}
|
|
148
|
+
"version": "1.1.0"
|
|
133
149
|
}
|
|
@@ -4,13 +4,18 @@
|
|
|
4
4
|
"title": "Work types",
|
|
5
5
|
"description": "Canonical taxonomy of commit work types used by release-kit. Drives section ordering, audience classification, and the `!` (breaking) policy. The structured single-source-of-truth for everything that previously lived in `DEFAULT_WORK_TYPES` and `cliff.toml.template` group definitions.",
|
|
6
6
|
"type": "object",
|
|
7
|
-
"required": ["tiers", "types", "markers"],
|
|
7
|
+
"required": ["tiers", "types", "markers", "version"],
|
|
8
8
|
"additionalProperties": false,
|
|
9
9
|
"properties": {
|
|
10
10
|
"$schema": {
|
|
11
11
|
"type": "string",
|
|
12
12
|
"description": "Optional reference to this schema for IDE validation."
|
|
13
13
|
},
|
|
14
|
+
"version": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "Semantic version of the data shape. Bumped when the structure changes in a way that breaks downstream consumers.",
|
|
17
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+$"
|
|
18
|
+
},
|
|
14
19
|
"tiers": {
|
|
15
20
|
"type": "array",
|
|
16
21
|
"description": "Render tiers in canonical order. Each entry's `tier` field must reference one of these names.",
|
|
@@ -55,7 +60,7 @@
|
|
|
55
60
|
},
|
|
56
61
|
"workType": {
|
|
57
62
|
"type": "object",
|
|
58
|
-
"required": ["tier", "key", "aliases", "emoji", "label", "breakingPolicy"],
|
|
63
|
+
"required": ["tier", "key", "aliases", "emoji", "label", "breakingPolicy", "description"],
|
|
59
64
|
"additionalProperties": false,
|
|
60
65
|
"properties": {
|
|
61
66
|
"tier": {
|
|
@@ -84,6 +89,11 @@
|
|
|
84
89
|
"description": "Human-readable section label (rendered as `${emoji} ${label}` in changelogs and release notes).",
|
|
85
90
|
"minLength": 1
|
|
86
91
|
},
|
|
92
|
+
"description": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "The changes that the type covers, read by an agent choosing a type for a change.",
|
|
95
|
+
"minLength": 1
|
|
96
|
+
},
|
|
87
97
|
"breakingPolicy": {
|
|
88
98
|
"type": "string",
|
|
89
99
|
"description": "Policy governing the `!` (breaking) marker for this type. `forbidden`: `!` is a policy violation. `optional`: `!` is allowed. `required`: bare type is a policy violation; only the `!` form is accepted.",
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Canonical work-types data
|
|
2
|
+
* Canonical work-types data: the runtime mirror of `work-types.json`.
|
|
3
3
|
*
|
|
4
|
-
* `work-types.json` is
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* esbuild's `bundle: false` mode strips, so a plain TS module is the most reliable way
|
|
8
|
-
* to ship the data to consumers.
|
|
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.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `
|
|
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`.
|
|
13
11
|
*/
|
|
14
12
|
/** Schema for a single entry. */
|
|
15
13
|
export interface WorkTypeEntry {
|
|
@@ -18,6 +16,7 @@ export interface WorkTypeEntry {
|
|
|
18
16
|
aliases: string[];
|
|
19
17
|
emoji: string;
|
|
20
18
|
label: string;
|
|
19
|
+
description: string;
|
|
21
20
|
breakingPolicy: 'forbidden' | 'optional' | 'required';
|
|
22
21
|
excludedFromChangelog?: boolean;
|
|
23
22
|
}
|
|
@@ -34,6 +33,8 @@ export interface MarkerEntry {
|
|
|
34
33
|
}
|
|
35
34
|
/** Schema for the full data. */
|
|
36
35
|
export interface WorkTypesData {
|
|
36
|
+
/** Semantic version of the data shape, as declared by the upstream canonical. */
|
|
37
|
+
version: string;
|
|
37
38
|
tiers: string[];
|
|
38
39
|
types: WorkTypeEntry[];
|
|
39
40
|
/**
|
|
@@ -1,18 +1,60 @@
|
|
|
1
1
|
export const WORK_TYPES_DATA = {
|
|
2
|
+
version: '1.1.0',
|
|
2
3
|
tiers: ['public', 'internal', 'process'],
|
|
3
4
|
types: [
|
|
4
|
-
{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
+
},
|
|
9
50
|
{
|
|
10
51
|
tier: 'public',
|
|
11
52
|
key: 'perf',
|
|
12
53
|
aliases: ['performance'],
|
|
13
54
|
emoji: 'โก',
|
|
14
55
|
label: 'Performance',
|
|
15
|
-
|
|
56
|
+
description: 'A change that reduces the time, memory, or other resources that consumer-facing work uses, without changing its result.',
|
|
57
|
+
breakingPolicy: 'optional',
|
|
16
58
|
},
|
|
17
59
|
{
|
|
18
60
|
tier: 'internal',
|
|
@@ -20,6 +62,7 @@ export const WORK_TYPES_DATA = {
|
|
|
20
62
|
aliases: ['utility'],
|
|
21
63
|
emoji: '๐๏ธ',
|
|
22
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.',
|
|
23
66
|
breakingPolicy: 'forbidden',
|
|
24
67
|
},
|
|
25
68
|
{
|
|
@@ -28,19 +71,61 @@ export const WORK_TYPES_DATA = {
|
|
|
28
71
|
aliases: [],
|
|
29
72
|
emoji: 'โป๏ธ',
|
|
30
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.",
|
|
31
120
|
breakingPolicy: 'forbidden',
|
|
32
121
|
},
|
|
33
|
-
{ tier: 'internal', key: 'tests', aliases: ['test'], emoji: '๐งช', label: 'Tests', breakingPolicy: 'forbidden' },
|
|
34
|
-
{ tier: 'process', key: 'tooling', aliases: [], emoji: 'โ๏ธ', label: 'Tooling', breakingPolicy: 'forbidden' },
|
|
35
|
-
{ tier: 'process', key: 'ci', aliases: [], emoji: '๐ท', label: 'CI', breakingPolicy: 'forbidden' },
|
|
36
|
-
{ tier: 'process', key: 'deps', aliases: ['dep'], emoji: '๐ฆ', label: 'Dependencies', breakingPolicy: 'forbidden' },
|
|
37
|
-
{ tier: 'process', key: 'ai', aliases: [], emoji: '๐ค', label: 'Agentic support', breakingPolicy: 'forbidden' },
|
|
38
122
|
{
|
|
39
123
|
tier: 'process',
|
|
40
124
|
key: 'docs',
|
|
41
125
|
aliases: ['doc'],
|
|
42
126
|
emoji: '๐',
|
|
43
127
|
label: 'Documentation',
|
|
128
|
+
description: 'A change to documentation for human readers, such as a README, a guide, or a code comment.',
|
|
44
129
|
breakingPolicy: 'forbidden',
|
|
45
130
|
},
|
|
46
131
|
{
|
|
@@ -49,6 +134,7 @@ export const WORK_TYPES_DATA = {
|
|
|
49
134
|
aliases: [],
|
|
50
135
|
emoji: '๐จ',
|
|
51
136
|
label: 'Formatting',
|
|
137
|
+
description: 'A change to formatting alone, such as whitespace or line wrapping, that leaves the content unchanged.',
|
|
52
138
|
breakingPolicy: 'forbidden',
|
|
53
139
|
excludedFromChangelog: true,
|
|
54
140
|
},
|
package/docs/changelogs.md
CHANGED
|
@@ -8,13 +8,13 @@ Neither `CHANGELOG.md` nor `.meta/changelog.json` reaches a published tarball on
|
|
|
8
8
|
|
|
9
9
|
Each item under a section in `.meta/changelog.json` carries one required field and four optional ones:
|
|
10
10
|
|
|
11
|
-
| Field | Type | Meaning
|
|
12
|
-
| ------------- | --------- |
|
|
13
|
-
| `description` | `string` | The bullet headline, taken from the commit subject with the ticket ID and type prefix stripped.
|
|
14
|
-
| `body` | `string` | The commit body, with trailing trailer metadata stripped.
|
|
15
|
-
| `breaking` | `boolean` | Present and `true` where the commit subject carried the `!` prefix. See [`!` (breaking change) policy](work-types.md#-breaking-change-policy). |
|
|
16
|
-
| `migration` | `string` | The migration step for a consumer. See below.
|
|
17
|
-
| `hash` | `string` | The full commit SHA, and the key on which an override entry matches. Absent on synthetic propagation entries.
|
|
11
|
+
| Field | Type | Meaning |
|
|
12
|
+
| ------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
13
|
+
| `description` | `string` | The bullet headline, taken from the commit subject with the ticket ID and type prefix stripped. |
|
|
14
|
+
| `body` | `string` | The commit body, with trailing trailer metadata stripped. |
|
|
15
|
+
| `breaking` | `boolean` | Present and `true` where the commit subject carried the `!` prefix and the commit's type permits it. See [`!` (breaking change) policy](work-types.md#-breaking-change-policy). |
|
|
16
|
+
| `migration` | `string` | The migration step for a consumer. See below. |
|
|
17
|
+
| `hash` | `string` | The full commit SHA, and the key on which an override entry matches. Absent on synthetic propagation entries. |
|
|
18
18
|
|
|
19
19
|
Every optional field is omitted rather than emitted as `null`, so a consumer tests for presence.
|
|
20
20
|
|
|
@@ -32,7 +32,7 @@ A commit body states a migration step as a paragraph opening with the literal la
|
|
|
32
32
|
|
|
33
33
|
Three properties are worth knowing:
|
|
34
34
|
|
|
35
|
-
- **It is independent of `breaking`.** A `
|
|
35
|
+
- **It is independent of `breaking`.** A `deprecate` cannot carry `!` under the default breaking policy, and a `deprecate` still calls for a migration. Filter on `migration` to find every step; filter on `breaking` to find every breaking change.
|
|
36
36
|
- **`body` keeps the paragraph.** The field is an extraction, not a move, so `CHANGELOG.md` and `.meta/changelog.json` go on agreeing.
|
|
37
37
|
- **It is derived, not authored.** `migration` is not a field an override file can set (see [File shape](editorial-overrides.md#file-shape)); it is re-derived from whatever `body` an override installs, and cleared where that body carries no labeled paragraph. To change the migration text, override `body`.
|
|
38
38
|
|
package/docs/work-types.md
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
The taxonomy against which release-kit parses commits: its tiers, the breaking-change policy, section markers, customization, and the commands that compare it with its upstream.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
release-kit bundles a copy of the codeassembly canonical taxonomy in `packages/release-kit/src/work-types.json`, kept level by `release-kit work-types sync`. The taxonomy is split into three tiers that drive section rendering and audience classification.
|
|
6
6
|
|
|
7
7
|
| Tier | Key | Header | Aliases | `!` policy |
|
|
8
8
|
| -------- | ----------- | ------------------------- | ------------- | ------------ |
|
|
9
9
|
| public | `feat` | ๐ Features | `feature` | optional |
|
|
10
10
|
| public | `drop` | ๐ชฆ Removed | | **required** |
|
|
11
11
|
| public | `deprecate` | ๐๏ธ Deprecated | | forbidden |
|
|
12
|
-
| public | `fix` | ๐ Bug fixes | `bugfix` |
|
|
12
|
+
| public | `fix` | ๐ Bug fixes | `bugfix` | optional |
|
|
13
13
|
| public | `sec` | ๐ Security | `security` | optional |
|
|
14
|
-
| public | `perf` | โก Performance | `performance` |
|
|
14
|
+
| public | `perf` | โก Performance | `performance` | optional |
|
|
15
15
|
| internal | `internal` | ๐๏ธ Internal features | `utility` | forbidden |
|
|
16
16
|
| internal | `refactor` | โป๏ธ Refactoring | | forbidden |
|
|
17
17
|
| internal | `tests` | ๐งช Tests | `test` | forbidden |
|
|
@@ -38,18 +38,15 @@ Section render order is **tier order (`public` โ `internal` โ `process`), th
|
|
|
38
38
|
|
|
39
39
|
Each work-type carries a `breakingPolicy` value:
|
|
40
40
|
|
|
41
|
-
- `optional` (`feat`, `sec`)
|
|
42
|
-
- `forbidden` (
|
|
43
|
-
- `required` (`drop`)
|
|
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.
|
|
42
|
+
- `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
44
|
|
|
45
|
-
###
|
|
45
|
+
### Policy enforcement
|
|
46
46
|
|
|
47
|
-
|
|
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.
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
- **Release-time** (`parseCommitMessage`) โ tolerant warn-and-continue. 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 a `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.
|
|
51
|
-
|
|
52
|
-
A `BREAKING CHANGE:` body footer on a `forbidden`-policy type triggers the same warning path as the prefix `!` does โ the spirit of the policy is "internal/perf/etc. cannot be breaking", which must apply to both surfaces.
|
|
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.
|
|
53
50
|
|
|
54
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:
|
|
55
52
|
|
|
@@ -62,17 +59,23 @@ arrays
|
|
|
62
59
|
๐ฆ 1.0.0 โ 1.0.1 (patch)
|
|
63
60
|
```
|
|
64
61
|
|
|
65
|
-
To customize, set `breakingPolicies` in `release-kit.config.ts
|
|
62
|
+
To customize, set `breakingPolicies` in `release-kit.config.ts`. The map replaces the default policies rather than merging with them, and the parser treats any type that the map omits as `'optional'`: A config that changes one type lists every policy that it keeps, and `{}` disables enforcement entirely. Violations remain warnings, never failures.
|
|
66
63
|
|
|
67
64
|
## `๐จ **Breaking:**` bullet marker
|
|
68
65
|
|
|
69
|
-
Items whose commit subject carries the `!` prefix (e.g. `feat!`, `drop!`, `feat(api)!`) are rendered with a `๐จ **Breaking:** ` prefix on the bullet:
|
|
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:
|
|
70
67
|
|
|
71
68
|
```markdown
|
|
72
69
|
- ๐จ **Breaking:** Drop legacy /v1 endpoint
|
|
73
70
|
```
|
|
74
71
|
|
|
75
|
-
|
|
72
|
+
The marker agrees with the version bump:
|
|
73
|
+
|
|
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.
|
|
75
|
+
- 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.
|
|
77
|
+
|
|
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.
|
|
76
79
|
|
|
77
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.
|
|
78
81
|
|
|
@@ -104,18 +107,10 @@ The default `devOnlySections` (excluded from public release notes but still writ
|
|
|
104
107
|
|
|
105
108
|
Manage the canonical work-types taxonomy used by changelog and release-notes generation.
|
|
106
109
|
|
|
107
|
-
|
|
110
|
+
`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.
|
|
108
111
|
|
|
109
112
|
These commands are also exposed as `nmr work-types:check` / `nmr work-types:sync` from any package directory.
|
|
110
113
|
|
|
111
114
|
### Authenticated fetches
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
```sh
|
|
116
|
-
# Source from `gh auth` for local runs:
|
|
117
|
-
export GITHUB_TOKEN=$(gh auth token)
|
|
118
|
-
pnpm exec release-kit work-types check
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
The token needs `contents: read` on the codeassembly repo (fine-grained PAT scope) or the equivalent classic-PAT scope. A token without sufficient scope still produces a 404 โ same response as a missing upstream โ so a misconfigured token degrades to the transitional-warning path rather than failing loudly. CI wiring against private upstream is deferred until either codeassembly is publicly readable or a cross-repo PAT is provisioned as a workflow secret.
|
|
116
|
+
The upstream codeassembly repo is public, so `check` and `sync` need no token. When `GITHUB_TOKEN` is set in the environment, both commands send it as `Authorization: Bearer <token>`.
|