@williamthorsen/nmr 0.36.0 โ 0.37.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 +83 -0
- package/.readyup/kits/default.js +91 -3
- package/.readyup/manifest.json +5 -5
- package/CHANGELOG.md +63 -0
- package/README.md +116 -1127
- package/agents/README.md +1 -1
- package/agents/guidance/rulebooks/nmr.md +2 -2
- package/dist/esm/context.d.ts +2 -0
- package/dist/esm/context.js +1 -0
- package/dist/esm/help.js +1 -1
- package/dist/esm/helpers/filter-selection.d.ts +42 -0
- package/dist/esm/helpers/filter-selection.js +61 -0
- package/dist/esm/runCli.js +70 -2
- package/dist/esm/runner.js +6 -5
- package/dist/esm/steps.d.ts +4 -0
- package/dist/esm/verdict.d.ts +1 -1
- package/dist/esm/vitest-source-resolution.d.ts +37 -0
- package/dist/esm/vitest-source-resolution.js +205 -0
- package/dist/esm/vitest.d.ts +3 -2
- package/dist/esm/vitest.js +7 -6
- package/dist/esm/workspace.d.ts +9 -0
- package/dist/esm/workspace.js +17 -0
- package/docs/check-cache.md +176 -0
- package/docs/prettier.md +47 -0
- package/docs/reporting.md +90 -0
- package/docs/scripts.md +168 -0
- package/docs/upgrades.md +110 -0
- package/docs/utilities.md +64 -0
- package/docs/vitest.md +233 -0
- package/docs/workspace.md +11 -0
- package/package.json +6 -4
package/.meta/changelog.json
CHANGED
|
@@ -1,4 +1,87 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.37.0",
|
|
4
|
+
"date": "2026-09-15",
|
|
5
|
+
"sections": [
|
|
6
|
+
{
|
|
7
|
+
"title": "๐ Features",
|
|
8
|
+
"audience": "all",
|
|
9
|
+
"items": [
|
|
10
|
+
{
|
|
11
|
+
"description": "Guard lefthook install in root prepare and report unguarded installs (#798)",
|
|
12
|
+
"body": "- Adds a `warn` check to the readyup kit of `@williamthorsen/nmr` that reports a root script run by `pnpm install`, such as `prepare` or `postinstall`, whose command calls `lefthook install` without `lefthook check-install`.\n- Includes in the check's suggested fix the guarded form `lefthook check-install || lefthook install`, which skips rewriting `.git/hooks` while `lefthook.yml` is unchanged since the last install, so that a repo using that form can run `pnpm install` without write access to `.git/hooks`, as inside the Claude Code sandbox, and under pnpm's default `verifyDepsBeforeRun` avoids a reinstall before every `pnpm exec`.",
|
|
13
|
+
"hash": "bd624dbe72c843266986f725411e067ca5127275"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"description": "Report misplaced test files and a missing guard from the readyup kit (#804)",
|
|
17
|
+
"body": "- Adds an `error` check to the `@williamthorsen/nmr` readyup kit that reports each `*.test.ts` or `*.test.tsx` file outside a `__tests__` directory, which no Vitest project collects and which therefore runs nowhere.\n- Adds a `warn` check that passes once a test file under `__tests__` imports `checkTestFileConventions` from `@williamthorsen/nmr/tests`, and whose fix shows the one-line guard test to add.\n- Makes the kit skip both test-file checks once it finds that guard, because the guard reports the same files and applies the repo's `exclude` list, which the kit cannot read.",
|
|
18
|
+
"hash": "233e66c24dd77d64c041b7170fefeb608f0f53d6"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"title": "๐ Bug fixes",
|
|
24
|
+
"audience": "all",
|
|
25
|
+
"items": [
|
|
26
|
+
{
|
|
27
|
+
"description": "Fail when a -F pattern selects no workspace (#785)",
|
|
28
|
+
"body": "- Fixes a run that reported success without doing anything. `nmr -F <pattern> <command>` printed nothing and exited 0 when the pattern matched no package. It now exits 1, names the rejected pattern, and explains the likely cause.\n- Covers three further selections that ran nothing and exited 0: an exclusion that leaves only the workspace root, such as `nmr -F '!./packages/*'`; `-R` in a workspace that declares no package; and an empty `-F ''`.\n\nMigration: Replace any `-F` pattern that names a directory with the package's manifest `name`. A filter that selects nothing now fails the run instead of passing in silence.",
|
|
29
|
+
"migration": "Replace any `-F` pattern that names a directory with the package's manifest `name`. A filter that selects nothing now fails the run instead of passing in silence.",
|
|
30
|
+
"hash": "542fe79b7fe8acdcc237841b85e7bea7f466bab2"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"description": "Fix test runs failing on a dependency with a TypeScript source export (#793)",
|
|
34
|
+
"body": "- Fixes the issue that, with `resolveFromSource` at its default of `true`, every test in a file failed with `Stripping types is currently unsupported for files under node_modules` when the file's imports reached a dependency whose `exports` map declares a `source` condition pointing at TypeScript.\n- Limits the source resolution enabled by `resolveFromSource` to packages whose real path lies outside every `node_modules`, which covers workspace packages and packages linked into the repo from elsewhere.\n- Makes an import of a workspace package fail when that package's `source` condition names a missing file, instead of resolving to the build output without warning.\n- Makes conditions that a config adds to `resolve.conditions` or `ssr.resolve.conditions` extend Vite's defaults when `resolveFromSource` is `false`, instead of replacing them.\n\nMigration: Point each workspace package's `source` condition at a file that exists, or remove the condition. Build a workspace package before running a test that reaches it through an externalized dependency (one that Vitest loads through Node instead of transforming): Node resolves that import without the `source` condition, so it loads the package's build output.",
|
|
35
|
+
"migration": "Point each workspace package's `source` condition at a file that exists, or remove the condition. Build a workspace package before running a test that reaches it through an externalized dependency (one that Vitest loads through Node instead of transforming): Node resolves that import without the `source` condition, so it loads the package's build output.",
|
|
36
|
+
"hash": "cd196ee47a17a891732b583ed706137ab3500507"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"description": "Prevent a recursive or multi-package run from hanging under pnpm 12 (#814)",
|
|
40
|
+
"body": "- Fixes a hang under pnpm 12: In a terminal, `nmr -R <command>`, a root command that runs in every package such as `nmr build`, and a `-F` pattern that selects several packages printed nothing and waited until Ctrl+C when a package command read keyboard input or changed the terminal's mode, as the spinner in `next build` does.\n- Gives no terminal input to each package of a `-R` run or a multi-package `-F` run, including a dependency-chain filter such as `-F 'app...'`, and keeps it for a `-F` filter that selects one package, which an interactive command such as `nmr -F <pkg> test:watch` needs.",
|
|
41
|
+
"hash": "c3a3305875fe2bd086b6f0cbb948186846fffb3d"
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"title": "๐งช Tests",
|
|
47
|
+
"audience": "dev",
|
|
48
|
+
"items": [
|
|
49
|
+
{
|
|
50
|
+
"description": "Run the descriptor-inheritance test on Linux and skip it in a sandbox (#803)",
|
|
51
|
+
"body": "- Stops `nmr ci` from failing in every Claude Code sandbox session on macOS by skipping the suite in `inherit-descriptor.tool.test.ts` when `SANDBOX_RUNTIME` is set, because the sandbox does not let `script(1)` open a pseudo-terminal.",
|
|
52
|
+
"hash": "fbdef48ba26d405a04241ab420c7f7eeafcdab12"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"title": "โ๏ธ Tooling",
|
|
58
|
+
"audience": "dev",
|
|
59
|
+
"items": [
|
|
60
|
+
{
|
|
61
|
+
"description": "Upgrade eslint-config-typescript to v17 and adopt its ignore lists (#797)",
|
|
62
|
+
"body": "- Declares `vitest` as `catalog:` in every workspace that imports it, with the pnpm catalog pinning 4.1.11, because v17 no longer exempts `vitest` from `n/no-extraneous-import`.\n- Builds the global ignores in `eslint.config.ts` from the published `commonIgnores` and `toolIgnores`, which also exclude `pnpm-lock.yaml` and each `.readyup/manifest.json`, so the `eslint --fix` in `nmr lint` can no longer rewrite a kit manifest and make the next build's `rdy verify` fail.",
|
|
63
|
+
"hash": "b201669444763ad5bef85730b114098ef352e09b"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"title": "๐ Documentation",
|
|
69
|
+
"audience": "dev",
|
|
70
|
+
"items": [
|
|
71
|
+
{
|
|
72
|
+
"description": "Trim the README and move reference detail into shipped topic docs (#800)",
|
|
73
|
+
"body": "- Deletes the default script registry tables and the CLI flag table, which `nmr --help` prints, and the migration sections, which `CHANGELOG.md` records, rather than moving them.\n- Adds `docs` to the files published with `@williamthorsen/nmr`, and changes the closing pointer in `agents/guidance/rulebooks/nmr.md` to name each topic's document under `node_modules/@williamthorsen/nmr/docs/` in place of `README.md`.",
|
|
74
|
+
"hash": "4758385382a0c720bbae60eed93b7718b16fbd6b"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"description": "Trim the release-kit README and move reference detail into shipped docs (#802)",
|
|
78
|
+
"body": "- Adds `docs` to the published `files` of `@williamthorsen/release-kit` and a `!docs/*.v*.md` exclusion to both it and `@williamthorsen/nmr`, because `pnpm pack` would otherwise include the release-notes previews that a local checkout holds.\n- Adds `--version` to the options that `release-kit --help` lists, and points the hints for the removed `releaseNotes.shouldCreateGithubRelease` field at `release-kit init` instead of the README.",
|
|
79
|
+
"hash": "bce2e74071cffd44e64e8bf9e6d2e6a2adaaf363"
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
},
|
|
2
85
|
{
|
|
3
86
|
"version": "0.36.0",
|
|
4
87
|
"date": "2026-09-08",
|
package/.readyup/kits/default.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @noformat -- @generated. Do not edit. Compiled by rdy. */
|
|
2
2
|
/* eslint-disable */
|
|
3
|
-
export const __readyupVersion = "0.
|
|
3
|
+
export const __readyupVersion = "0.36.0";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// .readyup/kits/default.ts
|
|
@@ -129,9 +129,15 @@ var TEST_EXTENSIONS = "{ts,tsx}";
|
|
|
129
129
|
var TEST_GLOB_PREFIX = `**/${TEST_DIR}/**`;
|
|
130
130
|
var TEST_FILE_PATTERN = /\.test\.tsx?$/;
|
|
131
131
|
var ALL_TEST_PATTERNS = [`${TEST_GLOB_PREFIX}/*.test.${TEST_EXTENSIONS}`];
|
|
132
|
+
function findMisplacedTestFiles(rootDir, options = {}) {
|
|
133
|
+
return walkTestFiles(rootDir, options, true);
|
|
134
|
+
}
|
|
132
135
|
function findTestFiles(rootDir, options = {}) {
|
|
133
136
|
return walkTestFiles(rootDir, options, false);
|
|
134
137
|
}
|
|
138
|
+
function findUntieredTestFiles(rootDir, options = {}) {
|
|
139
|
+
return findTestFiles(rootDir, options).filter((file) => !hasTierInfix(file));
|
|
140
|
+
}
|
|
135
141
|
function hasTierInfix(filePath) {
|
|
136
142
|
const tiers = TIER_NAMES;
|
|
137
143
|
return tiers.includes(path.basename(filePath).split(".").at(-3) ?? "");
|
|
@@ -252,6 +258,14 @@ var default_default = defineRdyKit({
|
|
|
252
258
|
check: noRedundantRootScripts,
|
|
253
259
|
fix: "Remove scripts from root package.json that nmr provides as built-in root scripts \u2014 invoke via nmr directly"
|
|
254
260
|
},
|
|
261
|
+
// -- Git hooks -----------------------------------------------------------
|
|
262
|
+
{
|
|
263
|
+
name: "no root install script runs lefthook install unguarded",
|
|
264
|
+
severity: "warn",
|
|
265
|
+
quiet: true,
|
|
266
|
+
check: () => noUnguardedLefthookInstall(),
|
|
267
|
+
fix: "Guard each listed script as `lefthook check-install || lefthook install`, which writes hooks only when they are missing or stale. A bare `lefthook install` rewrites `.git/hooks` on every install, so when that directory is not writable, as in an agent's sandbox, `pnpm install` fails and pnpm's `verifyDepsBeforeRun` then reinstalls before every `pnpm exec`"
|
|
268
|
+
},
|
|
255
269
|
// -- Workspace build readiness -------------------------------------------
|
|
256
270
|
{
|
|
257
271
|
name: "all workspace packages can build",
|
|
@@ -298,12 +312,26 @@ var default_default = defineRdyKit({
|
|
|
298
312
|
check: () => everyViteConfigHasVitestConfig(),
|
|
299
313
|
fix: "Add a vitest.config.ts calling defineVitestConfig() from @williamthorsen/nmr/vitest beside each listed vite.config -- Vitest stops its config search at the first directory holding either name, so the Vite config otherwise wins and the projects model is never reached"
|
|
300
314
|
},
|
|
315
|
+
{
|
|
316
|
+
name: "the test suite gates the test-file conventions",
|
|
317
|
+
severity: "warn",
|
|
318
|
+
check: () => testSuiteGatesTestFileConventions(),
|
|
319
|
+
fix: "Add a test of the repo's own under a __tests__ directory that declares the check: import { checkTestFileConventions } from '@williamthorsen/nmr/tests'; checkTestFileConventions(); -- passing `exclude` the directory names that the repo passes to `testCollectionExclude`. Without it no test run reports an untiered or misplaced test file, and this kit reports them in its place against nmr's built-in exclusions alone"
|
|
320
|
+
},
|
|
301
321
|
{
|
|
302
322
|
name: "every test file names its isolation tier",
|
|
303
323
|
severity: "error",
|
|
324
|
+
skip: () => describeConventionsGuardSkip(),
|
|
304
325
|
check: () => everyTestFileNamesItsTier(),
|
|
305
326
|
fix: `Rename each to <subject>[.<aspect>].<tier>.test.ts, naming one of ${TIER_NAMES.join(", ")}. Use tool for a test that reaches a program the environment supplies, which is where a retired .int. or .integration. file belongs. Only the segment before .test. selects a project, so an untiered file runs under the residual unit project and reports success`
|
|
306
327
|
},
|
|
328
|
+
{
|
|
329
|
+
name: "every test file sits under a __tests__ directory",
|
|
330
|
+
severity: "error",
|
|
331
|
+
skip: () => describeConventionsGuardSkip(),
|
|
332
|
+
check: () => everyTestFileSitsUnderTestsDir(),
|
|
333
|
+
fix: "Move each into a __tests__ directory, the only place from which the shared Vitest config collects. No project collects a file outside one, so it runs nowhere and reports nothing. For a file that is not a test, declare checkTestFileConventions with its directory in `exclude` instead, which this check then defers to"
|
|
334
|
+
},
|
|
307
335
|
{
|
|
308
336
|
name: "no package re-exports the ancestor Vitest config",
|
|
309
337
|
severity: "recommend",
|
|
@@ -368,6 +396,7 @@ var SHARED_VITEST_MODULE = "@williamthorsen/nmr/vitest";
|
|
|
368
396
|
var SHARED_PRETTIER_MODULE = "@williamthorsen/nmr/prettier";
|
|
369
397
|
var INERT_PRETTIER_CONFIGS = [".prettierrc", ".prettierrc.{json,json5,yaml,yml,toml}"];
|
|
370
398
|
var SHARED_TAZE_MODULE = "@williamthorsen/nmr/taze";
|
|
399
|
+
var SHARED_TESTS_MODULE = "@williamthorsen/nmr/tests";
|
|
371
400
|
var INERT_TAZE_CONFIGS = [".tazerc", ".tazerc.json", "taze.config.json"];
|
|
372
401
|
var CLOBBERED_TAZE_OPTIONS = [
|
|
373
402
|
{ key: "concurrency", pattern: /\bconcurrency\s*:/ },
|
|
@@ -377,6 +406,17 @@ var CLOBBERED_TAZE_OPTIONS = [
|
|
|
377
406
|
{ key: "requestTimeout", pattern: /\brequestTimeout\s*:/ }
|
|
378
407
|
];
|
|
379
408
|
var RE_EXPORT_LINE_PATTERN = /^export\s*(?:\{\s*default\s*}|\*)\s*from\s*['"]\.\.\/[^'"]*['"];?$/;
|
|
409
|
+
var INSTALL_LIFECYCLE_SCRIPTS = [
|
|
410
|
+
"pnpm:devPreinstall",
|
|
411
|
+
"preinstall",
|
|
412
|
+
"install",
|
|
413
|
+
"postinstall",
|
|
414
|
+
"preprepare",
|
|
415
|
+
"prepare",
|
|
416
|
+
"postprepare"
|
|
417
|
+
];
|
|
418
|
+
var LEFTHOOK_CHECK_INSTALL_PATTERN = /\blefthook\s+check-install\b/;
|
|
419
|
+
var LEFTHOOK_INSTALL_PATTERN = /\blefthook\s+install\b/;
|
|
380
420
|
var MIN_ESLINT_VERSION = "10.0.0";
|
|
381
421
|
var MIN_STRICT_LINT_VERSION = "9.3.0";
|
|
382
422
|
var WORKSPACE_VERSION_MARKERS = ["catalog:", "workspace:"];
|
|
@@ -526,10 +566,15 @@ function readWrapperTarget(cwd, workspace, entry) {
|
|
|
526
566
|
return posix.normalize(posix.join(posix.dirname(entry.target), specifier));
|
|
527
567
|
}
|
|
528
568
|
function everyTestFileNamesItsTier(cwd = process.cwd()) {
|
|
529
|
-
const untiered =
|
|
569
|
+
const untiered = findUntieredTestFiles(cwd);
|
|
530
570
|
if (untiered.length === 0) return true;
|
|
531
571
|
return { ok: false, detail: formatPaths(untiered) };
|
|
532
572
|
}
|
|
573
|
+
function everyTestFileSitsUnderTestsDir(cwd = process.cwd()) {
|
|
574
|
+
const misplaced = findMisplacedTestFiles(cwd);
|
|
575
|
+
if (misplaced.length === 0) return true;
|
|
576
|
+
return { ok: false, detail: formatPaths(misplaced) };
|
|
577
|
+
}
|
|
533
578
|
function everyViteConfigHasVitestConfig() {
|
|
534
579
|
const discovery = discoverMemberWorkspaces();
|
|
535
580
|
if (!discovery.ok) return discovery;
|
|
@@ -552,7 +597,7 @@ function formatPaths(paths) {
|
|
|
552
597
|
${paths.map((path2) => ` ${path2}`).join("\n")}`;
|
|
553
598
|
}
|
|
554
599
|
function getMinVersion() {
|
|
555
|
-
const picked = { "version": "0.
|
|
600
|
+
const picked = { "version": "0.37.0" };
|
|
556
601
|
if (typeof picked["version"] !== "string") {
|
|
557
602
|
throw new TypeError("nmr/package.json: 'version' must be a string");
|
|
558
603
|
}
|
|
@@ -618,6 +663,17 @@ function noRetiredVitestConfigs(cwd = process.cwd()) {
|
|
|
618
663
|
cwd
|
|
619
664
|
);
|
|
620
665
|
}
|
|
666
|
+
function noUnguardedLefthookInstall(cwd = process.cwd()) {
|
|
667
|
+
const scripts = readRootScripts(cwd);
|
|
668
|
+
const unguarded = INSTALL_LIFECYCLE_SCRIPTS.flatMap((name) => {
|
|
669
|
+
const command = scripts[name];
|
|
670
|
+
if (typeof command !== "string") return [];
|
|
671
|
+
const isUnguarded = LEFTHOOK_INSTALL_PATTERN.test(command) && !LEFTHOOK_CHECK_INSTALL_PATTERN.test(command);
|
|
672
|
+
return isUnguarded ? [`${name}: ${command}`] : [];
|
|
673
|
+
});
|
|
674
|
+
if (unguarded.length === 0) return true;
|
|
675
|
+
return { ok: false, detail: formatPaths(unguarded) };
|
|
676
|
+
}
|
|
621
677
|
function noWorkspaceRunScriptReferences() {
|
|
622
678
|
const packagesDir = join(process.cwd(), "packages");
|
|
623
679
|
if (!existsSync(packagesDir)) return true;
|
|
@@ -652,6 +708,19 @@ function readPnpmFieldKeys(content) {
|
|
|
652
708
|
const pnpm = parsed["pnpm"];
|
|
653
709
|
return isRecord(pnpm) ? Object.keys(pnpm).toSorted() : void 0;
|
|
654
710
|
}
|
|
711
|
+
function readRootScripts(cwd) {
|
|
712
|
+
const content = readFileIn(cwd, "package.json");
|
|
713
|
+
if (content === void 0) return {};
|
|
714
|
+
let parsed;
|
|
715
|
+
try {
|
|
716
|
+
parsed = JSON.parse(content);
|
|
717
|
+
} catch {
|
|
718
|
+
return {};
|
|
719
|
+
}
|
|
720
|
+
if (!isRecord(parsed)) return {};
|
|
721
|
+
const scripts = parsed["scripts"];
|
|
722
|
+
return isRecord(scripts) ? scripts : {};
|
|
723
|
+
}
|
|
655
724
|
function resolvesVersionViaWorkspace(range) {
|
|
656
725
|
return WORKSPACE_VERSION_MARKERS.some((marker) => range.startsWith(marker));
|
|
657
726
|
}
|
|
@@ -683,6 +752,22 @@ function describeMissingTazeConfig(cwd) {
|
|
|
683
752
|
if (inert.length > 0) return `holds no code to call the factory: ${inert.join(", ")}`;
|
|
684
753
|
return "taze.config.ts is missing";
|
|
685
754
|
}
|
|
755
|
+
function testSuiteGatesTestFileConventions(cwd = process.cwd()) {
|
|
756
|
+
if (findConventionsGuard(cwd) !== void 0) return true;
|
|
757
|
+
return {
|
|
758
|
+
ok: false,
|
|
759
|
+
detail: `no test file under __tests__ imports checkTestFileConventions from ${SHARED_TESTS_MODULE}`
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
function describeConventionsGuardSkip() {
|
|
763
|
+
const guard = findConventionsGuard(process.cwd());
|
|
764
|
+
return guard === void 0 ? false : `reported by checkTestFileConventions in ${guard}`;
|
|
765
|
+
}
|
|
766
|
+
function findConventionsGuard(cwd) {
|
|
767
|
+
return findTestFiles(cwd).find(
|
|
768
|
+
(relativePath) => importsSharedExport(readFileIn(cwd, relativePath), "checkTestFileConventions", SHARED_TESTS_MODULE)
|
|
769
|
+
);
|
|
770
|
+
}
|
|
686
771
|
function toolVersionsHasNoPnpm() {
|
|
687
772
|
const content = readFile(".tool-versions");
|
|
688
773
|
if (content === void 0) return true;
|
|
@@ -709,15 +794,18 @@ export {
|
|
|
709
794
|
everyBinTargetIsACommittedWrapper,
|
|
710
795
|
everyBinWrapperTargetIsCoveredByFiles,
|
|
711
796
|
everyTestFileNamesItsTier,
|
|
797
|
+
everyTestFileSitsUnderTestsDir,
|
|
712
798
|
everyViteConfigHasVitestConfig,
|
|
713
799
|
hasSupportedEslintVersion,
|
|
714
800
|
hasSupportedStrictLintVersion,
|
|
715
801
|
noPnpmFieldInPackageJson,
|
|
716
802
|
noReExportOnlyVitestConfigs,
|
|
717
803
|
noRetiredVitestConfigs,
|
|
804
|
+
noUnguardedLefthookInstall,
|
|
718
805
|
prettierConfigBuildsOnSharedConfig,
|
|
719
806
|
tazeConfigAvoidsClobberedOptions,
|
|
720
807
|
tazeConfigBuildsOnSharedConfig,
|
|
808
|
+
testSuiteGatesTestFileConventions,
|
|
721
809
|
vitestConfigBuildsOnSharedConfig,
|
|
722
810
|
vitestRootConfigBuildsOnSharedConfig
|
|
723
811
|
};
|
package/.readyup/manifest.json
CHANGED
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
"esbuildVersion": "0.28.2",
|
|
12
12
|
"inputs": [
|
|
13
13
|
{
|
|
14
|
-
"hash": "
|
|
14
|
+
"hash": "488459c0",
|
|
15
15
|
"kind": "module",
|
|
16
16
|
"path": "kits/default.ts"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
"hash": "
|
|
19
|
+
"hash": "d4b2e208",
|
|
20
20
|
"kind": "inline",
|
|
21
21
|
"path": "../package.json",
|
|
22
22
|
"paths": [
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
],
|
|
42
42
|
"name": "default",
|
|
43
43
|
"path": "kits/default.js",
|
|
44
|
-
"readyupVersion": "0.
|
|
44
|
+
"readyupVersion": "0.36.0",
|
|
45
45
|
"source": "kits/default.ts",
|
|
46
|
-
"sourceHash": "
|
|
47
|
-
"targetHash": "
|
|
46
|
+
"sourceHash": "488459c0",
|
|
47
|
+
"targetHash": "d1c8d02c"
|
|
48
48
|
}
|
|
49
49
|
]
|
|
50
50
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,69 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.37.0 โ 2026-09-15
|
|
6
|
+
|
|
7
|
+
### ๐ Features
|
|
8
|
+
|
|
9
|
+
- Guard lefthook install in root prepare and report unguarded installs (#798)
|
|
10
|
+
|
|
11
|
+
- Adds a `warn` check to the readyup kit of `@williamthorsen/nmr` that reports a root script run by `pnpm install`, such as `prepare` or `postinstall`, whose command calls `lefthook install` without `lefthook check-install`.
|
|
12
|
+
- Includes in the check's suggested fix the guarded form `lefthook check-install || lefthook install`, which skips rewriting `.git/hooks` while `lefthook.yml` is unchanged since the last install, so that a repo using that form can run `pnpm install` without write access to `.git/hooks`, as inside the Claude Code sandbox, and under pnpm's default `verifyDepsBeforeRun` avoids a reinstall before every `pnpm exec`.
|
|
13
|
+
|
|
14
|
+
- Report misplaced test files and a missing guard from the readyup kit (#804)
|
|
15
|
+
|
|
16
|
+
- Adds an `error` check to the `@williamthorsen/nmr` readyup kit that reports each `*.test.ts` or `*.test.tsx` file outside a `__tests__` directory, which no Vitest project collects and which therefore runs nowhere.
|
|
17
|
+
- Adds a `warn` check that passes once a test file under `__tests__` imports `checkTestFileConventions` from `@williamthorsen/nmr/tests`, and whose fix shows the one-line guard test to add.
|
|
18
|
+
- Makes the kit skip both test-file checks once it finds that guard, because the guard reports the same files and applies the repo's `exclude` list, which the kit cannot read.
|
|
19
|
+
|
|
20
|
+
### ๐ Bug fixes
|
|
21
|
+
|
|
22
|
+
- Fail when a -F pattern selects no workspace (#785)
|
|
23
|
+
|
|
24
|
+
- Fixes a run that reported success without doing anything. `nmr -F <pattern> <command>` printed nothing and exited 0 when the pattern matched no package. It now exits 1, names the rejected pattern, and explains the likely cause.
|
|
25
|
+
- Covers three further selections that ran nothing and exited 0: an exclusion that leaves only the workspace root, such as `nmr -F '!./packages/*'`; `-R` in a workspace that declares no package; and an empty `-F ''`.
|
|
26
|
+
|
|
27
|
+
Migration: Replace any `-F` pattern that names a directory with the package's manifest `name`. A filter that selects nothing now fails the run instead of passing in silence.
|
|
28
|
+
|
|
29
|
+
- Fix test runs failing on a dependency with a TypeScript source export (#793)
|
|
30
|
+
|
|
31
|
+
- Fixes the issue that, with `resolveFromSource` at its default of `true`, every test in a file failed with `Stripping types is currently unsupported for files under node_modules` when the file's imports reached a dependency whose `exports` map declares a `source` condition pointing at TypeScript.
|
|
32
|
+
- Limits the source resolution enabled by `resolveFromSource` to packages whose real path lies outside every `node_modules`, which covers workspace packages and packages linked into the repo from elsewhere.
|
|
33
|
+
- Makes an import of a workspace package fail when that package's `source` condition names a missing file, instead of resolving to the build output without warning.
|
|
34
|
+
- Makes conditions that a config adds to `resolve.conditions` or `ssr.resolve.conditions` extend Vite's defaults when `resolveFromSource` is `false`, instead of replacing them.
|
|
35
|
+
|
|
36
|
+
Migration: Point each workspace package's `source` condition at a file that exists, or remove the condition. Build a workspace package before running a test that reaches it through an externalized dependency (one that Vitest loads through Node instead of transforming): Node resolves that import without the `source` condition, so it loads the package's build output.
|
|
37
|
+
|
|
38
|
+
- Prevent a recursive or multi-package run from hanging under pnpm 12 (#814)
|
|
39
|
+
|
|
40
|
+
- Fixes a hang under pnpm 12: In a terminal, `nmr -R <command>`, a root command that runs in every package such as `nmr build`, and a `-F` pattern that selects several packages printed nothing and waited until Ctrl+C when a package command read keyboard input or changed the terminal's mode, as the spinner in `next build` does.
|
|
41
|
+
- Gives no terminal input to each package of a `-R` run or a multi-package `-F` run, including a dependency-chain filter such as `-F 'app...'`, and keeps it for a `-F` filter that selects one package, which an interactive command such as `nmr -F <pkg> test:watch` needs.
|
|
42
|
+
|
|
43
|
+
### ๐งช Tests
|
|
44
|
+
|
|
45
|
+
- Run the descriptor-inheritance test on Linux and skip it in a sandbox (#803)
|
|
46
|
+
|
|
47
|
+
- Stops `nmr ci` from failing in every Claude Code sandbox session on macOS by skipping the suite in `inherit-descriptor.tool.test.ts` when `SANDBOX_RUNTIME` is set, because the sandbox does not let `script(1)` open a pseudo-terminal.
|
|
48
|
+
|
|
49
|
+
### โ๏ธ Tooling
|
|
50
|
+
|
|
51
|
+
- Upgrade eslint-config-typescript to v17 and adopt its ignore lists (#797)
|
|
52
|
+
|
|
53
|
+
- Declares `vitest` as `catalog:` in every workspace that imports it, with the pnpm catalog pinning 4.1.11, because v17 no longer exempts `vitest` from `n/no-extraneous-import`.
|
|
54
|
+
- Builds the global ignores in `eslint.config.ts` from the published `commonIgnores` and `toolIgnores`, which also exclude `pnpm-lock.yaml` and each `.readyup/manifest.json`, so the `eslint --fix` in `nmr lint` can no longer rewrite a kit manifest and make the next build's `rdy verify` fail.
|
|
55
|
+
|
|
56
|
+
### ๐ Documentation
|
|
57
|
+
|
|
58
|
+
- Trim the README and move reference detail into shipped topic docs (#800)
|
|
59
|
+
|
|
60
|
+
- Deletes the default script registry tables and the CLI flag table, which `nmr --help` prints, and the migration sections, which `CHANGELOG.md` records, rather than moving them.
|
|
61
|
+
- Adds `docs` to the files published with `@williamthorsen/nmr`, and changes the closing pointer in `agents/guidance/rulebooks/nmr.md` to name each topic's document under `node_modules/@williamthorsen/nmr/docs/` in place of `README.md`.
|
|
62
|
+
|
|
63
|
+
- Trim the release-kit README and move reference detail into shipped docs (#802)
|
|
64
|
+
|
|
65
|
+
- Adds `docs` to the published `files` of `@williamthorsen/release-kit` and a `!docs/*.v*.md` exclusion to both it and `@williamthorsen/nmr`, because `pnpm pack` would otherwise include the release-notes previews that a local checkout holds.
|
|
66
|
+
- Adds `--version` to the options that `release-kit --help` lists, and points the hints for the removed `releaseNotes.shouldCreateGithubRelease` field at `release-kit init` instead of the README.
|
|
67
|
+
|
|
5
68
|
## 0.36.0 โ 2026-09-08
|
|
6
69
|
|
|
7
70
|
### ๐ Features
|