@rainy-updates/cli 0.5.3 → 0.5.6

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 (44) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/README.md +8 -0
  3. package/dist/bin/cli.js +38 -2
  4. package/dist/commands/audit/runner.js +43 -26
  5. package/dist/commands/dashboard/parser.d.ts +2 -0
  6. package/dist/commands/dashboard/parser.js +59 -0
  7. package/dist/commands/dashboard/runner.d.ts +2 -0
  8. package/dist/commands/dashboard/runner.js +47 -0
  9. package/dist/commands/doctor/parser.js +6 -0
  10. package/dist/commands/ga/parser.d.ts +2 -0
  11. package/dist/commands/ga/parser.js +50 -0
  12. package/dist/commands/ga/runner.d.ts +2 -0
  13. package/dist/commands/ga/runner.js +129 -0
  14. package/dist/commands/resolve/runner.js +7 -3
  15. package/dist/commands/review/parser.js +6 -0
  16. package/dist/commands/review/runner.js +4 -3
  17. package/dist/core/analysis-bundle.d.ts +4 -0
  18. package/dist/core/analysis-bundle.js +241 -0
  19. package/dist/core/artifacts.d.ts +3 -0
  20. package/dist/core/artifacts.js +48 -0
  21. package/dist/core/check.js +6 -1
  22. package/dist/core/options.d.ts +7 -1
  23. package/dist/core/options.js +14 -0
  24. package/dist/core/review-model.js +51 -177
  25. package/dist/core/summary.js +13 -0
  26. package/dist/output/format.js +15 -0
  27. package/dist/output/github.js +8 -0
  28. package/dist/output/sarif.js +12 -0
  29. package/dist/types/index.d.ts +92 -0
  30. package/dist/ui/dashboard/DashboardTUI.d.ts +6 -0
  31. package/dist/ui/dashboard/DashboardTUI.js +34 -0
  32. package/dist/ui/dashboard/components/DetailPanel.d.ts +4 -0
  33. package/dist/ui/dashboard/components/DetailPanel.js +30 -0
  34. package/dist/ui/dashboard/components/Footer.d.ts +4 -0
  35. package/dist/ui/dashboard/components/Footer.js +9 -0
  36. package/dist/ui/dashboard/components/Header.d.ts +4 -0
  37. package/dist/ui/dashboard/components/Header.js +12 -0
  38. package/dist/ui/dashboard/components/Sidebar.d.ts +4 -0
  39. package/dist/ui/dashboard/components/Sidebar.js +23 -0
  40. package/dist/ui/dashboard/store.d.ts +34 -0
  41. package/dist/ui/dashboard/store.js +148 -0
  42. package/dist/ui/tui.d.ts +2 -2
  43. package/dist/ui/tui.js +310 -79
  44. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,108 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## [0.5.6] - 2026-03-01
6
+
7
+ GA readiness, shared analysis plumbing, and richer review operations.
8
+
9
+ ### Added
10
+
11
+ - **New `ga` command** for release and CI readiness auditing:
12
+ - package manager detection,
13
+ - workspace discovery,
14
+ - lockfile presence checks,
15
+ - cache backend inspection,
16
+ - dist build verification,
17
+ - benchmark gate presence,
18
+ - README / CHANGELOG contract checks.
19
+ - **Artifact run metadata**:
20
+ - stable `runId`,
21
+ - generated artifact manifests under `.artifacts/`,
22
+ - additive JSON / SARIF / GitHub output fields for run and decision metadata.
23
+ - **Review and doctor changelog-aware flags**:
24
+ - `review --show-changelog`
25
+ - `doctor --include-changelog`
26
+ - **Interactive review console upgrades**:
27
+ - filter rail,
28
+ - grouping and sorting modes,
29
+ - inline search,
30
+ - detail tabs,
31
+ - help overlay,
32
+ - bulk selection shortcuts,
33
+ - explicit policy and decision-state rendering.
34
+
35
+ ### Changed
36
+
37
+ - `review` and `doctor` now consume a single shared analysis bundle across check, audit, resolve, health, licenses, and unused dependency signals.
38
+ - Update records now carry additive operator metadata:
39
+ - `policyAction`,
40
+ - `decisionState`,
41
+ - `releaseNotesSummary`,
42
+ - `workspaceGroup`,
43
+ - `groupKey`,
44
+ - `selectedByDefault`,
45
+ - `blockedReason`,
46
+ - `monitorReason`.
47
+ - Summary/output contracts now add:
48
+ - `runId`,
49
+ - `artifactManifest`,
50
+ - `blockedPackages`,
51
+ - `reviewPackages`,
52
+ - `monitorPackages`,
53
+ - `cacheBackend`,
54
+ - `degradedSources`,
55
+ - `gaReady`.
56
+ - `check` now records the active cache backend in summary output and attaches workspace grouping metadata to updates.
57
+ - CLI help now documents:
58
+ - `ga`,
59
+ - `--show-changelog`,
60
+ - `--include-changelog`,
61
+ - `--show-links`.
62
+
63
+ ### Tests
64
+
65
+ - Added parser coverage for `ga`, `review --show-changelog`, and `doctor --include-changelog`.
66
+ - Added output coverage for new GitHub output fields.
67
+ - Added GA readiness command coverage.
68
+
69
+ ## [0.5.5] - 2026-03-01
70
+
71
+ Interactive Dashboard TUI overhaul and domain logic integration.
72
+
73
+ ### Added
74
+
75
+ - **Fully functional Interactive Dashboard TUI** (`dashboard` command):
76
+ - Built with Ink for a high-performance (60FPS+) CLI experience.
77
+ - Quick Actions directly bound to core CLI domain logic:
78
+ - **`[R]esolve`**: Runs peer-conflict resolution in the background and updates the UI with severity levels.
79
+ - **`[A]udit`**: Runs security audits in the background and surfaces CVE advisories and risk levels inline.
80
+ - **`<Enter>`**: Applies selected updates and exits the TUI to run the native package manager install.
81
+ - Zero-dependency atomic state manager (`useSyncExternalStore`) to ensure efficient rendering and avoid React Context cascading updates.
82
+ - Seamless background task execution with non-blocking modal overlays (`resolving`, `auditing`).
83
+
84
+ ### Changed
85
+
86
+ - Added `silent: true` flag to `AuditOptions` and `ResolveOptions` to prevent standard stream pollution during background TUI operations.
87
+ - Modified `dashboard` command runner to natively hand-off installation duties to the core `upgrade` flow upon `<Enter>`.
88
+
89
+ ## [0.5.4] - 2026-03-01
90
+
91
+ Production hotfix for interactive review stability.
92
+
93
+ ### Fixed
94
+
95
+ - Fixed a production bug where `review --interactive` could leak raw output from aggregated runners such as `resolve` before the Ink TUI rendered.
96
+ - Fixed the review aggregation silencing model so concurrent dependency analysis no longer races on `stdout` / `stderr` restoration.
97
+ - Restored the intended interactive entry experience for review mode:
98
+ - `Rainy Review Queue`
99
+ - `Review Queue`
100
+ - `Decision Panel`
101
+
102
+ ### Changed
103
+
104
+ - Clarified `doctor --verdict-only` help text so it matches the real 3-line quick-verdict contract.
105
+ - Added dedicated TUI usage documentation in `docs/tui-guide.md` and linked it from the review workflow docs and README.
106
+
5
107
  ## [0.5.3] - 2026-03-01
6
108
 
7
109
  GA stabilization and review-centered workflow refinement.
package/README.md CHANGED
@@ -13,6 +13,9 @@ Command model:
13
13
  Review workflow:
14
14
  [Review workflow guide](./docs/review-workflow.md)
15
15
 
16
+ TUI usage:
17
+ [TUI guide](./docs/tui-guide.md)
18
+
16
19
  Risk engine:
17
20
  [Risk engine guide](./docs/risk-engine.md)
18
21
 
@@ -104,6 +107,7 @@ npx @rainy-updates/cli ci --workspace --mode strict
104
107
  - `doctor` — summarize the current dependency situation
105
108
  - `review` — decide what to do with security, risk, peer, and policy context
106
109
  - `upgrade` — apply the approved change set
110
+ - `ga` — audit GA and CI readiness for the current checkout
107
111
 
108
112
  ### Supporting workflow
109
113
 
@@ -133,6 +137,7 @@ rup doctor --workspace
133
137
  # 3) Review and decide
134
138
  npx @rainy-updates/cli review --security-only
135
139
  rup review --interactive
140
+ rup review --show-changelog
136
141
 
137
142
  # 4) Apply upgrades with workspace sync
138
143
  npx @rainy-updates/cli upgrade --target latest --workspace --sync --install
@@ -178,6 +183,9 @@ rup bisect axios --cmd "bun test" # if installed
178
183
 
179
184
  # 12) Focus review on high-risk changes
180
185
  rup review --risk high --diff major
186
+
187
+ # 13) Audit GA / CI readiness
188
+ rup ga --workspace
181
189
  ```
182
190
 
183
191
  ## What it does in production
package/dist/bin/cli.js CHANGED
@@ -12,6 +12,7 @@ import { initCiWorkflow } from "../core/init-ci.js";
12
12
  import { diffBaseline, saveBaseline } from "../core/baseline.js";
13
13
  import { applyFixPr } from "../core/fix-pr.js";
14
14
  import { applyFixPrBatches } from "../core/fix-pr-batch.js";
15
+ import { createRunId, writeArtifactManifest } from "../core/artifacts.js";
15
16
  import { renderResult } from "../output/format.js";
16
17
  import { writeGitHubOutput } from "../output/github.js";
17
18
  import { createSarifReport } from "../output/sarif.js";
@@ -85,7 +86,7 @@ async function main() {
85
86
  process.exitCode = result.totalFlagged > 0 ? 1 : 0;
86
87
  return;
87
88
  }
88
- // ─── v0.5.3 commands ─────────────────────────────────────────────────────
89
+ // ─── v0.5.4 commands ─────────────────────────────────────────────────────
89
90
  if (parsed.command === "unused") {
90
91
  const { runUnused } = await import("../commands/unused/runner.js");
91
92
  const result = await runUnused(parsed.options);
@@ -128,6 +129,18 @@ async function main() {
128
129
  process.exitCode = result.verdict === "safe" ? 0 : 1;
129
130
  return;
130
131
  }
132
+ if (parsed.command === "dashboard") {
133
+ const { runDashboard } = await import("../commands/dashboard/runner.js");
134
+ const result = await runDashboard(parsed.options);
135
+ process.exitCode = result.errors.length > 0 ? 1 : 0;
136
+ return;
137
+ }
138
+ if (parsed.command === "ga") {
139
+ const { runGa } = await import("../commands/ga/runner.js");
140
+ const result = await runGa(parsed.options);
141
+ process.exitCode = result.ready ? 0 : 1;
142
+ return;
143
+ }
131
144
  if (parsed.options.interactive &&
132
145
  (parsed.command === "check" ||
133
146
  parsed.command === "upgrade" ||
@@ -141,10 +154,13 @@ async function main() {
141
154
  applySelected: parsed.command === "upgrade",
142
155
  });
143
156
  process.exitCode =
144
- result.summary.verdict === "safe" && result.updates.length === 0 ? 0 : 1;
157
+ result.summary.verdict === "safe" && result.updates.length === 0
158
+ ? 0
159
+ : 1;
145
160
  return;
146
161
  }
147
162
  const result = await runCommand(parsed);
163
+ result.summary.runId = createRunId(parsed.command, parsed.options, result);
148
164
  if (parsed.options.fixPr &&
149
165
  (parsed.command === "check" ||
150
166
  parsed.command === "upgrade" ||
@@ -179,6 +195,10 @@ async function main() {
179
195
  const markdown = renderPrReport(result);
180
196
  await writeFileAtomic(parsed.options.prReportFile, markdown + "\n");
181
197
  }
198
+ const artifactManifest = await writeArtifactManifest(parsed.command, parsed.options, result);
199
+ if (artifactManifest) {
200
+ result.summary.artifactManifest = artifactManifest.artifactManifestPath;
201
+ }
182
202
  result.summary.failReason = resolveFailReason(result.updates, result.errors, parsed.options.failOn, parsed.options.maxUpdates, parsed.options.ci);
183
203
  const renderStartedAt = Date.now();
184
204
  let rendered = renderResult(result, parsed.options.format, {
@@ -265,6 +285,7 @@ Options:
265
285
  --only-changed
266
286
  --interactive
267
287
  --show-impact
288
+ --show-links
268
289
  --show-homepage
269
290
  --lockfile-mode preserve|update|error
270
291
  --log-level error|warn|info|debug
@@ -414,6 +435,7 @@ Options:
414
435
  --risk critical|high|medium|low
415
436
  --diff patch|minor|major|latest
416
437
  --apply-selected
438
+ --show-changelog
417
439
  --policy-file <path>
418
440
  --json-file <path>
419
441
  --concurrency <n>
@@ -428,7 +450,18 @@ Produce a fast summary verdict and point the operator to review when action is n
428
450
  Options:
429
451
  --workspace
430
452
  --verdict-only
453
+ --include-changelog
431
454
  --json-file <path>`;
455
+ }
456
+ if (isCommand && command === "ga") {
457
+ return `rainy-updates ga [options]
458
+
459
+ Audit release and CI readiness for Rainy Updates.
460
+
461
+ Options:
462
+ --workspace
463
+ --json-file <path>
464
+ --cwd <path>`;
432
465
  }
433
466
  return `rainy-updates (rup / rainy-up) <command> [options]
434
467
 
@@ -437,6 +470,7 @@ Commands:
437
470
  doctor Summarize what matters
438
471
  review Decide what to do
439
472
  upgrade Apply the approved change set
473
+ dashboard Open the interactive DevOps dashboard (Ink TUI)
440
474
  ci Run CI-focused orchestration
441
475
  warm-cache Warm local cache for fast/offline checks
442
476
  init-ci Scaffold GitHub Actions workflow
@@ -448,6 +482,7 @@ Commands:
448
482
  resolve Check peer dependency conflicts (pure-TS, no subprocess)
449
483
  licenses Scan dependency licenses and generate SPDX SBOM
450
484
  snapshot Save, list, restore, and diff dependency state snapshots
485
+ ga Audit GA and CI readiness for this checkout
451
486
 
452
487
  Global options:
453
488
  --cwd <path>
@@ -468,6 +503,7 @@ Global options:
468
503
  --only-changed
469
504
  --interactive
470
505
  --show-impact
506
+ --show-links
471
507
  --show-homepage
472
508
  --mode minimal|strict|enterprise
473
509
  --fix-pr
@@ -54,7 +54,9 @@ export async function runAudit(options) {
54
54
  result.warnings.push("No dependencies found to audit.");
55
55
  return result;
56
56
  }
57
- process.stderr.write(`[audit] Querying ${describeSourceMode(options.sourceMode)} for ${targetResolution.targets.length} dependency version${targetResolution.targets.length === 1 ? "" : "s"}...\n`);
57
+ if (!options.silent) {
58
+ process.stderr.write(`[audit] Querying ${describeSourceMode(options.sourceMode)} for ${targetResolution.targets.length} dependency version${targetResolution.targets.length === 1 ? "" : "s"}...\n`);
59
+ }
58
60
  const fetched = await fetchAdvisories(targetResolution.targets, {
59
61
  concurrency: options.concurrency,
60
62
  registryTimeoutMs: options.registryTimeoutMs,
@@ -77,15 +79,17 @@ export async function runAudit(options) {
77
79
  result.advisories = advisories;
78
80
  result.packages = summarizeAdvisories(advisories);
79
81
  result.autoFixable = advisories.filter((a) => a.patchedVersion !== null).length;
80
- if (options.reportFormat === "summary") {
81
- process.stdout.write(renderAuditSummary(result.packages) +
82
- renderAuditSourceHealth(result.sourceHealth) +
83
- "\n");
84
- }
85
- else if (options.reportFormat === "table" || !options.jsonFile) {
86
- process.stdout.write(renderAuditTable(advisories) +
87
- renderAuditSourceHealth(result.sourceHealth) +
88
- "\n");
82
+ if (!options.silent) {
83
+ if (options.reportFormat === "summary") {
84
+ process.stdout.write(renderAuditSummary(result.packages) +
85
+ renderAuditSourceHealth(result.sourceHealth) +
86
+ "\n");
87
+ }
88
+ else if (options.reportFormat === "table" || !options.jsonFile) {
89
+ process.stdout.write(renderAuditTable(advisories) +
90
+ renderAuditSourceHealth(result.sourceHealth) +
91
+ "\n");
92
+ }
89
93
  }
90
94
  if (options.jsonFile) {
91
95
  await writeFileAtomic(options.jsonFile, stableStringify({
@@ -97,7 +101,9 @@ export async function runAudit(options) {
97
101
  errors: result.errors,
98
102
  warnings: result.warnings,
99
103
  }, 2) + "\n");
100
- process.stderr.write(`[audit] JSON report written to ${options.jsonFile}\n`);
104
+ if (!options.silent) {
105
+ process.stderr.write(`[audit] JSON report written to ${options.jsonFile}\n`);
106
+ }
101
107
  }
102
108
  if (options.fix && result.autoFixable > 0) {
103
109
  await applyFix(advisories, options);
@@ -120,27 +126,35 @@ async function applyFix(advisories, options) {
120
126
  const installArgs = buildInstallArgs(pm, patchMap);
121
127
  const installCmd = `${pm} ${installArgs.join(" ")}`;
122
128
  if (options.dryRun) {
123
- process.stderr.write(`[audit] --dry-run: would execute:\n ${installCmd}\n`);
124
- if (options.commit) {
125
- const msg = buildCommitMessage(patchMap);
126
- process.stderr.write(`[audit] --dry-run: would commit:\n git commit -m "${msg}"\n`);
129
+ if (!options.silent) {
130
+ process.stderr.write(`[audit] --dry-run: would execute:\n ${installCmd}\n`);
131
+ if (options.commit) {
132
+ const msg = buildCommitMessage(patchMap);
133
+ process.stderr.write(`[audit] --dry-run: would commit:\n git commit -m "${msg}"\n`);
134
+ }
127
135
  }
128
136
  return;
129
137
  }
130
- process.stderr.write(`[audit] Applying ${patchMap.size} fix(es)...\n`);
131
- process.stderr.write(` ${installCmd}\n`);
138
+ if (!options.silent) {
139
+ process.stderr.write(`[audit] Applying ${patchMap.size} fix(es)...\n`);
140
+ process.stderr.write(` → ${installCmd}\n`);
141
+ }
132
142
  try {
133
143
  await runCommand(pm, installArgs, options.cwd);
134
144
  }
135
145
  catch (err) {
136
- process.stderr.write(`[audit] Install failed: ${String(err)}\n`);
146
+ if (!options.silent) {
147
+ process.stderr.write(`[audit] Install failed: ${String(err)}\n`);
148
+ }
137
149
  return;
138
150
  }
139
- process.stderr.write(`[audit] ✔ Patches applied successfully.\n`);
151
+ if (!options.silent) {
152
+ process.stderr.write(`[audit] ✔ Patches applied successfully.\n`);
153
+ }
140
154
  if (options.commit) {
141
- await commitFix(patchMap, options.cwd);
155
+ await commitFix(patchMap, options.cwd, options.silent);
142
156
  }
143
- else {
157
+ else if (!options.silent) {
144
158
  process.stderr.write(`[audit] Tip: run with --commit to automatically commit the changes.\n`);
145
159
  }
146
160
  }
@@ -157,7 +171,7 @@ function buildInstallArgs(pm, patchMap) {
157
171
  return ["install", ...packages]; // npm
158
172
  }
159
173
  }
160
- async function commitFix(patchMap, cwd) {
174
+ async function commitFix(patchMap, cwd, silent) {
161
175
  const msg = buildCommitMessage(patchMap);
162
176
  try {
163
177
  // Stage all modified files (package.json + lockfiles)
@@ -171,12 +185,15 @@ async function commitFix(patchMap, cwd) {
171
185
  "bun.lockb",
172
186
  ], cwd, true);
173
187
  await runCommand("git", ["commit", "-m", msg], cwd);
174
- process.stderr.write(`[audit] ✔ Committed: "${msg}"\n`);
188
+ if (!silent)
189
+ process.stderr.write(`[audit] ✔ Committed: "${msg}"\n`);
175
190
  }
176
191
  catch (err) {
177
- process.stderr.write(`[audit] Git commit failed: ${String(err)}\n`);
178
- process.stderr.write(`[audit] Changes are applied — commit manually with:\n`);
179
- process.stderr.write(` git add -A && git commit -m "${msg}"\n`);
192
+ if (!silent) {
193
+ process.stderr.write(`[audit] Git commit failed: ${String(err)}\n`);
194
+ process.stderr.write(`[audit] Changes are applied commit manually with:\n`);
195
+ process.stderr.write(` git add -A && git commit -m "${msg}"\n`);
196
+ }
180
197
  }
181
198
  }
182
199
  function buildCommitMessage(patchMap) {
@@ -0,0 +1,2 @@
1
+ import type { DashboardOptions } from "../../types/index.js";
2
+ export declare function parseDashboardArgs(args: string[]): DashboardOptions;
@@ -0,0 +1,59 @@
1
+ export function parseDashboardArgs(args) {
2
+ const options = {
3
+ cwd: process.cwd(),
4
+ target: "latest",
5
+ includeKinds: [
6
+ "dependencies",
7
+ "devDependencies",
8
+ "optionalDependencies",
9
+ "peerDependencies",
10
+ ],
11
+ cacheTtlSeconds: 3600,
12
+ ci: false,
13
+ format: "table",
14
+ workspace: false,
15
+ concurrency: 16,
16
+ registryTimeoutMs: 8000,
17
+ registryRetries: 3,
18
+ offline: false,
19
+ stream: false,
20
+ logLevel: "info",
21
+ groupBy: "none",
22
+ onlyChanged: false,
23
+ ciProfile: "minimal",
24
+ lockfileMode: "preserve",
25
+ interactive: true,
26
+ showImpact: false,
27
+ showHomepage: true,
28
+ };
29
+ for (let i = 0; i < args.length; i++) {
30
+ const arg = args[i];
31
+ const nextArg = args[i + 1];
32
+ if (arg === "--view" && nextArg) {
33
+ if (nextArg === "dependencies" ||
34
+ nextArg === "security" ||
35
+ nextArg === "health") {
36
+ options.view = nextArg;
37
+ }
38
+ else {
39
+ throw new Error(`Invalid --view: ${nextArg}`);
40
+ }
41
+ i++;
42
+ continue;
43
+ }
44
+ if (arg === "--view") {
45
+ throw new Error("Missing value for --view");
46
+ }
47
+ // Pass through common workspace / cwd args
48
+ if (arg === "--workspace") {
49
+ options.workspace = true;
50
+ continue;
51
+ }
52
+ if (arg === "--cwd" && nextArg) {
53
+ options.cwd = nextArg;
54
+ i++;
55
+ continue;
56
+ }
57
+ }
58
+ return options;
59
+ }
@@ -0,0 +1,2 @@
1
+ import type { DashboardOptions, DashboardResult } from "../../types/index.js";
2
+ export declare function runDashboard(options: DashboardOptions): Promise<DashboardResult>;
@@ -0,0 +1,47 @@
1
+ import React from "react";
2
+ import { render } from "ink";
3
+ import { loadConfig } from "../../config/loader.js";
4
+ import { DashboardTUI } from "../../ui/dashboard/DashboardTUI.js";
5
+ // We'll need to load initial state or data before or during the render
6
+ import { check } from "../../core/check.js";
7
+ export async function runDashboard(options) {
8
+ // Load configuration
9
+ const resolvedConfig = await loadConfig(options.cwd);
10
+ // Create an initial check result. In a real scenario, this could run
11
+ // progressively in the TUI, but for simplicity we fetch initial data first.
12
+ const checkResult = await check({
13
+ ...options,
14
+ // We do not want `check` to exit or log heavily here, the UI will take over.
15
+ logLevel: "error",
16
+ });
17
+ // Render the interactive Ink Dashboard
18
+ const { waitUntilExit } = render(React.createElement(DashboardTUI, {
19
+ options,
20
+ initialResult: checkResult,
21
+ }));
22
+ await waitUntilExit();
23
+ const finalStore = await import("../../ui/dashboard/store.js");
24
+ const finalState = finalStore.getStore()?.getState();
25
+ if (finalState?.shouldApply) {
26
+ process.stderr.write("[dashboard] Applying updates...\n");
27
+ const { applySelectedUpdates } = await import("../../core/upgrade.js");
28
+ const { detectPackageManager } = await import("../../pm/detect.js");
29
+ const { installDependencies } = await import("../../pm/install.js");
30
+ await applySelectedUpdates({
31
+ ...options,
32
+ install: false, // We handle installation explicitly below
33
+ packageManager: "auto",
34
+ sync: true,
35
+ lockfileMode: options.lockfileMode || "preserve",
36
+ }, finalState.updates);
37
+ // Install using the correct package manager if desired
38
+ const detected = await detectPackageManager(options.cwd);
39
+ await installDependencies(options.cwd, "auto", detected);
40
+ process.stderr.write("[dashboard] Successfully applied updates and installed dependencies.\n");
41
+ }
42
+ return {
43
+ completed: true,
44
+ errors: [],
45
+ warnings: [],
46
+ };
47
+ }
@@ -42,6 +42,7 @@ export function parseDoctorArgs(args) {
42
42
  showImpact: true,
43
43
  showHomepage: true,
44
44
  verdictOnly: false,
45
+ includeChangelog: false,
45
46
  };
46
47
  for (let i = 0; i < args.length; i += 1) {
47
48
  const current = args[i];
@@ -61,6 +62,10 @@ export function parseDoctorArgs(args) {
61
62
  options.verdictOnly = true;
62
63
  continue;
63
64
  }
65
+ if (current === "--include-changelog") {
66
+ options.includeChangelog = true;
67
+ continue;
68
+ }
64
69
  if (current === "--json-file" && next) {
65
70
  options.jsonFile = path.resolve(options.cwd, next);
66
71
  i += 1;
@@ -86,6 +91,7 @@ Usage:
86
91
 
87
92
  Options:
88
93
  --verdict-only Print the 3-line quick verdict without counts
94
+ --include-changelog Include release note summaries in the aggregated review data
89
95
  --workspace Scan all workspace packages
90
96
  --json-file <path> Write JSON doctor report to file
91
97
  --cwd <path>
@@ -0,0 +1,2 @@
1
+ import type { GaOptions } from "../../types/index.js";
2
+ export declare function parseGaArgs(args: string[]): GaOptions;
@@ -0,0 +1,50 @@
1
+ import path from "node:path";
2
+ import process from "node:process";
3
+ export function parseGaArgs(args) {
4
+ const options = {
5
+ cwd: process.cwd(),
6
+ workspace: false,
7
+ jsonFile: undefined,
8
+ };
9
+ for (let i = 0; i < args.length; i += 1) {
10
+ const current = args[i];
11
+ const next = args[i + 1];
12
+ if (current === "--cwd" && next) {
13
+ options.cwd = path.resolve(next);
14
+ i += 1;
15
+ continue;
16
+ }
17
+ if (current === "--cwd")
18
+ throw new Error("Missing value for --cwd");
19
+ if (current === "--workspace") {
20
+ options.workspace = true;
21
+ continue;
22
+ }
23
+ if (current === "--json-file" && next) {
24
+ options.jsonFile = path.resolve(options.cwd, next);
25
+ i += 1;
26
+ continue;
27
+ }
28
+ if (current === "--json-file")
29
+ throw new Error("Missing value for --json-file");
30
+ if (current === "--help" || current === "-h") {
31
+ process.stdout.write(GA_HELP);
32
+ process.exit(0);
33
+ }
34
+ if (current.startsWith("-"))
35
+ throw new Error(`Unknown ga option: ${current}`);
36
+ throw new Error(`Unexpected ga argument: ${current}`);
37
+ }
38
+ return options;
39
+ }
40
+ const GA_HELP = `
41
+ rup ga — Audit release and CI readiness for Rainy Updates
42
+
43
+ Usage:
44
+ rup ga [options]
45
+
46
+ Options:
47
+ --workspace Evaluate workspace package coverage
48
+ --json-file <path> Write JSON GA report to file
49
+ --cwd <path>
50
+ `.trimStart();
@@ -0,0 +1,2 @@
1
+ import type { GaOptions, GaResult } from "../../types/index.js";
2
+ export declare function runGa(options: GaOptions): Promise<GaResult>;