get-tbd 0.1.28 → 0.1.29
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/dist/bin.mjs +3 -3
- package/dist/bin.mjs.map +1 -1
- package/dist/cli.mjs +3 -3
- package/dist/cli.mjs.map +1 -1
- package/dist/docs/SKILL.md +0 -4
- package/dist/docs/guidelines/bun-monorepo-patterns.md +92 -289
- package/dist/docs/guidelines/cli-agent-skill-patterns.md +706 -1240
- package/dist/docs/guidelines/pnpm-monorepo-patterns.md +104 -321
- package/dist/docs/guidelines/supply-chain-hardening.md +237 -0
- package/dist/docs/shortcuts/standard/new-validation-plan.md +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-D2xEmH4L.mjs → src-CJyVkC3V.mjs} +2 -2
- package/dist/{src-D2xEmH4L.mjs.map → src-CJyVkC3V.mjs.map} +1 -1
- package/dist/tbd +3 -3
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ author: Joshua Levy (github.com/jlevy) with LLM assistance
|
|
|
24
24
|
|
|
25
25
|
| Tool / Package | Version | Check For Updates |
|
|
26
26
|
| --- | --- | --- |
|
|
27
|
-
| **Node.js** | 24 (LTS
|
|
27
|
+
| **Node.js** | 24 (LTS “Krypton”) | [nodejs.org/releases](https://nodejs.org/en/about/previous-releases) — Node 24 Active LTS until Oct 2026. **Node 26 Current** shipped 2026-05-05 (Temporal API enabled by default, V8 14.6, Undici 8.0). **Node 20 went EOL 2026-03-24.** Node 26 is the last release on the old two-major-per-year cadence; starting v27, all majors become LTS (one per year). |
|
|
28
28
|
| **pnpm** | ^11.0.0 (11.2.x too recent) | [github.com/pnpm/pnpm/releases](https://github.com/pnpm/pnpm/releases) — **Pinned to 11.0.0 (2026-04-28) per the 14-day rule**; 11.2.0/11.2.2 shipped 2026-05-20/21 (1–2 days old today). Breaking changes: pure ESM (requires **Node 22+**); SQLite-based store (`$STORE/index.db`); **`minimumReleaseAge` defaults to 1440 minutes (1 day)** for supply-chain hygiene; **`blockExoticSubdeps` defaults to `true`**; `onlyBuiltDependencies`/`neverBuiltDependencies` removed and replaced by **`allowBuilds`**; `patchedDependencies` format simplified; experimental Rust-based `@pnpm/pacquet` engine arrives in 11.2+. v11.1 added `pnpm audit signatures`, `pnpm bugs`, `pnpm owner`. |
|
|
29
29
|
| **TypeScript** | ^6.0.3 | [github.com/microsoft/TypeScript/releases](https://github.com/microsoft/TypeScript/releases) — **6.0.3 stable** (shipped 2026-03-23). 6.0 is the last JavaScript-based release; `strict: true` is now the default, ESM is the default module system, ~9 compiler settings flipped defaults. **TS 7.0 Beta** (Project Corsa, Go rewrite) shipped 2026-04-21 as `@typescript/native-preview` (binary: `tsgo`); claims ~10× type-check speed and ~3× less memory. Stable expected mid-to-late 2026. Do not adopt `tsgo` for production builds yet. |
|
|
30
30
|
| **tsdown** | ^0.22.0 | [github.com/rolldown/tsdown/releases](https://github.com/rolldown/tsdown/releases) — 0.22.0 (2026-05-07). Has not reached 1.0; incremental 0.20→0.22 releases since Feb 2026; no deprecations. Requires Node.js 20.19+. |
|
|
@@ -32,8 +32,8 @@ author: Joshua Levy (github.com/jlevy) with LLM assistance
|
|
|
32
32
|
| **@changesets/cli** | ^2.31.0 | [github.com/changesets/changesets/releases](https://github.com/changesets/changesets/releases) — 2.31.0 latest. No native Bun support added. |
|
|
33
33
|
| **@types/node** | ^24.0.0 | [@types/node npm](https://www.npmjs.com/package/@types/node) — Track Node.js major version. @types/node@25.x available; @types/node@26.x will follow Node 26. |
|
|
34
34
|
| **actions/checkout** | v6 | [github.com/actions/checkout/releases](https://github.com/actions/checkout/releases) — v6.0.2 (2026-01-09). Credentials now stored in `$RUNNER_TEMP` rather than `.git/config`; Node 24 runtime; requires runner ≥ 2.327.1. |
|
|
35
|
-
| **actions/setup-node** | v6 | [github.com/actions/setup-node/releases](https://github.com/actions/setup-node/releases) — Supports Node 24 by default. **Note GitHub
|
|
36
|
-
| **pnpm/action-setup** | v6 | [github.com/pnpm/action-setup/releases](https://github.com/pnpm/action-setup/releases) — **v6 required for pnpm 11+ support.** v4 (previously documented) does not handle pnpm 11
|
|
35
|
+
| **actions/setup-node** | v6 | [github.com/actions/setup-node/releases](https://github.com/actions/setup-node/releases) — Supports Node 24 by default. **Note GitHub’s 2026-06-02 deadline forcing Node.js 20 actions to Node.js 24.** |
|
|
36
|
+
| **pnpm/action-setup** | v6 | [github.com/pnpm/action-setup/releases](https://github.com/pnpm/action-setup/releases) — **v6 required for pnpm 11+ support.** v4 (previously documented) does not handle pnpm 11’s ESM-only distribution correctly. |
|
|
37
37
|
| **changesets/action** | v1 | [github.com/changesets/action](https://github.com/changesets/action) — Still v1. No v2. |
|
|
38
38
|
| **lefthook** | ^2.1.5 (2.1.7/2.1.8 too recent) | [github.com/evilmartians/lefthook/releases](https://github.com/evilmartians/lefthook/releases) — **Pinned to 2.1.5 (2026-04-06) per the 14-day rule**; 2.1.7/2.1.8 both shipped 2026-05-19. Patch-level since 2.1.1. v2 still excludes regexp `exclude` and `skip_output` from v1. |
|
|
39
39
|
| **npm-check-updates** | ^22.0.0 (22.2.0 too recent) | [npmjs.com/package/npm-check-updates](https://www.npmjs.com/package/npm-check-updates) — **Major version jump from 19 to 22.** **Pinned to 22.0.0 (2026-04-25) per the 14-day rule**; 22.2.0 (2026-05-12) is 10 days old today. Now pure ESM; named imports only (`import { run } from 'npm-check-updates'`); `.ncurc.js` with `module.exports` no longer works in `"type": "module"` projects (use `.ncurc.cjs`). **Ships `--cooldown <days>` to refuse versions younger than the specified age** — primary enforcement for the 14-day package-age rule. See [Supply-Chain Mitigation](#supply-chain-mitigation). |
|
|
@@ -47,7 +47,7 @@ author: Joshua Levy (github.com/jlevy) with LLM assistance
|
|
|
47
47
|
| **picocolors** | ^1.1.1 | [npmjs.com/package/picocolors](https://www.npmjs.com/package/picocolors) — Last release October 2024. Stable; no changes expected. |
|
|
48
48
|
| **dotenv** | ^17.4.2 | [npmjs.com/package/dotenv](https://www.npmjs.com/package/dotenv) — Stable. **Prefer Node.js native `--env-file` for Node ≥20.6** (production-ready since Node 24 LTS); use dotenv only when you need variable expansion, multiline values, or custom precedence logic. |
|
|
49
49
|
| **atomically** | ^2.1.1 | [npmjs.com/package/atomically](https://www.npmjs.com/package/atomically) — 2.1.1 (2026-02-08). Still maintained. |
|
|
50
|
-
| **yaml** | ^2.8.4 | [npmjs.com/package/yaml](https://www.npmjs.com/package/yaml) — 2.8.4 (2026-05-02). v3.0.0-1 is tagged
|
|
50
|
+
| **yaml** | ^2.8.4 | [npmjs.com/package/yaml](https://www.npmjs.com/package/yaml) — 2.8.4 (2026-05-02). v3.0.0-1 is tagged “next” (pre-release) — do not adopt yet. |
|
|
51
51
|
| **@vitest/coverage-v8** | ^4.1.7 | [npmjs.com/package/@vitest/coverage-v8](https://www.npmjs.com/package/@vitest/coverage-v8) — Track Vitest version. |
|
|
52
52
|
|
|
53
53
|
### Reminders When Updating
|
|
@@ -75,8 +75,8 @@ author: Joshua Levy (github.com/jlevy) with LLM assistance
|
|
|
75
75
|
|
|
76
76
|
6. **Review “Open Research Questions”** section for any resolved items
|
|
77
77
|
|
|
78
|
-
7. **Honor the 14-day package-age rule** when bumping versions in code examples.
|
|
79
|
-
[Supply-Chain Mitigation](#supply-chain-mitigation) — versions cited here should
|
|
78
|
+
7. **Honor the 14-day package-age rule** when bumping versions in code examples.
|
|
79
|
+
See [Supply-Chain Mitigation](#supply-chain-mitigation) — versions cited here should
|
|
80
80
|
be ≥14 days old at the time the table is updated, except where a clearly-noted
|
|
81
81
|
security exception applies.
|
|
82
82
|
|
|
@@ -154,20 +154,20 @@ recommendations from the TypeScript and JavaScript ecosystem maintainers.
|
|
|
154
154
|
|
|
155
155
|
- `pnpm deploy` command enables isolated production deployments for Docker
|
|
156
156
|
|
|
157
|
-
- **pnpm 11 (shipped 2026-04-28)** adds significant supply-chain hardening
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
- **pnpm 11 (shipped 2026-04-28)** adds significant supply-chain hardening defaults:
|
|
158
|
+
`minimumReleaseAge: 1440` (1 day) and `blockExoticSubdeps: true`. We recommend
|
|
159
|
+
overriding `minimumReleaseAge` to 14 days — see
|
|
160
160
|
[Supply-Chain Mitigation](#supply-chain-mitigation).
|
|
161
161
|
|
|
162
|
-
- **pnpm 11 is pure ESM and requires Node.js 22+.** Lifecycle script gating
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
- **pnpm 11 is pure ESM and requires Node.js 22+.** Lifecycle script gating has moved
|
|
163
|
+
from `onlyBuiltDependencies`/`neverBuiltDependencies` to **`allowBuilds`** (an
|
|
164
|
+
explicit allowlist).
|
|
165
165
|
|
|
166
|
-
- The store is now a single SQLite database (`$STORE/index.db`) for faster
|
|
167
|
-
|
|
166
|
+
- The store is now a single SQLite database (`$STORE/index.db`) for faster cache reads;
|
|
167
|
+
this is invisible to users but matters for CI cache configs.
|
|
168
168
|
|
|
169
|
-
**Assessment**: pnpm remains the consensus choice for TypeScript monorepos, with
|
|
170
|
-
|
|
169
|
+
**Assessment**: pnpm remains the consensus choice for TypeScript monorepos, with pnpm 11
|
|
170
|
+
adding meaningful supply-chain defaults and faster store I/O.
|
|
171
171
|
|
|
172
172
|
**Key Configuration** (`pnpm-workspace.yaml`):
|
|
173
173
|
|
|
@@ -1118,15 +1118,15 @@ Vite’s transformation pipeline.
|
|
|
1118
1118
|
|
|
1119
1119
|
- Visual regression testing (added in Vitest 4.0)
|
|
1120
1120
|
|
|
1121
|
-
- **Vitest 4.1 (Mar 2026)** added Vite 8 support, test tags for organizing tests,
|
|
1122
|
-
|
|
1123
|
-
installed Vite instead of bundling a separate dependency.
|
|
1121
|
+
- **Vitest 4.1 (Mar 2026)** added Vite 8 support, test tags for organizing tests, and
|
|
1122
|
+
extended chai-style assertions for mocking.
|
|
1123
|
+
Vitest now reuses the installed Vite instead of bundling a separate dependency.
|
|
1124
1124
|
|
|
1125
|
-
- **`coverage.all` was removed in v4** — use `coverage.include` and
|
|
1126
|
-
|
|
1125
|
+
- **`coverage.all` was removed in v4** — use `coverage.include` and `coverage.exclude`
|
|
1126
|
+
to control which files are reported.
|
|
1127
1127
|
|
|
1128
|
-
- **Vitest 5.0.0-beta** is in pre-release (requires Node 22+ and Vite 6.4+).
|
|
1129
|
-
|
|
1128
|
+
- **Vitest 5.0.0-beta** is in pre-release (requires Node 22+ and Vite 6.4+). Stay on
|
|
1129
|
+
4.1.x for production until stable.
|
|
1130
1130
|
|
|
1131
1131
|
**Installation**:
|
|
1132
1132
|
|
|
@@ -1809,8 +1809,8 @@ pnpm add -Dw npm-check-updates
|
|
|
1809
1809
|
|
|
1810
1810
|
- Pure ESM. Named imports only: `import { run } from 'npm-check-updates'`. Default
|
|
1811
1811
|
exports no longer work.
|
|
1812
|
-
- Config files: `.ncurc.js` with `module.exports` no longer works in
|
|
1813
|
-
|
|
1812
|
+
- Config files: `.ncurc.js` with `module.exports` no longer works in `"type": "module"`
|
|
1813
|
+
projects. Use `.ncurc.cjs`.
|
|
1814
1814
|
- Node.js requirement: `^20.19.0 || ^22.12.0 || >=24.0.0`.
|
|
1815
1815
|
|
|
1816
1816
|
**Upgrade Targets Explained**:
|
|
@@ -2536,237 +2536,19 @@ than discovering them when users try to use the library in browser/edge contexts
|
|
|
2536
2536
|
|
|
2537
2537
|
## Supply-Chain Mitigation
|
|
2538
2538
|
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2539
|
+
Supply-chain hardening applies to **every repo, not just new monorepos**, so the full
|
|
2540
|
+
policy and hands-on enforcement now live in a standalone guideline:
|
|
2541
|
+
**`tbd guidelines supply-chain-hardening`**. It covers the cross-ecosystem 14-day
|
|
2542
|
+
cool-off plus the Node/pnpm/Bun specifics — lifecycle-script allowlists, lockfile
|
|
2543
|
+
discipline, `npm-check-updates --cooldown 14`, the CI audit gate, and the
|
|
2544
|
+
`check-package-age` pre-push guard.
|
|
2545
|
+
Deeper background and the named-incident watch list:
|
|
2546
|
+
<https://github.com/jlevy/supply-chain-hardening>.
|
|
2543
2547
|
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
similar campaigns ran through 2025 (`debug`, `chalk`, `ansi-styles` lookalikes;
|
|
2549
|
-
`expr-eval` post-install RCE). pnpm shipped `minimumReleaseAge` as a default in
|
|
2550
|
-
v11.0 (1 day). Bun ships a built-in trusted-dependency allowlist and `bun audit`.
|
|
2551
|
-
The settings below are stricter than the ecosystem defaults and intentionally so.
|
|
2552
|
-
|
|
2553
|
-
### The 14-day package-age rule
|
|
2554
|
-
|
|
2555
|
-
**Never install or upgrade to a package version less than 14 days old.**
|
|
2556
|
-
|
|
2557
|
-
Why 14 days specifically:
|
|
2558
|
-
|
|
2559
|
-
- **Detection window**: most malicious publishes are reported and yanked within
|
|
2560
|
-
3–7 days; 14 days gives a generous buffer past that median.
|
|
2561
|
-
- **Patch-level releases ship dangerous code more often**: many compromises arrive
|
|
2562
|
-
as `1.2.3 → 1.2.4` patch bumps. A trailing window neutralizes the entire class
|
|
2563
|
-
of "fresh patch is malicious" attacks regardless of which dependency moved.
|
|
2564
|
-
- **Cheap to enforce, cheap to wait**: there is essentially no business cost to
|
|
2565
|
-
waiting 14 days on a routine upgrade, and the upside is large.
|
|
2566
|
-
|
|
2567
|
-
Scope:
|
|
2568
|
-
|
|
2569
|
-
- Applies to **`dependencies`, `devDependencies`, `peerDependencies`, and
|
|
2570
|
-
`optionalDependencies`** alike. devDependencies (bundlers, linters, test
|
|
2571
|
-
runners) have historically been *more* dangerous than runtime deps because
|
|
2572
|
-
they execute with full developer privileges on every install.
|
|
2573
|
-
- Applies to **transitive dependencies** to the extent the package manager
|
|
2574
|
-
enforces it (see below). Direct deps are the primary control point.
|
|
2575
|
-
- Applies to **upgrades and new installs**. Existing pins resolved before this
|
|
2576
|
-
policy was adopted are grandfathered until their next planned upgrade.
|
|
2577
|
-
|
|
2578
|
-
Exception process: if a security patch within the 14-day window is needed —
|
|
2579
|
-
e.g., a CVE patch published yesterday that fixes a vulnerability you are
|
|
2580
|
-
exposed to — the exception **must** be documented in the upgrade commit message
|
|
2581
|
-
or PR description, including:
|
|
2582
|
-
|
|
2583
|
-
- The CVE ID (or vulnerability description if no CVE yet).
|
|
2584
|
-
- A link to the upstream release notes.
|
|
2585
|
-
- A reviewer sign-off line (`Reviewed-by: …`).
|
|
2586
|
-
|
|
2587
|
-
No exception is "trivial" — even a `prettier` patch is in scope. The whole
|
|
2588
|
-
point of the rule is that we don't trust ourselves to spot-judge which fresh
|
|
2589
|
-
versions are safe.
|
|
2590
|
-
|
|
2591
|
-
### Enforcement: pnpm
|
|
2592
|
-
|
|
2593
|
-
pnpm 11 ships **`minimumReleaseAge`** as a config setting (default 1440 minutes
|
|
2594
|
-
= 1 day). Override it to 14 days in `.npmrc` or `pnpm-workspace.yaml`:
|
|
2595
|
-
|
|
2596
|
-
```ini
|
|
2597
|
-
# .npmrc
|
|
2598
|
-
# 14 days in minutes (14 * 24 * 60).
|
|
2599
|
-
minimum-release-age=20160
|
|
2600
|
-
```
|
|
2601
|
-
|
|
2602
|
-
```yaml
|
|
2603
|
-
# pnpm-workspace.yaml
|
|
2604
|
-
minimumReleaseAge: 20160
|
|
2605
|
-
```
|
|
2606
|
-
|
|
2607
|
-
pnpm will refuse to resolve to any version published less than that long ago.
|
|
2608
|
-
Use a per-package allowlist exception (`minimumReleaseAgeExclude`) only with
|
|
2609
|
-
the documented exception process above.
|
|
2610
|
-
|
|
2611
|
-
pnpm 11 also defaults **`blockExoticSubdeps`** to `true` (blocks transitive
|
|
2612
|
-
dependencies installed from non-registry sources like `github:`, `git+ssh://`,
|
|
2613
|
-
or arbitrary URLs). Keep this default on.
|
|
2614
|
-
|
|
2615
|
-
Lifecycle script hygiene in pnpm 11 uses the new **`allowBuilds`** allowlist
|
|
2616
|
-
(replacing `onlyBuiltDependencies` / `neverBuiltDependencies`). Declare the
|
|
2617
|
-
exact packages allowed to run install scripts:
|
|
2618
|
-
|
|
2619
|
-
```yaml
|
|
2620
|
-
# pnpm-workspace.yaml
|
|
2621
|
-
allowBuilds:
|
|
2622
|
-
- esbuild
|
|
2623
|
-
- sharp
|
|
2624
|
-
```
|
|
2625
|
-
|
|
2626
|
-
Everything not in this list runs without `postinstall`/`preinstall`/`install`
|
|
2627
|
-
scripts. This is the single most important mitigation pnpm gives you out of
|
|
2628
|
-
the box.
|
|
2629
|
-
|
|
2630
|
-
`pnpm audit` and `pnpm audit signatures` (added in 11.1) provide vulnerability
|
|
2631
|
-
and provenance checks:
|
|
2632
|
-
|
|
2633
|
-
```bash
|
|
2634
|
-
pnpm audit --audit-level=moderate
|
|
2635
|
-
pnpm audit signatures
|
|
2636
|
-
```
|
|
2637
|
-
|
|
2638
|
-
### Enforcement: cross-tool tooling
|
|
2639
|
-
|
|
2640
|
-
**`npm-check-updates --cooldown`** is the upgrade-time check, complementing
|
|
2641
|
-
pnpm's resolution-time `minimumReleaseAge`. Use it in scripts even on
|
|
2642
|
-
pnpm-managed projects:
|
|
2643
|
-
|
|
2644
|
-
```bash
|
|
2645
|
-
# Refuse any candidate version younger than 14 days
|
|
2646
|
-
pnpm dlx npm-check-updates --cooldown 14
|
|
2647
|
-
|
|
2648
|
-
# Interactive upgrade with the 14-day filter applied
|
|
2649
|
-
pnpm dlx npm-check-updates --cooldown 14 --target minor --interactive
|
|
2650
|
-
|
|
2651
|
-
# CI-style check: exits non-zero if upgrades are available
|
|
2652
|
-
pnpm dlx npm-check-updates --cooldown 14 --errorLevel 2
|
|
2653
|
-
```
|
|
2654
|
-
|
|
2655
|
-
**Direct registry query** (when in doubt about a specific version):
|
|
2656
|
-
|
|
2657
|
-
```bash
|
|
2658
|
-
# Show all publish times for a package
|
|
2659
|
-
npm view typescript time
|
|
2660
|
-
|
|
2661
|
-
# Show the time of a specific version
|
|
2662
|
-
npm view typescript time.6.0.3
|
|
2663
|
-
```
|
|
2664
|
-
|
|
2665
|
-
If `npm view <pkg> time.<version>` reports less than 14 days ago, **wait**.
|
|
2666
|
-
|
|
2667
|
-
### Enforcement: lockfile discipline
|
|
2668
|
-
|
|
2669
|
-
- **Always commit `pnpm-lock.yaml`**.
|
|
2670
|
-
- **Use `pnpm install --frozen-lockfile` in CI** so any drift between
|
|
2671
|
-
`package.json` and `pnpm-lock.yaml` fails the build instead of silently
|
|
2672
|
-
resolving to fresh versions.
|
|
2673
|
-
- **Never run `pnpm update` (or `pnpm install` on a fresh `node_modules` with
|
|
2674
|
-
an unpinned `package.json`) without lockfile review.** Treat lockfile diffs
|
|
2675
|
-
the same as code diffs.
|
|
2676
|
-
- In a monorepo, **a single root `pnpm-lock.yaml`** is the source of truth;
|
|
2677
|
-
per-package lockfiles are an anti-pattern.
|
|
2678
|
-
|
|
2679
|
-
### Enforcement: provenance and signatures
|
|
2680
|
-
|
|
2681
|
-
- Prefer dependencies that publish with [npm provenance attestations](https://docs.npmjs.com/generating-provenance-statements).
|
|
2682
|
-
Major projects (TypeScript, Vitest, Prettier, ESLint, etc.) ship these.
|
|
2683
|
-
- Run `pnpm audit signatures` in CI on a periodic basis to catch tampered
|
|
2684
|
-
packages.
|
|
2685
|
-
|
|
2686
|
-
### Sample CI gate
|
|
2687
|
-
|
|
2688
|
-
Add this job to the CI workflow alongside lint/test:
|
|
2689
|
-
|
|
2690
|
-
```yaml
|
|
2691
|
-
audit:
|
|
2692
|
-
runs-on: ubuntu-latest
|
|
2693
|
-
steps:
|
|
2694
|
-
- uses: actions/checkout@v6
|
|
2695
|
-
- uses: pnpm/action-setup@v6
|
|
2696
|
-
with:
|
|
2697
|
-
run_install: false
|
|
2698
|
-
- uses: actions/setup-node@v6
|
|
2699
|
-
with:
|
|
2700
|
-
node-version: 24
|
|
2701
|
-
cache: pnpm
|
|
2702
|
-
- run: pnpm install --frozen-lockfile
|
|
2703
|
-
- name: Vulnerability audit
|
|
2704
|
-
run: pnpm audit --audit-level=moderate
|
|
2705
|
-
- name: Signature audit
|
|
2706
|
-
run: pnpm audit signatures
|
|
2707
|
-
- name: Package-age check
|
|
2708
|
-
run: pnpm dlx npm-check-updates --cooldown 14 --errorLevel 0
|
|
2709
|
-
# errorLevel 0 logs but doesn't fail — flip to 2 once you've cleared
|
|
2710
|
-
# the existing backlog.
|
|
2711
|
-
```
|
|
2712
|
-
|
|
2713
|
-
### Recommended local script
|
|
2714
|
-
|
|
2715
|
-
Drop a `scripts/check-package-age.mjs` one-liner in the repo that a pre-push
|
|
2716
|
-
hook can call:
|
|
2717
|
-
|
|
2718
|
-
```ts
|
|
2719
|
-
#!/usr/bin/env tsx
|
|
2720
|
-
// Refuses to commit if any direct dependency in package.json was published
|
|
2721
|
-
// less than COOLDOWN_DAYS ago. Intended for the pre-push hook.
|
|
2722
|
-
import pkg from '../package.json' with { type: 'json' };
|
|
2723
|
-
|
|
2724
|
-
const COOLDOWN_MS = 14 * 24 * 60 * 60 * 1000;
|
|
2725
|
-
const now = Date.now();
|
|
2726
|
-
const all = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2727
|
-
|
|
2728
|
-
let violations = 0;
|
|
2729
|
-
for (const [name, spec] of Object.entries(all)) {
|
|
2730
|
-
const version = String(spec).replace(/^[\^~=<>]+/, '');
|
|
2731
|
-
const meta = await (await fetch(`https://registry.npmjs.org/${name}`)).json();
|
|
2732
|
-
const publishedAt = meta.time?.[version];
|
|
2733
|
-
if (!publishedAt) continue;
|
|
2734
|
-
const ageMs = now - new Date(publishedAt).getTime();
|
|
2735
|
-
if (ageMs < COOLDOWN_MS) {
|
|
2736
|
-
const days = (ageMs / 86_400_000).toFixed(1);
|
|
2737
|
-
console.error(`✗ ${name}@${version} is only ${days} days old (< 14)`);
|
|
2738
|
-
violations++;
|
|
2739
|
-
}
|
|
2740
|
-
}
|
|
2741
|
-
process.exit(violations > 0 ? 1 : 0);
|
|
2742
|
-
```
|
|
2743
|
-
|
|
2744
|
-
Wire it into lefthook:
|
|
2745
|
-
|
|
2746
|
-
```yaml
|
|
2747
|
-
pre-push:
|
|
2748
|
-
commands:
|
|
2749
|
-
package-age:
|
|
2750
|
-
glob: "package.json"
|
|
2751
|
-
run: pnpm tsx scripts/check-package-age.ts
|
|
2752
|
-
```
|
|
2753
|
-
|
|
2754
|
-
### Exception bookkeeping
|
|
2755
|
-
|
|
2756
|
-
When you take an exception, leave a one-line marker in `package.json` adjacent
|
|
2757
|
-
to the pin:
|
|
2758
|
-
|
|
2759
|
-
```jsonc
|
|
2760
|
-
{
|
|
2761
|
-
"devDependencies": {
|
|
2762
|
-
// Exception: CVE-2026-XXXX patch within 14d window. Reviewed 2026-05-21.
|
|
2763
|
-
"vitest": "4.1.7"
|
|
2764
|
-
}
|
|
2765
|
-
}
|
|
2766
|
-
```
|
|
2767
|
-
|
|
2768
|
-
(JSON strict-parsers will reject `//` comments — use a JSONC-aware tool or
|
|
2769
|
-
move the note to a `README.md` / `CHANGELOG.md` entry instead.)
|
|
2548
|
+
**pnpm specifics**: set `minimumReleaseAge: 20160` (14 days) in `pnpm-workspace.yaml`
|
|
2549
|
+
(pnpm 11 defaults to 1 day), declare lifecycle-eligible packages via `allowBuilds`, keep
|
|
2550
|
+
`blockExoticSubdeps` on, and run `pnpm audit` + `pnpm audit signatures` in CI with
|
|
2551
|
+
`pnpm install --frozen-lockfile`.
|
|
2770
2552
|
|
|
2771
2553
|
* * *
|
|
2772
2554
|
|
|
@@ -2805,87 +2587,87 @@ move the note to a `README.md` / `CHANGELOG.md` entry instead.)
|
|
|
2805
2587
|
## Best Practices
|
|
2806
2588
|
|
|
2807
2589
|
1. **Follow the 14-day package-age rule** for every dependency install and upgrade.
|
|
2808
|
-
See [Supply-Chain Mitigation](#supply-chain-mitigation).
|
|
2809
|
-
`minimumReleaseAge: 20160` (14 days in minutes) in pnpm config; use
|
|
2810
|
-
`ncu --cooldown 14`; declare lifecycle-script-eligible packages via
|
|
2811
|
-
|
|
2812
|
-
`pnpm
|
|
2590
|
+
See [Supply-Chain Mitigation](#supply-chain-mitigation).
|
|
2591
|
+
Set `minimumReleaseAge: 20160` (14 days in minutes) in pnpm config; use
|
|
2592
|
+
`ncu --cooldown 14`; declare lifecycle-script-eligible packages via `allowBuilds`;
|
|
2593
|
+
run `pnpm audit` and `pnpm audit signatures` in CI; commit `pnpm-lock.yaml` and use
|
|
2594
|
+
`pnpm install --frozen-lockfile` in CI.
|
|
2813
2595
|
|
|
2814
2596
|
2. **Scope your package names**: Use `@org/package-name` format for easier GitHub
|
|
2815
2597
|
Packages integration and namespace clarity.
|
|
2816
2598
|
|
|
2817
|
-
|
|
2599
|
+
3. **Structure for splitting**: Organize internal code (`core/`, `cli/`, `adapters/`) to
|
|
2818
2600
|
make future package splits painless.
|
|
2819
2601
|
|
|
2820
|
-
|
|
2602
|
+
4. **Use subpath exports from day one**: Define `./cli`, `./adapter` exports even in
|
|
2821
2603
|
v0.1 to stabilize the API surface.
|
|
2822
2604
|
|
|
2823
|
-
|
|
2605
|
+
5. **Types first in exports**: Always put `"types"` condition before `"default"` in
|
|
2824
2606
|
export conditions.
|
|
2825
2607
|
|
|
2826
|
-
|
|
2608
|
+
6. **Optional peer deps for integrations**: Don’t force SDK dependencies on users who
|
|
2827
2609
|
don’t need them.
|
|
2828
2610
|
|
|
2829
|
-
|
|
2611
|
+
7. **Validate before publish**: Run publint in CI and before every release.
|
|
2830
2612
|
|
|
2831
|
-
|
|
2613
|
+
8. **Changeset per PR**: Require changesets for user-facing changes to maintain accurate
|
|
2832
2614
|
changelogs.
|
|
2833
2615
|
|
|
2834
|
-
|
|
2616
|
+
9. **Lock your tooling versions**: Pin exact versions in `packageManager` field and CI
|
|
2835
2617
|
configurations.
|
|
2836
2618
|
|
|
2837
|
-
|
|
2838
|
-
|
|
2619
|
+
10. **Test both ESM and CJS**: Ensure both module formats work correctly, especially for
|
|
2620
|
+
CLI tools.
|
|
2839
2621
|
|
|
2840
|
-
|
|
2622
|
+
11. **Keep the monorepo root private**: The root `package.json` should have
|
|
2841
2623
|
`"private": true` and only contain workspace tooling.
|
|
2842
2624
|
|
|
2843
|
-
|
|
2625
|
+
12. **Use type-aware ESLint**: Configure `recommendedTypeChecked` for comprehensive bug
|
|
2844
2626
|
detection, especially promise safety rules.
|
|
2845
2627
|
See Appendix C for detailed configuration.
|
|
2846
2628
|
|
|
2847
|
-
|
|
2629
|
+
13. **Enforce code style consistency**: Use `curly: 'all'` and `brace-style: '1tbs'` to
|
|
2848
2630
|
prevent subtle bugs and improve readability.
|
|
2849
2631
|
|
|
2850
|
-
|
|
2632
|
+
14. **Use fast pre-commit hooks**: Run formatting and linting with auto-fix on staged
|
|
2851
2633
|
files only. Target 2-5 seconds total.
|
|
2852
2634
|
Use lefthook for better monorepo support.
|
|
2853
2635
|
|
|
2854
|
-
|
|
2636
|
+
15. **Cache test results by commit hash**: In pre-push hooks, skip test runs if the
|
|
2855
2637
|
current commit has already passed tests.
|
|
2856
2638
|
This makes repeated pushes instant.
|
|
2857
2639
|
|
|
2858
|
-
|
|
2640
|
+
16. **Use structured upgrade scripts**: Add `upgrade:check`, `upgrade`, and
|
|
2859
2641
|
`upgrade:major` scripts to make dependency updates consistent and safe.
|
|
2860
2642
|
Separate minor/patch from major upgrades.
|
|
2861
2643
|
|
|
2862
|
-
|
|
2644
|
+
17. **Separate format and lint script variants**: Provide `format`/`format:check` and
|
|
2863
2645
|
`lint`/`lint:check` scripts.
|
|
2864
2646
|
Use `--fix` variants for local development and `--check`/zero-warnings variants for
|
|
2865
2647
|
CI.
|
|
2866
2648
|
|
|
2867
|
-
|
|
2649
|
+
18. **Run format before lint in builds**: The `build` script should run `format` then
|
|
2868
2650
|
`lint:check` to ensure formatting is applied before linting.
|
|
2869
2651
|
|
|
2870
|
-
|
|
2652
|
+
19. **Use dynamic git-based versioning**: Inject version at build time using
|
|
2871
2653
|
`X.Y.Z-dev.N.hash` format.
|
|
2872
2654
|
This provides traceability during development without manual version bumps.
|
|
2873
2655
|
See “Dynamic Git-Based Versioning” section for implementation.
|
|
2874
2656
|
|
|
2875
|
-
|
|
2657
|
+
20. **Run CLI from source during development**: Use the dual-script pattern with tsx to
|
|
2876
2658
|
run CLI commands directly from TypeScript source.
|
|
2877
2659
|
Provide a separate `:bin` script for verifying the built output.
|
|
2878
2660
|
This eliminates “did I forget to build?”
|
|
2879
2661
|
confusion.
|
|
2880
2662
|
|
|
2881
|
-
|
|
2663
|
+
21. **Use CJS bootstrap for CLI startup**: Enable Node.js compile cache via a CJS
|
|
2882
2664
|
bootstrap file that runs before ESM module loading.
|
|
2883
2665
|
This significantly improves repeated CLI invocation times on Node.js 22.8+.
|
|
2884
2666
|
|
|
2885
|
-
|
|
2667
|
+
22. **Bundle CLI dependencies**: Use tsdown’s `noExternal` to bundle runtime deps into
|
|
2886
2668
|
the CLI binary for faster startup (no `node_modules` resolution at runtime).
|
|
2887
2669
|
|
|
2888
|
-
|
|
2670
|
+
23. **Add guard tests for node-free core**: If your library entry point should be
|
|
2889
2671
|
node-free, add automated tests that verify no `node:` imports leak into the public
|
|
2890
2672
|
API surface.
|
|
2891
2673
|
|
|
@@ -2898,51 +2680,52 @@ move the note to a `README.md` / `CHANGELOG.md` entry instead.)
|
|
|
2898
2680
|
Monitor for announcements that may affect best practices.
|
|
2899
2681
|
|
|
2900
2682
|
2. ~~**TypeScript 6.0**~~: **SHIPPED** 2026-03-23 (currently 6.0.3). The last
|
|
2901
|
-
JavaScript-based release.
|
|
2902
|
-
default module system, and ~9 compiler
|
|
2903
|
-
|
|
2683
|
+
JavaScript-based release.
|
|
2684
|
+
`strict: true` is now the default, ESM is the default module system, and ~9 compiler
|
|
2685
|
+
settings flipped defaults.
|
|
2686
|
+
Adopt for the codebase; review `tsconfig.base.json` for now-redundant flag
|
|
2687
|
+
declarations.
|
|
2904
2688
|
|
|
2905
2689
|
3. **TypeScript 7.0 (Project Corsa, Go rewrite)**: Beta shipped 2026-04-21 as
|
|
2906
|
-
`@typescript/native-preview` (binary `tsgo`). Claims ~10× type-check speed
|
|
2907
|
-
|
|
2908
|
-
Visual Studio 2026 18.6 Insiders by default.
|
|
2909
|
-
builds yet** — wait for stable (expected mid-to-late
|
|
2910
|
-
tsdown/Vitest compatibility announcements.
|
|
2690
|
+
`@typescript/native-preview` (binary `tsgo`). Claims ~10× type-check speed and ~3×
|
|
2691
|
+
less memory; passes 95%+ of the test suite.
|
|
2692
|
+
Available in Visual Studio 2026 18.6 Insiders by default.
|
|
2693
|
+
**Do not adopt for production builds yet** — wait for stable (expected mid-to-late
|
|
2694
|
+
2026). Monitor for tsdown/Vitest compatibility announcements.
|
|
2911
2695
|
|
|
2912
2696
|
4. **Native TypeScript Execution**: TypeScript 5.8+ supports `--erasableSyntaxOnly`,
|
|
2913
|
-
enabling direct execution in Node.js 23.6+ without transpilation.
|
|
2914
|
-
TypeScript 6.0 stable and Node 24 LTS, this is increasingly viable for
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
5. ~~**ESLint v10**~~: **SHIPPED** 2026-02-06. `.eslintrc.*` configuration is
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
6. ~~**pnpm 11**~~: **SHIPPED** 2026-04-28 (currently 11.2.2). Breaking changes:
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
validation. Migration from Zod 3 required — see
|
|
2697
|
+
enabling direct execution in Node.js 23.6+ without transpilation.
|
|
2698
|
+
With TypeScript 6.0 stable and Node 24 LTS, this is increasingly viable for scripts.
|
|
2699
|
+
Monitor for broader tooling adoption (linters, coverage tools).
|
|
2700
|
+
|
|
2701
|
+
5. ~~**ESLint v10**~~: **SHIPPED** 2026-02-06. `.eslintrc.*` configuration is completely
|
|
2702
|
+
removed — flat config (`eslint.config.js`) is the only supported format.
|
|
2703
|
+
Download size reduced 11 MB → 9.4 MB. Minimum Node.js v20.19.0. ESLint 9.x EOL is
|
|
2704
|
+
2026-08-06 — migrate now.
|
|
2705
|
+
|
|
2706
|
+
6. ~~**pnpm 11**~~: **SHIPPED** 2026-04-28 (currently 11.2.2). Breaking changes: pure
|
|
2707
|
+
ESM (requires Node 22+), SQLite-based store, `minimumReleaseAge` default (1 day),
|
|
2708
|
+
`blockExoticSubdeps` default `true`, `allowBuilds` replacing `onlyBuiltDependencies`.
|
|
2709
|
+
Experimental Rust-based `@pnpm/pacquet` engine in 11.2+. Migrate via the pnpm 11
|
|
2710
|
+
migration guide; bump `pnpm/action-setup` to v6 in CI.
|
|
2711
|
+
|
|
2712
|
+
7. ~~**Zod 4**~~: **SHIPPED** (currently 4.4.3). 14× faster string parsing, 7× faster
|
|
2713
|
+
array parsing, 6.5× faster object parsing vs Zod 3; core bundle 2.3× smaller; new
|
|
2714
|
+
`@zod/mini` (~1.9 KB gzipped) for tree-shakable frontend validation.
|
|
2715
|
+
Migration from Zod 3 required — see
|
|
2933
2716
|
[zod.dev/v4/changelog](https://zod.dev/v4/changelog).
|
|
2934
2717
|
|
|
2935
|
-
8. **Commander 15 (ESM-only)**: Commander 15 ships May 2026, requires
|
|
2936
|
-
|
|
2937
|
-
|
|
2718
|
+
8. **Commander 15 (ESM-only)**: Commander 15 ships May 2026, requires Node v22.12.0+,
|
|
2719
|
+
drops CJS. Commander 14 moves to maintenance (security only) until May 2027. Upgrade
|
|
2720
|
+
path for CLI tools using Commander.
|
|
2938
2721
|
|
|
2939
|
-
9. **`dotenv` vs Node `--env-file`**: Node 20.6+ has built-in `--env-file`
|
|
2940
|
-
|
|
2941
|
-
should default to `--env-file` and reserve `dotenv` for advanced
|
|
2942
|
-
(variable expansion, multiline values, custom precedence logic).
|
|
2722
|
+
9. **`dotenv` vs Node `--env-file`**: Node 20.6+ has built-in `--env-file` support, and
|
|
2723
|
+
with Node 24 LTS it is production-ready.
|
|
2724
|
+
Most new projects should default to `--env-file` and reserve `dotenv` for advanced
|
|
2725
|
+
needs (variable expansion, multiline values, custom precedence logic).
|
|
2943
2726
|
|
|
2944
|
-
10. **Vitest 5**: 5.0.0-beta.3 in pre-release; requires Node 22+ and
|
|
2945
|
-
|
|
2727
|
+
10. **Vitest 5**: 5.0.0-beta.3 in pre-release; requires Node 22+ and Vite 6.4+. Stable
|
|
2728
|
+
not yet shipped. Stay on 4.1.x for now.
|
|
2946
2729
|
|
|
2947
2730
|
* * *
|
|
2948
2731
|
|
|
@@ -3170,8 +2953,8 @@ ready for public release.
|
|
|
3170
2953
|
```
|
|
3171
2954
|
|
|
3172
2955
|
All pinned versions above are ≥14 days old as of 2026-05-21 per the
|
|
3173
|
-
[Supply-Chain Mitigation](#supply-chain-mitigation) policy.
|
|
3174
|
-
(`pnpm` 11.2.2, `lefthook` 2.1.8, `npm-check-updates` 22.2.0,
|
|
2956
|
+
[Supply-Chain Mitigation](#supply-chain-mitigation) policy.
|
|
2957
|
+
Newer releases exist (`pnpm` 11.2.2, `lefthook` 2.1.8, `npm-check-updates` 22.2.0,
|
|
3175
2958
|
`publint` 0.3.21, `vitest` 4.1.7) but were too fresh at this document update.
|
|
3176
2959
|
Bump on the next refresh once the 14-day window has elapsed.
|
|
3177
2960
|
|