@geenius/release-toolkit 0.10.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/CHANGELOG.md +335 -0
- package/LICENSE +88 -0
- package/README.md +104 -0
- package/bin/geenius-release.js +5 -0
- package/dist/cli.js +6226 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +1401 -0
- package/dist/index.js +5256 -0
- package/dist/index.js.map +1 -0
- package/package.json +88 -0
- package/templates/husky/pre-push +11 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@geenius/release-toolkit` are documented in this file.
|
|
4
|
+
The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
|
|
5
|
+
versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.9.2] — 2026-05-18
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Hide optional `@playwright/test` dynamic import from consumer-side static
|
|
12
|
+
analyzers.** When a consuming package's vitest config imported anything
|
|
13
|
+
from `@geenius/release-toolkit` (e.g. `packageVariants`), vite's
|
|
14
|
+
`import-analysis` plugin tried to resolve `@playwright/test` through the
|
|
15
|
+
toolkit's dist and failed with "Failed to resolve import @playwright/test"
|
|
16
|
+
even when the consumer hadn't asked to use the storybook static-smoke
|
|
17
|
+
command at all. The dynamic import now uses a variable specifier
|
|
18
|
+
(`const s = "@playwright/test"; await import(s)`) — semantically
|
|
19
|
+
identical, but invisible to static analyzers.
|
|
20
|
+
|
|
21
|
+
## [0.9.1] — 2026-05-18
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **`lint` now accepts positional passthrough args.** Previously `geenius-release
|
|
26
|
+
lint -- --error-on-warnings` rejected with "too many arguments". The command
|
|
27
|
+
now declares `[passthrough...]` and forwards everything after the options
|
|
28
|
+
(and after a literal `--`) to biome. Unblocks geenie / config migrations
|
|
29
|
+
that want to enforce `--error-on-warnings` in their gauntlets.
|
|
30
|
+
|
|
31
|
+
## [0.9.0] — 2026-05-18
|
|
32
|
+
|
|
33
|
+
### Added — smoke-packed UI/workspace-dep enhancements
|
|
34
|
+
|
|
35
|
+
Surfaced from auditing the 34 packages each carrying their own
|
|
36
|
+
~80-400 LOC `scripts/smoke-packed-imports.mjs` variants. The toolkit's
|
|
37
|
+
existing `smoke-packed` already handled pack → install → import; the
|
|
38
|
+
per-package divergence was all in extra checks and UI runtime mocks.
|
|
39
|
+
Six additive features absorb that divergence:
|
|
40
|
+
|
|
41
|
+
- **`--check-exports-on-disk`** — extract tarball + verify every declared
|
|
42
|
+
`exports[*].{types,import,default}` target file exists.
|
|
43
|
+
- **`--check-tarball-purity <regex>`** — every tar entry must match the
|
|
44
|
+
pattern; reports unexpected files (catches accidental dev-asset leaks).
|
|
45
|
+
- **`--check-stylesheets`** — file-exists verification for `.css` export
|
|
46
|
+
targets (no import; matters for CSS-only subpaths).
|
|
47
|
+
- **`--browser-conditions`** — pass `--conditions=browser` to the import
|
|
48
|
+
probe so browser/server condition splits resolve the browser branch.
|
|
49
|
+
- **`--dom-stubs`** — prepend DOM stubs (window, document, matchMedia,
|
|
50
|
+
HTMLElement, …) to the probe so UI imports with module-evaluation-time
|
|
51
|
+
DOM access don't crash.
|
|
52
|
+
- **`--inject-deps <list>`** — comma-separated workspace package names to
|
|
53
|
+
symlink into the consumer's `node_modules` before the probe runs. Each
|
|
54
|
+
name resolves against the sibling packages root via the
|
|
55
|
+
`@geenius/<x>` → `<siblingsRoot>/geenius-<x>` convention. Use for
|
|
56
|
+
`link:` workspace deps that can't be satisfied from a registry.
|
|
57
|
+
|
|
58
|
+
All six are also available as `release-toolkit.config.json#smokePacked`
|
|
59
|
+
fields (`checkExportsOnDisk`, `checkTarballPurity`, `checkStylesheets`,
|
|
60
|
+
`browserConditions`, `domStubs`, `injectDeps`); CLI flags take precedence
|
|
61
|
+
per-field.
|
|
62
|
+
|
|
63
|
+
Distinct from `pack-contract` (which delegates assertions to a vitest
|
|
64
|
+
config) — these flags are the convention-over-configuration path for the
|
|
65
|
+
common UI smoke-test shape.
|
|
66
|
+
|
|
67
|
+
## [0.8.0] — 2026-05-17
|
|
68
|
+
|
|
69
|
+
### Performance (major)
|
|
70
|
+
|
|
71
|
+
- **`pnpm-filters` no longer shells out to pnpm.** The previous implementation
|
|
72
|
+
invoked `pnpm -r --filter ./pkg run <task>` per fan-out, paying a
|
|
73
|
+
~100-300ms pnpm bootstrap per package. The new implementation reads each
|
|
74
|
+
variant's `package.json`, looks up `scripts.<task>`, and spawns it
|
|
75
|
+
directly via `/bin/sh -c <cmd>` in the variant's cwd with PATH augmented
|
|
76
|
+
to include every ancestor `node_modules/.bin`. Result:
|
|
77
|
+
- 16 variants × parallel mode goes from ~3-4s of pure pnpm overhead to
|
|
78
|
+
~50ms of orchestration overhead
|
|
79
|
+
- parallel mode no longer requires pnpm to be installed at all
|
|
80
|
+
- all `package.json` script semantics (shell pipes, &&, env subst)
|
|
81
|
+
are preserved because the command body is handed to sh untouched
|
|
82
|
+
|
|
83
|
+
- **`publint`, `mutation-report`, `supply-chain` (socket probe) now spawn
|
|
84
|
+
their target binaries directly** instead of `pnpm exec`. Same direct-spawn
|
|
85
|
+
pattern as 0.7.2 lint/coverage/e2e/convex-build. publint and mutation-report
|
|
86
|
+
retain `pnpm dlx` fallbacks for explicit opt-in (`--dlx <spec>`).
|
|
87
|
+
|
|
88
|
+
### Internal
|
|
89
|
+
|
|
90
|
+
- `PnpmFiltersResult.argv` field renamed to `invocations: {label, cwd, command}[]`.
|
|
91
|
+
CLI consumers (`cli.ts`) only read `status`, which is unchanged. Library
|
|
92
|
+
consumers parsing the report shape are affected — hence the minor bump.
|
|
93
|
+
|
|
94
|
+
### Benchmarks (against geenius-logger, 4 implemented variants)
|
|
95
|
+
|
|
96
|
+
pnpm build (sequential, --workspace-concurrency=1):
|
|
97
|
+
0.7.2 → ~12s (~3s pnpm bootstrap + ~9s real build)
|
|
98
|
+
0.8.0 → ~8.8s (~0s pnpm bootstrap + ~8.8s real build)
|
|
99
|
+
|
|
100
|
+
pnpm clean (parallel):
|
|
101
|
+
0.7.2 → ~1.5s (pnpm bootstrap + rm -rf dist × 3)
|
|
102
|
+
0.8.0 → ~0.8s (sh -c rm -rf dist × 3)
|
|
103
|
+
|
|
104
|
+
Under heavy concurrent agent workloads (10-20× parallel), the savings
|
|
105
|
+
compound — pnpm bootstrap was previously the dominant cost.
|
|
106
|
+
|
|
107
|
+
## [0.7.2] — 2026-05-17
|
|
108
|
+
|
|
109
|
+
### Performance
|
|
110
|
+
|
|
111
|
+
- **`lint`, `coverage`, `e2e`, `convex-build` now spawn local binaries
|
|
112
|
+
directly** instead of routing through `pnpm exec`. Saves the
|
|
113
|
+
~100-300ms pnpm bootstrap per spawn — critical when 10-20 agents
|
|
114
|
+
invoke a `geenius-release` subcommand concurrently. New helper
|
|
115
|
+
`src/lib/resolve-bin.ts` walks ancestor `node_modules/.bin` (cached
|
|
116
|
+
per-process); env-PATH augmentation lets child processes find sibling
|
|
117
|
+
bins (tsup → esbuild, vitest → workers) without further hops.
|
|
118
|
+
|
|
119
|
+
### Changed
|
|
120
|
+
|
|
121
|
+
- Removed all in-tree references to `@geenius-agents`. The release
|
|
122
|
+
toolkit ships as a self-contained CLI/library; downstream report
|
|
123
|
+
consumers (CI integrations, dashboards) are not named in source or
|
|
124
|
+
docs.
|
|
125
|
+
|
|
126
|
+
## [0.7.1] — 2026-05-17
|
|
127
|
+
|
|
128
|
+
### Added
|
|
129
|
+
|
|
130
|
+
- **`bundle-budgets`** — gzip-check `<packageDir>/dist/{index.js,index.css}` against
|
|
131
|
+
each variant's `bundleBudget` declared in `variants.json`. Replaces
|
|
132
|
+
`scripts/check-bundle-budgets.mjs` (surfaced from geenius-perf). 8 packages
|
|
133
|
+
declare `bundleBudget` (perf, agent, ai-magic, devtools, errors, onboarding,
|
|
134
|
+
ui, tools-legacy); this command absorbs the pattern for all of them.
|
|
135
|
+
Flags: `--assets`, `--include-unimplemented`, `--optional`.
|
|
136
|
+
|
|
137
|
+
## [0.7.0] — 2026-05-17
|
|
138
|
+
|
|
139
|
+
### Added
|
|
140
|
+
|
|
141
|
+
Nine new commands that absorb every standalone `scripts/*.mjs` used in 3 or more
|
|
142
|
+
geenius packages. Designed to clear the per-package script tail so package
|
|
143
|
+
`scripts/` directories can hold only genuinely package-unique logic. See
|
|
144
|
+
`standardization-plan.md` for the full migration map.
|
|
145
|
+
|
|
146
|
+
- **`lint`** — canonical biome runner. Collapses `run-lint.mjs` (9 pkgs),
|
|
147
|
+
`lint-apps.mjs` (4), `lint-scope.mjs` (3), `biome-scope.mjs` (5). Flags:
|
|
148
|
+
`--scope <package|apps|all>`, `--apps`, `--command`, `--fix`, `--print`.
|
|
149
|
+
|
|
150
|
+
- **`coverage`** — canonical `vitest run --coverage` runner. Collapses
|
|
151
|
+
`run-coverage.mjs` (5). Cleans coverage dirs, runs root pass excluding
|
|
152
|
+
separate-coverage packages, then runs per-package passes. Flags:
|
|
153
|
+
`--separate-frameworks`, `--separate-package-dirs`, `--no-clean`, `--strict`.
|
|
154
|
+
|
|
155
|
+
- **`e2e`** — Playwright runner with ephemeral port reservation and
|
|
156
|
+
variant-derived `--project` filters. Collapses `e2e-runner.mjs` (5) and
|
|
157
|
+
`playwright-projects.mjs` (2). Flags: `--projects`, `--all-browsers`,
|
|
158
|
+
`--browser`, `--env-prefix`, `--print`.
|
|
159
|
+
|
|
160
|
+
- **`vitest-browser-prepare`** — exports `vitestBrowserPrepareRetry()` for
|
|
161
|
+
vitest configs; the CLI prints the injected script. Collapses
|
|
162
|
+
`vitest-browser-prepare-retry.ts` (4 pkgs).
|
|
163
|
+
|
|
164
|
+
- **`patch-dts`** — post-build dist patcher. Collapses `patch-dts-imports.mjs`
|
|
165
|
+
(4), `patch-solid-web-import.mjs` (2). Flags: `--rewrite <from=to>`
|
|
166
|
+
(repeatable, .d.ts only), `--solid`, `--solid-jsx`, `--dir`, `--files`.
|
|
167
|
+
|
|
168
|
+
- **`db-migrations`** — runs migration tests for every `db-provider` variant
|
|
169
|
+
with `tests.migrations: true`. Collapses `db-migrations-check.mjs` (4).
|
|
170
|
+
|
|
171
|
+
- **`sanitize-dist`** — strips tsup source-path comments, sourcemap URLs, and
|
|
172
|
+
optionally the Solid JSX runtime import from `dist/`. Collapses
|
|
173
|
+
`sanitize-dist-comments.mjs` (3) and `sanitize-dist.mjs` (2). Flags:
|
|
174
|
+
`--no-comments`, `--maps`, `--fix-solid-jsx-runtime`, `--dir`.
|
|
175
|
+
|
|
176
|
+
- **`convex-codegen`** — generates `_generated/{server,api,dataModel}` shims
|
|
177
|
+
for Convex variants. Promotes the bin previously shipped from
|
|
178
|
+
`geenius-db`'s convex sub-package. Flags: `--src`, `--check`, `--clean`.
|
|
179
|
+
|
|
180
|
+
- **`convex-build`** — Convex sub-package build = `convex-codegen` + `tsup`.
|
|
181
|
+
One implementation for the 16 packages carrying `convex.config.ts`. Flags:
|
|
182
|
+
`--src`, `--no-codegen`, `--no-build`, `--clean`, `--builder <tsup|tsc>`.
|
|
183
|
+
|
|
184
|
+
## [0.6.1] — 2026-05-17
|
|
185
|
+
|
|
186
|
+
### Fixed
|
|
187
|
+
|
|
188
|
+
- **`pnpm-filters` CLI now exposes `--requires` and `--mode`**. The 0.6.0 release wired both options into the `runPnpmFilters` library API but forgot to register them on the CLI definition, so `geenius-release pnpm-filters … --mode shared-then-parallel` rejected the flag. Both flags now work as documented.
|
|
189
|
+
- **`storybook --runner test-runner` no longer passes the invalid `--static-dir` flag** to `@storybook/test-runner`. The toolkit now spins up an ephemeral static file server on a free port, points the runner at it via `--url http://127.0.0.1:<port>`, and tears the server down after the run completes.
|
|
190
|
+
|
|
191
|
+
## [0.6.0] — 2026-05-17
|
|
192
|
+
|
|
193
|
+
### Added
|
|
194
|
+
|
|
195
|
+
- **`variants check`** subcommand — verifies every required variant has an on-disk `packageDir`. With `--require-all`, every variant is required regardless of `required:false`. Replaces ad-hoc `variants-check.mjs` shims.
|
|
196
|
+
- **`pnpm-filters --requires <names>`** — verify a comma-separated list of binaries is on PATH before fanning out. Fails fast with a clear error instead of a confusing per-variant spawn failure.
|
|
197
|
+
- **`pnpm-filters --mode shared-then-parallel`** — run a single shared package first (e.g. `packages/shared`) and then fan the rest out in parallel. Replaces hand-written shared-first wrappers that called pnpm twice.
|
|
198
|
+
- **`mutation-report --check-config-only`** — validate Stryker config without running mutations. For CI gates that want to ensure config drift is caught early.
|
|
199
|
+
- **`mutation-report --dlx <spec>`** — fall back to `pnpm dlx <spec>` when Stryker isn't installed locally. Lets packages opt into mutation testing without committing the dependency.
|
|
200
|
+
- **`mutation-report --markdown <path> --json <path> --report-json <path>`** — emit derived reports alongside the raw Stryker output, with fallback score computation when Stryker's summary fails.
|
|
201
|
+
- **`attw --safe-pack-dir <path>`** — reuse a stable dir (relative to `packageRoot`) instead of mkdtemp for the tarball. Useful when CI caches need a deterministic path.
|
|
202
|
+
- **`diff-coverage --min-ci <pct>` and `--min-local <pct>`** — CI-conditional thresholds. Common pattern: 0 locally, strict in CI, so contributors aren't blocked but coverage regressions still fail the pipeline.
|
|
203
|
+
- **`storybook --runner test-runner|vitest|static-smoke`** — pick between `@storybook/test-runner`, Vitest browser-mode runner, or the original Playwright static smoke. Replaces 3 categories of per-package storybook smoke scripts.
|
|
204
|
+
- **`rewrite-imports --preset solid-web`** — built-in preset that rewrites `solid-js/web` to `solid-js/web/dist/web.js` so Node ESM consumers can resolve it without subpath redirects. Replaces per-Solid-package rewrite shims.
|
|
205
|
+
|
|
206
|
+
### Changed
|
|
207
|
+
|
|
208
|
+
- **`variants-rich`** now understands `packagePath` as a fallback for `packageDir`, plus top-level `workspacePackages` arrays. Lets packages that follow either convention (admin's bare-name `react`, or ai-workflow's separate `workspacePackages`) consume the toolkit without rewriting their `variants.json`.
|
|
209
|
+
|
|
210
|
+
## [0.5.0] — 2026-05-17
|
|
211
|
+
|
|
212
|
+
### Added
|
|
213
|
+
|
|
214
|
+
- **`run-scripts <s1> <s2> …`** + `runScripts` API — run multiple top-level `package.json` scripts sequentially in the package root, with PATH augmented to `node_modules/.bin` and `npm_package_*` env vars set. Stops on first failure (or `--continue-on-failure`). Replaces local `_run-root-scripts.mjs` shims used to chain build/test/exports/dist-contract.
|
|
215
|
+
- **`type-check`** + `runTypeCheck` API — per-variant runner with a `type-check → lint → tsc --noEmit` fallback chain. Augments PATH with the variant's and root's `node_modules/.bin`. Honors `--shared-first`, `--continue-on-failure`, `--exclude-out-of-scope`. Replaces `scripts/type-check-packages.mjs`.
|
|
216
|
+
- **`size-limit-config`** + `runSizeLimitConfig` API — emit size-limit entries to stdout, derived from `variants.json` `budget.gzip` and the root manifest's `exports` map. Enforces that every exported package has a `budget.gzip`. Replaces ~5 copies of per-package `size-limit-config.mjs`.
|
|
217
|
+
- **`pack-contract`** + `runPackContract` API — generic harness: `pnpm pack --json` into a tmp dir, expose path via `PACK_CONTRACT_JSON` env, run a consumer-supplied `vitest --config <path>`. Replaces local `pack-contract.mjs` shims.
|
|
218
|
+
|
|
219
|
+
### Changed
|
|
220
|
+
|
|
221
|
+
- **`pnpm-filters` gains sequential mode**. New flags: `--sequential`, `--shared-first <packageDir>`, `--heartbeat-ms <ms>`, `--kind-order <tiers>` (pipe-separated tiers, comma-separated kinds). Sequential mode walks variants one at a time, runs `packages/shared` first when requested, skips packages that don't declare the script, emits a heartbeat line every N ms so CI doesn't kill a quiet job. The default parallel mode is unchanged. Replaces 43 copies of `_pnpm-filters.mjs` and the package-specific shared-first variants in adapters/admin/agent/ai.
|
|
222
|
+
- **`runPnpmFilters` is now `async`**. The signature returns `Promise<PnpmFiltersResult>` because the sequential path uses `spawn` to run the heartbeat alongside the child process. Parallel callers must `await` the result (no behavior change otherwise). The CLI was already async, so no user-facing change.
|
|
223
|
+
- **`coverage-report` accepts per-subpackage thresholds**. New flags: `--threshold-file <path>`, `--output <path>` (Markdown), `--json <path>` (structured), `--fail-on-gaps`. The threshold file shape is `{ subpackages: { <name>: { thresholds: { lines, statements, branches, functions }, required?, kind? } } }`. The toolkit walks per-subpackage `coverage-summary.json` files under `packages/<name>/coverage/`, computes pass/fail per metric, and writes Markdown + JSON reports. Replaces the 36-script category for packages whose call sites use these flags.
|
|
224
|
+
- **`storybook` gains variant-driven discovery + shape check**. New flags: `--from-variants` (read app list from `variants.json` instead of auto-globbing `apps/storybook-*`), `--variants-scope <all|published>`, `--check-shape <jsonOrPath>` (asserts `requiredFiles`/`forbiddenFiles`/`requiredTitles` per app). Replaces variant-filtered `storybook-build.mjs` and `storybook-vitest-runner.mjs` shims, plus per-package `storybook-app-smoke.mjs`.
|
|
225
|
+
|
|
226
|
+
### Migration
|
|
227
|
+
|
|
228
|
+
`runPnpmFilters` is now async. If you import it as a library, `await` the call. CLI users see no change.
|
|
229
|
+
|
|
230
|
+
## [0.4.0] — 2026-05-17
|
|
231
|
+
|
|
232
|
+
### Fixed
|
|
233
|
+
|
|
234
|
+
- **`smoke-packed` no longer swallows the npm install error.** The `--silent` flag was suppressing the stderr stream the `link:`/`workspace:` fallback regex depended on, producing "npm install exited 1" with empty `output` and forcing every Geenius package to ship its own `smoke-packed-imports.mjs` workaround (~36 copies, ~286 LOC each). The install now runs without `--silent`, falls back to `pnpm add` unconditionally on exit≠0, and reports the combined stderr from every attempt.
|
|
235
|
+
|
|
236
|
+
### Added
|
|
237
|
+
|
|
238
|
+
- **`publint` source-time `link:` tolerance.** When publint reports diagnostics of the form `The "X" dependency references "link:..."` for `X` declared in the manifest and matching `publint.sourceLinkScope` (default `^@geenius/`), the toolkit treats the run as passed. The semver rewrite that converts these to ranges still happens at publish time. Config: `publint.allowSourceTimeLinks` (default `true`), `publint.sourceLinkScope`. Replaces ~25 per-package `lint-pub.mjs` / `publint-package.mjs` wrappers.
|
|
239
|
+
- **Gauntlet sibling-dist freshness pre-check.** Before running the first step, the gauntlet walks every `link:` `@geenius/*` dep, verifies its `dist/index.js` + `dist/index.d.ts` are newer than its `src/`, and either fails (`siblingDistFreshness: "check"`, default) or auto-builds (`siblingDistFreshness: "build"`). Eliminates the recurring TS7016 "cannot resolve declarations" failures inside nested gauntlet runs.
|
|
240
|
+
- **`geenius-release variants [list|missing|published-subpaths|ui|db|storybook-apps]`** + a programmatic `loadRichVariants` / `packageVariants` / `uiVariants` / `storybookApps` / `publishedSubpaths` API. Reads `variants.json`, honors `OMEGA_INCLUDE_OUT_OF_SCOPE`, returns derived `packagePath` / `exists` / `subpaths` fields. Replaces 43 copies of `scripts/_variants.mjs`.
|
|
241
|
+
- **`geenius-release pnpm-filters <task> [...passthrough]`** + `runPnpmFilters` programmatic API. Builds `pnpm -r --filter ./packages/<X>` invocations from the active variant matrix. Replaces 43 copies of `scripts/_pnpm-filters.mjs`.
|
|
242
|
+
- **`geenius-release storybook --static-smoke <replace|after|only>`** runs the toolkit's built-in Playwright + http-server smoke against `apps/*/storybook-static`. Visits every indexed story under headless Chromium, asserts `#storybook-root` is non-empty, fails on page errors. `@playwright/test` is loaded lazily; if the consuming package doesn't have it the step reports a clear missing-peer error. Replaces ~30 copies of `storybook-runner.mjs` / `storybook-test-runner.mjs` / `test-storybook-static.mjs` that agents had to keep reinventing after Storybook's Vitest browser addon kept hanging.
|
|
243
|
+
|
|
244
|
+
## [0.3.4] — 2026-05-16
|
|
245
|
+
|
|
246
|
+
### Added
|
|
247
|
+
|
|
248
|
+
- `rewrite-imports` now supports `deriveFromExports: true` (config + `--derive-from-exports` CLI flag). When set, the toolkit reads the root manifest's `exports` map, walks `packages/<name>/package.json` for each referenced variant, and generates one literal rule per private→public pair (e.g. `@geenius/i18n-react` → `@geenius/i18n/react`). Replaces hand-rolled scripts like i18n's `patch-dts-imports.mjs` (~129 LOC). Derived rules are appended after explicit `rules`.
|
|
249
|
+
|
|
250
|
+
## [0.3.3] — 2026-05-16
|
|
251
|
+
|
|
252
|
+
### Added
|
|
253
|
+
|
|
254
|
+
- `rewrite-imports` rules now support a `literal: true` flag — when set, `replaceWith` is treated as literal text instead of a path-relative-to-packageRoot. Useful for JSDoc / comment cleanup ("internal-name → public-name") where there's no file to resolve against.
|
|
255
|
+
- `rewrite-imports` rules now support a `quoted: true` flag — when set, only quoted occurrences are matched (both `"<match>"` and `'<match>'`). Use this for specifier rewrites that must not touch identical strings in JSDoc / comments.
|
|
256
|
+
- `rewriteImports.extensions` config (and `extensions` option on the programmatic API) — list of file extensions to rewrite. Defaults to `[".js", ".d.ts"]`. Packages emitting `.cjs`/`.cts`/`.mjs` can now opt in.
|
|
257
|
+
|
|
258
|
+
## [0.3.2] — 2026-05-16
|
|
259
|
+
|
|
260
|
+
### Fixed
|
|
261
|
+
|
|
262
|
+
- **`loadConfig` now walks up from a subdirectory** to find the package root before reading `release-toolkit.config.json`. Previously, when a CLI command was invoked from a variant subdirectory (e.g. a per-variant build script chaining `tsup && geenius-release rewrite-imports packages/<variant>`), the config was silently missed because `loadConfig` joined `release-toolkit.config.json` onto the raw cwd. Affected every command that reads config — most visibly `rewrite-imports`, where the resulting `no rules configured` skip silently let private specifiers leak into dist. The CLI now calls `resolvePaths(startCwd).packageRoot` first.
|
|
263
|
+
|
|
264
|
+
## [0.3.1] — 2026-05-16
|
|
265
|
+
|
|
266
|
+
### Added
|
|
267
|
+
|
|
268
|
+
- `rewrite-imports <variant-dir>` — post-build codemod that rewrites private subpath imports (e.g. `@geenius/<pkg>/shared/react`) in a variant's built `dist/` into relative dist paths, so packed tarballs don't need to expose internal `./shared` exports. Replaces ~36 copies of `rewrite-private-imports.mjs` (≈ 2,800 LOC). Token-aware rules (`${packageName}`, `${framework}`, `${variant}`) configured under `rewriteImports` in `release-toolkit.config.json`, or supplied inline via repeatable `--rule <match>=<replaceWith>`. Auto-detects framework from variant basename (`solidjs*` → `solidjs`, else `react`); overridable via `--framework` or `rewriteImports.frameworkDetect` regex map.
|
|
269
|
+
|
|
270
|
+
### Fixed
|
|
271
|
+
|
|
272
|
+
- `manifest-contract`: replace hand-rolled glob with picomatch so `files` patterns like `packages/*/dist/**/*` correctly cover exports/main/types targets.
|
|
273
|
+
- `size-check`: default to optional (mirrors `mutation-report`); CLI flag flipped from `--optional` to `--required`. Packages without `size-limit` configured no longer break the gauntlet.
|
|
274
|
+
- `smoke-packed`: when `npm install` of the packed tarball fails due to unresolved `link:`/`workspace:` deps, retry with `pnpm add` so monorepo packages with workspace siblings can be smoke-tested end-to-end.
|
|
275
|
+
|
|
276
|
+
## [0.3.0] — 2026-05-16
|
|
277
|
+
|
|
278
|
+
### Added
|
|
279
|
+
|
|
280
|
+
- **4 new subcommands**, taking the surface from 11 → 15 and completing every legacy-script category:
|
|
281
|
+
- `diff-coverage` — changed-line coverage diff vs a git base ref. Parses `git diff --unified=0 <base>...HEAD`, walks istanbul `coverage-final.json`, enforces `--min` (default 80%). Replaces 22 copies of `diff-coverage.mjs`.
|
|
282
|
+
- `manifest-contract` — verify `package.json:main/types/module/exports/bin` resolve on disk, `bin` entries are executable + have shebangs, and `files` patterns cover every export target. Absorbs the `test -f dist/index.js` inline checks scattered across the ecosystem (e.g. tools/devtools' `test:dist-contract`).
|
|
283
|
+
- `storybook` — build + test-run every Storybook app declared (or auto-discovered under `apps/storybook-*`). Replaces ~28 scripts across 5 filename variations (`storybook-runner.mjs`, `storybook-test-runner.mjs`, `test-storybook-static.mjs`, `storybook-build.mjs`, `storybook-apps.mjs`).
|
|
284
|
+
- `perf-smoke` — enforce perf budgets against `.eval/perf/results.json`. Supports both array `[{ metric, value }]` and object `{ metric: value }` result formats; reads budgets from `perf-budgets.json` if no inline config. Replaces 7 copies.
|
|
285
|
+
- Each new command exported from the programmatic API (`runDiffCoverage`, `runManifestContract`, `runStorybook`, `runPerfSmoke`).
|
|
286
|
+
- Gauntlet integration: all 4 new commands are recognized internal steps.
|
|
287
|
+
|
|
288
|
+
### Cumulative absorption
|
|
289
|
+
|
|
290
|
+
The toolkit now replaces approximately **260+ legacy `scripts/*.mjs` files** across the ecosystem (≈ 49,000 LOC of duplication). Every category of release-gate script identified in the original audit has a corresponding canonical subcommand.
|
|
291
|
+
|
|
292
|
+
## [0.2.0] — 2026-05-16
|
|
293
|
+
|
|
294
|
+
### Added
|
|
295
|
+
|
|
296
|
+
- **6 new subcommands** absorbing ~80 more legacy `scripts/*.mjs` files across the ecosystem:
|
|
297
|
+
- `publint` — run publint against the packed tarball. Replaces 4 filename variations (~17 copies).
|
|
298
|
+
- `attw` — run `@arethetypeswrong/cli` against the packed tarball. Replaces 3 filename variations (~13 copies).
|
|
299
|
+
- `size-check` — size-limit driver. Replaces 13 copies.
|
|
300
|
+
- `coverage-report` — aggregate `coverage-summary.json` and enforce per-metric thresholds. Replaces 36 copies. Reads `coverage-thresholds.json` if present.
|
|
301
|
+
- `mutation-report` — Stryker driver. Optional by default. Replaces 36 copies.
|
|
302
|
+
- `a11y-report` — aggregate axe-core results from `.eval/a11y/results.json` and enforce a severity threshold. Replaces 28 copies.
|
|
303
|
+
- **Programmatic API** for every new subcommand: `runPublint`, `runAttw`, `runSizeCheck`, `runCoverageReport`, `runMutationReport`, `runA11yReport`.
|
|
304
|
+
- **Gauntlet integration**: every new subcommand is a recognised internal step in `geenius-release gauntlet`.
|
|
305
|
+
- **`$schema` allowed in `release-toolkit.config.json`** so editors get JSON-schema autocomplete (no runtime effect).
|
|
306
|
+
- **Repository infrastructure** to match the rest of the geenius ecosystem:
|
|
307
|
+
- `LICENSE` file (FSL-1.1-Apache-2.0)
|
|
308
|
+
- `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md`, `SECURITY.md`, `SUPPORT.md`
|
|
309
|
+
- `.github/CODEOWNERS`, `dependabot.yml`, `PULL_REQUEST_TEMPLATE.md`, issue templates
|
|
310
|
+
- `.github/workflows/ci.yml` (PR + nightly with `osv-scanner` install + Socket strict mode)
|
|
311
|
+
- `.github/workflows/release.yml` (changesets-driven publish)
|
|
312
|
+
- `.changeset/config.json`
|
|
313
|
+
- `.nvmrc`
|
|
314
|
+
- `@changesets/cli` added to devDependencies; `publint` and `@arethetypeswrong/cli` added so the toolkit's own gauntlet can run them.
|
|
315
|
+
|
|
316
|
+
### Changed
|
|
317
|
+
|
|
318
|
+
- `tsup.config.ts` scopes `dts` generation to the `index` entry only — `cli.ts` is a script, not a typed-library entry, so an empty `.d.ts` is no longer emitted.
|
|
319
|
+
- Package exports now include `default` alongside `import` for stricter ESM-only resolver tolerance.
|
|
320
|
+
|
|
321
|
+
### Known issues
|
|
322
|
+
|
|
323
|
+
- **`attw` crashes with `Cannot read properties of undefined (reading 'filename')`** when run against the toolkit's own packed tarball under `@arethetypeswrong/cli@0.18.2`. The same attw version works correctly on every other geenius package; the toolkit's own bootstrap dogfood gauntlet excludes `attw` until the upstream issue is resolved. The toolkit itself is unaffected — running `geenius-release attw` against consumer packages works as designed.
|
|
324
|
+
|
|
325
|
+
## [0.1.0] — 2026-05-15
|
|
326
|
+
|
|
327
|
+
Initial greenfield release. See the git history of this file for the original v0.1 entry.
|
|
328
|
+
|
|
329
|
+
### Added
|
|
330
|
+
|
|
331
|
+
- CLI `geenius-release` with subcommands `supply-chain`, `license`, `sbom`, `smoke-packed`, `gauntlet`.
|
|
332
|
+
- Programmatic API exports for every subcommand.
|
|
333
|
+
- `release-toolkit.config.json` schema (Zod) with sensible defaults.
|
|
334
|
+
- Env overrides (`GEENIUS_SUPPLY_CHAIN_<SCANNER>=off|optional|required`, `GEENIUS_RELEASE_STRICTNESS`, `SOCKET_API_TOKEN`).
|
|
335
|
+
- Stable exit codes (0–4) and stable JSON report shape.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
Functional Source License, Version 1.1, Apache 2.0 Future License
|
|
2
|
+
|
|
3
|
+
Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-Apache-2.0
|
|
6
|
+
|
|
7
|
+
Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 Mehdi Nabhani
|
|
10
|
+
|
|
11
|
+
License
|
|
12
|
+
|
|
13
|
+
Terms and Conditions
|
|
14
|
+
|
|
15
|
+
Licensor ("We") provides the Software described in the Notice, and reserves
|
|
16
|
+
all rights in it other than those expressly granted in this License.
|
|
17
|
+
|
|
18
|
+
Permitted Purpose means any purpose other than a Competing Use. A Competing
|
|
19
|
+
Use means making the Software available to third parties as a hosted or
|
|
20
|
+
managed service, where the service provides users with access to any
|
|
21
|
+
substantial set of the features or functionality of the Software. Permitted
|
|
22
|
+
Purpose expressly includes any internal use by employees and contractors of
|
|
23
|
+
your business, and use by your customers that is limited to interactions
|
|
24
|
+
with your products and services.
|
|
25
|
+
|
|
26
|
+
License Grant
|
|
27
|
+
|
|
28
|
+
Subject to your compliance with this License, We grant you a non-exclusive,
|
|
29
|
+
royalty-free, worldwide, non-sublicensable, non-transferable license to
|
|
30
|
+
use, copy, distribute, make available, and prepare derivative works of the
|
|
31
|
+
Software, in each case subject to the limitations and conditions below.
|
|
32
|
+
|
|
33
|
+
Limitations
|
|
34
|
+
|
|
35
|
+
You may not make any use of the Software that competes with Our business.
|
|
36
|
+
That includes (without limitation) offering the Software as a hosted or
|
|
37
|
+
managed service to third parties.
|
|
38
|
+
|
|
39
|
+
You may not move, change, disable, or circumvent any license key functionality
|
|
40
|
+
in the Software, and you may not remove or obscure any functionality in the
|
|
41
|
+
Software that is protected by a license key.
|
|
42
|
+
|
|
43
|
+
Patents
|
|
44
|
+
|
|
45
|
+
To the extent your use for a Permitted Purpose would necessarily infringe
|
|
46
|
+
Our patents, the license grant above includes a license under Our patents.
|
|
47
|
+
If you make a claim against any party that the Software infringes or
|
|
48
|
+
contributes to the infringement of any patent, then your patent license to
|
|
49
|
+
the Software ends immediately.
|
|
50
|
+
|
|
51
|
+
Redistribution
|
|
52
|
+
|
|
53
|
+
The Terms and Conditions of this License apply to any copy, modification,
|
|
54
|
+
or derivative work of the Software that you distribute. You must include
|
|
55
|
+
a copy of this License with every such copy, and you must retain all
|
|
56
|
+
copyright, trademark, and attribution notices.
|
|
57
|
+
|
|
58
|
+
Disclaimer
|
|
59
|
+
|
|
60
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND,
|
|
61
|
+
INCLUDING WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
|
62
|
+
A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR THAT THE SOFTWARE WILL BE
|
|
63
|
+
ERROR-FREE.
|
|
64
|
+
|
|
65
|
+
IN NO EVENT WILL WE BE LIABLE TO YOU FOR ANY DAMAGES ARISING OUT OF OR
|
|
66
|
+
RELATED TO THIS LICENSE, INCLUDING DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
|
|
67
|
+
CONSEQUENTIAL, OR PUNITIVE DAMAGES, EVEN IF WE HAVE BEEN ADVISED OF THE
|
|
68
|
+
POSSIBILITY OF SUCH DAMAGES.
|
|
69
|
+
|
|
70
|
+
Future License
|
|
71
|
+
|
|
72
|
+
On the second anniversary of the date the Software is first distributed
|
|
73
|
+
under this License, the Software will automatically also be made available
|
|
74
|
+
under the Apache License, Version 2.0 (the "Future License"). You may, at
|
|
75
|
+
your option, continue to use the Software under the terms of this License,
|
|
76
|
+
or you may use the Software under the terms of the Future License.
|
|
77
|
+
|
|
78
|
+
Your compliance with the Future License is a condition of your receiving
|
|
79
|
+
the Software under that license.
|
|
80
|
+
|
|
81
|
+
The Future License text is available at:
|
|
82
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
|
83
|
+
|
|
84
|
+
Trademarks
|
|
85
|
+
|
|
86
|
+
Except for the limited use required to comply with the Notice section
|
|
87
|
+
above or as required by the redistribution terms, this License does not
|
|
88
|
+
grant you any right in any trademark, service mark, or logo of Ours.
|
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# @geenius/release-toolkit
|
|
2
|
+
|
|
3
|
+
> Canonical release toolkit for every Geenius package and boilerplate. One CLI (`geenius-release`) replaces the per-package supply-chain / license / SBOM / smoke-packed / gauntlet scripts that previously lived as 26–36 hand-copied duplicates.
|
|
4
|
+
|
|
5
|
+
**Dev-only.** Add to `devDependencies`; never appears in your runtime bundle.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add -D @geenius/release-toolkit
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
Wire the canonical scripts into your `package.json`:
|
|
14
|
+
|
|
15
|
+
```jsonc
|
|
16
|
+
{
|
|
17
|
+
"scripts": {
|
|
18
|
+
"audit:supply-chain": "geenius-release supply-chain",
|
|
19
|
+
"audit:license": "geenius-release license",
|
|
20
|
+
"audit:sbom": "geenius-release sbom",
|
|
21
|
+
"test:smoke-packed": "geenius-release smoke-packed",
|
|
22
|
+
"test:gauntlet": "geenius-release gauntlet"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
No config file required — the toolkit ships ecosystem-sensible defaults. Add `release-toolkit.config.json` next to `package.json` to override.
|
|
28
|
+
|
|
29
|
+
## Subcommands (v0.1)
|
|
30
|
+
|
|
31
|
+
| Subcommand | Replaces | Description |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `supply-chain` | 26 per-package scripts | pnpm audit + osv-scanner + Socket + license, all required/optional configurable |
|
|
34
|
+
| `license` | 36 copies of `license-check.mjs` | Forbidden-license scan over installed deps |
|
|
35
|
+
| `sbom` | 36 copies of `sbom.mjs` | CycloneDX 1.5 JSON SBOM (optional SPDX via `syft`) |
|
|
36
|
+
| `smoke-packed` | 36 copies of `smoke-packed-imports.mjs` | Pack, install, dynamic-import every subpath in `package.json:exports` |
|
|
37
|
+
| `gauntlet` | The `&&`-chained `pnpm test:gauntlet` macro | Compose the configured step sequence into one structured report |
|
|
38
|
+
|
|
39
|
+
v0.2 adds `coverage-report`, `diff-coverage`, `mutation-report`, `a11y-report`, `size-check`. v0.3 adds `storybook`, `publint`, `attw`, `perf-smoke`.
|
|
40
|
+
|
|
41
|
+
## Opting out of Socket
|
|
42
|
+
|
|
43
|
+
Socket requires a free account. To opt out:
|
|
44
|
+
|
|
45
|
+
```jsonc
|
|
46
|
+
{
|
|
47
|
+
"supplyChain": {
|
|
48
|
+
"scanners": { "socket": { "required": false } }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`required: false` is the default for every boilerplate. Internal `@geenius/*` packages opt-in to strict mode in CI via `SOCKET_API_TOKEN`. Env override for one-off CI runs:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
GEENIUS_SUPPLY_CHAIN_SOCKET=off geenius-release supply-chain
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Configuration reference
|
|
60
|
+
|
|
61
|
+
See [`.docs/DOCS/PACKAGES/RELEASE_TOOLKIT.md`](../../.docs/DOCS/PACKAGES/RELEASE_TOOLKIT.md) for the full config schema and examples, and [`.docs/PRDS/packages/PACKAGE_RELEASE_TOOLKIT_PRD.md`](../../.docs/PRDS/packages/PACKAGE_RELEASE_TOOLKIT_PRD.md) for the design rationale.
|
|
62
|
+
|
|
63
|
+
## Exit codes
|
|
64
|
+
|
|
65
|
+
| Code | Meaning |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `0` | Required steps passed (optional steps may have skipped) |
|
|
68
|
+
| `1` | At least one required step failed |
|
|
69
|
+
| `2` | Configuration error |
|
|
70
|
+
| `3` | Environment error (missing pnpm, missing lockfile) |
|
|
71
|
+
| `4` | Internal toolkit bug |
|
|
72
|
+
|
|
73
|
+
Stable across versions. CI integrations can rely on them.
|
|
74
|
+
|
|
75
|
+
## Optional git hooks
|
|
76
|
+
|
|
77
|
+
The toolkit ships a non-blocking pre-push hook template at `templates/husky/pre-push`. It runs `pnpm run audit:supply-chain` before each push and reports findings without blocking the push (remove the trailing `|| exit 0` in the script to make findings blocking).
|
|
78
|
+
|
|
79
|
+
Install per-repo:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
cp node_modules/@geenius/release-toolkit/templates/husky/pre-push .husky/pre-push
|
|
83
|
+
chmod +x .husky/pre-push
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The hook is not auto-installed by adding the toolkit as a dependency — adoption is opt-in.
|
|
87
|
+
|
|
88
|
+
## Reports
|
|
89
|
+
|
|
90
|
+
Every subcommand writes a JSON report at `.eval/release-toolkit/<command>.json`. The shape is documented in [`src/types.ts`](./src/types.ts) and is consumed by CI integrations and downstream report aggregators.
|
|
91
|
+
|
|
92
|
+
## Development
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pnpm install
|
|
96
|
+
pnpm build
|
|
97
|
+
pnpm test
|
|
98
|
+
pnpm lint
|
|
99
|
+
pnpm exec geenius-release gauntlet # dogfood
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
FSL-1.1-Apache-2.0
|