openplanr 2.2640.1 → 2.2640.3
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 +11 -0
- package/dist/cli/commands/planning-artifacts.js +1 -1
- package/dist/cli/commands/planning-artifacts.js.map +1 -1
- package/dist/cli/commands/runtime-output.d.ts +11 -0
- package/dist/cli/commands/runtime-output.d.ts.map +1 -0
- package/dist/cli/commands/runtime-output.js +26 -0
- package/dist/cli/commands/runtime-output.js.map +1 -0
- package/dist/cli/commands/runtime.d.ts.map +1 -1
- package/dist/cli/commands/runtime.js +30 -17
- package/dist/cli/commands/runtime.js.map +1 -1
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +2 -3
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts +1 -1
- package/dist/cli/commands/upgrade.d.ts.map +1 -1
- package/dist/cli/commands/upgrade.js +23 -54
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/dashboard/.vite/manifest.json +1 -1
- package/dist/dashboard/assets/{index-9DLb9EO5.js → index-CaX9EJp4.js} +2 -2
- package/dist/dashboard/assets/{index-9DLb9EO5.js.map → index-CaX9EJp4.js.map} +1 -1
- package/dist/dashboard/dashboard-manifest.json +13 -13
- package/dist/dashboard/index.html +1 -1
- package/dist/services/artifact-service.d.ts.map +1 -1
- package/dist/services/artifact-service.js +4 -1
- package/dist/services/artifact-service.js.map +1 -1
- package/dist/services/runtime-change-summary.d.ts +33 -0
- package/dist/services/runtime-change-summary.d.ts.map +1 -0
- package/dist/services/runtime-change-summary.js +88 -0
- package/dist/services/runtime-change-summary.js.map +1 -0
- package/dist/services/runtime-manager/inventory.d.ts.map +1 -1
- package/dist/services/runtime-manager/inventory.js +8 -1
- package/dist/services/runtime-manager/inventory.js.map +1 -1
- package/dist/services/runtime-manager-service.d.ts +6 -0
- package/dist/services/runtime-manager-service.d.ts.map +1 -1
- package/dist/services/runtime-manager-service.js +28 -0
- package/dist/services/runtime-manager-service.js.map +1 -1
- package/dist/services/upgrade-offer-service.d.ts.map +1 -1
- package/dist/services/upgrade-offer-service.js +6 -30
- package/dist/services/upgrade-offer-service.js.map +1 -1
- package/dist/services/upgrade-report.d.ts +13 -0
- package/dist/services/upgrade-report.d.ts.map +1 -0
- package/dist/services/upgrade-report.js +90 -0
- package/dist/services/upgrade-report.js.map +1 -0
- package/dist/services/upgrade-service.d.ts +48 -29
- package/dist/services/upgrade-service.d.ts.map +1 -1
- package/dist/services/upgrade-service.js +236 -48
- package/dist/services/upgrade-service.js.map +1 -1
- package/dist/templates/backlog/backlog-item.md.hbs +0 -3
- package/docs/CLI.md +7 -2
- package/docs/CROSS_RUNTIME_SETUP.md +2 -2
- package/lib/host-packages/adapter-registry.json +5 -5
- package/lib/host-packages/capability-map.json +1 -1
- package/lib/host-packages/claude/.claude-plugin/marketplace.json +2 -2
- package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +1 -1
- package/lib/host-packages/claude/openplanr/.openplanr-content.json +20 -20
- package/lib/host-packages/claude/openplanr/README.md +1 -1
- package/lib/host-packages/claude/openplanr/skills/design/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design/scripts/design-document.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-document.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-document.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/design-review/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/claude/openplanr/skills/doctor/references/upgrade.md +61 -63
- package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-document.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/claude/openplanr/skills/plan/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/cursor/openplanr/.openplanr-content.json +19 -19
- package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-document.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-document.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-document.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-doctor/references/upgrade.md +61 -63
- package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-document.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/openai/.claude-plugin/marketplace.json +2 -2
- package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +1 -1
- package/lib/host-packages/openai/openplanr/.openplanr-content.json +19 -19
- package/lib/host-packages/openai/openplanr/skills/design/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design/scripts/design-document.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-document.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-document.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/design-review/scripts/runtime/packages/protocol/package.json +1 -1
- package/lib/host-packages/openai/openplanr/skills/doctor/references/upgrade.md +61 -63
- package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-artifact-shell.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-document.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-review-handoff.mjs +1 -1
- package/lib/host-packages/openai/openplanr/skills/plan/scripts/runtime/packages/protocol/package.json +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { display, logger } from '../utils/logger.js';
|
|
2
|
+
import { joinNames } from './runtime-change-summary.js';
|
|
3
|
+
const HIGHLIGHTS_PER_RELEASE = 5;
|
|
4
|
+
function releaseNotesUrl(version) {
|
|
5
|
+
return `https://github.com/openplanr/OpenPlanr/releases/tag/openplanr%40${version}`;
|
|
6
|
+
}
|
|
7
|
+
/** The first sentence of a changelog entry, or the whole entry when it has one sentence. */
|
|
8
|
+
export function firstSentence(text) {
|
|
9
|
+
return /^(.+?[.!?])\s+(?=[A-Z`"(*])/s.exec(text)?.[1] ?? text;
|
|
10
|
+
}
|
|
11
|
+
/** Word-wraps `text` to lines of at most `width` columns; a longer word gets its own line. */
|
|
12
|
+
export function wrapText(text, width) {
|
|
13
|
+
const lines = [];
|
|
14
|
+
let line = '';
|
|
15
|
+
for (const word of text.split(/\s+/).filter(Boolean)) {
|
|
16
|
+
if (line && line.length + 1 + word.length > width) {
|
|
17
|
+
lines.push(line);
|
|
18
|
+
line = word;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
line = line ? `${line} ${word}` : word;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (line)
|
|
25
|
+
lines.push(line);
|
|
26
|
+
return lines;
|
|
27
|
+
}
|
|
28
|
+
function terminalWidth() {
|
|
29
|
+
return Math.min(process.stdout.columns || 80, 100);
|
|
30
|
+
}
|
|
31
|
+
/** Per release, up to five first sentences in `highlights` mode, or every entry in full. */
|
|
32
|
+
export function printReleaseNotes(sections, installedVersion, mode) {
|
|
33
|
+
if (sections.length === 0)
|
|
34
|
+
return;
|
|
35
|
+
display.blank();
|
|
36
|
+
display.heading("What's new");
|
|
37
|
+
const width = terminalWidth() - 6;
|
|
38
|
+
for (const section of sections) {
|
|
39
|
+
display.line(` ${section.version}`);
|
|
40
|
+
const entries = mode === 'full'
|
|
41
|
+
? section.entries
|
|
42
|
+
: section.entries.slice(0, HIGHLIGHTS_PER_RELEASE).map(firstSentence);
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const [first, ...rest] = wrapText(entry, width);
|
|
45
|
+
display.line(` • ${first}`);
|
|
46
|
+
for (const line of rest)
|
|
47
|
+
display.line(` ${line}`);
|
|
48
|
+
}
|
|
49
|
+
const hidden = section.entries.length - entries.length;
|
|
50
|
+
if (hidden > 0)
|
|
51
|
+
display.line(` … and ${hidden} more`);
|
|
52
|
+
}
|
|
53
|
+
display.line(` Full notes: ${releaseNotesUrl(installedVersion)}`);
|
|
54
|
+
}
|
|
55
|
+
/** The commands that bring each installed coding agent up to date, then the restart. */
|
|
56
|
+
export function printNextSteps(steps, error) {
|
|
57
|
+
display.blank();
|
|
58
|
+
display.heading('Next');
|
|
59
|
+
if (error) {
|
|
60
|
+
logger.warn(`${error} Run \`planr upgrade status\` to see what else needs updating.`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (steps.length === 0) {
|
|
64
|
+
logger.success('Your coding agents are up to date.');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
steps.forEach((step, index) => {
|
|
68
|
+
display.numbered(index + 1, step.command);
|
|
69
|
+
display.line(` ${step.host}: ${step.detail}`);
|
|
70
|
+
});
|
|
71
|
+
const hosts = [...new Set(steps.filter((step) => step.runtime).map((step) => step.host))];
|
|
72
|
+
display.line(hosts.length > 0
|
|
73
|
+
? ` Then restart ${joinNames(hosts)} and check with \`planr upgrade status\`.`
|
|
74
|
+
: ' Then check with `planr upgrade status`.');
|
|
75
|
+
}
|
|
76
|
+
/** How `planr upgrade apply` and the inline upgrade offer report an upgrade. */
|
|
77
|
+
export function printUpgradeReport(result, mode) {
|
|
78
|
+
if (!result.ok) {
|
|
79
|
+
logger.error(result.failure?.message ?? 'The upgrade did not complete.');
|
|
80
|
+
if (result.restoredTo)
|
|
81
|
+
logger.info(`Restored the previous version ${result.restoredTo}.`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
logger.success(`Upgraded OpenPlanr from ${result.previousVersion} to ${result.installedVersion}.`);
|
|
85
|
+
if (result.releaseNotesError)
|
|
86
|
+
logger.warn(result.releaseNotesError);
|
|
87
|
+
printReleaseNotes(result.releaseNotes, result.installedVersion, mode);
|
|
88
|
+
printNextSteps(result.nextSteps, result.nextStepsError);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=upgrade-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade-report.js","sourceRoot":"","sources":["../../src/services/upgrade-report.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `planr upgrade`: reconciles the installed CLI, bundled pipeline and host plugin with the
|
|
3
3
|
* published compatible set (npm `latest`, cached, short fetch timeout), upgrades the CLI half
|
|
4
|
-
* with verify-after-install and restore, runs crossed migrations and
|
|
5
|
-
*
|
|
4
|
+
* with verify-after-install and restore, runs crossed migrations and reports the command that
|
|
5
|
+
* updates each installed coding agent. Entry points: `reconcileInstalledTuple`, `planCliUpgrade`,
|
|
6
6
|
* `executeCliHalfUpgrade`. It never changes the host plugin itself.
|
|
7
7
|
*/
|
|
8
|
-
import { type ClaudeCommandRunner
|
|
8
|
+
import { type ClaudeCommandRunner } from './claude-plugin-service.js';
|
|
9
|
+
import { type RuntimeId } from './runtime-manager-service.js';
|
|
9
10
|
/**
|
|
10
11
|
* The command that registers the bundled `openplanr-local` marketplace and installs
|
|
11
|
-
* `planr@openplanr-local` from it. Prescribed instead of
|
|
12
|
+
* `planr@openplanr-local` from it. Prescribed instead of `planr runtime update` when
|
|
12
13
|
* Claude Code has no such marketplace yet, because only setup records the installation.
|
|
13
14
|
*/
|
|
14
15
|
export declare const CLAUDE_PLUGIN_SETUP_COMMAND = "planr setup --runtime claude --scope user";
|
|
15
|
-
/** Shown above the prescribed plugin-half commands by `planr upgrade apply` and the inline offer. */
|
|
16
|
-
export declare const PLUGIN_HALF_INSTRUCTION = "Run these yourself, in order, or ask the agent to run planr-doctor\u2019s upgrade skill. They bring the plugin `planr setup` installs, `planr@openplanr-local`, up to the version bundled with this CLI:";
|
|
17
16
|
/**
|
|
18
17
|
* One component of the published compatibility manifest (`ecosystem.json`'s
|
|
19
18
|
* `components.*`). Each artifact carries its own version plus the mutual
|
|
@@ -120,19 +119,36 @@ export declare function planCliUpgrade(reconciliation: UpgradeReconciliation): U
|
|
|
120
119
|
* version header so a summary can never reach back past the target's section.
|
|
121
120
|
*/
|
|
122
121
|
export declare function summarizeChangelogBetween(oldVersion: string, newVersion: string): string[];
|
|
122
|
+
/** One released version's changelog entries. */
|
|
123
|
+
export interface ReleaseNoteSection {
|
|
124
|
+
version: string;
|
|
125
|
+
entries: string[];
|
|
126
|
+
}
|
|
127
|
+
/** `parseReleaseNotes` over the changelog this CLI ships, or nothing when it ships none. */
|
|
128
|
+
export declare function summarizeReleaseNotes(oldVersion: string, newVersion: string): ReleaseNoteSection[];
|
|
129
|
+
/**
|
|
130
|
+
* The changelog entries released after `oldVersion` up to `newVersion`, newest first, without
|
|
131
|
+
* commit hashes or dependency bumps. Without an `oldVersion` header only the target's own
|
|
132
|
+
* section is returned.
|
|
133
|
+
*/
|
|
134
|
+
export declare function parseReleaseNotes(changelog: string, oldVersion: string, newVersion: string): ReleaseNoteSection[];
|
|
135
|
+
/**
|
|
136
|
+
* A command that brings one installed coding agent up to what this CLI bundles.
|
|
137
|
+
* Without `runtime` it concerns OpenPlanr's own runtime state rather than one agent.
|
|
138
|
+
*/
|
|
139
|
+
export interface UpgradeNextStep {
|
|
140
|
+
runtime?: RuntimeId;
|
|
141
|
+
host: string;
|
|
142
|
+
command: string;
|
|
143
|
+
detail: string;
|
|
144
|
+
}
|
|
123
145
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* every other operation in the order the bundled inspection produced, and each is
|
|
127
|
-
* rendered by `formatClaudePluginOperationCommand` (the same argv setup would run),
|
|
128
|
-
* so the prescription can never drift from what would actually execute. A missing
|
|
129
|
-
* `openplanr-local` marketplace means `planr setup` never ran on this machine, and
|
|
130
|
-
* setup is the one command that both registers it and records the installation.
|
|
131
|
-
* A retired plugin beside it needs `--replace-managed`: setup refuses the removal
|
|
132
|
-
* without the flag, and `--runtime` skips the guided prompt that would offer it.
|
|
133
|
-
* This is a pure formatter — it prints the plugin half, it never runs it.
|
|
146
|
+
* One command per installed coding agent whose OpenPlanr files or plugin trail this CLI,
|
|
147
|
+
* planned with the same preview `planr runtime update` applies.
|
|
134
148
|
*/
|
|
135
|
-
export declare function
|
|
149
|
+
export declare function upgradeNextSteps(projectDir: string, options?: {
|
|
150
|
+
claudeCommandRunner?: ClaudeCommandRunner;
|
|
151
|
+
}): Promise<UpgradeNextStep[]>;
|
|
136
152
|
/** One migration's outcome as the injected registry runner reports it. */
|
|
137
153
|
export interface MigrationRunResult {
|
|
138
154
|
id: string;
|
|
@@ -150,23 +166,20 @@ export interface MigrationRunResult {
|
|
|
150
166
|
export type MigrationRunner = (fromVersion: string, toVersion: string, ctx: {
|
|
151
167
|
projectDir: string;
|
|
152
168
|
}) => Promise<MigrationRunResult[]>;
|
|
153
|
-
/**
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
* from one place and can never print different instructions for the same machine.
|
|
161
|
-
*/
|
|
162
|
-
export declare function pluginHalfPrescription(claudeCommandRunner?: ClaudeCommandRunner): string[];
|
|
169
|
+
/** Runs the OpenPlanr CLI now installed on disk with the given arguments. */
|
|
170
|
+
export type InstalledCliRunner = (args: string[]) => NpmCommandResult;
|
|
171
|
+
/** The next steps as the upgraded CLI reports them from `planr upgrade status --json`. */
|
|
172
|
+
export declare function readInstalledCliNextSteps(projectDir: string, runner?: InstalledCliRunner): {
|
|
173
|
+
nextSteps: UpgradeNextStep[];
|
|
174
|
+
error?: string;
|
|
175
|
+
};
|
|
163
176
|
export interface ExecuteCliHalfUpgradeInput {
|
|
164
177
|
projectDir: string;
|
|
165
178
|
targetCliVersion: string;
|
|
166
179
|
/** Injectable npm runner; defaults to the real (or `OPENPLANR_NPM_BIN`) npm. */
|
|
167
180
|
npmCommandRunner?: NpmCommandRunner;
|
|
168
|
-
/** Injectable
|
|
169
|
-
|
|
181
|
+
/** Injectable runner for the upgraded CLI; defaults to a new process of this entry point. */
|
|
182
|
+
installedCliRunner?: InstalledCliRunner;
|
|
170
183
|
/**
|
|
171
184
|
* Migration runner, run after the CLI half verifies. Omitted (no runner)
|
|
172
185
|
* means no migrations are attempted; the `apply` command injects the real
|
|
@@ -177,9 +190,15 @@ export interface ExecuteCliHalfUpgradeInput {
|
|
|
177
190
|
export interface ExecuteCliHalfUpgradeResult {
|
|
178
191
|
ok: boolean;
|
|
179
192
|
cliUpgraded: boolean;
|
|
193
|
+
previousVersion: string;
|
|
180
194
|
installedVersion: string;
|
|
181
195
|
restoredTo?: string;
|
|
182
196
|
changelogBullets: string[];
|
|
197
|
+
releaseNotes: ReleaseNoteSection[];
|
|
198
|
+
releaseNotesError?: string;
|
|
199
|
+
nextSteps: UpgradeNextStep[];
|
|
200
|
+
nextStepsError?: string;
|
|
201
|
+
/** The commands of `nextSteps`, for readers of the older field. */
|
|
183
202
|
pluginHalfCommands: string[];
|
|
184
203
|
/** Per-migration results for every registered migration this upgrade crossed. */
|
|
185
204
|
migrations: MigrationRunResult[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgrade-service.d.ts","sourceRoot":"","sources":["../../src/services/upgrade-service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EACL,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"upgrade-service.d.ts","sourceRoot":"","sources":["../../src/services/upgrade-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `planr upgrade`: reconciles the installed CLI, bundled pipeline and host plugin with the
|
|
3
3
|
* published compatible set (npm `latest`, cached, short fetch timeout), upgrades the CLI half
|
|
4
|
-
* with verify-after-install and restore, runs crossed migrations and
|
|
5
|
-
*
|
|
4
|
+
* with verify-after-install and restore, runs crossed migrations and reports the command that
|
|
5
|
+
* updates each installed coding agent. Entry points: `reconcileInstalledTuple`, `planCliUpgrade`,
|
|
6
6
|
* `executeCliHalfUpgrade`. It never changes the host plugin itself.
|
|
7
7
|
*/
|
|
8
8
|
import { spawnSync } from 'node:child_process';
|
|
@@ -13,18 +13,17 @@ import { fileURLToPath } from 'node:url';
|
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
import { parseExternalJson } from '../utils/external-json.js';
|
|
15
15
|
import { logger } from '../utils/logger.js';
|
|
16
|
-
import {
|
|
16
|
+
import { inspectBundledClaudePluginIntegration, OPENPLANR_CLAUDE_PLUGIN, } from './claude-plugin-service.js';
|
|
17
17
|
import { resolvePipelinePackage } from './pipeline-package-service.js';
|
|
18
18
|
import { readOpenPlanrVersion } from './provenance-service.js';
|
|
19
|
-
import {
|
|
19
|
+
import { RUNTIME_LABELS, summarizeRuntimeChanges } from './runtime-change-summary.js';
|
|
20
|
+
import { bundledHostRoot, classifyComponentDrift, installedRuntimeScopes, previewSetup, RuntimeManagerError, runtimeRoot, } from './runtime-manager-service.js';
|
|
20
21
|
/**
|
|
21
22
|
* The command that registers the bundled `openplanr-local` marketplace and installs
|
|
22
|
-
* `planr@openplanr-local` from it. Prescribed instead of
|
|
23
|
+
* `planr@openplanr-local` from it. Prescribed instead of `planr runtime update` when
|
|
23
24
|
* Claude Code has no such marketplace yet, because only setup records the installation.
|
|
24
25
|
*/
|
|
25
26
|
export const CLAUDE_PLUGIN_SETUP_COMMAND = 'planr setup --runtime claude --scope user';
|
|
26
|
-
/** Shown above the prescribed plugin-half commands by `planr upgrade apply` and the inline offer. */
|
|
27
|
-
export const PLUGIN_HALF_INSTRUCTION = 'Run these yourself, in order, or ask the agent to run planr-doctor’s upgrade skill. They bring the plugin `planr setup` installs, `planr@openplanr-local`, up to the version bundled with this CLI:';
|
|
28
27
|
/**
|
|
29
28
|
* The published compatible set is the npm registry's `latest` document for the
|
|
30
29
|
* CLI: its version is what a global install lands, and its exact `planr-pipeline`
|
|
@@ -406,7 +405,7 @@ export function planCliUpgrade(reconciliation) {
|
|
|
406
405
|
return {
|
|
407
406
|
proceed: false,
|
|
408
407
|
targetCliVersion: null,
|
|
409
|
-
reason: 'The
|
|
408
|
+
reason: 'The latest OpenPlanr version could not be checked; the npm registry is unreachable.',
|
|
410
409
|
};
|
|
411
410
|
}
|
|
412
411
|
const target = published.cli.version;
|
|
@@ -414,34 +413,34 @@ export function planCliUpgrade(reconciliation) {
|
|
|
414
413
|
return {
|
|
415
414
|
proceed: false,
|
|
416
415
|
targetCliVersion: null,
|
|
417
|
-
reason:
|
|
416
|
+
reason: `OpenPlanr ${installed.cli} is up to date.`,
|
|
418
417
|
};
|
|
419
418
|
}
|
|
420
419
|
if (status === 'upgrade-available') {
|
|
421
420
|
return {
|
|
422
421
|
proceed: true,
|
|
423
422
|
targetCliVersion: target,
|
|
424
|
-
reason: `
|
|
423
|
+
reason: `OpenPlanr ${target} is available; ${installed.cli} is installed.`,
|
|
425
424
|
};
|
|
426
425
|
}
|
|
427
426
|
if (status === 'incompatible' && compareStableVersions(installed.cli, target) < 0) {
|
|
428
427
|
return {
|
|
429
428
|
proceed: true,
|
|
430
429
|
targetCliVersion: target,
|
|
431
|
-
reason: `
|
|
430
|
+
reason: `OpenPlanr ${target} is available, and the installed ${installed.cli} no longer matches its plugins.`,
|
|
432
431
|
};
|
|
433
432
|
}
|
|
434
433
|
if (status === 'incompatible') {
|
|
435
434
|
return {
|
|
436
435
|
proceed: false,
|
|
437
436
|
targetCliVersion: null,
|
|
438
|
-
reason: `
|
|
437
|
+
reason: `OpenPlanr ${installed.cli} is current, but a coding agent's plugin is behind it. Run the commands below.`,
|
|
439
438
|
};
|
|
440
439
|
}
|
|
441
440
|
return {
|
|
442
441
|
proceed: false,
|
|
443
442
|
targetCliVersion: null,
|
|
444
|
-
reason: 'The
|
|
443
|
+
reason: 'The installed OpenPlanr version could not be judged.',
|
|
445
444
|
};
|
|
446
445
|
}
|
|
447
446
|
/**
|
|
@@ -528,44 +527,211 @@ export function summarizeChangelogBetween(oldVersion, newVersion) {
|
|
|
528
527
|
endIndex = firstHeaderAfterStart;
|
|
529
528
|
return extractChangelogBullets(lines.slice(startIndex + 1, endIndex));
|
|
530
529
|
}
|
|
530
|
+
const CHANGESET_COMMIT_PREFIX = /^(?:\[`?[0-9a-f]{7,40}`?\]\([^)]*\):?|[0-9a-f]{7,40}:)\s+/;
|
|
531
|
+
/** `parseReleaseNotes` over the changelog this CLI ships, or nothing when it ships none. */
|
|
532
|
+
export function summarizeReleaseNotes(oldVersion, newVersion) {
|
|
533
|
+
const changelogPath = locateChangelog();
|
|
534
|
+
if (!changelogPath)
|
|
535
|
+
return [];
|
|
536
|
+
return parseReleaseNotes(readFileSync(changelogPath, 'utf8'), oldVersion, newVersion);
|
|
537
|
+
}
|
|
531
538
|
/**
|
|
532
|
-
* The
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
* rendered by `formatClaudePluginOperationCommand` (the same argv setup would run),
|
|
536
|
-
* so the prescription can never drift from what would actually execute. A missing
|
|
537
|
-
* `openplanr-local` marketplace means `planr setup` never ran on this machine, and
|
|
538
|
-
* setup is the one command that both registers it and records the installation.
|
|
539
|
-
* A retired plugin beside it needs `--replace-managed`: setup refuses the removal
|
|
540
|
-
* without the flag, and `--runtime` skips the guided prompt that would offer it.
|
|
541
|
-
* This is a pure formatter — it prints the plugin half, it never runs it.
|
|
539
|
+
* The changelog entries released after `oldVersion` up to `newVersion`, newest first, without
|
|
540
|
+
* commit hashes or dependency bumps. Without an `oldVersion` header only the target's own
|
|
541
|
+
* section is returned.
|
|
542
542
|
*/
|
|
543
|
-
export function
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
543
|
+
export function parseReleaseNotes(changelog, oldVersion, newVersion) {
|
|
544
|
+
const lines = changelog.split(/\r?\n/);
|
|
545
|
+
const startIndex = lines.findIndex((line) => changelogHeaderMatches(line, newVersion));
|
|
546
|
+
if (startIndex === -1)
|
|
547
|
+
return [];
|
|
548
|
+
const hasOldSection = lines.some((line) => changelogHeaderMatches(line, oldVersion));
|
|
549
|
+
const sections = [];
|
|
550
|
+
let entry;
|
|
551
|
+
let skipEntry = false;
|
|
552
|
+
const closeEntry = () => {
|
|
553
|
+
if (entry && !skipEntry)
|
|
554
|
+
sections[sections.length - 1]?.entries.push(entry.join(' '));
|
|
555
|
+
entry = undefined;
|
|
556
|
+
skipEntry = false;
|
|
557
|
+
};
|
|
558
|
+
for (const line of lines.slice(startIndex)) {
|
|
559
|
+
const header = /^##\s+\[?([^\]\s]+)\]?$/.exec(line.trim());
|
|
560
|
+
if (header) {
|
|
561
|
+
closeEntry();
|
|
562
|
+
if (header[1] === oldVersion || (!hasOldSection && sections.length > 0))
|
|
563
|
+
break;
|
|
564
|
+
sections.push({ version: header[1], entries: [] });
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
const item = /^-\s+(.*\S)\s*$/.exec(line);
|
|
568
|
+
if (item) {
|
|
569
|
+
closeEntry();
|
|
570
|
+
const text = item[1].replace(CHANGESET_COMMIT_PREFIX, '');
|
|
571
|
+
skipEntry = /^Updated dependencies\b/.test(text);
|
|
572
|
+
entry = [text];
|
|
573
|
+
}
|
|
574
|
+
else if (entry && /^\s+\S/.test(line)) {
|
|
575
|
+
entry.push(line.trim().replace(/^-\s+/, ''));
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
closeEntry();
|
|
579
|
+
return sections.filter((section) => section.entries.length > 0);
|
|
580
|
+
}
|
|
581
|
+
const RUNTIME_COMMAND_NAMES = {
|
|
582
|
+
'claude-code': 'claude',
|
|
583
|
+
codex: 'codex',
|
|
584
|
+
cursor: 'cursor',
|
|
585
|
+
};
|
|
586
|
+
function nextStepCommand(runtime, scope, skillMode, operations) {
|
|
587
|
+
const claudeKinds = operations
|
|
588
|
+
.filter((operation) => operation.runtime === 'claude-code')
|
|
589
|
+
.map((operation) => operation.kind);
|
|
590
|
+
// Only setup registers the local marketplace and may remove a retired plugin.
|
|
591
|
+
if (claudeKinds.includes('add-marketplace') || claudeKinds.includes('remove')) {
|
|
592
|
+
return `${CLAUDE_PLUGIN_SETUP_COMMAND}${claudeKinds.includes('remove') ? ' --replace-managed' : ''} --yes`;
|
|
593
|
+
}
|
|
594
|
+
// `runtime update` has no skill-mode flag and would move a unified-plugin install to direct skills.
|
|
595
|
+
if (runtime === 'codex' && skillMode === 'unified-plugin') {
|
|
596
|
+
return `planr setup --runtime codex --scope ${scope} --skill-mode unified-plugin --yes`;
|
|
597
|
+
}
|
|
598
|
+
return `planr runtime update ${RUNTIME_COMMAND_NAMES[runtime]} --scope ${scope} --yes`;
|
|
599
|
+
}
|
|
600
|
+
/** Recorded installs, plus a Claude plugin installed without a record of it. */
|
|
601
|
+
async function nextStepCandidates(projectDir, claudeCommandRunner) {
|
|
602
|
+
let candidates = [];
|
|
603
|
+
let stateError;
|
|
604
|
+
try {
|
|
605
|
+
candidates = await installedRuntimeScopes(projectDir);
|
|
606
|
+
}
|
|
607
|
+
catch (error) {
|
|
608
|
+
if (!(error instanceof RuntimeManagerError))
|
|
609
|
+
throw error;
|
|
610
|
+
stateError = error;
|
|
611
|
+
}
|
|
612
|
+
if (!candidates.some(({ runtime, scope }) => runtime === 'claude-code' && scope === 'user')) {
|
|
613
|
+
const plugin = inspectBundledHostPlugin(claudeCommandRunner).plugins.find((entry) => entry.name === OPENPLANR_CLAUDE_PLUGIN);
|
|
614
|
+
if (plugin?.installed)
|
|
615
|
+
candidates.unshift({ runtime: 'claude-code', scope: 'user' });
|
|
616
|
+
}
|
|
617
|
+
return { candidates, ...(stateError ? { stateError } : {}) };
|
|
618
|
+
}
|
|
619
|
+
/** The step one install needs, or `undefined` when it already matches this CLI. */
|
|
620
|
+
async function planNextStep({ runtime, scope, skillMode }, projectDir, claudeCommandRunner) {
|
|
621
|
+
const preview = await previewSetup({
|
|
622
|
+
projectDir,
|
|
623
|
+
cliVersion: readOpenPlanrVersion(),
|
|
624
|
+
runtime,
|
|
625
|
+
scope,
|
|
626
|
+
dryRun: true,
|
|
627
|
+
...(skillMode ? { skillMode } : {}),
|
|
628
|
+
...(claudeCommandRunner ? { claudeCommandRunner } : {}),
|
|
629
|
+
});
|
|
630
|
+
const change = summarizeRuntimeChanges(preview, {
|
|
631
|
+
bookkeepingRoot: runtimeRoot(),
|
|
632
|
+
applied: false,
|
|
633
|
+
}).find((entry) => entry.runtime === runtime);
|
|
634
|
+
if (!change?.changed)
|
|
635
|
+
return undefined;
|
|
636
|
+
return {
|
|
637
|
+
runtime,
|
|
638
|
+
host: change.host,
|
|
639
|
+
command: nextStepCommand(runtime, scope, skillMode, preview.runtimeOperations),
|
|
640
|
+
detail: change.summary,
|
|
641
|
+
};
|
|
556
642
|
}
|
|
557
643
|
/**
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
* Two situations need these commands: a completed CLI upgrade, and a tuple where the CLI
|
|
561
|
-
* is already current but the plugins trail (the state every release creates for anyone
|
|
562
|
-
* who upgrades the npm half first). The second path used to reach no prescription at all
|
|
563
|
-
* while its own message promised one. Deriving the commands here means both surfaces read
|
|
564
|
-
* from one place and can never print different instructions for the same machine.
|
|
644
|
+
* One command per installed coding agent whose OpenPlanr files or plugin trail this CLI,
|
|
645
|
+
* planned with the same preview `planr runtime update` applies.
|
|
565
646
|
*/
|
|
566
|
-
export function
|
|
567
|
-
const
|
|
568
|
-
|
|
647
|
+
export async function upgradeNextSteps(projectDir, options = {}) {
|
|
648
|
+
const steps = [];
|
|
649
|
+
const doctorStep = (error, runtime) => {
|
|
650
|
+
if (steps.some((step) => step.detail === error.message))
|
|
651
|
+
return;
|
|
652
|
+
steps.push({
|
|
653
|
+
...(runtime ? { runtime } : {}),
|
|
654
|
+
host: runtime ? RUNTIME_LABELS[runtime] : 'OpenPlanr',
|
|
655
|
+
command: 'planr doctor',
|
|
656
|
+
detail: error.message,
|
|
657
|
+
});
|
|
658
|
+
};
|
|
659
|
+
const { candidates, stateError } = await nextStepCandidates(projectDir, options.claudeCommandRunner);
|
|
660
|
+
if (stateError)
|
|
661
|
+
doctorStep(stateError);
|
|
662
|
+
for (const candidate of candidates) {
|
|
663
|
+
try {
|
|
664
|
+
const step = await planNextStep(candidate, projectDir, options.claudeCommandRunner);
|
|
665
|
+
if (step)
|
|
666
|
+
steps.push(step);
|
|
667
|
+
}
|
|
668
|
+
catch (error) {
|
|
669
|
+
if (!(error instanceof Error))
|
|
670
|
+
throw error;
|
|
671
|
+
doctorStep(error, candidate.runtime);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return steps;
|
|
675
|
+
}
|
|
676
|
+
// After `npm install -g` this process still executes the previous version's modules,
|
|
677
|
+
// so only a fresh process of the same entry point runs the upgraded code.
|
|
678
|
+
function defaultInstalledCliRunner(args) {
|
|
679
|
+
const entry = process.argv[1];
|
|
680
|
+
if (!entry) {
|
|
681
|
+
return {
|
|
682
|
+
status: null,
|
|
683
|
+
stdout: '',
|
|
684
|
+
stderr: '',
|
|
685
|
+
error: new Error('The entry point of the running CLI is unknown.'),
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
const result = spawnSync(process.execPath, [...process.execArgv, entry, ...args], {
|
|
689
|
+
encoding: 'utf8',
|
|
690
|
+
windowsHide: true,
|
|
691
|
+
timeout: 120_000,
|
|
692
|
+
});
|
|
693
|
+
return {
|
|
694
|
+
status: result.status,
|
|
695
|
+
stdout: result.stdout ?? '',
|
|
696
|
+
stderr: result.stderr ?? '',
|
|
697
|
+
...(result.error ? { error: result.error } : {}),
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
const nextStepsReportSchema = z.object({
|
|
701
|
+
nextSteps: z.array(z.object({
|
|
702
|
+
runtime: z.enum(['claude-code', 'codex', 'cursor']).optional(),
|
|
703
|
+
host: z.string(),
|
|
704
|
+
command: z.string(),
|
|
705
|
+
detail: z.string(),
|
|
706
|
+
})),
|
|
707
|
+
});
|
|
708
|
+
const installedStatusSchema = z.union([
|
|
709
|
+
nextStepsReportSchema,
|
|
710
|
+
z.object({ ok: z.literal(false), problem: z.string() }),
|
|
711
|
+
]);
|
|
712
|
+
/** The next steps as the upgraded CLI reports them from `planr upgrade status --json`. */
|
|
713
|
+
export function readInstalledCliNextSteps(projectDir, runner = defaultInstalledCliRunner) {
|
|
714
|
+
const result = runner(['--project-dir', projectDir, 'upgrade', 'status', '--json']);
|
|
715
|
+
if (result.error) {
|
|
716
|
+
return { nextSteps: [], error: `The upgraded CLI could not be run: ${result.error.message}.` };
|
|
717
|
+
}
|
|
718
|
+
const report = result.stdout.trim().split(/\r?\n/).pop() ?? '';
|
|
719
|
+
try {
|
|
720
|
+
const parsed = parseExternalJson(report, installedStatusSchema, 'planr upgrade status --json');
|
|
721
|
+
if ('nextSteps' in parsed)
|
|
722
|
+
return { nextSteps: parsed.nextSteps };
|
|
723
|
+
return {
|
|
724
|
+
nextSteps: [],
|
|
725
|
+
error: `The upgraded CLI could not list its next steps: ${parsed.problem}`,
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
catch (error) {
|
|
729
|
+
const detail = result.stderr.trim() || (error instanceof Error ? error.message : String(error));
|
|
730
|
+
return {
|
|
731
|
+
nextSteps: [],
|
|
732
|
+
error: `The upgraded CLI did not report its next steps (exit ${result.status}): ${detail}`,
|
|
733
|
+
};
|
|
734
|
+
}
|
|
569
735
|
}
|
|
570
736
|
/**
|
|
571
737
|
* Execute the one half the CLI owns — a global npm install — and
|
|
@@ -593,7 +759,10 @@ export async function executeCliHalfUpgrade(input) {
|
|
|
593
759
|
ok: false,
|
|
594
760
|
cliUpgraded: false,
|
|
595
761
|
installedVersion: readOpenPlanrVersion(),
|
|
762
|
+
previousVersion,
|
|
596
763
|
changelogBullets: [],
|
|
764
|
+
releaseNotes: [],
|
|
765
|
+
nextSteps: [],
|
|
597
766
|
pluginHalfCommands: [],
|
|
598
767
|
migrations: [],
|
|
599
768
|
failure: {
|
|
@@ -618,7 +787,10 @@ export async function executeCliHalfUpgrade(input) {
|
|
|
618
787
|
cliUpgraded: false,
|
|
619
788
|
installedVersion: restoredVersion,
|
|
620
789
|
restoredTo: previousVersion,
|
|
790
|
+
previousVersion,
|
|
621
791
|
changelogBullets: [],
|
|
792
|
+
releaseNotes: [],
|
|
793
|
+
nextSteps: [],
|
|
622
794
|
pluginHalfCommands: [],
|
|
623
795
|
migrations: [],
|
|
624
796
|
failure: { step: 'verify', message },
|
|
@@ -644,7 +816,10 @@ export async function executeCliHalfUpgrade(input) {
|
|
|
644
816
|
ok: false,
|
|
645
817
|
cliUpgraded: true,
|
|
646
818
|
installedVersion: verifiedVersion,
|
|
819
|
+
previousVersion,
|
|
647
820
|
changelogBullets: [],
|
|
821
|
+
releaseNotes: [],
|
|
822
|
+
nextSteps: [],
|
|
648
823
|
pluginHalfCommands: [],
|
|
649
824
|
migrations,
|
|
650
825
|
failure: {
|
|
@@ -659,13 +834,26 @@ export async function executeCliHalfUpgrade(input) {
|
|
|
659
834
|
// "no entries", not as a failed upgrade (which would misreport a machine that
|
|
660
835
|
// is, in fact, upgraded).
|
|
661
836
|
const changelogBullets = summarizeChangelogBetween(previousVersion, verifiedVersion);
|
|
662
|
-
|
|
837
|
+
let releaseNotes = [];
|
|
838
|
+
let releaseNotesError;
|
|
839
|
+
try {
|
|
840
|
+
releaseNotes = summarizeReleaseNotes(previousVersion, verifiedVersion);
|
|
841
|
+
}
|
|
842
|
+
catch (error) {
|
|
843
|
+
releaseNotesError = `The release notes could not be read: ${error instanceof Error ? error.message : String(error)}`;
|
|
844
|
+
}
|
|
845
|
+
const next = readInstalledCliNextSteps(input.projectDir, input.installedCliRunner);
|
|
663
846
|
return {
|
|
664
847
|
ok: true,
|
|
665
848
|
cliUpgraded: true,
|
|
849
|
+
previousVersion,
|
|
666
850
|
installedVersion: verifiedVersion,
|
|
667
851
|
changelogBullets,
|
|
668
|
-
|
|
852
|
+
releaseNotes,
|
|
853
|
+
...(releaseNotesError ? { releaseNotesError } : {}),
|
|
854
|
+
nextSteps: next.nextSteps,
|
|
855
|
+
...(next.error ? { nextStepsError: next.error } : {}),
|
|
856
|
+
pluginHalfCommands: next.nextSteps.map((step) => step.command),
|
|
669
857
|
migrations,
|
|
670
858
|
};
|
|
671
859
|
}
|