@rainy-updates/cli 0.5.7 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +90 -31
  3. package/dist/bin/cli.js +16 -16
  4. package/dist/bin/dispatch.js +29 -32
  5. package/dist/bin/help.js +32 -2
  6. package/dist/cache/cache.js +13 -11
  7. package/dist/commands/audit/parser.js +2 -2
  8. package/dist/commands/audit/runner.js +27 -46
  9. package/dist/commands/audit/targets.js +13 -13
  10. package/dist/commands/bisect/oracle.js +28 -11
  11. package/dist/commands/bisect/parser.js +3 -3
  12. package/dist/commands/bisect/runner.js +15 -8
  13. package/dist/commands/changelog/fetcher.js +11 -5
  14. package/dist/commands/dashboard/parser.js +103 -1
  15. package/dist/commands/dashboard/runner.d.ts +2 -2
  16. package/dist/commands/dashboard/runner.js +67 -37
  17. package/dist/commands/doctor/parser.js +9 -4
  18. package/dist/commands/doctor/runner.js +2 -2
  19. package/dist/commands/ga/parser.js +4 -4
  20. package/dist/commands/ga/runner.js +13 -7
  21. package/dist/commands/health/parser.js +2 -2
  22. package/dist/commands/licenses/runner.js +4 -4
  23. package/dist/commands/resolve/runner.js +9 -4
  24. package/dist/commands/review/parser.js +57 -4
  25. package/dist/commands/review/runner.js +31 -5
  26. package/dist/commands/snapshot/runner.js +17 -17
  27. package/dist/commands/snapshot/store.d.ts +0 -12
  28. package/dist/commands/snapshot/store.js +26 -38
  29. package/dist/commands/unused/runner.js +6 -7
  30. package/dist/commands/unused/scanner.js +17 -20
  31. package/dist/config/loader.d.ts +2 -2
  32. package/dist/config/loader.js +2 -5
  33. package/dist/config/policy.js +20 -11
  34. package/dist/core/analysis/run-silenced.js +0 -1
  35. package/dist/core/artifacts.js +6 -5
  36. package/dist/core/baseline.js +3 -5
  37. package/dist/core/check.js +2 -2
  38. package/dist/core/ci.js +52 -1
  39. package/dist/core/decision-plan.d.ts +14 -0
  40. package/dist/core/decision-plan.js +107 -0
  41. package/dist/core/doctor/result.js +8 -5
  42. package/dist/core/fix-pr-batch.js +38 -28
  43. package/dist/core/fix-pr.js +27 -24
  44. package/dist/core/init-ci.js +25 -21
  45. package/dist/core/options.js +95 -4
  46. package/dist/core/review-model.js +3 -0
  47. package/dist/core/summary.js +6 -0
  48. package/dist/core/upgrade.js +64 -2
  49. package/dist/core/verification.d.ts +2 -0
  50. package/dist/core/verification.js +106 -0
  51. package/dist/core/warm-cache.js +2 -2
  52. package/dist/output/format.js +15 -0
  53. package/dist/output/github.js +6 -0
  54. package/dist/output/sarif.js +12 -12
  55. package/dist/parsers/package-json.js +2 -4
  56. package/dist/pm/detect.d.ts +3 -1
  57. package/dist/pm/detect.js +24 -12
  58. package/dist/pm/install.d.ts +2 -1
  59. package/dist/pm/install.js +15 -16
  60. package/dist/registry/npm.js +34 -76
  61. package/dist/rup +0 -0
  62. package/dist/types/index.d.ts +76 -5
  63. package/dist/ui/tui.d.ts +4 -1
  64. package/dist/ui/tui.js +5 -4
  65. package/dist/utils/io.js +5 -6
  66. package/dist/utils/lockfile.js +24 -19
  67. package/dist/utils/runtime-paths.d.ts +4 -0
  68. package/dist/utils/runtime-paths.js +35 -0
  69. package/dist/utils/runtime.d.ts +7 -0
  70. package/dist/utils/runtime.js +32 -0
  71. package/dist/workspace/discover.js +55 -51
  72. package/package.json +16 -16
  73. package/dist/ui/dashboard/DashboardTUI.d.ts +0 -6
  74. package/dist/ui/dashboard/DashboardTUI.js +0 -34
  75. package/dist/ui/dashboard/components/DetailPanel.d.ts +0 -4
  76. package/dist/ui/dashboard/components/DetailPanel.js +0 -30
  77. package/dist/ui/dashboard/components/Footer.d.ts +0 -4
  78. package/dist/ui/dashboard/components/Footer.js +0 -9
  79. package/dist/ui/dashboard/components/Header.d.ts +0 -4
  80. package/dist/ui/dashboard/components/Header.js +0 -12
  81. package/dist/ui/dashboard/components/Sidebar.d.ts +0 -4
  82. package/dist/ui/dashboard/components/Sidebar.js +0 -23
  83. package/dist/ui/dashboard/store.d.ts +0 -34
  84. package/dist/ui/dashboard/store.js +0 -148
package/CHANGELOG.md CHANGED
@@ -2,6 +2,87 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## [0.6.0] - 2026-03-01
6
+
7
+ Dashboard-first release candidate for the `v0.6` series, focused on unifying the interactive surface, introducing replayable decision plans, tightening CI/apply verification flows, and undergoing a complete native Bun performance optimization.
8
+
9
+ ### Added
10
+
11
+ - **Decision plan artifact flow**:
12
+ - new deterministic decision plan model for reviewed update sets,
13
+ - reusable `.artifacts/decision-plan.json` workflow,
14
+ - `upgrade --from-plan <path>` replay support,
15
+ - additive summary/output metadata for:
16
+ - `suggestedCommand`,
17
+ - `decisionPlan`,
18
+ - `interactiveSurface`,
19
+ - `queueFocus`.
20
+ - **Verification flow for applied plans and upgrades**:
21
+ - `--verify none|install|test|install,test`,
22
+ - `--test-command "<cmd>"`,
23
+ - `--verification-report-file <path>`,
24
+ - additive verification metadata in summary and GitHub/metrics outputs:
25
+ - `verificationState`,
26
+ - `verificationFailures`.
27
+ - **New CI gate model**:
28
+ - `ci --gate check|doctor|review|upgrade`,
29
+ - review gate emits a decision plan artifact without mutating manifests,
30
+ - upgrade gate replays a prior decision plan and can run verification.
31
+ - **New verification core** under `src/core/verification.ts`.
32
+ - **New decision plan core** under `src/core/decision-plan.ts`.
33
+ - **New test coverage** for:
34
+ - decision plan serialization and replay,
35
+ - CI upgrade gate plan replay,
36
+ - verification report generation.
37
+
38
+ - **Native Bun Optimizations**:
39
+ - Bun is now the primary Rainy runtime path for local execution, CI templates, and release verification flows.
40
+ - Added a shared Bun-first runtime layer for cwd/env/stdout/stderr/exit handling across the CLI command surface.
41
+ - Migrated verification and package-manager-aware test execution onto `Bun.spawn`, while keeping npm, pnpm, Bun, and yarn target-repo support intact.
42
+ - Migrated internal hot-path file operations onto `Bun.file()`, `Bun.write()`, `Bun.Glob`, and `Bun.CryptoHasher` across workspace discovery, lockfile hashing, snapshot persistence, audit target resolution, changelog cache reads, and CLI/package metadata loading.
43
+ - Added real atomic file writes for Rainy-managed artifacts, reports, caches, baselines, and snapshot restore paths.
44
+ - Added native `build:exe` target compilation for standalone Bun-first distributions using `bun build --compile`.
45
+
46
+ ### Changed
47
+
48
+ - `dashboard` is now the primary interactive dependency decision surface.
49
+ - `review --interactive` now routes into the shared dashboard flow instead of maintaining a separate interactive implementation path.
50
+ - `doctor` now recommends dashboard-first next steps:
51
+ - `rup dashboard --mode review`
52
+ - `rup dashboard --mode review --focus security`
53
+ - `rup dashboard --mode review --focus blocked`
54
+ - CLI help and README now document:
55
+ - `dashboard` as the primary interactive workflow,
56
+ - `upgrade --from-plan`,
57
+ - `ci --gate ...`,
58
+ - verification and verification-report flows,
59
+ - Bun as the preferred Rainy runtime via `bunx --bun` and compiled Bun artifacts.
60
+ - `init-ci` generated workflows now:
61
+ - use Bun as the Rainy runtime by default,
62
+ - use explicit CI gates,
63
+ - emit a decision plan artifact in strict and enterprise modes,
64
+ - replay approved plans with verification in enterprise mode,
65
+ - align install and test commands with detected npm, pnpm, or Bun target repos.
66
+ - Artifact manifests now include verification report output paths when configured.
67
+ - Package-manager detection and verification defaults now treat Bun as a first-class package ecosystem instead of falling back to npm/pnpm-only assumptions.
68
+ - GA readiness checks now validate both the JS dist CLI and the compiled Bun runtime artifact.
69
+
70
+ ### Removed
71
+
72
+ - Removed the legacy standalone dashboard Ink/store implementation under `src/ui/dashboard/` in favor of a single shared interactive path.
73
+ - Removed the remaining explicit `node:process` imports from the main CLI command surface in favor of the shared runtime layer.
74
+ - Removed manual recursive workspace directory walking in favor of Bun-native glob expansion.
75
+
76
+ ### Tests
77
+
78
+ - Added coverage for:
79
+ - `dashboard` parser support for mode/focus/plan/verification flags,
80
+ - additive GitHub output fields for decision-plan and verification metadata,
81
+ - updated CI bootstrap templates for review/upgrade gates,
82
+ - Bun-aware package-manager detection and verification defaults,
83
+ - GA runtime-artifact readiness checks,
84
+ - Bun-glob workspace discovery with hidden-directory and `node_modules` exclusions.
85
+
5
86
  ## [0.5.7] - 2026-03-01
6
87
 
7
88
  Final stabilization release for the `v0.5` series, focused on modularization, doctor scan quality, and maintainability.
package/README.md CHANGED
@@ -29,6 +29,7 @@ Rainy Updates gives teams one dependency lifecycle:
29
29
  - `check` detects candidate updates.
30
30
  - `doctor` summarizes the current situation.
31
31
  - `review` decides what should happen.
32
+ - `dashboard` is the primary interactive decision surface.
32
33
  - `upgrade` applies the approved change set.
33
34
 
34
35
  Everything else supports that lifecycle: CI orchestration, advisory lookup, peer resolution, licenses, snapshots, baselines, and fix-PR automation.
@@ -43,16 +44,16 @@ Everything else supports that lifecycle: CI orchestration, advisory lookup, peer
43
44
 
44
45
  ```bash
45
46
  # 1) Detect what changed
46
- npx @rainy-updates/cli check --workspace --show-impact
47
+ bunx --bun @rainy-updates/cli check --workspace --show-impact
47
48
 
48
49
  # 2) Summarize what matters
49
- npx @rainy-updates/cli doctor --workspace
50
+ bunx --bun @rainy-updates/cli doctor --workspace
50
51
 
51
- # 3) Decide in the review surface
52
- npx @rainy-updates/cli review --interactive
52
+ # 3) Decide in the dashboard
53
+ bunx --bun @rainy-updates/cli dashboard --mode review --plan-file .artifacts/decision-plan.json
53
54
 
54
- # 4) Apply the approved set
55
- npx @rainy-updates/cli upgrade --interactive
55
+ # 4) Apply the approved plan
56
+ bunx --bun @rainy-updates/cli upgrade --from-plan .artifacts/decision-plan.json
56
57
  ```
57
58
 
58
59
  ## Why teams use it
@@ -67,10 +68,15 @@ npx @rainy-updates/cli upgrade --interactive
67
68
  ## Install
68
69
 
69
70
  ```bash
71
+ # Preferred: run with Bun's runtime directly
72
+ bunx --bun @rainy-updates/cli check
73
+
70
74
  # As a project dev dependency (recommended for teams)
71
75
  npm install --save-dev @rainy-updates/cli
72
76
  # or
73
77
  pnpm add -D @rainy-updates/cli
78
+ # or
79
+ bun add -d @rainy-updates/cli
74
80
  ```
75
81
 
76
82
  Once installed, three binary aliases are available in your `node_modules/.bin/`:
@@ -88,16 +94,25 @@ rainy-up check
88
94
  rainy-updates check
89
95
  ```
90
96
 
91
- ### One-off usage with npx (no install required)
97
+ ### Bun-first runtime
92
98
 
93
99
  ```bash
94
- # Always works without installing:
100
+ # Preferred no-install path:
101
+ bunx --bun @rainy-updates/cli check
102
+ bunx --bun @rainy-updates/cli audit --severity high
103
+ bunx --bun @rainy-updates/cli ci --workspace --mode strict
104
+ ```
105
+
106
+ ### One-off usage with npx (compatibility path)
107
+
108
+ ```bash
109
+ # Compatibility path when Bun is not available:
95
110
  npx @rainy-updates/cli check
96
111
  npx @rainy-updates/cli audit --severity high
97
112
  npx @rainy-updates/cli ci --workspace --mode strict
98
113
  ```
99
114
 
100
- > **Note:** The short aliases (`rup`, `rainy-up`) only work after installing the package. For one-off `npx` runs, use `npx @rainy-updates/cli <command>`.
115
+ > **Note:** Rainy is Bun-first at runtime. `bunx --bun @rainy-updates/cli ...` is the fastest no-install path. The npm package and `npx` remain supported compatibility paths.
101
116
 
102
117
  ## Commands
103
118
 
@@ -106,6 +121,7 @@ npx @rainy-updates/cli ci --workspace --mode strict
106
121
  - `check` — detect candidate dependency updates
107
122
  - `doctor` — summarize the current dependency situation
108
123
  - `review` — decide what to do with security, risk, peer, and policy context
124
+ - `dashboard` — open the primary interactive decision console
109
125
  - `upgrade` — apply the approved change set
110
126
  - `ga` — audit GA and CI readiness for the current checkout
111
127
 
@@ -123,71 +139,108 @@ npx @rainy-updates/cli ci --workspace --mode strict
123
139
 
124
140
  ## Quick usage
125
141
 
126
- > Commands work with `npx` (no install) **or** with the `rup` / `rainy-up` shortcut if the package is installed.
142
+ > Commands work with `bunx --bun`, with `npx` as a compatibility path, or with the `rup` / `rainy-up` shortcut if the package is installed.
127
143
 
128
144
  ```bash
129
145
  # 1) Detect updates
146
+ bunx --bun @rainy-updates/cli check --format table
130
147
  npx @rainy-updates/cli check --format table
131
148
  rup check --format table # if installed
132
149
 
133
150
  # 2) Summarize the state
134
- npx @rainy-updates/cli doctor --workspace
151
+ bunx --bun @rainy-updates/cli doctor --workspace
135
152
  rup doctor --workspace
136
153
 
137
154
  # 3) Review and decide
138
- npx @rainy-updates/cli review --security-only
139
- rup review --interactive
155
+ bunx --bun @rainy-updates/cli review --security-only
156
+ rup dashboard --mode review --plan-file .artifacts/decision-plan.json
140
157
  rup review --show-changelog
141
158
 
142
- # 4) Apply upgrades with workspace sync
143
- npx @rainy-updates/cli upgrade --target latest --workspace --sync --install
144
- rup upgrade --target latest --workspace --sync --install
159
+ # 4) Apply an approved decision plan with verification
160
+ bunx --bun @rainy-updates/cli upgrade --from-plan .artifacts/decision-plan.json --verify install,test --test-command "bun test"
161
+ rup upgrade --from-plan .artifacts/decision-plan.json --verify install,test --test-command "npm test"
145
162
 
146
163
  # 5) CI orchestration with policy gates
147
- npx @rainy-updates/cli ci --workspace --mode strict --format github
148
- rup ci --workspace --mode strict --format github
164
+ bunx --bun @rainy-updates/cli ci --workspace --mode strict --gate review --plan-file .artifacts/decision-plan.json --format github
165
+ rup ci --workspace --mode strict --gate review --plan-file .artifacts/decision-plan.json --format github
166
+
167
+ # 6) Replay an approved plan in CI
168
+ rup ci --workspace --mode strict --gate upgrade --from-plan .artifacts/decision-plan.json --verify test --test-command "npm test"
149
169
 
150
- # 6) Batch fix branches by scope (enterprise)
170
+ # 7) Batch fix branches by scope (enterprise)
151
171
  npx @rainy-updates/cli ci --workspace --mode enterprise --group-by scope --fix-pr --fix-pr-batch-size 2
152
172
  rup ci --workspace --mode enterprise --group-by scope --fix-pr --fix-pr-batch-size 2
153
173
 
154
- # 7) Warm cache deterministic offline CI check
174
+ # 8) Warm cache -> deterministic offline CI check
155
175
  npx @rainy-updates/cli warm-cache --workspace --concurrency 32
156
176
  npx @rainy-updates/cli check --workspace --offline --ci
157
177
 
158
- # 8) Save and compare baseline drift
178
+ # 9) Save and compare baseline drift
159
179
  npx @rainy-updates/cli baseline --save --file .artifacts/deps-baseline.json --workspace
160
180
  npx @rainy-updates/cli baseline --check --file .artifacts/deps-baseline.json --workspace --ci
161
181
 
162
- # 9) Scan for known CVEs
182
+ # 10) Scan for known CVEs
163
183
  npx @rainy-updates/cli audit
164
184
  npx @rainy-updates/cli audit --severity high
165
185
  npx @rainy-updates/cli audit --summary
166
186
  npx @rainy-updates/cli audit --source osv
167
- npx @rainy-updates/cli audit --fix # prints the patching npm install command
187
+ npx @rainy-updates/cli audit --fix # prints the patching install command for the detected package manager
168
188
  rup audit --severity high # if installed
169
189
 
170
- `audit` prefers npm/pnpm lockfiles today for exact installed-version inference, and now also reads simple `bun.lock` workspace entries when available. It reports source-health warnings when OSV or GitHub returns only partial coverage.
190
+ `audit` resolves installed versions from lockfiles across npm, pnpm, and simple `bun.lock` workspace entries when available. It reports source-health warnings when OSV or GitHub returns only partial coverage.
171
191
 
172
- # 10) Check dependency maintenance health
192
+ # 11) Check dependency maintenance health
173
193
  npx @rainy-updates/cli health
174
194
  npx @rainy-updates/cli health --stale 6m # flag packages with no release in 6 months
175
195
  npx @rainy-updates/cli health --stale 180d # same but in days
176
196
  rup health --stale 6m # if installed
177
197
 
178
- # 11) Find which version introduced a breaking change
198
+ # 12) Find which version introduced a breaking change
179
199
  npx @rainy-updates/cli bisect axios --cmd "bun test"
180
200
  npx @rainy-updates/cli bisect react --range "18.0.0..19.0.0" --cmd "npm test"
181
201
  npx @rainy-updates/cli bisect lodash --cmd "npm run test:unit" --dry-run
182
202
  rup bisect axios --cmd "bun test" # if installed
183
203
 
184
- # 12) Focus review on high-risk changes
204
+ # 13) Focus review on high-risk changes
185
205
  rup review --risk high --diff major
186
206
 
187
- # 13) Audit GA / CI readiness
207
+ # 14) Audit GA / CI readiness
188
208
  rup ga --workspace
189
209
  ```
190
210
 
211
+ ## Decision Plans And Verification
212
+
213
+ Rainy can persist an approved update set as a deterministic decision plan and replay it later:
214
+
215
+ ```bash
216
+ # Create a reviewed plan
217
+ rup dashboard --mode review --plan-file .artifacts/decision-plan.json
218
+
219
+ # Apply only that approved plan later
220
+ rup upgrade --from-plan .artifacts/decision-plan.json
221
+
222
+ # Apply and verify install + tests
223
+ rup upgrade \
224
+ --from-plan .artifacts/decision-plan.json \
225
+ --verify install,test \
226
+ --test-command "bun test" \
227
+ --verification-report-file .artifacts/verification.json
228
+ ```
229
+
230
+ This is the intended local review -> CI replay workflow.
231
+
232
+ Verification follows the target repository's package manager when one is detected.
233
+ That means Bun repositories can verify with `bun install` / `bun test`, while npm and pnpm projects keep their native install/test flows.
234
+
235
+ ## CI Gates
236
+
237
+ `ci` supports explicit execution gates:
238
+
239
+ - `--gate check` runs detection only.
240
+ - `--gate doctor` computes the high-level verdict and doctor metadata.
241
+ - `--gate review` emits a decision plan artifact without mutating the repo.
242
+ - `--gate upgrade` replays an existing plan and can run verification.
243
+
191
244
  ## What it does in production
192
245
 
193
246
  ### Update detection engine
@@ -275,8 +328,8 @@ Generated file:
275
328
 
276
329
  Modes:
277
330
 
278
- - `strict`: warm-cache + offline check + artifacts + SARIF upload.
279
- - `enterprise`: strict checks + runtime matrix + retention policy + rollout gates.
331
+ - `strict`: warm-cache + review gate + artifacts + SARIF upload.
332
+ - `enterprise`: strict checks + runtime matrix + review/upgrade gates + retention policy.
280
333
  - `minimal`: fast check-only workflow for quick adoption.
281
334
 
282
335
  Schedule:
@@ -307,9 +360,15 @@ Schedule:
307
360
  - `--pr-limit <n>`
308
361
  - `--only-changed`
309
362
  - `--interactive`
363
+ - `--plan-file <path>`
364
+ - `--from-plan <path>`
365
+ - `--verify none|install|test|install,test`
366
+ - `--test-command <cmd>`
367
+ - `--verification-report-file <path>`
310
368
  - `--show-impact`
311
369
  - `--show-homepage`
312
370
  - `--mode minimal|strict|enterprise` (for `ci`)
371
+ - `--gate check|doctor|review|upgrade` (for `ci`)
313
372
  - `--fix-pr-batch-size <n>` (for batched fix branches in `ci`)
314
373
  - `--policy-file <path>`
315
374
  - `--format table|json|minimal|github`
@@ -328,7 +387,7 @@ Schedule:
328
387
  ### Upgrade-only
329
388
 
330
389
  - `--install`
331
- - `--pm auto|npm|pnpm`
390
+ - `--pm auto|bun|npm|pnpm|yarn`
332
391
  - `--sync`
333
392
 
334
393
  ### Review-only
package/dist/bin/cli.js CHANGED
@@ -1,8 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { promises as fs } from "node:fs";
3
- import path from "node:path";
4
- import process from "node:process";
5
- import { fileURLToPath } from "node:url";
2
+ import { readFileSync } from "node:fs";
6
3
  import { parseCliArgs } from "../core/options.js";
7
4
  import { applyFixPr } from "../core/fix-pr.js";
8
5
  import { applyFixPrBatches } from "../core/fix-pr-batch.js";
@@ -14,17 +11,18 @@ import { renderPrReport } from "../output/pr-report.js";
14
11
  import { writeFileAtomic } from "../utils/io.js";
15
12
  import { resolveFailReason } from "../core/summary.js";
16
13
  import { stableStringify } from "../utils/stable-json.js";
14
+ import { getRuntimeArgv, setRuntimeExitCode, writeStderr, writeStdout, } from "../utils/runtime.js";
17
15
  import { handleDirectCommand, runPrimaryCommand } from "./dispatch.js";
18
16
  import { renderHelp } from "./help.js";
19
17
  async function main() {
20
18
  try {
21
- const argv = process.argv.slice(2);
19
+ const argv = getRuntimeArgv();
22
20
  if (argv.includes("--version") || argv.includes("-v")) {
23
- process.stdout.write((await readPackageVersion()) + "\n");
21
+ writeStdout((await readPackageVersion()) + "\n");
24
22
  return;
25
23
  }
26
24
  if (argv.includes("--help") || argv.includes("-h")) {
27
- process.stdout.write(renderHelp(argv[0]) + "\n");
25
+ writeStdout(renderHelp(argv[0]) + "\n");
28
26
  return;
29
27
  }
30
28
  const parsed = await parseCliArgs(argv);
@@ -109,21 +107,23 @@ async function main() {
109
107
  const sarif = createSarifReport(result);
110
108
  await writeFileAtomic(parsed.options.sarifFile, stableStringify(sarif, 2) + "\n");
111
109
  }
112
- process.stdout.write(rendered + "\n");
113
- process.exitCode = resolveExitCode(result, result.summary.failReason);
110
+ writeStdout(rendered + "\n");
111
+ setRuntimeExitCode(resolveExitCode(result, result.summary.failReason));
114
112
  }
115
113
  catch (error) {
116
- process.stderr.write(`rainy-updates (rup): ${String(error)}\n`);
117
- process.exitCode = 2;
114
+ writeStderr(`rainy-updates (rup): ${String(error)}\n`);
115
+ setRuntimeExitCode(2);
118
116
  }
119
117
  }
120
118
  void main();
121
119
  async function readPackageVersion() {
122
- const currentFile = fileURLToPath(import.meta.url);
123
- const packageJsonPath = path.resolve(path.dirname(currentFile), "../../package.json");
124
- const content = await fs.readFile(packageJsonPath, "utf8");
125
- const parsed = JSON.parse(content);
126
- return parsed.version ?? "0.0.0";
120
+ try {
121
+ const packageJson = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8"));
122
+ return packageJson.version ?? "0.0.0";
123
+ }
124
+ catch {
125
+ return "0.0.0";
126
+ }
127
127
  }
128
128
  function resolveExitCode(result, failReason) {
129
129
  if (result.errors.length > 0)
@@ -1,17 +1,17 @@
1
- import process from "node:process";
2
1
  import { check } from "../core/check.js";
3
2
  import { upgrade } from "../core/upgrade.js";
4
3
  import { warmCache } from "../core/warm-cache.js";
5
4
  import { runCi } from "../core/ci.js";
6
5
  import { initCiWorkflow } from "../core/init-ci.js";
7
6
  import { diffBaseline, saveBaseline } from "../core/baseline.js";
7
+ import { setRuntimeExitCode, writeStdout, } from "../utils/runtime.js";
8
8
  export async function handleDirectCommand(parsed) {
9
9
  if (parsed.command === "init-ci") {
10
10
  const workflow = await initCiWorkflow(parsed.options.cwd, parsed.options.force, {
11
11
  mode: parsed.options.mode,
12
12
  schedule: parsed.options.schedule,
13
13
  });
14
- process.stdout.write(workflow.created
14
+ writeStdout(workflow.created
15
15
  ? `Created CI workflow at ${workflow.path}\n`
16
16
  : `CI workflow already exists at ${workflow.path}. Use --force to overwrite.\n`);
17
17
  return true;
@@ -19,110 +19,107 @@ export async function handleDirectCommand(parsed) {
19
19
  if (parsed.command === "baseline") {
20
20
  if (parsed.options.action === "save") {
21
21
  const saved = await saveBaseline(parsed.options);
22
- process.stdout.write(`Saved baseline at ${saved.filePath} (${saved.entries} entries)\n`);
22
+ writeStdout(`Saved baseline at ${saved.filePath} (${saved.entries} entries)\n`);
23
23
  return true;
24
24
  }
25
25
  const diff = await diffBaseline(parsed.options);
26
26
  const changes = diff.added.length + diff.removed.length + diff.changed.length;
27
27
  if (changes === 0) {
28
- process.stdout.write(`No baseline drift detected (${diff.filePath}).\n`);
28
+ writeStdout(`No baseline drift detected (${diff.filePath}).\n`);
29
29
  return true;
30
30
  }
31
- process.stdout.write(`Baseline drift detected (${diff.filePath}).\n`);
31
+ writeStdout(`Baseline drift detected (${diff.filePath}).\n`);
32
32
  if (diff.added.length > 0)
33
- process.stdout.write(`Added: ${diff.added.length}\n`);
33
+ writeStdout(`Added: ${diff.added.length}\n`);
34
34
  if (diff.removed.length > 0)
35
- process.stdout.write(`Removed: ${diff.removed.length}\n`);
35
+ writeStdout(`Removed: ${diff.removed.length}\n`);
36
36
  if (diff.changed.length > 0)
37
- process.stdout.write(`Changed: ${diff.changed.length}\n`);
38
- process.exitCode = 1;
37
+ writeStdout(`Changed: ${diff.changed.length}\n`);
38
+ setRuntimeExitCode(1);
39
39
  return true;
40
40
  }
41
41
  if (parsed.command === "bisect") {
42
42
  const { runBisect } = await import("../commands/bisect/runner.js");
43
43
  const result = await runBisect(parsed.options);
44
- process.exitCode = result.breakingVersion ? 1 : 0;
44
+ setRuntimeExitCode(result.breakingVersion ? 1 : 0);
45
45
  return true;
46
46
  }
47
47
  if (parsed.command === "audit") {
48
48
  const { runAudit } = await import("../commands/audit/runner.js");
49
49
  const result = await runAudit(parsed.options);
50
- process.exitCode = result.advisories.length > 0 ? 1 : 0;
50
+ setRuntimeExitCode(result.advisories.length > 0 ? 1 : 0);
51
51
  return true;
52
52
  }
53
53
  if (parsed.command === "health") {
54
54
  const { runHealth } = await import("../commands/health/runner.js");
55
55
  const result = await runHealth(parsed.options);
56
- process.exitCode = result.totalFlagged > 0 ? 1 : 0;
56
+ setRuntimeExitCode(result.totalFlagged > 0 ? 1 : 0);
57
57
  return true;
58
58
  }
59
59
  if (parsed.command === "unused") {
60
60
  const { runUnused } = await import("../commands/unused/runner.js");
61
61
  const result = await runUnused(parsed.options);
62
- process.exitCode = result.totalUnused > 0 || result.totalMissing > 0 ? 1 : 0;
62
+ setRuntimeExitCode(result.totalUnused > 0 || result.totalMissing > 0 ? 1 : 0);
63
63
  return true;
64
64
  }
65
65
  if (parsed.command === "resolve") {
66
66
  const { runResolve } = await import("../commands/resolve/runner.js");
67
67
  const result = await runResolve(parsed.options);
68
- process.exitCode = result.errorConflicts > 0 ? 1 : 0;
68
+ setRuntimeExitCode(result.errorConflicts > 0 ? 1 : 0);
69
69
  return true;
70
70
  }
71
71
  if (parsed.command === "licenses") {
72
72
  const { runLicenses } = await import("../commands/licenses/runner.js");
73
73
  const result = await runLicenses(parsed.options);
74
- process.exitCode = result.totalViolations > 0 ? 1 : 0;
74
+ setRuntimeExitCode(result.totalViolations > 0 ? 1 : 0);
75
75
  return true;
76
76
  }
77
77
  if (parsed.command === "snapshot") {
78
78
  const { runSnapshot } = await import("../commands/snapshot/runner.js");
79
79
  const result = await runSnapshot(parsed.options);
80
- process.exitCode = result.errors.length > 0 ? 1 : 0;
80
+ setRuntimeExitCode(result.errors.length > 0 ? 1 : 0);
81
81
  return true;
82
82
  }
83
83
  if (parsed.command === "review") {
84
84
  const { runReview } = await import("../commands/review/runner.js");
85
85
  const result = await runReview(parsed.options);
86
- process.exitCode =
87
- result.summary.verdict === "blocked" ||
88
- result.summary.verdict === "actionable" ||
89
- result.summary.verdict === "review"
90
- ? 1
91
- : 0;
86
+ setRuntimeExitCode(result.summary.verdict === "blocked" ||
87
+ result.summary.verdict === "actionable" ||
88
+ result.summary.verdict === "review"
89
+ ? 1
90
+ : 0);
92
91
  return true;
93
92
  }
94
93
  if (parsed.command === "doctor") {
95
94
  const { runDoctor } = await import("../commands/doctor/runner.js");
96
95
  const result = await runDoctor(parsed.options);
97
- process.exitCode = result.verdict === "safe" ? 0 : 1;
96
+ setRuntimeExitCode(result.verdict === "safe" ? 0 : 1);
98
97
  return true;
99
98
  }
100
99
  if (parsed.command === "dashboard") {
101
100
  const { runDashboard } = await import("../commands/dashboard/runner.js");
102
101
  const result = await runDashboard(parsed.options);
103
- process.exitCode = result.errors.length > 0 ? 1 : 0;
102
+ setRuntimeExitCode(result.errors.length > 0 ? 1 : 0);
104
103
  return true;
105
104
  }
106
105
  if (parsed.command === "ga") {
107
106
  const { runGa } = await import("../commands/ga/runner.js");
108
107
  const result = await runGa(parsed.options);
109
- process.exitCode = result.ready ? 0 : 1;
108
+ setRuntimeExitCode(result.ready ? 0 : 1);
110
109
  return true;
111
110
  }
112
111
  if (parsed.options.interactive &&
113
112
  (parsed.command === "check" ||
114
113
  parsed.command === "upgrade" ||
115
114
  parsed.command === "ci")) {
116
- const { runReview } = await import("../commands/review/runner.js");
117
- const result = await runReview({
115
+ const { runDashboard } = await import("../commands/dashboard/runner.js");
116
+ const result = await runDashboard({
118
117
  ...parsed.options,
119
- securityOnly: false,
120
- risk: undefined,
121
- diff: undefined,
118
+ mode: parsed.command === "upgrade" ? "upgrade" : "review",
119
+ focus: "all",
122
120
  applySelected: parsed.command === "upgrade",
123
121
  });
124
- process.exitCode =
125
- result.summary.verdict === "safe" && result.updates.length === 0 ? 0 : 1;
122
+ setRuntimeExitCode(result.errors.length > 0 ? 1 : 0);
126
123
  return true;
127
124
  }
128
125
  return false;
package/dist/bin/help.js CHANGED
@@ -41,6 +41,10 @@ Options:
41
41
  --pr-limit <n>
42
42
  --only-changed
43
43
  --interactive
44
+ --plan-file <path>
45
+ --verify none|install|test|install,test
46
+ --test-command <cmd>
47
+ --verification-report-file <path>
44
48
  --show-impact
45
49
  --show-links
46
50
  --show-homepage
@@ -79,7 +83,7 @@ Options:
79
83
  --workspace
80
84
  --sync
81
85
  --install
82
- --pm auto|npm|pnpm
86
+ --pm auto|bun|npm|pnpm|yarn
83
87
  --target patch|minor|major|latest
84
88
  --policy-file <path>
85
89
  --concurrency <n>
@@ -92,6 +96,10 @@ Options:
92
96
  --fix-pr-no-checkout
93
97
  --fix-pr-batch-size <n>
94
98
  --interactive
99
+ --from-plan <path>
100
+ --verify none|install|test|install,test
101
+ --test-command <cmd>
102
+ --verification-report-file <path>
95
103
  --lockfile-mode preserve|update|error
96
104
  --no-pr-report
97
105
  --json-file <path>
@@ -109,6 +117,7 @@ Run CI-oriented automation around the same lifecycle:
109
117
  Options:
110
118
  --workspace
111
119
  --mode minimal|strict|enterprise
120
+ --gate check|doctor|review|upgrade
112
121
  --group-by none|name|scope|kind|risk
113
122
  --group-max <n>
114
123
  --cooldown-days <n>
@@ -126,6 +135,10 @@ Options:
126
135
  --fix-pr-no-checkout
127
136
  --fix-pr-batch-size <n>
128
137
  --no-pr-report
138
+ --plan-file <path>
139
+ --verify none|install|test|install,test
140
+ --test-command <cmd>
141
+ --verification-report-file <path>
129
142
  --json-file <path>
130
143
  --github-output <path>
131
144
  --sarif-file <path>
@@ -192,6 +205,7 @@ Options:
192
205
  --risk critical|high|medium|low
193
206
  --diff patch|minor|major|latest
194
207
  --apply-selected
208
+ --plan-file <path>
195
209
  --show-changelog
196
210
  --policy-file <path>
197
211
  --json-file <path>
@@ -209,6 +223,22 @@ Options:
209
223
  --verdict-only
210
224
  --include-changelog
211
225
  --json-file <path>`;
226
+ }
227
+ if (isCommand && command === "dashboard") {
228
+ return `rainy-updates dashboard [options]
229
+
230
+ Open the primary interactive dependency operations console.
231
+
232
+ Options:
233
+ --workspace
234
+ --mode check|review|upgrade
235
+ --focus all|security|risk|major|blocked|workspace
236
+ --apply-selected
237
+ --plan-file <path>
238
+ --verify none|install|test|install,test
239
+ --test-command <cmd>
240
+ --verification-report-file <path>
241
+ --cwd <path>`;
212
242
  }
213
243
  if (isCommand && command === "ga") {
214
244
  return `rainy-updates ga [options]
@@ -227,7 +257,7 @@ Commands:
227
257
  doctor Summarize what matters
228
258
  review Decide what to do
229
259
  upgrade Apply the approved change set
230
- dashboard Open the interactive DevOps dashboard (Ink TUI)
260
+ dashboard Open the primary interactive dependency dashboard
231
261
  ci Run CI-focused orchestration
232
262
  warm-cache Warm local cache for fast/offline checks
233
263
  init-ci Scaffold GitHub Actions workflow