@williamthorsen/release-kit 10.8.0 → 10.9.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 (51) hide show
  1. package/.meta/changelog.json +43 -3
  2. package/.readyup/kits/default.js +3 -3
  3. package/.readyup/kits/npm-auto-publish.js +1 -1
  4. package/.readyup/manifest.json +9 -9
  5. package/CHANGELOG.md +34 -3
  6. package/README.md +25 -9
  7. package/dist/esm/bin/release-kit.js +20 -102
  8. package/dist/esm/createGithubReleaseCommand.d.ts +2 -1
  9. package/dist/esm/createGithubReleaseCommand.js +4 -2
  10. package/dist/esm/createTags.d.ts +2 -0
  11. package/dist/esm/createTags.js +5 -4
  12. package/dist/esm/format.d.ts +5 -5
  13. package/dist/esm/format.js +5 -4
  14. package/dist/esm/glyphs.d.ts +3 -0
  15. package/dist/esm/glyphs.js +6 -0
  16. package/dist/esm/init/initCommand.d.ts +3 -1
  17. package/dist/esm/init/initCommand.js +15 -15
  18. package/dist/esm/loadValidatedConfig.d.ts +2 -1
  19. package/dist/esm/loadValidatedConfig.js +3 -3
  20. package/dist/esm/prepareCommand.d.ts +2 -1
  21. package/dist/esm/prepareCommand.js +17 -16
  22. package/dist/esm/publishCommand.d.ts +2 -1
  23. package/dist/esm/publishCommand.js +2 -2
  24. package/dist/esm/reportPrepare.d.ts +2 -0
  25. package/dist/esm/reportPrepare.js +44 -38
  26. package/dist/esm/resolveReleaseNotesConfig.d.ts +2 -1
  27. package/dist/esm/resolveReleaseNotesConfig.js +4 -4
  28. package/dist/esm/resolveStylesOrExit.d.ts +10 -0
  29. package/dist/esm/resolveStylesOrExit.js +10 -0
  30. package/dist/esm/showTagPrefixesCommand.d.ts +2 -1
  31. package/dist/esm/showTagPrefixesCommand.js +16 -10
  32. package/dist/esm/sync-labels/generateCommand.d.ts +4 -2
  33. package/dist/esm/sync-labels/generateCommand.js +4 -4
  34. package/dist/esm/sync-labels/initCommand.d.ts +3 -1
  35. package/dist/esm/sync-labels/initCommand.js +7 -7
  36. package/dist/esm/tagCommand.d.ts +2 -1
  37. package/dist/esm/tagCommand.js +2 -2
  38. package/dist/esm/validateOverridesCommand.d.ts +4 -4
  39. package/dist/esm/validateOverridesCommand.js +6 -6
  40. package/docs/configuration.md +23 -1
  41. package/docs/work-types.md +11 -8
  42. package/package.json +11 -11
  43. package/presets/labels/common.yaml +2 -2
  44. package/dist/esm/checkWorkTypesDrift.d.ts +0 -35
  45. package/dist/esm/checkWorkTypesDrift.js +0 -117
  46. package/dist/esm/syncWorkTypes.d.ts +0 -28
  47. package/dist/esm/syncWorkTypes.js +0 -94
  48. package/dist/esm/work-types.json +0 -149
  49. package/dist/esm/work-types.schema.json +0 -110
  50. package/dist/esm/workTypesUtils.d.ts +0 -22
  51. package/dist/esm/workTypesUtils.js +0 -16
@@ -1,4 +1,47 @@
1
1
  [
2
+ {
3
+ "version": "10.9.0",
4
+ "date": "2026-09-18",
5
+ "sections": [
6
+ {
7
+ "title": "🎉 Features",
8
+ "audience": "all",
9
+ "items": [
10
+ {
11
+ "description": "Give release-kit plain output in pipes and CI logs (#835)",
12
+ "body": "- Adds the `RELEASE_KIT_OUTPUT_STYLE` environment variable, which accepts `auto`, `plain`, or `rich` and outranks the detection from `CI`, the stream's terminal state, and `TERM`; any other value is a usage error that exits with code 1.\n- Changes the emoji in rich output so that none has a different meaning from the one that it has in `nmr`: warnings from ⚠️ to 🟠, skips from ⏭️ to ⏩, the errors of `show-tag-prefixes` from ⛔ to ❌, and the tag marker from 🏷️ to 🔖.\n- Adds a required `style` parameter to `formatValidateOverridesResult`, which the package root exports.",
13
+ "hash": "aae401b4bbcafc7014e4b3804d80528d2d098a30"
14
+ },
15
+ {
16
+ "description": "Give nmr plain output in pipes and CI logs (#838)",
17
+ "body": "- Stops `nmr` from printing emoji to a pipe or a CI log: When the output stream is not a terminal or `CI` is set, a verdict reads `PASS`, `FAIL`, `SKIP`, or `NOOP` and a command icon is omitted, so that a log can be searched for a verdict.\n- Adds `--output-style <auto|plain|rich>` to `nmr` and the `NMR_OUTPUT_STYLE` variable, each forcing either style; the flag outranks the variable, a value that names no style exits 1 with a usage error, and neither enters a check-cache key: A rich run and a plain run share a recorded pass.\n- Replaces several rich glyphs, taking the status markers from the set that release-kit and v11y-check print so that one status has one glyph across the three tools: a recalled pass shows ⏩ in place of ⏭️, a skipped empty override shows ⚪ in place of ⛔, a warning and the `--log` refusal show 🟠 in place of ⚠️ and 📭, the `--log` header shows 💾 in place of 📼, and `nmr-ensure-prepublish-hooks` reports ✅ and ❌ in place of ✓ and ✗.",
18
+ "hash": "693b3a7f57def3d299ced240c19bda90f6253bdc"
19
+ }
20
+ ]
21
+ },
22
+ {
23
+ "title": "🐛 Bug fixes",
24
+ "audience": "all",
25
+ "items": [
26
+ {
27
+ "description": "Move work-types check and sync from the CLI into maintainer scripts (#820)",
28
+ "body": "- Removes the `release-kit work-types` command, whose `sync` rewrote an unused copy of `work-types.json` inside `node_modules` and whose `check` reported drift that a consumer could not fix.",
29
+ "hash": "31db5888038d69369422fdabbb1cc411dc95d6e1"
30
+ },
31
+ {
32
+ "description": "Exclude distributed agent guidance from ai and documentation labels (#825)",
33
+ "body": "- Marks a `.github/labels.yaml` generated from the previous `common` preset as stale in the default readyup kit, whose \"labels.yaml has current common preset\" check reports the file until the repo regenerates it.",
34
+ "hash": "0c4b0c59d8d87cdee66257ea7ca1bf9be86ce017"
35
+ },
36
+ {
37
+ "description": "Suppress bold and dim escapes for a stream that cannot render them (#830)",
38
+ "body": "- Stops `release-kit prepare` from writing raw escape bytes into piped output, redirected files, and CI logs: It styled bold and dim unconditionally, without checking whether the destination renders escapes.\n- Honors `NO_COLOR`, `NODE_DISABLE_COLORS`, and `FORCE_COLOR`, which the previous styling ignored.",
39
+ "hash": "eee5717f231615f9330c43239279d46d2a77a262"
40
+ }
41
+ ]
42
+ }
43
+ ]
44
+ },
2
45
  {
3
46
  "version": "10.8.0",
4
47
  "date": "2026-09-15",
@@ -537,7 +580,6 @@
537
580
  {
538
581
  "description": "Move defineConfig to a dedicated config subpath (#566)",
539
582
  "body": "`defineConfig` now comes from the `@williamthorsen/release-kit/config` subpath rather than from the package root. The subpath also carries the config types.",
540
- "breaking": true,
541
583
  "hash": "e0769815f41c23d64302be26c8369209fad72e22"
542
584
  },
543
585
  {
@@ -1134,13 +1176,11 @@
1134
1176
  {
1135
1177
  "description": "Rename `component` to `workspace` in config API and internals (#296)",
1136
1178
  "body": "Renames release-kit's per-workspace vocabulary from \"component\" to \"workspace\" throughout the public API, internal types, validation messages, CLI help, init templates, and documentation. Behavior is unchanged; only identifiers, error-message strings, scaffolded template text, and prose have been changed.",
1137
- "breaking": true,
1138
1179
  "hash": "dfe0a70903997b85a2ebf57a612345be5232a2c6"
1139
1180
  },
1140
1181
  {
1141
1182
  "description": "Rename `node-monorepo-core` to `nmr-core` (#304)",
1142
1183
  "body": "Renames the shared-utilities package from `@williamthorsen/node-monorepo-core` to `@williamthorsen/nmr-core`, aligning it with the repository's `nmr-*` naming convention. The package's functionality and version are unchanged; only the published name differs.",
1143
- "breaking": true,
1144
1184
  "hash": "085d4a57d1828bcd33933652aa47423989c090a9"
1145
1185
  }
1146
1186
  ]
@@ -1,6 +1,6 @@
1
1
  /** @noformat -- @generated. Do not edit. Compiled by rdy. */
2
2
  /* eslint-disable */
3
- export const __readyupVersion = "0.36.0";
3
+ export const __readyupVersion = "0.38.0";
4
4
 
5
5
 
6
6
  // .readyup/kits/default.ts
@@ -98,7 +98,7 @@ function translateGlob(pattern) {
98
98
 
99
99
  // .readyup/kits/default.ts
100
100
  function getMinVersion() {
101
- const picked = { "version": "10.8.0" };
101
+ const picked = { "version": "10.9.0" };
102
102
  if (typeof picked["version"] !== "string") {
103
103
  throw new TypeError("release-kit/package.json: 'version' must be a string");
104
104
  }
@@ -115,7 +115,7 @@ var CONFIG_EXPORT_PATTERNS = [
115
115
  /export\s*\*/
116
116
  ];
117
117
  var CLIFF_TEMPLATE_HASH = "93b72e0b1393cd6b1fe8e2a0e303cd326fd323435951b0493396b305af32d2ec";
118
- var COMMON_PRESET_HASH = "86f9e1db9000793a91168e8c6b5695311a422ee208121324549c068fe67fa184";
118
+ var COMMON_PRESET_HASH = "8c52654d4eee216c22377dd1e65b89f6bbb0a3478d74379bd28b04a877f0b02a";
119
119
  var SYNC_LABELS_WORKFLOW_HASH = "d6e2403fb551d2d415f679125989c92760444eec887644565b2e05c9bf8f4c1e";
120
120
  var RELEASE_WORKFLOW_HASH_MONOREPO = "0a9724b7b3c5e24087fd3a8f36fed8e990d699267fcf36028ce048ab40dc2946";
121
121
  var RELEASE_WORKFLOW_HASH_SINGLE = "a3d19bbc1ba8bb30622e53c590137b97e3179e80988c0967737b021cdaeab73f";
@@ -1,6 +1,6 @@
1
1
  /** @noformat -- @generated. Do not edit. Compiled by rdy. */
2
2
  /* eslint-disable */
3
- export const __readyupVersion = "0.36.0";
3
+ export const __readyupVersion = "0.38.0";
4
4
 
5
5
 
6
6
  // .readyup/kits/npm-auto-publish.ts
@@ -8,12 +8,12 @@
8
8
  "esbuildVersion": "0.28.2",
9
9
  "inputs": [
10
10
  {
11
- "hash": "55ff5731",
11
+ "hash": "a20ce64b",
12
12
  "kind": "module",
13
13
  "path": "kits/default.ts"
14
14
  },
15
15
  {
16
- "hash": "a8611365",
16
+ "hash": "beeecbc7",
17
17
  "kind": "inline",
18
18
  "path": "../package.json",
19
19
  "paths": [
@@ -43,10 +43,10 @@
43
43
  ],
44
44
  "name": "default",
45
45
  "path": "kits/default.js",
46
- "readyupVersion": "0.36.0",
46
+ "readyupVersion": "0.38.0",
47
47
  "source": "kits/default.ts",
48
- "sourceHash": "55ff5731",
49
- "targetHash": "be5f29ad"
48
+ "sourceHash": "a20ce64b",
49
+ "targetHash": "d3d5b51c"
50
50
  },
51
51
  {
52
52
  "checklists": [
@@ -56,17 +56,17 @@
56
56
  "esbuildVersion": "0.28.2",
57
57
  "inputs": [
58
58
  {
59
- "hash": "2f1fb68c",
59
+ "hash": "4eed1e9c",
60
60
  "kind": "module",
61
61
  "path": "kits/npm-auto-publish.ts"
62
62
  }
63
63
  ],
64
64
  "name": "npm-auto-publish",
65
65
  "path": "kits/npm-auto-publish.js",
66
- "readyupVersion": "0.36.0",
66
+ "readyupVersion": "0.38.0",
67
67
  "source": "kits/npm-auto-publish.ts",
68
- "sourceHash": "2f1fb68c",
69
- "targetHash": "cbabceb3"
68
+ "sourceHash": "4eed1e9c",
69
+ "targetHash": "d6126351"
70
70
  }
71
71
  ]
72
72
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,37 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 10.9.0 — 2026-09-18
6
+
7
+ ### 🎉 Features
8
+
9
+ - Give release-kit plain output in pipes and CI logs (#835)
10
+
11
+ - Adds the `RELEASE_KIT_OUTPUT_STYLE` environment variable, which accepts `auto`, `plain`, or `rich` and outranks the detection from `CI`, the stream's terminal state, and `TERM`; any other value is a usage error that exits with code 1.
12
+ - Changes the emoji in rich output so that none has a different meaning from the one that it has in `nmr`: warnings from ⚠️ to 🟠, skips from ⏭️ to ⏩, the errors of `show-tag-prefixes` from ⛔ to ❌, and the tag marker from 🏷️ to 🔖.
13
+ - Adds a required `style` parameter to `formatValidateOverridesResult`, which the package root exports.
14
+
15
+ - Give nmr plain output in pipes and CI logs (#838)
16
+
17
+ - Stops `nmr` from printing emoji to a pipe or a CI log: When the output stream is not a terminal or `CI` is set, a verdict reads `PASS`, `FAIL`, `SKIP`, or `NOOP` and a command icon is omitted, so that a log can be searched for a verdict.
18
+ - Adds `--output-style <auto|plain|rich>` to `nmr` and the `NMR_OUTPUT_STYLE` variable, each forcing either style; the flag outranks the variable, a value that names no style exits 1 with a usage error, and neither enters a check-cache key: A rich run and a plain run share a recorded pass.
19
+ - Replaces several rich glyphs, taking the status markers from the set that release-kit and v11y-check print so that one status has one glyph across the three tools: a recalled pass shows ⏩ in place of ⏭️, a skipped empty override shows ⚪ in place of ⛔, a warning and the `--log` refusal show 🟠 in place of ⚠️ and 📭, the `--log` header shows 💾 in place of 📼, and `nmr-ensure-prepublish-hooks` reports ✅ and ❌ in place of ✓ and ✗.
20
+
21
+ ### 🐛 Bug fixes
22
+
23
+ - Move work-types check and sync from the CLI into maintainer scripts (#820)
24
+
25
+ - Removes the `release-kit work-types` command, whose `sync` rewrote an unused copy of `work-types.json` inside `node_modules` and whose `check` reported drift that a consumer could not fix.
26
+
27
+ - Exclude distributed agent guidance from ai and documentation labels (#825)
28
+
29
+ - Marks a `.github/labels.yaml` generated from the previous `common` preset as stale in the default readyup kit, whose "labels.yaml has current common preset" check reports the file until the repo regenerates it.
30
+
31
+ - Suppress bold and dim escapes for a stream that cannot render them (#830)
32
+
33
+ - Stops `release-kit prepare` from writing raw escape bytes into piped output, redirected files, and CI logs: It styled bold and dim unconditionally, without checking whether the destination renders escapes.
34
+ - Honors `NO_COLOR`, `NODE_DISABLE_COLORS`, and `FORCE_COLOR`, which the previous styling ignored.
35
+
5
36
  ## 10.8.0 — 2026-09-15
6
37
 
7
38
  ### 🎉 Features
@@ -334,7 +365,7 @@ All notable changes to this project will be documented in this file.
334
365
 
335
366
  ### ♻️ Refactoring
336
367
 
337
- - 🚨 **Breaking:** Move defineConfig to a dedicated config subpath (#566)
368
+ - Move defineConfig to a dedicated config subpath (#566)
338
369
 
339
370
  `defineConfig` now comes from the `@williamthorsen/release-kit/config` subpath rather than from the package root. The subpath also carries the config types.
340
371
 
@@ -680,11 +711,11 @@ All notable changes to this project will be documented in this file.
680
711
 
681
712
  ### ♻️ Refactoring
682
713
 
683
- - 🚨 **Breaking:** Rename `component` to `workspace` in config API and internals (#296)
714
+ - Rename `component` to `workspace` in config API and internals (#296)
684
715
 
685
716
  Renames release-kit's per-workspace vocabulary from "component" to "workspace" throughout the public API, internal types, validation messages, CLI help, init templates, and documentation. Behavior is unchanged; only identifiers, error-message strings, scaffolded template text, and prose have been changed.
686
717
 
687
- - 🚨 **Breaking:** Rename `node-monorepo-core` to `nmr-core` (#304)
718
+ - Rename `node-monorepo-core` to `nmr-core` (#304)
688
719
 
689
720
  Renames the shared-utilities package from `@williamthorsen/node-monorepo-core` to `@williamthorsen/nmr-core`, aligning it with the repository's `nmr-*` naming convention. The package's functionality and version are unchanged; only the published name differs.
690
721
 
package/README.md CHANGED
@@ -7,20 +7,36 @@ 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.8.0 (2026-09-15)
10
+ ## Release notes — v10.9.0 (2026-09-18)
11
11
 
12
12
  ### 🎉 Features
13
13
 
14
- - Allow the breaking marker on fix and perf commits (#818)
14
+ - Give release-kit plain output in pipes and CI logs (#835)
15
15
 
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`.
16
+ - Adds the `RELEASE_KIT_OUTPUT_STYLE` environment variable, which accepts `auto`, `plain`, or `rich` and outranks the detection from `CI`, the stream's terminal state, and `TERM`; any other value is a usage error that exits with code 1.
17
+ - Changes the emoji in rich output so that none has a different meaning from the one that it has in `nmr`: warnings from ⚠️ to 🟠, skips from ⏭️ to ⏩, the errors of `show-tag-prefixes` from ⛔ to ❌, and the tag marker from 🏷️ to 🔖.
18
+ - Adds a required `style` parameter to `formatValidateOverridesResult`, which the package root exports.
19
+
20
+ - Give nmr plain output in pipes and CI logs (#838)
21
+
22
+ - Stops `nmr` from printing emoji to a pipe or a CI log: When the output stream is not a terminal or `CI` is set, a verdict reads `PASS`, `FAIL`, `SKIP`, or `NOOP` and a command icon is omitted, so that a log can be searched for a verdict.
23
+ - Adds `--output-style <auto|plain|rich>` to `nmr` and the `NMR_OUTPUT_STYLE` variable, each forcing either style; the flag outranks the variable, a value that names no style exits 1 with a usage error, and neither enters a check-cache key: A rich run and a plain run share a recorded pass.
24
+ - Replaces several rich glyphs, taking the status markers from the set that release-kit and v11y-check print so that one status has one glyph across the three tools: a recalled pass shows ⏩ in place of ⏭️, a skipped empty override shows ⚪ in place of ⛔, a warning and the `--log` refusal show 🟠 in place of ⚠️ and 📭, the `--log` header shows 💾 in place of 📼, and `nmr-ensure-prepublish-hooks` reports ✅ and ❌ in place of ✓ and ✗.
18
25
 
19
26
  ### 🐛 Bug fixes
20
27
 
21
- - Omit the breaking marker from changelog entries whose type forbids it (#819)
28
+ - Move work-types check and sync from the CLI into maintainer scripts (#820)
29
+
30
+ - Removes the `release-kit work-types` command, whose `sync` rewrote an unused copy of `work-types.json` inside `node_modules` and whose `check` reported drift that a consumer could not fix.
31
+
32
+ - Exclude distributed agent guidance from ai and documentation labels (#825)
33
+
34
+ - Marks a `.github/labels.yaml` generated from the previous `common` preset as stale in the default readyup kit, whose "labels.yaml has current common preset" check reports the file until the repo regenerates it.
35
+
36
+ - Suppress bold and dim escapes for a stream that cannot render them (#830)
22
37
 
23
- - Makes the configured `breakingPolicies` map decide whether the changelog marks a commit breaking, as it already decides the version bump.
38
+ - Stops `release-kit prepare` from writing raw escape bytes into piped output, redirected files, and CI logs: It styled bold and dim unconditionally, without checking whether the destination renders escapes.
39
+ - Honors `NO_COLOR`, `NODE_DISABLE_COLORS`, and `FORCE_COLOR`, which the previous styling ignored.
24
40
  <!-- /section:release-notes -->
25
41
 
26
42
  ## Installation
@@ -54,10 +70,10 @@ Example output from `prepare --dry-run` in a monorepo whose `arrays` workspace h
54
70
  [dry-run] Would bump packages/arrays/package.json
55
71
  Generating changelogs...
56
72
  [dry-run] Would run: npx --prefer-offline --yes git-cliff@<version> ... --output packages/arrays/CHANGELOG.md
57
- 🏷️ arrays-v1.3.0
73
+ 🔖 arrays-v1.3.0
58
74
 
59
75
  ✅ Release preparation complete.
60
- 🏷️ arrays-v1.3.0
76
+ 🔖 arrays-v1.3.0
61
77
  [dry-run] Would write tmp/.release-tags: arrays-v1.3.0
62
78
  [dry-run] Would write tmp/.release-summary
63
79
  ```
@@ -173,7 +189,7 @@ No cliff config copy is needed — the bundled template is used automatically. T
173
189
  - [Publishing](docs/publishing.md): `publish`, the publishability filter, and `create-github-release`
174
190
  - [Changelogs](docs/changelogs.md): the `changelog.json` item schema, the git-cliff config, and release-notes injection
175
191
  - [Editorial overrides](docs/editorial-overrides.md): correcting generated changelog entries, and `overrides validate`
176
- - [Work types and tiers](docs/work-types.md): tiers, the `!` policy, markers, custom work types, and `work-types check` and `sync`
192
+ - [Work types and tiers](docs/work-types.md): tiers, the `!` policy, markers, custom work types, and maintenance of the bundled taxonomy
177
193
  - [Labels](docs/labels.md): `sync-labels`, label configuration, the workflow's triggers, and the `label-map.json` schema
178
194
  - [Readiness checks](docs/readiness-checks.md): both readyup kits, and how to run each
179
195
  - [Programmatic API](docs/api.md): `deriveWorkspaceConfig()`, the script-based approach, and `resolveReleaseTags`
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { parseArgsOrExit, readPackageVersion, reportError } from '@williamthorsen/nmr-core';
3
3
  import { describeError } from '@williamthorsen/toolbelt.errors';
4
- import { checkWorkTypesDrift } from "../checkWorkTypesDrift.js";
5
4
  import { commitCommand } from "../commitCommand.js";
6
5
  import { createGithubReleaseCommand } from "../createGithubReleaseCommand.js";
7
6
  import { showPrepareHelp } from "../help/prepareHelp.js";
@@ -9,11 +8,11 @@ import { initCommand } from "../init/initCommand.js";
9
8
  import { prepareCommand } from "../prepareCommand.js";
10
9
  import { publishCommand } from "../publishCommand.js";
11
10
  import { pushCommand } from "../pushCommand.js";
11
+ import { OUTPUT_STYLE_ENV_VAR, resolveStylesOrExit } from "../resolveStylesOrExit.js";
12
12
  import { showTagPrefixesCommand } from "../showTagPrefixesCommand.js";
13
13
  import { generateCommand } from "../sync-labels/generateCommand.js";
14
14
  import { syncLabelsInitCommand } from "../sync-labels/initCommand.js";
15
15
  import { syncLabelsCommand } from "../sync-labels/syncCommand.js";
16
- import { syncWorkTypes } from "../syncWorkTypes.js";
17
16
  import { tagCommand } from "../tagCommand.js";
18
17
  import { validateOverridesCommand } from "../validateOverridesCommand.js";
19
18
  const VERSION = readPackageVersion(import.meta.url);
@@ -32,12 +31,16 @@ Commands:
32
31
  init Initialize release-kit in the current repository
33
32
  overrides Manage editorial changelog overrides
34
33
  sync-labels Manage GitHub label synchronization
35
- work-types Check for or sync work-type taxonomy drift against the upstream canonical
36
34
 
37
35
  Options:
38
36
  --dry-run Preview changes without writing files
39
37
  --help, -h Show this help message
40
38
  --version, -V Show the version number
39
+
40
+ Environment:
41
+ ${OUTPUT_STYLE_ENV_VAR}
42
+ Output style: auto (default), plain, or rich. auto prints plain,
43
+ without emoji, when CI is set or the stream is not a terminal.
41
44
  `);
42
45
  }
43
46
  function showSyncLabelsHelp() {
@@ -194,49 +197,6 @@ Exit codes:
194
197
  1 Stale-key warnings only (no errors)
195
198
  2 Schema/parse or ambiguous-prefix errors (errors dominate)
196
199
 
197
- Options:
198
- --help, -h Show this help message
199
- `);
200
- }
201
- function showWorkTypesHelp() {
202
- console.info(`
203
- Usage: release-kit work-types <subcommand>
204
-
205
- Manage the canonical work-types taxonomy used by changelog and release-notes generation.
206
-
207
- Subcommands:
208
- check Compare the local work-types.json against the upstream codeassembly canonical
209
- sync Overwrite the local work-types.json with the upstream contents
210
-
211
- Exit codes (check):
212
- 0 Match (or upstream not found, with a warning)
213
- 1 Drift detected
214
- 2 Network error
215
- 3 Schema mismatch
216
-
217
- Options:
218
- --help, -h Show this help message
219
- `);
220
- }
221
- function showWorkTypesCheckHelp() {
222
- console.info(`
223
- Usage: release-kit work-types check
224
-
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 not found, 2 on network
227
- error, 3 on schema mismatch.
228
-
229
- Options:
230
- --help, -h Show this help message
231
- `);
232
- }
233
- function showWorkTypesSyncHelp() {
234
- console.info(`
235
- Usage: release-kit work-types sync
236
-
237
- Fetch the upstream work-types.json, validate its top-level shape, and overwrite the local
238
- copy with the upstream content (formatted with 2-space indent + trailing newline).
239
-
240
200
  Options:
241
201
  --help, -h Show this help message
242
202
  `);
@@ -269,12 +229,17 @@ if (command === undefined || ['--help', '-h'].includes(command)) {
269
229
  process.exit(0);
270
230
  }
271
231
  const flags = args.slice(1);
232
+ const styles = resolveStylesOrExit({
233
+ env: process.env,
234
+ stderrIsTty: process.stderr.isTTY,
235
+ stdoutIsTty: process.stdout.isTTY,
236
+ });
272
237
  if (command === 'prepare') {
273
238
  if (flags.some((f) => f === '--help' || f === '-h')) {
274
239
  showPrepareHelp();
275
240
  process.exit(0);
276
241
  }
277
- await prepareCommand(flags);
242
+ await prepareCommand(flags, styles);
278
243
  process.exit(0);
279
244
  }
280
245
  if (command === 'commit') {
@@ -296,7 +261,7 @@ if (command === 'tag') {
296
261
  showTagHelp();
297
262
  process.exit(0);
298
263
  }
299
- tagCommand(flags);
264
+ tagCommand(flags, styles);
300
265
  process.exit(0);
301
266
  }
302
267
  if (command === 'push') {
@@ -312,7 +277,7 @@ if (command === 'create-github-release') {
312
277
  showCreateGithubReleaseHelp();
313
278
  process.exit(0);
314
279
  }
315
- await createGithubReleaseCommand(flags);
280
+ await createGithubReleaseCommand(flags, styles);
316
281
  process.exit(0);
317
282
  }
318
283
  if (command === 'publish') {
@@ -320,7 +285,7 @@ if (command === 'publish') {
320
285
  showPublishHelp();
321
286
  process.exit(0);
322
287
  }
323
- await publishCommand(flags);
288
+ await publishCommand(flags, styles);
324
289
  process.exit(0);
325
290
  }
326
291
  if (command === 'show-tag-prefixes') {
@@ -332,7 +297,7 @@ if (command === 'show-tag-prefixes') {
332
297
  reportError(`Unknown option: ${flags[0]}`);
333
298
  process.exit(1);
334
299
  }
335
- const exitCode = await showTagPrefixesCommand();
300
+ const exitCode = await showTagPrefixesCommand(styles);
336
301
  process.exit(exitCode);
337
302
  }
338
303
  if (command === 'init') {
@@ -346,7 +311,7 @@ if (command === 'init') {
346
311
  withConfig: { long: '--with-config', type: 'boolean' },
347
312
  };
348
313
  const { dryRun, force, withConfig } = parseArgsOrExit(flags, initFlagSchema).flags;
349
- const exitCode = initCommand({ dryRun, force, withConfig });
314
+ const exitCode = initCommand({ dryRun, force, styles, withConfig });
350
315
  process.exit(exitCode);
351
316
  }
352
317
  if (command === 'sync-labels') {
@@ -366,7 +331,7 @@ if (command === 'sync-labels') {
366
331
  force: { long: '--force', type: 'boolean' },
367
332
  };
368
333
  const { dryRun, force } = parseArgsOrExit(subflags, syncLabelsInitFlagSchema).flags;
369
- const exitCode = await syncLabelsInitCommand({ dryRun, force });
334
+ const exitCode = await syncLabelsInitCommand({ dryRun, force, styles });
370
335
  process.exit(exitCode);
371
336
  }
372
337
  if (subcommand === 'generate') {
@@ -378,7 +343,7 @@ if (command === 'sync-labels') {
378
343
  check: { long: '--check', type: 'boolean' },
379
344
  };
380
345
  const { check } = parseArgsOrExit(subflags, generateFlagSchema).flags;
381
- const exitCode = await generateCommand({ check });
346
+ const exitCode = await generateCommand({ check, styles });
382
347
  process.exit(exitCode);
383
348
  }
384
349
  if (subcommand === 'sync') {
@@ -413,7 +378,7 @@ if (command === 'overrides') {
413
378
  reportError(`Unknown option: ${subflags[0]}`);
414
379
  process.exit(1);
415
380
  }
416
- const result = await validateOverridesCommand();
381
+ const result = await validateOverridesCommand(styles);
417
382
  if (result.exitCode === 0) {
418
383
  console.info(result.message);
419
384
  }
@@ -426,53 +391,6 @@ if (command === 'overrides') {
426
391
  showOverridesHelp();
427
392
  process.exit(1);
428
393
  }
429
- if (command === 'work-types') {
430
- const subcommand = flags[0];
431
- if (subcommand === undefined || ['--help', '-h'].includes(subcommand)) {
432
- showWorkTypesHelp();
433
- process.exit(0);
434
- }
435
- const subflags = flags.slice(1);
436
- if (subcommand === 'check') {
437
- if (subflags.some((f) => f === '--help' || f === '-h')) {
438
- showWorkTypesCheckHelp();
439
- process.exit(0);
440
- }
441
- if (subflags.length > 0) {
442
- reportError(`Unknown option: ${subflags[0]}`);
443
- process.exit(1);
444
- }
445
- const result = await checkWorkTypesDrift();
446
- if (result.exitCode === 0) {
447
- console.info(result.message);
448
- }
449
- else {
450
- process.stderr.write(`${result.message}\n`);
451
- }
452
- process.exit(result.exitCode);
453
- }
454
- if (subcommand === 'sync') {
455
- if (subflags.some((f) => f === '--help' || f === '-h')) {
456
- showWorkTypesSyncHelp();
457
- process.exit(0);
458
- }
459
- if (subflags.length > 0) {
460
- reportError(`Unknown option: ${subflags[0]}`);
461
- process.exit(1);
462
- }
463
- const result = await syncWorkTypes();
464
- if (result.exitCode === 0) {
465
- console.info(result.message);
466
- }
467
- else {
468
- process.stderr.write(`${result.message}\n`);
469
- }
470
- process.exit(result.exitCode);
471
- }
472
- reportError(`Unknown subcommand: ${subcommand}`);
473
- showWorkTypesHelp();
474
- process.exit(1);
475
- }
476
394
  reportError(`Unknown command: ${command}`);
477
395
  showUsage();
478
396
  process.exit(1);
@@ -1,3 +1,4 @@
1
+ import { type StreamStyles } from '@williamthorsen/nmr-core';
1
2
  /**
2
3
  * Orchestrate the CLI `create-github-release` command: Create GitHub Releases from changelog.json
3
4
  * for tags on HEAD (or a comma-separated `--tags` subset), without requiring npm publish.
@@ -5,4 +6,4 @@
5
6
  * Private/unpublishable workspaces are skipped with a warning and never get a Release, matching
6
7
  * `release-kit publish`; an all-private tag set is a clean no-op.
7
8
  */
8
- export declare function createGithubReleaseCommand(argv: string[]): Promise<void>;
9
+ export declare function createGithubReleaseCommand(argv: string[], styles: StreamStyles): Promise<void>;
@@ -9,7 +9,7 @@ const createGithubReleaseFlagSchema = {
9
9
  dryRun: { long: '--dry-run', type: 'boolean' },
10
10
  tags: { long: '--tags', type: 'string' },
11
11
  };
12
- export async function createGithubReleaseCommand(argv) {
12
+ export async function createGithubReleaseCommand(argv, styles) {
13
13
  const parsed = parseArgsOrExit(argv, createGithubReleaseFlagSchema);
14
14
  const { dryRun } = parsed.flags;
15
15
  const requestedTags = parseRequestedTags(parsed.flags.tags);
@@ -23,7 +23,9 @@ export async function createGithubReleaseCommand(argv) {
23
23
  if (publishableTags.length === 0) {
24
24
  return;
25
25
  }
26
- const { changelogJsonOutputPath, sectionOrder } = await resolveReleaseNotesConfig({ strictLoad: true });
26
+ const { changelogJsonOutputPath, sectionOrder } = await resolveReleaseNotesConfig(styles.stderr, {
27
+ strictLoad: true,
28
+ });
27
29
  let outcome;
28
30
  try {
29
31
  outcome = createGithubReleases(publishableTags, changelogJsonOutputPath, dryRun, sectionOrder);
@@ -1,6 +1,8 @@
1
+ import { type OutputStyle } from '@williamthorsen/nmr-core';
1
2
  export interface CreateTagsOptions {
2
3
  dryRun: boolean;
3
4
  noGitChecks: boolean;
5
+ style: OutputStyle;
4
6
  }
5
7
  /**
6
8
  * Read tag names from the tags file produced by `prepare` and create annotated git tags.
@@ -1,9 +1,10 @@
1
1
  import { execFileSync } from 'node:child_process';
2
- import { GIT_OUTPUT_LIMIT, hasErrnoCode } from '@williamthorsen/nmr-core';
2
+ import { formatGlyphLine, GIT_OUTPUT_LIMIT, hasErrnoCode } from '@williamthorsen/nmr-core';
3
3
  import { deleteFileIfExists } from "./deleteFileIfExists.js";
4
+ import { RELEASE_GLYPHS } from "./glyphs.js";
4
5
  import { readReleaseTags, RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE } from "./releaseFiles.js";
5
6
  export function createTags(options) {
6
- const { dryRun, noGitChecks } = options;
7
+ const { dryRun, noGitChecks, style } = options;
7
8
  const tags = readReleaseTags();
8
9
  if (tags.length === 0) {
9
10
  return [];
@@ -14,7 +15,7 @@ export function createTags(options) {
14
15
  if (dryRun) {
15
16
  console.info('[dry-run] Would create tags:');
16
17
  for (const tag of tags) {
17
- console.info(`🏷️ ${tag}`);
18
+ console.info(formatGlyphLine(RELEASE_GLYPHS, style, 'tag', tag));
18
19
  }
19
20
  return tags;
20
21
  }
@@ -36,7 +37,7 @@ export function createTags(options) {
36
37
  }
37
38
  console.info('Created tags:');
38
39
  for (const tag of tags) {
39
- console.info(`🏷️ ${tag}`);
40
+ console.info(formatGlyphLine(RELEASE_GLYPHS, style, 'tag', tag));
40
41
  }
41
42
  deleteFileIfExists(RELEASE_TAGS_FILE);
42
43
  deleteFileIfExists(RELEASE_SUMMARY_FILE);
@@ -1,6 +1,6 @@
1
- /** Wrap text in ANSI bold. */
2
- export declare function bold(text: string): string;
3
- /** Wrap text in ANSI dim. */
4
- export declare function dim(text: string): string;
5
- /** Render a section header for separating workspaces in CLI output. */
1
+ /** Styles text bold, returning it unstyled for a stream that cannot render color. */
2
+ export declare function bold(text: string, stream?: NodeJS.WritableStream): string;
3
+ /** Styles text dim, returning it unstyled for a stream that cannot render color. */
4
+ export declare function dim(text: string, stream?: NodeJS.WritableStream): string;
5
+ /** Renders a section header for separating workspaces in CLI output. */
6
6
  export declare function sectionHeader(name: string): string;
@@ -1,8 +1,9 @@
1
- export function bold(text) {
2
- return `\u{1B}[1m${text}\u{1B}[0m`;
1
+ import { styleText } from 'node:util';
2
+ export function bold(text, stream = process.stdout) {
3
+ return styleText('bold', text, { stream });
3
4
  }
4
- export function dim(text) {
5
- return `\u{1B}[2m${text}\u{1B}[0m`;
5
+ export function dim(text, stream = process.stdout) {
6
+ return styleText('dim', text, { stream });
6
7
  }
7
8
  export function sectionHeader(name) {
8
9
  return `━━━ ${name} ━━━`;
@@ -0,0 +1,3 @@
1
+ /** Glyphs that name no status; a status marker comes from nmr-core's `STATUS_GLYPHS`. */
2
+ export declare const RELEASE_GLYPHS: Readonly<Record<"plain" | "rich", Readonly<Record<"bump" | "dryRun" | "tag", import("@williamthorsen/toolbelt.terminal/candidate").Glyph>>>>;
3
+ export type ReleaseGlyphName = keyof (typeof RELEASE_GLYPHS)['rich'];
@@ -0,0 +1,6 @@
1
+ import { defineGlyphSet } from '@williamthorsen/nmr-core';
2
+ export const RELEASE_GLYPHS = defineGlyphSet({
3
+ bump: { plain: 'BUMP', rich: '📦' },
4
+ dryRun: { plain: '', rich: '🔍' },
5
+ tag: { plain: 'TAG', rich: '🔖' },
6
+ });
@@ -1,6 +1,8 @@
1
+ import { type StreamStyles } from '@williamthorsen/nmr-core';
1
2
  interface InitOptions {
2
3
  dryRun: boolean;
3
4
  force: boolean;
5
+ styles: StreamStyles;
4
6
  withConfig: boolean;
5
7
  }
6
8
  /**
@@ -9,5 +11,5 @@ interface InitOptions {
9
11
  * Checks eligibility, detects repo type, scaffolds files, and prints next steps.
10
12
  * Returns the process exit code (0 for success, 1 for failure).
11
13
  */
12
- export declare function initCommand({ dryRun, force, withConfig }: InitOptions): number;
14
+ export declare function initCommand({ dryRun, force, styles, withConfig }: InitOptions): number;
13
15
  export {};