@williamthorsen/nmr 2.0.0 → 2.0.2

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 (113) hide show
  1. package/.meta/changelog.json +164 -0
  2. package/.readyup/kits/default.js +51 -15
  3. package/.readyup/manifest.json +26 -21
  4. package/CHANGELOG.md +45 -0
  5. package/README.md +10 -4
  6. package/dist/esm/{check-cache-build-output.d.ts → check-cache/check-cache-build-output.d.ts} +1 -1
  7. package/dist/esm/{check-cache-build-output.js → check-cache/check-cache-build-output.js} +6 -6
  8. package/dist/esm/{check-cache-delegation.d.ts → check-cache/check-cache-delegation.d.ts} +3 -3
  9. package/dist/esm/{check-cache-delegation.js → check-cache/check-cache-delegation.js} +2 -2
  10. package/dist/esm/{check-cache-entries.js → check-cache/check-cache-entries.js} +1 -1
  11. package/dist/esm/{check-cache-gate.d.ts → check-cache/check-cache-gate.d.ts} +5 -4
  12. package/dist/esm/{check-cache-gate.js → check-cache/check-cache-gate.js} +10 -10
  13. package/dist/esm/{check-cache-key.d.ts → check-cache/check-cache-key.d.ts} +1 -1
  14. package/dist/esm/{check-cache-record.d.ts → check-cache/check-cache-record.d.ts} +6 -5
  15. package/dist/esm/{check-cache-record.js → check-cache/check-cache-record.js} +7 -6
  16. package/dist/esm/{check-cache.d.ts → check-cache/check-cache.d.ts} +10 -2
  17. package/dist/esm/{check-cache.js → check-cache/check-cache.js} +7 -4
  18. package/dist/esm/{config-check-cache.d.ts → check-cache/config-check-cache.d.ts} +1 -1
  19. package/dist/esm/{config-check-cache.js → check-cache/config-check-cache.js} +4 -4
  20. package/dist/esm/{pass-manifest.d.ts → check-cache/pass-manifest.d.ts} +1 -1
  21. package/dist/esm/{pass-manifest.js → check-cache/pass-manifest.js} +1 -1
  22. package/dist/esm/{recording.js → check-cache/recording.js} +2 -2
  23. package/dist/esm/{replay-assembly.d.ts → check-cache/replay-assembly.d.ts} +1 -1
  24. package/dist/esm/{replay-assembly.js → check-cache/replay-assembly.js} +2 -2
  25. package/dist/esm/child-env.d.ts +1 -1
  26. package/dist/esm/child-env.js +2 -2
  27. package/dist/esm/cli-build.js +3 -10
  28. package/dist/esm/cli-clean.js +1 -2
  29. package/dist/esm/cli-report-catalog.js +2 -3
  30. package/dist/esm/cli-report-overrides.js +3 -5
  31. package/dist/esm/commands/actionlint.d.ts +2 -7
  32. package/dist/esm/commands/actionlint.js +5 -11
  33. package/dist/esm/commands/build-output.d.ts +7 -32
  34. package/dist/esm/commands/build-output.js +8 -13
  35. package/dist/esm/commands/build-report.d.ts +6 -0
  36. package/dist/esm/commands/build-report.js +21 -0
  37. package/dist/esm/commands/build.d.ts +27 -4
  38. package/dist/esm/commands/build.js +24 -86
  39. package/dist/esm/commands/clean-report.d.ts +6 -0
  40. package/dist/esm/commands/clean-report.js +20 -0
  41. package/dist/esm/commands/clean.d.ts +39 -7
  42. package/dist/esm/commands/clean.js +55 -31
  43. package/dist/esm/commands/compile.d.ts +5 -0
  44. package/dist/esm/commands/compile.js +32 -0
  45. package/dist/esm/commands/fmt-cache.js +3 -2
  46. package/dist/esm/commands/fmt.d.ts +6 -2
  47. package/dist/esm/commands/fmt.js +48 -27
  48. package/dist/esm/commands/node-pin.d.ts +15 -5
  49. package/dist/esm/commands/node-pin.js +43 -10
  50. package/dist/esm/commands/package-manifest.d.ts +28 -0
  51. package/dist/esm/commands/package-manifest.js +32 -0
  52. package/dist/esm/commands/publish-output.d.ts +40 -0
  53. package/dist/esm/commands/publish-output.js +66 -0
  54. package/dist/esm/commands/report-catalog.d.ts +5 -0
  55. package/dist/esm/commands/report-catalog.js +19 -0
  56. package/dist/esm/commands/report-overrides.d.ts +5 -0
  57. package/dist/esm/commands/report-overrides.js +20 -1
  58. package/dist/esm/commands/run-vitest.js +21 -20
  59. package/dist/esm/commands/shellcheck.d.ts +2 -7
  60. package/dist/esm/commands/shellcheck.js +3 -11
  61. package/dist/esm/commands/spawn-inherited.d.ts +21 -0
  62. package/dist/esm/commands/spawn-inherited.js +11 -0
  63. package/dist/esm/commands/taze.d.ts +6 -6
  64. package/dist/esm/commands/taze.js +3 -7
  65. package/dist/esm/config-validation.js +1 -1
  66. package/dist/esm/config.js +3 -12
  67. package/dist/esm/{delegate-host.d.ts → delegation/delegate-host.d.ts} +3 -3
  68. package/dist/esm/{delegate-host.js → delegation/delegate-host.js} +9 -8
  69. package/dist/esm/{delegation-target.js → delegation/delegation-target.js} +1 -1
  70. package/dist/esm/{remote-probe.js → delegation/remote-probe.js} +2 -2
  71. package/dist/esm/{remote-run.js → delegation/remote-run.js} +5 -5
  72. package/dist/esm/{remote-session.js → delegation/remote-session.js} +1 -1
  73. package/dist/esm/{user-config.js → delegation/user-config.js} +4 -13
  74. package/dist/esm/env-switch.d.ts +25 -0
  75. package/dist/esm/env-switch.js +26 -0
  76. package/dist/esm/fan-out.d.ts +4 -1
  77. package/dist/esm/fan-out.js +1 -3
  78. package/dist/esm/help.js +1 -1
  79. package/dist/esm/helpers/filter-selection.d.ts +2 -0
  80. package/dist/esm/helpers/importConfigDefault.d.ts +7 -0
  81. package/dist/esm/helpers/importConfigDefault.js +45 -0
  82. package/dist/esm/invocation.d.ts +7 -3
  83. package/dist/esm/machine-lock.js +2 -1
  84. package/dist/esm/route.d.ts +6 -0
  85. package/dist/esm/route.js +15 -2
  86. package/dist/esm/run-chain.d.ts +1 -1
  87. package/dist/esm/run-chain.js +1 -1
  88. package/dist/esm/runCli.d.ts +9 -0
  89. package/dist/esm/runCli.js +24 -9
  90. package/dist/esm/runner.d.ts +2 -0
  91. package/dist/esm/runner.js +1 -1
  92. package/dist/esm/verdict.d.ts +1 -1
  93. package/docs/check-cache.md +7 -7
  94. package/docs/delegate.md +2 -2
  95. package/docs/machine-lock.md +4 -4
  96. package/docs/scripts.md +4 -0
  97. package/docs/upgrades.md +10 -2
  98. package/docs/utilities.md +6 -4
  99. package/package.json +7 -7
  100. /package/dist/esm/{check-cache-entries.d.ts → check-cache/check-cache-entries.d.ts} +0 -0
  101. /package/dist/esm/{check-cache-key.js → check-cache/check-cache-key.js} +0 -0
  102. /package/dist/esm/{recording.d.ts → check-cache/recording.d.ts} +0 -0
  103. /package/dist/esm/{delegation-target.d.ts → delegation/delegation-target.d.ts} +0 -0
  104. /package/dist/esm/{remote-host-session.d.ts → delegation/remote-host-session.d.ts} +0 -0
  105. /package/dist/esm/{remote-host-session.js → delegation/remote-host-session.js} +0 -0
  106. /package/dist/esm/{remote-probe-host.d.ts → delegation/remote-probe-host.d.ts} +0 -0
  107. /package/dist/esm/{remote-probe-host.js → delegation/remote-probe-host.js} +0 -0
  108. /package/dist/esm/{remote-probe.d.ts → delegation/remote-probe.d.ts} +0 -0
  109. /package/dist/esm/{remote-run.d.ts → delegation/remote-run.d.ts} +0 -0
  110. /package/dist/esm/{remote-session.d.ts → delegation/remote-session.d.ts} +0 -0
  111. /package/dist/esm/{remote-snapshot.d.ts → delegation/remote-snapshot.d.ts} +0 -0
  112. /package/dist/esm/{remote-snapshot.js → delegation/remote-snapshot.js} +0 -0
  113. /package/dist/esm/{user-config.d.ts → delegation/user-config.d.ts} +0 -0
@@ -1,4 +1,168 @@
1
1
  [
2
+ {
3
+ "version": "2.0.2",
4
+ "date": "2026-11-12",
5
+ "sections": [
6
+ {
7
+ "title": "🐛 Bug fixes",
8
+ "audience": "all",
9
+ "items": [
10
+ {
11
+ "description": "Fixes the issue that `nmr-fmt` and `nmr-taze` exited with 1 when a signal ended Prettier or taze, and makes each exit with 128 plus the signal number, as the other commands that nmr runs already did. (#1281)",
12
+ "hash": "9999694c843db32f1fc2851617402b61794abd3d",
13
+ "entry": 1
14
+ },
15
+ {
16
+ "description": "Fixes the issue that `nmr-fmt` formatted with nmr's own copy of Prettier when the repository's copy had a malformed or unreadable manifest, and makes `nmr-fmt` fail with an error that names that manifest instead. (#1282)",
17
+ "hash": "73319582559a85130ba65e810483acb24954e0ac",
18
+ "entry": 1
19
+ },
20
+ {
21
+ "description": "Fixes the issue that `nmr-vitest` reported a Vitest whose manifest is malformed or unreadable as not installed, and makes `nmr-vitest` name that manifest and the repair instead. (#1282)",
22
+ "hash": "73319582559a85130ba65e810483acb24954e0ac",
23
+ "entry": 2
24
+ },
25
+ {
26
+ "description": "Fixes the issue that `nmr-fmt` and `nmr-vitest` crashed on a Prettier or Vitest manifest that starts with a byte-order mark, which Node accepts. (#1282)",
27
+ "hash": "73319582559a85130ba65e810483acb24954e0ac",
28
+ "entry": 3
29
+ },
30
+ {
31
+ "description": "Fixes the issue that a `.config/nmr.config.ts` or `~/.config/nmr/config.ts` that failed to parse or threw while loading crashed `nmr` with an internal error that did not name the file, and makes `nmr` report an error that names the config and, for a syntax error, the file and line that Node reports, including those of a module that the config imports. (#1296)",
32
+ "hash": "3d120c5ce21b5cae276030dee7db1b63514fbe29",
33
+ "entry": 1
34
+ },
35
+ {
36
+ "description": "Fixes the issue that `nmr` read any value of `NMR_DEBUG`, `NMR_NO_CACHE`, `NMR_NO_LOCK`, or `NMR_RUN_IF_PRESENT` other than `1`, such as `true`, as off without reporting it, by making `nmr` and `nmr-fmt` exit 2 with a message that names the variable and the values that it accepts. (#1297)",
37
+ "migration": "Set each of these variables to `1` to turn it on, and to `0` or an empty value, or leave it unset, to turn it off. Any other value now stops the run with exit 2 before a command runs.",
38
+ "hash": "3a396f8788b37d60546eebf5b4c33859064314c6",
39
+ "entry": 1
40
+ },
41
+ {
42
+ "description": "Fixes the issue that `nmr upgrade --write` rewrote the `nodejs` pin in `.tool-versions` to a release that asdf could not install yet, by limiting the check to releases that node-build defines and reporting a newer release without a definition as held back. (#1300)",
43
+ "hash": "d97eab803118bb0055b9acd781f928c4ec548a55",
44
+ "entry": 1
45
+ }
46
+ ]
47
+ },
48
+ {
49
+ "title": "♻️ Refactoring",
50
+ "audience": "dev",
51
+ "items": [
52
+ {
53
+ "description": "Replaces the copies of the inherited-stdio spawn and exit-code mapping in `nmr-actionlint`, `nmr-shellcheck`, and `nmr-vitest` with the shared `spawnInherited` and `resolveInheritedExitCode` in `spawn-inherited.ts`, so that the copies can no longer change independently. (#1281)",
54
+ "hash": "9999694c843db32f1fc2851617402b61794abd3d",
55
+ "entry": 2
56
+ },
57
+ {
58
+ "description": "Replaces the separate `bin` parsing in `resolveVitestCli` and `resolvePrettierCli` with one `resolveDeclaredCli` in `package-manifest.ts`, which takes `bin` either as a bare path or as a map keyed by the package name, so `nmr-vitest` now also accepts a Vitest manifest whose `bin` is a bare path. (#1283)",
59
+ "hash": "31ebafea1ceb209f1f8993520f90f10cb87bf88d",
60
+ "entry": 1
61
+ },
62
+ {
63
+ "description": "Groups nmr's check-cache modules under `packages/nmr/src/check-cache/` and its delegation modules under `packages/nmr/src/delegation/`, each directory containing its own tests in `__tests__/`. (#1293)",
64
+ "hash": "91f900f679d4e84687e1ba74ece7d42bf089abc3",
65
+ "entry": 1
66
+ },
67
+ {
68
+ "description": "Makes `runCli` accept `runSteps` and `readFilterSelection` as optional dependencies that default to the real functions, and passes them on the `Invocation` to fan-out and the check-cache gate, which no longer import the real functions. (#1295)",
69
+ "hash": "40098138b5136fdb4c6824d03e1873ab15583693",
70
+ "entry": 1
71
+ }
72
+ ]
73
+ },
74
+ {
75
+ "title": "🧪 Tests",
76
+ "audience": "dev",
77
+ "items": [
78
+ {
79
+ "description": "Adds `createRunCliHarness` and a shared `it` in `test-utils/run-cli-fixtures.ts` that gives each test a workspace `tree` and fresh fakes, and moves the five `runCli` unit suites onto them, so that the suites no longer depend on the file layout of the modules that they used to mock. (#1295)",
80
+ "hash": "40098138b5136fdb4c6824d03e1873ab15583693",
81
+ "entry": 2
82
+ },
83
+ {
84
+ "description": "Covers each decision branch of the check-cache gate with unit suites for lookup, recording, scope, and the command's own stated outcome, which inject a fake tree reader through a new `readTree` option on `runCli`, and removes the tool cases that they supersede, including `check-cache-gate.build-output.tool.test.ts`. (#1298)",
85
+ "hash": "2b3163471bc0adf4b70b8fe5b386e341241aaaae",
86
+ "entry": 1
87
+ }
88
+ ]
89
+ }
90
+ ]
91
+ },
92
+ {
93
+ "version": "2.0.1",
94
+ "date": "2026-11-11",
95
+ "sections": [
96
+ {
97
+ "title": "🐛 Bug fixes",
98
+ "audience": "all",
99
+ "items": [
100
+ {
101
+ "description": "Fixes the issue that `nmr-clean`, `nmr-compile`, `nmr-report-catalog`, and `nmr-report-overrides` ignored their arguments, so `--help` or a mistyped option ran the command, and `nmr-clean --help` removed build output instead of printing usage. (#1273)",
102
+ "hash": "a4bfd2bc9c298a919c15070bae4437188c0edb37",
103
+ "entry": 1
104
+ }
105
+ ]
106
+ },
107
+ {
108
+ "title": "♻️ Refactoring",
109
+ "audience": "dev",
110
+ "items": [
111
+ {
112
+ "description": "Adds an optional `spawn` adapter to `runPrettier` in `packages/nmr/src/commands/fmt.ts`, which defaults to `spawnSync` with inherited stdio, so that a test can replace the Prettier process without mocking `node:child_process`. (#1271)",
113
+ "hash": "18227bf9c7d8fb0fb11bf3382602be131603419a",
114
+ "entry": 1
115
+ },
116
+ {
117
+ "description": "Extracts the unchanged-build skip report from `detectBuildChanges` into the exported `reportUnchangedBuild`, which takes the environment as a parameter rather than reading `process.env`. (#1272)",
118
+ "hash": "7708c82fe5b528709dd3c822c1449b6a843292c4",
119
+ "entry": 1
120
+ },
121
+ {
122
+ "description": "Replaces the copies of the entry-point `glob` call in `buildPackage` and `hasBuildOutput` with one function, `resolveEntryPoints` in `build-output.ts`, so the build and the check cache's probe for build output cannot select different files. (#1274)",
123
+ "hash": "aadd160714f8a4b00aa9965897b97fb15ee8500b",
124
+ "entry": 1
125
+ },
126
+ {
127
+ "description": "Moves the printing of the build's progress and outcome lines from `buildPackage` to `nmr-compile`, which renders the `BuildOutcome` returned by `buildPackage` and the events from its new `onProgress` callback through `build-report.ts`. (#1277)",
128
+ "hash": "7204e9ebbb7ef2d60f0ddf74a1ea4de4b62e50c0",
129
+ "entry": 1
130
+ },
131
+ {
132
+ "description": "Moves the emit's staging, swap by rename, and scratch-directory handling from `build.ts` and `build-output.ts` into `publish-output.ts`, which `build.ts` now calls with the emit directory. (#1278)",
133
+ "hash": "27bc6915156ae739206679b977baf91267f73fa9",
134
+ "entry": 1
135
+ },
136
+ {
137
+ "description": "Makes `cleanFrom` in `clean.ts` return a `CleanOutcome` and report each completed step through an `onProgress` callback rather than print, leaving `runClean` as the only function that prints, through the renderers in the new `clean-report.ts`. (#1279)",
138
+ "hash": "5188dd2411cd737d337ae8bf232fc68d5bc911c6",
139
+ "entry": 1
140
+ }
141
+ ]
142
+ },
143
+ {
144
+ "title": "🧪 Tests",
145
+ "audience": "dev",
146
+ "items": [
147
+ {
148
+ "description": "Moves the `runPrettier` cases from `fmt.tool.test.ts` to a new `fmt.unit.test.ts` that asserts on the invocations recorded by a spawn fake, and adds cases for a spawn error and for a Prettier process killed by a signal. (#1271)",
149
+ "hash": "18227bf9c7d8fb0fb11bf3382602be131603419a",
150
+ "entry": 2
151
+ },
152
+ {
153
+ "description": "Replaces six skip-report cases in `build.publication.tool.test.ts`, each of which compiled a package to seed the cache, with unit tests of `reportUnchangedBuild` in `build.unit.test.ts` that write the recorded emit duration directly. (#1272)",
154
+ "hash": "7708c82fe5b528709dd3c822c1449b6a843292c4",
155
+ "entry": 2
156
+ },
157
+ {
158
+ "description": "Tests `resolveEntryPoints` directly in `build-output.unit.test.ts` and removes the tool-tier tests in `build.tool.test.ts` that checked the same default exclusions, `ignorePatterns` override, and `extraIgnorePatterns` composition through a full build. (#1274)",
159
+ "hash": "aadd160714f8a4b00aa9965897b97fb15ee8500b",
160
+ "entry": 2
161
+ }
162
+ ]
163
+ }
164
+ ]
165
+ },
2
166
  {
3
167
  "version": "2.0.0",
4
168
  "date": "2026-11-10",
@@ -1,6 +1,6 @@
1
1
  /** @noformat -- @generated. Do not edit. Compiled by rdy. */
2
2
  /* eslint-disable */
3
- export const __readyupVersion = "0.45.0";
3
+ export const __readyupVersion = "0.45.1";
4
4
  import { createRequire as __rdyCreateRequire } from 'node:module';
5
5
  const require = __rdyCreateRequire(import.meta.url);
6
6
 
@@ -7382,12 +7382,12 @@ import { isRecord, listTrackedFiles } from "readyup/check-utils";
7382
7382
  import { globSync } from "node:fs";
7383
7383
  import { basename, join, sep } from "node:path";
7384
7384
 
7385
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.9.0/node_modules/@williamthorsen/toolbelt.errors/dist/esm/4-release/isError.js
7385
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.9.1/node_modules/@williamthorsen/toolbelt.errors/dist/esm/4-release/isError.js
7386
7386
  function isError(error) {
7387
7387
  return error instanceof Error || Object.prototype.toString.call(error) === "[object Error]";
7388
7388
  }
7389
7389
 
7390
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.9.0/node_modules/@williamthorsen/toolbelt.errors/dist/esm/4-release/describeError.js
7390
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.errors@0.9.1/node_modules/@williamthorsen/toolbelt.errors/dist/esm/4-release/describeError.js
7391
7391
  function describeError(error) {
7392
7392
  try {
7393
7393
  if (isError(error) && typeof error.message === "string" && error.message !== "") {
@@ -8019,7 +8019,6 @@ import { isRecord as isRecord5 } from "readyup/check-utils";
8019
8019
 
8020
8020
  // src/config.ts
8021
8021
  import { existsSync as existsSync3 } from "node:fs";
8022
- import { pathToFileURL } from "node:url";
8023
8022
 
8024
8023
  // src/helpers/findClosestName.ts
8025
8024
  function findClosestName(name, candidates) {
@@ -8162,11 +8161,11 @@ function formatMalformedScript(dir, key, value) {
8162
8161
  return `${rejection} A step list belongs in \`${CONFIG_RELATIVE_PATH}\` under \`${field}\`.`;
8163
8162
  }
8164
8163
 
8165
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.0/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/parseArgs.js
8164
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/parseArgs.js
8166
8165
  import path6 from "node:path";
8167
8166
  import process2 from "node:process";
8168
8167
 
8169
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.0/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/UsageError.js
8168
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/UsageError.js
8170
8169
  var UsageError = class extends Error {
8171
8170
  constructor(message, options) {
8172
8171
  super(message, options);
@@ -8174,7 +8173,7 @@ var UsageError = class extends Error {
8174
8173
  }
8175
8174
  };
8176
8175
 
8177
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.0/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/ParseError.js
8176
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/ParseError.js
8178
8177
  var ParseError = class extends UsageError {
8179
8178
  kind;
8180
8179
  token;
@@ -8186,12 +8185,12 @@ var ParseError = class extends UsageError {
8186
8185
  }
8187
8186
  };
8188
8187
 
8189
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.0/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/resolveLongName.js
8188
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/resolveLongName.js
8190
8189
  function resolveLongName(key, definition) {
8191
8190
  return definition.long ?? key.replaceAll(/[A-Z]/g, (capital) => `-${capital.toLowerCase()}`);
8192
8191
  }
8193
8192
 
8194
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.0/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/tokenizeArgs.js
8193
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/tokenizeArgs.js
8195
8194
  import { parseArgs as nodeParseArgs } from "node:util";
8196
8195
  function tokenizeArgs(argv, schema, extraBooleans = []) {
8197
8196
  const nodeOptions = {};
@@ -8221,7 +8220,7 @@ function findFlagEntry(flagsByName, token) {
8221
8220
  return entry.definition.short === token.rawName.slice(1) ? entry : void 0;
8222
8221
  }
8223
8222
 
8224
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.0/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/validateSpec.js
8223
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/validateSpec.js
8225
8224
  var CAMEL_CASE_KEY = /^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]+)*$/;
8226
8225
  function validateSpec(spec) {
8227
8226
  validateFlags(spec.flags ?? {});
@@ -8302,7 +8301,7 @@ function validateOperands(operands) {
8302
8301
  }
8303
8302
  }
8304
8303
 
8305
- // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.0/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/parseArgs.js
8304
+ // ../../node_modules/.pnpm/@williamthorsen+toolbelt.cli@0.8.1/node_modules/@williamthorsen/toolbelt.cli/dist/esm/3-candidate/parseArgs.js
8306
8305
  function parseArgs(argv, spec, options = {}) {
8307
8306
  validateSpec(spec);
8308
8307
  return parseValidatedArgs(argv, spec, options);
@@ -8673,7 +8672,7 @@ function buildRootRegistry(config, monorepoRoot) {
8673
8672
  };
8674
8673
  }
8675
8674
 
8676
- // src/config-check-cache.ts
8675
+ // src/check-cache/config-check-cache.ts
8677
8676
  function assertResolvableCheckCacheCommands(config, configPath, baseDir) {
8678
8677
  const { checkCache } = config;
8679
8678
  if (checkCache === void 0 || !isMonorepoRoot(baseDir)) {
@@ -8968,6 +8967,44 @@ function escapeControlCharacters(text) {
8968
8967
  return escapedText;
8969
8968
  }
8970
8969
 
8970
+ // src/helpers/importConfigDefault.ts
8971
+ import { realpathSync } from "node:fs";
8972
+ import { pathToFileURL } from "node:url";
8973
+ async function importConfigDefault(configPath) {
8974
+ let importedModule;
8975
+ try {
8976
+ importedModule = await import(pathToFileURL(configPath).href);
8977
+ } catch (error) {
8978
+ const location = readSyntaxErrorLocation(error);
8979
+ const isInConfig = location !== void 0 && isConfigFile(location.file, configPath);
8980
+ const configLocation = isInConfig ? `${configPath}:${location.line}` : configPath;
8981
+ const foreignLocation = location === void 0 || isInConfig ? "" : `${location.file}:${location.line}: `;
8982
+ throw new UserError(
8983
+ `Cannot load nmr config at ${configLocation}: ${foreignLocation}${describeError(error)}. Fix the file and rerun.`,
8984
+ { cause: error }
8985
+ );
8986
+ }
8987
+ return isRecord2(importedModule) ? importedModule["default"] : void 0;
8988
+ }
8989
+ function isConfigFile(file, configPath) {
8990
+ return file === configPath || file === resolveRealPath(configPath);
8991
+ }
8992
+ function readSyntaxErrorLocation(error) {
8993
+ if (!isError(error) || error.stack === void 0) {
8994
+ return void 0;
8995
+ }
8996
+ const match = /^(?<file>.+):(?<line>\d+)$/u.exec(error.stack.split("\n", 1)[0] ?? "");
8997
+ const { file, line } = match?.groups ?? {};
8998
+ return file === void 0 || line === void 0 ? void 0 : { file, line };
8999
+ }
9000
+ function resolveRealPath(filePath) {
9001
+ try {
9002
+ return realpathSync(filePath);
9003
+ } catch {
9004
+ return void 0;
9005
+ }
9006
+ }
9007
+
8971
9008
  // src/config.ts
8972
9009
  var SCRIPT_FIELDS = [
8973
9010
  { field: "rootScripts", scope: "root" },
@@ -8978,8 +9015,7 @@ async function loadConfig(baseDir) {
8978
9015
  if (!existsSync3(configPath)) {
8979
9016
  return {};
8980
9017
  }
8981
- const importedModule = await import(pathToFileURL(configPath).href);
8982
- const loadedConfig = isRecord2(importedModule) ? importedModule["default"] : void 0;
9018
+ const loadedConfig = await importConfigDefault(configPath);
8983
9019
  return validateConfig(loadedConfig, configPath, baseDir);
8984
9020
  }
8985
9021
  async function loadRootConfig(monorepoRoot) {
@@ -9595,7 +9631,7 @@ function hasSupportedStrictLintVersion() {
9595
9631
  });
9596
9632
  }
9597
9633
  function getMinVersion() {
9598
- const pickedFields = { "version": "2.0.0" };
9634
+ const pickedFields = { "version": "2.0.2" };
9599
9635
  if (typeof pickedFields["version"] !== "string") {
9600
9636
  throw new TypeError("nmr/package.json: 'version' must be a string");
9601
9637
  }
@@ -3,19 +3,19 @@
3
3
  "kits": [
4
4
  {
5
5
  "bundledDependencies": {
6
- "@williamthorsen/toolbelt.arrays": "6.4.1",
7
- "@williamthorsen/toolbelt.cli": "0.8.0",
8
- "@williamthorsen/toolbelt.datetime": "4.1.1",
9
- "@williamthorsen/toolbelt.errors": "0.9.0",
10
- "@williamthorsen/toolbelt.filesystem": "0.10.0",
11
- "@williamthorsen/toolbelt.guards": "4.2.0",
12
- "@williamthorsen/toolbelt.numbers": "7.3.1",
13
- "@williamthorsen/toolbelt.objects": "4.4.0",
14
- "@williamthorsen/toolbelt.packaging": "0.7.0",
6
+ "@williamthorsen/toolbelt.arrays": "6.4.2",
7
+ "@williamthorsen/toolbelt.cli": "0.8.1",
8
+ "@williamthorsen/toolbelt.datetime": "4.1.2",
9
+ "@williamthorsen/toolbelt.errors": "0.9.1",
10
+ "@williamthorsen/toolbelt.filesystem": "0.10.1",
11
+ "@williamthorsen/toolbelt.guards": "4.2.1",
12
+ "@williamthorsen/toolbelt.numbers": "7.3.2",
13
+ "@williamthorsen/toolbelt.objects": "4.4.1",
14
+ "@williamthorsen/toolbelt.packaging": "0.7.1",
15
15
  "@williamthorsen/toolbelt.sets": "3.1.0",
16
- "@williamthorsen/toolbelt.strings": "8.2.1",
16
+ "@williamthorsen/toolbelt.strings": "8.2.2",
17
17
  "@williamthorsen/toolbelt.terminal": "0.3.0",
18
- "ansi-regex": "6.5.0",
18
+ "ansi-regex": "6.6.0",
19
19
  "ansi-styles": "6.2.3",
20
20
  "cli-truncate": "6.1.1",
21
21
  "diff": "9.0.0",
@@ -32,7 +32,7 @@
32
32
  "checklist": "nmr",
33
33
  "checks": [
34
34
  "@williamthorsen/nmr in devDependencies",
35
- "@williamthorsen/nmr >= 2.0.0",
35
+ "@williamthorsen/nmr >= 2.0.2",
36
36
  "pnpm-workspace.yaml exists",
37
37
  "catalogued dependencies use catalog:",
38
38
  "package.json has packageManager field",
@@ -236,7 +236,7 @@
236
236
  "path": "lib/workspace-build.ts"
237
237
  },
238
238
  {
239
- "hash": "6933f29e",
239
+ "hash": "cf90a835",
240
240
  "kind": "inline",
241
241
  "path": "../package.json",
242
242
  "paths": [
@@ -244,22 +244,22 @@
244
244
  ]
245
245
  },
246
246
  {
247
- "hash": "eb0306ed",
247
+ "hash": "a34d9027",
248
248
  "kind": "module",
249
- "path": "../src/commands/ensure-prepublish-hooks.ts"
249
+ "path": "../src/check-cache/config-check-cache.ts"
250
250
  },
251
251
  {
252
- "hash": "578af9fd",
252
+ "hash": "eb0306ed",
253
253
  "kind": "module",
254
- "path": "../src/config-check-cache.ts"
254
+ "path": "../src/commands/ensure-prepublish-hooks.ts"
255
255
  },
256
256
  {
257
- "hash": "d25aef4f",
257
+ "hash": "0555552a",
258
258
  "kind": "module",
259
259
  "path": "../src/config-validation.ts"
260
260
  },
261
261
  {
262
- "hash": "d345a285",
262
+ "hash": "f5e9e2fd",
263
263
  "kind": "module",
264
264
  "path": "../src/config.ts"
265
265
  },
@@ -293,6 +293,11 @@
293
293
  "kind": "module",
294
294
  "path": "../src/helpers/hook-name.ts"
295
295
  },
296
+ {
297
+ "hash": "d6455b2e",
298
+ "kind": "module",
299
+ "path": "../src/helpers/importConfigDefault.ts"
300
+ },
296
301
  {
297
302
  "hash": "62caa37e",
298
303
  "kind": "module",
@@ -356,10 +361,10 @@
356
361
  ],
357
362
  "name": "default",
358
363
  "path": "kits/default.js",
359
- "readyupVersion": "0.45.0",
364
+ "readyupVersion": "0.45.1",
360
365
  "source": "kits/default.ts",
361
366
  "sourceHash": "9fd61bf4",
362
- "targetHash": "7ddb0518"
367
+ "targetHash": "9895b0df"
363
368
  }
364
369
  ]
365
370
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,51 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 2.0.2 — 2026-11-12
6
+
7
+ ### 🐛 Bug fixes
8
+
9
+ - Fixes the issue that `nmr-fmt` and `nmr-taze` exited with 1 when a signal ended Prettier or taze, and makes each exit with 128 plus the signal number, as the other commands that nmr runs already did. (#1281)
10
+ - Fixes the issue that `nmr-fmt` formatted with nmr's own copy of Prettier when the repository's copy had a malformed or unreadable manifest, and makes `nmr-fmt` fail with an error that names that manifest instead. (#1282)
11
+ - Fixes the issue that `nmr-vitest` reported a Vitest whose manifest is malformed or unreadable as not installed, and makes `nmr-vitest` name that manifest and the repair instead. (#1282)
12
+ - Fixes the issue that `nmr-fmt` and `nmr-vitest` crashed on a Prettier or Vitest manifest that starts with a byte-order mark, which Node accepts. (#1282)
13
+ - Fixes the issue that a `.config/nmr.config.ts` or `~/.config/nmr/config.ts` that failed to parse or threw while loading crashed `nmr` with an internal error that did not name the file, and makes `nmr` report an error that names the config and, for a syntax error, the file and line that Node reports, including those of a module that the config imports. (#1296)
14
+ - Fixes the issue that `nmr` read any value of `NMR_DEBUG`, `NMR_NO_CACHE`, `NMR_NO_LOCK`, or `NMR_RUN_IF_PRESENT` other than `1`, such as `true`, as off without reporting it, by making `nmr` and `nmr-fmt` exit 2 with a message that names the variable and the values that it accepts. (#1297)
15
+ - Fixes the issue that `nmr upgrade --write` rewrote the `nodejs` pin in `.tool-versions` to a release that asdf could not install yet, by limiting the check to releases that node-build defines and reporting a newer release without a definition as held back. (#1300)
16
+
17
+ ### ♻️ Refactoring
18
+
19
+ - Replaces the copies of the inherited-stdio spawn and exit-code mapping in `nmr-actionlint`, `nmr-shellcheck`, and `nmr-vitest` with the shared `spawnInherited` and `resolveInheritedExitCode` in `spawn-inherited.ts`, so that the copies can no longer change independently. (#1281)
20
+ - Replaces the separate `bin` parsing in `resolveVitestCli` and `resolvePrettierCli` with one `resolveDeclaredCli` in `package-manifest.ts`, which takes `bin` either as a bare path or as a map keyed by the package name, so `nmr-vitest` now also accepts a Vitest manifest whose `bin` is a bare path. (#1283)
21
+ - Groups nmr's check-cache modules under `packages/nmr/src/check-cache/` and its delegation modules under `packages/nmr/src/delegation/`, each directory containing its own tests in `__tests__/`. (#1293)
22
+ - Makes `runCli` accept `runSteps` and `readFilterSelection` as optional dependencies that default to the real functions, and passes them on the `Invocation` to fan-out and the check-cache gate, which no longer import the real functions. (#1295)
23
+
24
+ ### 🧪 Tests
25
+
26
+ - Adds `createRunCliHarness` and a shared `it` in `test-utils/run-cli-fixtures.ts` that gives each test a workspace `tree` and fresh fakes, and moves the five `runCli` unit suites onto them, so that the suites no longer depend on the file layout of the modules that they used to mock. (#1295)
27
+ - Covers each decision branch of the check-cache gate with unit suites for lookup, recording, scope, and the command's own stated outcome, which inject a fake tree reader through a new `readTree` option on `runCli`, and removes the tool cases that they supersede, including `check-cache-gate.build-output.tool.test.ts`. (#1298)
28
+
29
+ ## 2.0.1 — 2026-11-11
30
+
31
+ ### 🐛 Bug fixes
32
+
33
+ - Fixes the issue that `nmr-clean`, `nmr-compile`, `nmr-report-catalog`, and `nmr-report-overrides` ignored their arguments, so `--help` or a mistyped option ran the command, and `nmr-clean --help` removed build output instead of printing usage. (#1273)
34
+
35
+ ### ♻️ Refactoring
36
+
37
+ - Adds an optional `spawn` adapter to `runPrettier` in `packages/nmr/src/commands/fmt.ts`, which defaults to `spawnSync` with inherited stdio, so that a test can replace the Prettier process without mocking `node:child_process`. (#1271)
38
+ - Extracts the unchanged-build skip report from `detectBuildChanges` into the exported `reportUnchangedBuild`, which takes the environment as a parameter rather than reading `process.env`. (#1272)
39
+ - Replaces the copies of the entry-point `glob` call in `buildPackage` and `hasBuildOutput` with one function, `resolveEntryPoints` in `build-output.ts`, so the build and the check cache's probe for build output cannot select different files. (#1274)
40
+ - Moves the printing of the build's progress and outcome lines from `buildPackage` to `nmr-compile`, which renders the `BuildOutcome` returned by `buildPackage` and the events from its new `onProgress` callback through `build-report.ts`. (#1277)
41
+ - Moves the emit's staging, swap by rename, and scratch-directory handling from `build.ts` and `build-output.ts` into `publish-output.ts`, which `build.ts` now calls with the emit directory. (#1278)
42
+ - Makes `cleanFrom` in `clean.ts` return a `CleanOutcome` and report each completed step through an `onProgress` callback rather than print, leaving `runClean` as the only function that prints, through the renderers in the new `clean-report.ts`. (#1279)
43
+
44
+ ### 🧪 Tests
45
+
46
+ - Moves the `runPrettier` cases from `fmt.tool.test.ts` to a new `fmt.unit.test.ts` that asserts on the invocations recorded by a spawn fake, and adds cases for a spawn error and for a Prettier process killed by a signal. (#1271)
47
+ - Replaces six skip-report cases in `build.publication.tool.test.ts`, each of which compiled a package to seed the cache, with unit tests of `reportUnchangedBuild` in `build.unit.test.ts` that write the recorded emit duration directly. (#1272)
48
+ - Tests `resolveEntryPoints` directly in `build-output.unit.test.ts` and removes the tool-tier tests in `build.tool.test.ts` that checked the same default exclusions, `ignorePatterns` override, and `extraIgnorePatterns` composition through a full build. (#1274)
49
+
5
50
  ## 2.0.0 — 2026-11-10
6
51
 
7
52
  ### 🪦 Removed
package/README.md CHANGED
@@ -5,11 +5,17 @@
5
5
  Context-aware script runner for pnpm monorepos. Includes an `nmr` (node-monorepo run) binary that provides centralized, consistent script execution across workspace packages and the monorepo root.
6
6
 
7
7
  <!-- section:release-notes -->
8
- ## Release notes — v2.0.0 (2026-11-10)
8
+ ## Release notes — v2.0.2 (2026-11-12)
9
9
 
10
- ### 🪦 Removed
10
+ ### 🐛 Bug fixes
11
11
 
12
- - 🚨 **Breaking:** Removes the `devBin` root-config field of `@williamthorsen/nmr`, which replaced the first token of a resolved command with a command that ran a bin from source. (#1269)
12
+ - Fixes the issue that `nmr-fmt` and `nmr-taze` exited with 1 when a signal ended Prettier or taze, and makes each exit with 128 plus the signal number, as the other commands that nmr runs already did. (#1281)
13
+ - Fixes the issue that `nmr-fmt` formatted with nmr's own copy of Prettier when the repository's copy had a malformed or unreadable manifest, and makes `nmr-fmt` fail with an error that names that manifest instead. (#1282)
14
+ - Fixes the issue that `nmr-vitest` reported a Vitest whose manifest is malformed or unreadable as not installed, and makes `nmr-vitest` name that manifest and the repair instead. (#1282)
15
+ - Fixes the issue that `nmr-fmt` and `nmr-vitest` crashed on a Prettier or Vitest manifest that starts with a byte-order mark, which Node accepts. (#1282)
16
+ - Fixes the issue that a `.config/nmr.config.ts` or `~/.config/nmr/config.ts` that failed to parse or threw while loading crashed `nmr` with an internal error that did not name the file, and makes `nmr` report an error that names the config and, for a syntax error, the file and line that Node reports, including those of a module that the config imports. (#1296)
17
+ - Fixes the issue that `nmr` read any value of `NMR_DEBUG`, `NMR_NO_CACHE`, `NMR_NO_LOCK`, or `NMR_RUN_IF_PRESENT` other than `1`, such as `true`, as off without reporting it, by making `nmr` and `nmr-fmt` exit 2 with a message that names the variable and the values that it accepts. (#1297)
18
+ - Fixes the issue that `nmr upgrade --write` rewrote the `nodejs` pin in `.tool-versions` to a release that asdf could not install yet, by limiting the check to releases that node-build defines and reporting a newer release without a definition as held back. (#1300)
13
19
  <!-- /section:release-notes -->
14
20
 
15
21
  ## Installation
@@ -189,7 +195,7 @@ $ nmr check
189
195
  nmr: waiting for test in /Users/me/repos/other-repo (pid 41872) to finish
190
196
  ```
191
197
 
192
- The lock lives in `/tmp/nmr-<uid>/`, or in `NMR_LOCK_DIR`; a sandboxed session needs write access to it. `nmr --no-lock <command>` or `NMR_NO_LOCK=1` runs without waiting. [Machine lock](docs/machine-lock.md) covers which commands take it, nesting and fan-outs, reclaiming a lock that its holder left behind, and CI.
198
+ The lock lives in `/tmp/nmr-<uid>/`, or in `NMR_LOCK_DIR`; a sandboxed session needs write access to it. `nmr --no-lock <command>` or `NMR_NO_LOCK=1` runs without waiting; [environment switches](docs/scripts.md#environment-switches) lists the values that the variable accepts. [Machine lock](docs/machine-lock.md) covers which commands take it, nesting and fan-outs, reclaiming a lock that its holder left behind, and CI.
193
199
 
194
200
  ## Delegating to another machine
195
201
 
@@ -1,4 +1,4 @@
1
- import type { NmrConfig } from './types.js';
1
+ import type { NmrConfig } from '../types.js';
2
2
  /** What nmr's own build has left on disk across the workspace. */
3
3
  export interface BuildOutputState {
4
4
  /** Covered packages whose output is absent. */
@@ -1,10 +1,10 @@
1
1
  import path from 'node:path';
2
- import { hasBuildOutput, readBuildDigest } from "./commands/build-output.js";
3
- import { loadWorkspaceConfig } from "./config.js";
4
- import { getDefaultWorkspaceScripts } from "./resolve-scripts.js";
5
- import { buildWorkspaceRegistry, resolveScript } from "./resolver.js";
6
- import { renderChain } from "./steps.js";
7
- import { getWorkspacePackageDirs } from "./workspace.js";
2
+ import { hasBuildOutput, readBuildDigest } from "../commands/build-output.js";
3
+ import { loadWorkspaceConfig } from "../config.js";
4
+ import { getDefaultWorkspaceScripts } from "../resolve-scripts.js";
5
+ import { buildWorkspaceRegistry, resolveScript } from "../resolver.js";
6
+ import { renderChain } from "../steps.js";
7
+ import { getWorkspacePackageDirs } from "../workspace.js";
8
8
  const BUILT_IN_COMPILE = 'nmr-compile';
9
9
  export function findStaleBuildOutput(earlierDigests, laterDigests) {
10
10
  const names = [...new Set([...Object.keys(earlierDigests), ...Object.keys(laterDigests)])].toSorted();
@@ -1,8 +1,8 @@
1
+ import type { HostRunResult } from '../delegation/delegate-host.js';
2
+ import { type RunPlan } from '../invocation.js';
3
+ import type { OutputChannels } from '../output-channel.js';
1
4
  import { type TreeSnapshot } from './check-cache.js';
2
5
  import type { BuildOutputState } from './check-cache-build-output.js';
3
- import type { HostRunResult } from './delegate-host.js';
4
- import { type RunPlan } from './invocation.js';
5
- import type { OutputChannels } from './output-channel.js';
6
6
  /** What the check-result cache gates a run on: the key, the tree, and the build output that the run saw. */
7
7
  export interface Gate {
8
8
  buildOutputBefore: BuildOutputState;
@@ -1,8 +1,8 @@
1
1
  import path from 'node:path';
2
+ import { VERSION } from "../invocation.js";
2
3
  import { resolveTreeSnapshot, writeDebugNote } from "./check-cache.js";
3
4
  import { computeCacheKey, computeRetentionKey } from "./check-cache-key.js";
4
5
  import { recordHostPass } from "./check-cache-record.js";
5
- import { VERSION } from "./invocation.js";
6
6
  import { formatManifestScope, validatePassManifest } from "./pass-manifest.js";
7
7
  export async function recordDelegatedPass(plan, gate, hostRun) {
8
8
  const { anchorDir, command, context, env, stderr } = plan.invocation;
@@ -11,7 +11,7 @@ export async function recordDelegatedPass(plan, gate, hostRun) {
11
11
  writeDebugNote(`not recording ${command}: the pushed tree is not the tree that the gate keyed on`, env, stderr);
12
12
  return;
13
13
  }
14
- const currentRead = resolveTreeSnapshot({ monorepoRoot, env: {} });
14
+ const currentRead = resolveTreeSnapshot({ monorepoRoot, env: {}, readTree: plan.invocation.readTree });
15
15
  if (!currentRead.ok) {
16
16
  writeDebugNote(`not recording ${command}: ${currentRead.reason}`, env, stderr);
17
17
  return;
@@ -1,8 +1,8 @@
1
1
  import path from 'node:path';
2
2
  import { isRecord, readCacheEntry, readJsonCacheEntry, removeCacheDir, removeCacheEntry, resolveCacheEntryPath, writeCacheEntry, } from '@williamthorsen/nmr-core';
3
3
  import { describeError } from '@williamthorsen/toolbelt.errors';
4
+ import { isStringRecord } from "../helpers/type-guards.js";
4
5
  import { writeDebugNote } from "./check-cache.js";
5
- import { isStringRecord } from "./helpers/type-guards.js";
6
6
  const CACHE_TOOL = 'nmr-check';
7
7
  const UNSAFE_SLUG_CHARACTERS = /[^\w.-]+/g;
8
8
  export async function certifyRetention(options) {
@@ -1,9 +1,9 @@
1
1
  import type { Writable } from 'node:stream';
2
2
  import { type OutputStyle } from '@williamthorsen/nmr-core';
3
- import { type TreeSnapshot } from './check-cache.js';
4
- import { type RunPlan } from './invocation.js';
5
- import type { NmrConfig } from './types.js';
6
- import type { VerdictOutcome } from './verdict.js';
3
+ import { type RunPlan } from '../invocation.js';
4
+ import type { NmrConfig } from '../types.js';
5
+ import type { VerdictOutcome } from '../verdict.js';
6
+ import { type TreeReader, type TreeSnapshot } from './check-cache.js';
7
7
  /**
8
8
  * Decides whether the check-result cache covers this invocation, and takes the tree snapshot on which it would
9
9
  * gate.
@@ -20,6 +20,7 @@ export declare function openGate(options: {
20
20
  env: NodeJS.ProcessEnv;
21
21
  monorepoRoot: string;
22
22
  passthrough: string[];
23
+ readTree: TreeReader;
23
24
  stderr: Writable;
24
25
  style: OutputStyle;
25
26
  }): TreeSnapshot | undefined;