@unbrained/pm-cli 2026.5.10 → 2026.5.12

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 (172) hide show
  1. package/.claude-plugin/marketplace.json +4 -4
  2. package/AGENTS.md +3 -116
  3. package/CHANGELOG.md +14 -0
  4. package/PRD.md +11 -11
  5. package/README.md +20 -2
  6. package/dist/cli/argv-utils.d.ts +5 -0
  7. package/dist/cli/argv-utils.js +34 -0
  8. package/dist/cli/argv-utils.js.map +1 -0
  9. package/dist/cli/bootstrap-args.d.ts +15 -0
  10. package/dist/cli/bootstrap-args.js +211 -0
  11. package/dist/cli/bootstrap-args.js.map +1 -1
  12. package/dist/cli/commander-usage.js +109 -3
  13. package/dist/cli/commander-usage.js.map +1 -1
  14. package/dist/cli/commands/completion.js +7 -3
  15. package/dist/cli/commands/completion.js.map +1 -1
  16. package/dist/cli/commands/contracts.d.ts +19 -0
  17. package/dist/cli/commands/contracts.js +40 -2
  18. package/dist/cli/commands/contracts.js.map +1 -1
  19. package/dist/cli/commands/create.js +112 -51
  20. package/dist/cli/commands/create.js.map +1 -1
  21. package/dist/cli/commands/docs.js +9 -2
  22. package/dist/cli/commands/docs.js.map +1 -1
  23. package/dist/cli/commands/extension.d.ts +12 -3
  24. package/dist/cli/commands/extension.js +421 -69
  25. package/dist/cli/commands/extension.js.map +1 -1
  26. package/dist/cli/commands/files.js +9 -2
  27. package/dist/cli/commands/files.js.map +1 -1
  28. package/dist/cli/commands/index.d.ts +1 -0
  29. package/dist/cli/commands/index.js +1 -0
  30. package/dist/cli/commands/index.js.map +1 -1
  31. package/dist/cli/commands/init.d.ts +2 -0
  32. package/dist/cli/commands/init.js +21 -1
  33. package/dist/cli/commands/init.js.map +1 -1
  34. package/dist/cli/commands/metadata-normalizers.d.ts +4 -0
  35. package/dist/cli/commands/metadata-normalizers.js +37 -0
  36. package/dist/cli/commands/metadata-normalizers.js.map +1 -0
  37. package/dist/cli/commands/reindex.js +173 -135
  38. package/dist/cli/commands/reindex.js.map +1 -1
  39. package/dist/cli/commands/search.js +16 -6
  40. package/dist/cli/commands/search.js.map +1 -1
  41. package/dist/cli/commands/test.js +23 -8
  42. package/dist/cli/commands/test.js.map +1 -1
  43. package/dist/cli/commands/update.js +70 -39
  44. package/dist/cli/commands/update.js.map +1 -1
  45. package/dist/cli/commands/upgrade.d.ts +63 -0
  46. package/dist/cli/commands/upgrade.js +260 -0
  47. package/dist/cli/commands/upgrade.js.map +1 -0
  48. package/dist/cli/error-guidance.d.ts +9 -1
  49. package/dist/cli/error-guidance.js +147 -6
  50. package/dist/cli/error-guidance.js.map +1 -1
  51. package/dist/cli/guide-topics.js +18 -16
  52. package/dist/cli/guide-topics.js.map +1 -1
  53. package/dist/cli/help-content.js +42 -2
  54. package/dist/cli/help-content.js.map +1 -1
  55. package/dist/cli/help-json-payload.js +11 -1
  56. package/dist/cli/help-json-payload.js.map +1 -1
  57. package/dist/cli/main.js +69 -6
  58. package/dist/cli/main.js.map +1 -1
  59. package/dist/cli/register-setup.js +174 -82
  60. package/dist/cli/register-setup.js.map +1 -1
  61. package/dist/cli/telemetry-flush.d.ts +2 -0
  62. package/dist/cli/telemetry-flush.js +4 -0
  63. package/dist/cli/telemetry-flush.js.map +1 -0
  64. package/dist/cli.js +1 -2
  65. package/dist/cli.js.map +1 -1
  66. package/dist/core/extensions/extension-types.d.ts +72 -0
  67. package/dist/core/extensions/extension-types.js +24 -0
  68. package/dist/core/extensions/extension-types.js.map +1 -1
  69. package/dist/core/extensions/loader.d.ts +1 -0
  70. package/dist/core/extensions/loader.js +766 -7
  71. package/dist/core/extensions/loader.js.map +1 -1
  72. package/dist/core/lock/lock.js +2 -0
  73. package/dist/core/lock/lock.js.map +1 -1
  74. package/dist/core/packages/manifest.d.ts +13 -0
  75. package/dist/core/packages/manifest.js +139 -0
  76. package/dist/core/packages/manifest.js.map +1 -0
  77. package/dist/core/sentry/instrument.d.ts +15 -0
  78. package/dist/core/sentry/instrument.js +35 -3
  79. package/dist/core/sentry/instrument.js.map +1 -1
  80. package/dist/core/shared/constants.js +20 -0
  81. package/dist/core/shared/constants.js.map +1 -1
  82. package/dist/core/shared/errors.d.ts +8 -0
  83. package/dist/core/shared/errors.js.map +1 -1
  84. package/dist/core/shared/levenshtein.d.ts +1 -0
  85. package/dist/core/shared/levenshtein.js +37 -0
  86. package/dist/core/shared/levenshtein.js.map +1 -0
  87. package/dist/core/store/paths.js +34 -1
  88. package/dist/core/store/paths.js.map +1 -1
  89. package/dist/core/store/settings.js +210 -1
  90. package/dist/core/store/settings.js.map +1 -1
  91. package/dist/core/telemetry/runtime.d.ts +1 -0
  92. package/dist/core/telemetry/runtime.js +102 -3
  93. package/dist/core/telemetry/runtime.js.map +1 -1
  94. package/dist/mcp/server.js +11 -2
  95. package/dist/mcp/server.js.map +1 -1
  96. package/dist/sdk/cli-contracts.d.ts +38 -17
  97. package/dist/sdk/cli-contracts.js +387 -35
  98. package/dist/sdk/cli-contracts.js.map +1 -1
  99. package/dist/sdk/index.d.ts +13 -1
  100. package/dist/sdk/index.js +9 -1
  101. package/dist/sdk/index.js.map +1 -1
  102. package/dist/types.d.ts +41 -0
  103. package/dist/types.js.map +1 -1
  104. package/docs/ARCHITECTURE.md +1 -1
  105. package/docs/CLAUDE_CODE_PLUGIN.md +39 -0
  106. package/docs/COMMANDS.md +14 -1
  107. package/docs/EXTENSIONS.md +782 -12
  108. package/docs/MIGRATION_CLI_SIMPLIFICATION.md +64 -0
  109. package/docs/QUICKSTART.md +10 -2
  110. package/docs/README.md +4 -6
  111. package/docs/SDK.md +445 -0
  112. package/docs/examples/ci/github-actions-pm-extension-gate.yml +53 -0
  113. package/docs/examples/ci/gitlab-ci-pm-extension-gate.yml +41 -0
  114. package/docs/examples/ci/jenkins-pm-extension-gate.Jenkinsfile +45 -0
  115. package/docs/examples/policy-restricted-extension/README.md +74 -0
  116. package/docs/examples/policy-restricted-extension/index.js +21 -0
  117. package/docs/examples/policy-restricted-extension/manifest.json +21 -0
  118. package/docs/examples/policy-restricted-extension/package.json +8 -0
  119. package/docs/examples/sdk-app-embedding/README.md +39 -0
  120. package/docs/examples/sdk-app-embedding/package.json +9 -0
  121. package/docs/examples/sdk-app-embedding/run-embedded-pm.mjs +61 -0
  122. package/docs/examples/sdk-contract-consumer/README.md +57 -0
  123. package/docs/examples/sdk-contract-consumer/inspect-contracts.mjs +47 -0
  124. package/docs/examples/sdk-contract-consumer/package.json +10 -0
  125. package/docs/examples/starter-extension/README.md +57 -42
  126. package/docs/examples/starter-extension/manifest.json +15 -0
  127. package/marketplace.json +3 -3
  128. package/package.json +5 -23
  129. package/packages/pm-beads/README.md +10 -0
  130. package/{.agents/pm → packages/pm-beads}/extensions/beads/index.js +24 -9
  131. package/packages/pm-beads/extensions/beads/index.ts +131 -0
  132. package/packages/pm-beads/package.json +17 -0
  133. package/packages/pm-todos/README.md +11 -0
  134. package/{.agents/pm → packages/pm-todos}/extensions/todos/index.js +24 -9
  135. package/packages/pm-todos/extensions/todos/index.ts +149 -0
  136. package/{.agents/pm → packages/pm-todos}/extensions/todos/runtime.js +1 -1
  137. package/{.agents/pm → packages/pm-todos}/extensions/todos/runtime.ts +1 -1
  138. package/packages/pm-todos/package.json +17 -0
  139. package/plugins/pm-cli-claude/.claude-plugin/plugin.json +2 -2
  140. package/plugins/pm-cli-claude/README.md +54 -14
  141. package/plugins/pm-cli-claude/agents/pm-delivery-chain.md +88 -0
  142. package/plugins/pm-cli-claude/agents/pm-triage-agent.md +83 -0
  143. package/plugins/pm-cli-claude/agents/pm-verification-agent.md +88 -0
  144. package/plugins/pm-cli-claude/hooks/session-start.mjs +35 -21
  145. package/.agents/pm/extensions/.managed-extensions.json +0 -42
  146. package/.agents/skills/HARNESS_COMPATIBILITY.md +0 -45
  147. package/.agents/skills/README.md +0 -21
  148. package/.agents/skills/pm-developer/SKILL.md +0 -73
  149. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +0 -48
  150. package/.agents/skills/pm-developer/references/PROMPTS.md +0 -17
  151. package/.agents/skills/pm-extensions/SKILL.md +0 -57
  152. package/.agents/skills/pm-extensions/references/LIFECYCLE.md +0 -40
  153. package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +0 -25
  154. package/.agents/skills/pm-sdk/SKILL.md +0 -50
  155. package/.agents/skills/pm-sdk/references/INTEGRATION_CHECKLIST.md +0 -31
  156. package/.agents/skills/pm-sdk/references/PROMPTS.md +0 -13
  157. package/.agents/skills/pm-user/SKILL.md +0 -59
  158. package/.agents/skills/pm-user/references/PROMPTS.md +0 -17
  159. package/.agents/skills/pm-user/references/WORKFLOWS.md +0 -35
  160. package/.pi/README.md +0 -26
  161. package/.pi/extensions/pm-cli/index.js +0 -147
  162. package/.pi/prompts/pm-workflow.md +0 -5
  163. package/.pi/skills/pm-native/SKILL.md +0 -40
  164. package/.pi/skills/pm-release/SKILL.md +0 -35
  165. package/dist/pi/native.d.ts +0 -5
  166. package/dist/pi/native.js +0 -183
  167. package/dist/pi/native.js.map +0 -1
  168. package/docs/PI_PACKAGE.md +0 -56
  169. /package/{.agents/pm → packages/pm-beads}/extensions/beads/manifest.json +0 -0
  170. /package/{.agents/pm → packages/pm-beads}/extensions/beads/runtime.js +0 -0
  171. /package/{.agents/pm → packages/pm-beads}/extensions/beads/runtime.ts +0 -0
  172. /package/{.agents/pm → packages/pm-todos}/extensions/todos/manifest.json +0 -0
@@ -0,0 +1,63 @@
1
+ import { type ExtensionScope, type ManagedExtensionSource } from "./extension.js";
2
+ import type { GlobalOptions } from "../../core/shared/command-types.js";
3
+ export interface UpgradeCommandOptions {
4
+ dryRun?: boolean;
5
+ cliOnly?: boolean;
6
+ packagesOnly?: boolean;
7
+ project?: boolean;
8
+ local?: boolean;
9
+ global?: boolean;
10
+ repair?: boolean;
11
+ tag?: string;
12
+ packageName?: string;
13
+ commandRunner?: UpgradeCommandRunner;
14
+ }
15
+ export interface UpgradeCommandRunnerResult {
16
+ stdout: string;
17
+ stderr: string;
18
+ }
19
+ export type UpgradeCommandRunner = (command: string, args: string[], options?: {
20
+ cwd?: string;
21
+ }) => Promise<UpgradeCommandRunnerResult>;
22
+ export interface UpgradeCliResult {
23
+ requested: boolean;
24
+ status: "planned" | "updated" | "failed" | "skipped";
25
+ package: string;
26
+ target: string;
27
+ command: string[];
28
+ before_version?: string;
29
+ after_version?: string;
30
+ repair: boolean;
31
+ reason?: string;
32
+ error?: string;
33
+ }
34
+ export interface UpgradePackageResult {
35
+ name: string;
36
+ directory: string;
37
+ scope: ExtensionScope;
38
+ source: ManagedExtensionSource;
39
+ status: "planned" | "updated" | "failed" | "skipped";
40
+ command: string[];
41
+ previous_version: string;
42
+ installed_version?: string;
43
+ reason?: string;
44
+ error?: string;
45
+ }
46
+ export interface UpgradeResult {
47
+ ok: boolean;
48
+ action: "upgrade";
49
+ dry_run: boolean;
50
+ scope: ExtensionScope;
51
+ target?: string;
52
+ cli: UpgradeCliResult;
53
+ packages: UpgradePackageResult[];
54
+ summary: {
55
+ requested_cli: boolean;
56
+ requested_packages: boolean;
57
+ planned: number;
58
+ updated: number;
59
+ skipped: number;
60
+ failed: number;
61
+ };
62
+ }
63
+ export declare function runUpgrade(target: string | undefined, options: UpgradeCommandOptions, global: GlobalOptions): Promise<UpgradeResult>;
@@ -0,0 +1,260 @@
1
+ import { execFile } from "node:child_process";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { promisify } from "node:util";
6
+ import { readManagedExtensionState, runExtension, } from "./extension.js";
7
+ import { resolveExtensionRoots } from "../../core/extensions/loader.js";
8
+ import { pathExists } from "../../core/fs/fs-utils.js";
9
+ import { EXIT_CODE } from "../../core/shared/constants.js";
10
+ import { PmCliError } from "../../core/shared/errors.js";
11
+ import { resolvePmRoot } from "../../core/store/paths.js";
12
+ const execFileAsync = promisify(execFile);
13
+ const DEFAULT_CLI_PACKAGE = "@unbrained/pm-cli";
14
+ const DEFAULT_TAG = "latest";
15
+ function resolveScope(options) {
16
+ const projectLike = options.project === true || options.local === true;
17
+ const global = options.global === true;
18
+ if (projectLike && global) {
19
+ throw new PmCliError('Options "--project/--local" and "--global" are mutually exclusive.', EXIT_CODE.USAGE);
20
+ }
21
+ return global ? "global" : "project";
22
+ }
23
+ function normalizeTarget(value) {
24
+ return value.trim().toLowerCase();
25
+ }
26
+ function packageRecordMatchesTarget(record, target) {
27
+ const normalizedTarget = normalizeTarget(target);
28
+ const values = [
29
+ record.name,
30
+ record.directory,
31
+ record.source.input,
32
+ record.source.location,
33
+ record.source.package,
34
+ record.source.repository,
35
+ record.source.owner && record.source.repo ? `${record.source.owner}/${record.source.repo}` : undefined,
36
+ ];
37
+ return values.some((value) => typeof value === "string" && normalizeTarget(value) === normalizedTarget);
38
+ }
39
+ function resolveRoots(scope, global) {
40
+ const pmRoot = resolvePmRoot(process.cwd(), global.path);
41
+ const roots = resolveExtensionRoots(pmRoot, process.cwd());
42
+ return {
43
+ selected_root: scope === "global" ? roots.global : roots.project,
44
+ };
45
+ }
46
+ async function defaultCommandRunner(command, args, options) {
47
+ try {
48
+ const result = await execFileAsync(command, args, {
49
+ cwd: options?.cwd,
50
+ encoding: "utf8",
51
+ });
52
+ return {
53
+ stdout: result.stdout ?? "",
54
+ stderr: result.stderr ?? "",
55
+ };
56
+ }
57
+ catch (error) {
58
+ const stderr = typeof error === "object" && error !== null && "stderr" in error
59
+ ? String(error.stderr ?? "")
60
+ : "";
61
+ const message = stderr.trim().length > 0 ? stderr.trim() : error instanceof Error ? error.message : String(error);
62
+ throw new PmCliError(`Command failed: ${command} ${args.join(" ")}\n${message}`, EXIT_CODE.GENERIC_FAILURE);
63
+ }
64
+ }
65
+ async function readCurrentVersion() {
66
+ const packageJsonPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../..", "package.json");
67
+ try {
68
+ const parsed = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
69
+ return typeof parsed.version === "string" ? parsed.version : undefined;
70
+ }
71
+ catch {
72
+ return undefined;
73
+ }
74
+ }
75
+ function resolveTag(options) {
76
+ return typeof options.tag === "string" && options.tag.trim().length > 0 ? options.tag.trim() : DEFAULT_TAG;
77
+ }
78
+ function resolveCliPackage(options) {
79
+ return typeof options.packageName === "string" && options.packageName.trim().length > 0
80
+ ? options.packageName.trim()
81
+ : DEFAULT_CLI_PACKAGE;
82
+ }
83
+ async function upgradeCli(options, dryRun) {
84
+ const runner = options.commandRunner ?? defaultCommandRunner;
85
+ const packageName = resolveCliPackage(options);
86
+ const tag = resolveTag(options);
87
+ const target = `${packageName}@${tag}`;
88
+ const command = ["npm", "install", "-g", target];
89
+ if (options.repair === true) {
90
+ command.push("--force");
91
+ }
92
+ const beforeVersion = await readCurrentVersion();
93
+ const planned = {
94
+ requested: true,
95
+ status: "planned",
96
+ package: packageName,
97
+ target,
98
+ command,
99
+ before_version: beforeVersion,
100
+ repair: options.repair === true,
101
+ };
102
+ if (dryRun) {
103
+ return planned;
104
+ }
105
+ try {
106
+ await runner(command[0], command.slice(1));
107
+ const verified = await runner("pm", ["--version"]);
108
+ return {
109
+ ...planned,
110
+ status: "updated",
111
+ after_version: verified.stdout.trim() || undefined,
112
+ };
113
+ }
114
+ catch (error) {
115
+ return {
116
+ ...planned,
117
+ status: "failed",
118
+ error: error instanceof Error ? error.message : String(error),
119
+ };
120
+ }
121
+ }
122
+ function isLocalNpmSpec(spec) {
123
+ return path.isAbsolute(spec) || spec.startsWith(".") || spec.startsWith("..") || spec.startsWith("file:");
124
+ }
125
+ function resolvePackageInstallSource(source, tag) {
126
+ if (source.kind === "npm") {
127
+ const rawSpec = source.input.startsWith("npm:") ? source.input.slice("npm:".length).trim() : source.input.trim();
128
+ if (!isLocalNpmSpec(rawSpec) && source.package && source.package.trim().length > 0) {
129
+ return `npm:${source.package.trim()}@${tag}`;
130
+ }
131
+ return source.input.startsWith("npm:") ? source.input : `npm:${source.input}`;
132
+ }
133
+ return source.input;
134
+ }
135
+ async function resolveRunnablePackageSource(source, tag) {
136
+ const installSource = resolvePackageInstallSource(source, tag);
137
+ if (source.kind !== "local") {
138
+ return installSource;
139
+ }
140
+ if (await pathExists(installSource)) {
141
+ return installSource;
142
+ }
143
+ if (await pathExists(source.location)) {
144
+ return source.location;
145
+ }
146
+ return installSource;
147
+ }
148
+ function packageCommandFor(source, installSource, scope, ref) {
149
+ const command = ["pm", "install", installSource, scope === "global" ? "--global" : "--project"];
150
+ if (source.kind === "github" && ref && ref.trim().length > 0) {
151
+ command.push("--ref", ref.trim());
152
+ }
153
+ return command;
154
+ }
155
+ async function readManagedRecords(scope, global) {
156
+ const roots = resolveRoots(scope, global);
157
+ const managedState = await readManagedExtensionState(roots.selected_root);
158
+ return managedState.state.entries.filter((entry) => entry.scope === scope);
159
+ }
160
+ async function refreshManagedRecord(scope, global, record) {
161
+ const records = await readManagedRecords(scope, global);
162
+ return records.find((candidate) => packageRecordMatchesTarget(candidate, record.name)) ??
163
+ records.find((candidate) => normalizeTarget(candidate.directory) === normalizeTarget(record.directory));
164
+ }
165
+ async function upgradePackageRecord(record, options, global, scope, dryRun) {
166
+ const tag = resolveTag(options);
167
+ const installSource = await resolveRunnablePackageSource(record.source, tag);
168
+ const command = packageCommandFor(record.source, installSource, scope, record.source.ref);
169
+ const planned = {
170
+ name: record.name,
171
+ directory: record.directory,
172
+ scope,
173
+ source: record.source,
174
+ status: "planned",
175
+ command,
176
+ previous_version: record.manifest_version,
177
+ };
178
+ if (dryRun) {
179
+ return planned;
180
+ }
181
+ try {
182
+ await runExtension(installSource, {
183
+ install: true,
184
+ project: scope === "project",
185
+ global: scope === "global",
186
+ ref: record.source.kind === "github" ? record.source.ref : undefined,
187
+ }, global);
188
+ const refreshed = await refreshManagedRecord(scope, global, record);
189
+ return {
190
+ ...planned,
191
+ status: "updated",
192
+ installed_version: refreshed?.manifest_version,
193
+ };
194
+ }
195
+ catch (error) {
196
+ return {
197
+ ...planned,
198
+ status: "failed",
199
+ error: error instanceof Error ? error.message : String(error),
200
+ };
201
+ }
202
+ }
203
+ function summarize(cli, packages, includeCli, includePackages) {
204
+ const statuses = [includeCli ? cli.status : undefined, ...packages.map((entry) => entry.status)].filter((value) => typeof value === "string");
205
+ return {
206
+ requested_cli: includeCli,
207
+ requested_packages: includePackages,
208
+ planned: statuses.filter((status) => status === "planned").length,
209
+ updated: statuses.filter((status) => status === "updated").length,
210
+ skipped: statuses.filter((status) => status === "skipped").length,
211
+ failed: statuses.filter((status) => status === "failed").length,
212
+ };
213
+ }
214
+ export async function runUpgrade(target, options, global) {
215
+ if (options.cliOnly === true && options.packagesOnly === true) {
216
+ throw new PmCliError('Options "--cli-only" and "--packages-only" are mutually exclusive.', EXIT_CODE.USAGE);
217
+ }
218
+ const scope = resolveScope(options);
219
+ const dryRun = options.dryRun === true;
220
+ const normalizedTarget = typeof target === "string" && target.trim().length > 0 ? target.trim() : undefined;
221
+ if (options.cliOnly === true && normalizedTarget) {
222
+ throw new PmCliError('A package target cannot be used with "--cli-only".', EXIT_CODE.USAGE);
223
+ }
224
+ const includeCli = options.packagesOnly === true || normalizedTarget ? false : true;
225
+ const includePackages = options.cliOnly === true ? false : true;
226
+ const cli = includeCli
227
+ ? await upgradeCli(options, dryRun)
228
+ : {
229
+ requested: false,
230
+ status: "skipped",
231
+ package: resolveCliPackage(options),
232
+ target: `${resolveCliPackage(options)}@${resolveTag(options)}`,
233
+ command: ["npm", "install", "-g", `${resolveCliPackage(options)}@${resolveTag(options)}`],
234
+ repair: options.repair === true,
235
+ reason: "not_requested",
236
+ };
237
+ let packageRecords = includePackages ? await readManagedRecords(scope, global) : [];
238
+ if (normalizedTarget) {
239
+ packageRecords = packageRecords.filter((entry) => packageRecordMatchesTarget(entry, normalizedTarget));
240
+ if (packageRecords.length === 0) {
241
+ throw new PmCliError(`Managed package "${normalizedTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
242
+ }
243
+ }
244
+ const packages = [];
245
+ for (const record of packageRecords) {
246
+ packages.push(await upgradePackageRecord(record, options, global, scope, dryRun));
247
+ }
248
+ const summary = summarize(cli, packages, includeCli, includePackages);
249
+ return {
250
+ ok: summary.failed === 0,
251
+ action: "upgrade",
252
+ dry_run: dryRun,
253
+ scope,
254
+ target: normalizedTarget,
255
+ cli,
256
+ packages,
257
+ summary,
258
+ };
259
+ }
260
+ //# sourceMappingURL=upgrade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade.js","sourceRoot":"/","sources":["cli/commands/upgrade.ts"],"names":[],"mappings":"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","sourcesContent":["import { execFile } from \"node:child_process\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { promisify } from \"node:util\";\nimport {\n readManagedExtensionState,\n runExtension,\n type ExtensionScope,\n type ManagedExtensionRecord,\n type ManagedExtensionSource,\n} from \"./extension.js\";\nimport { resolveExtensionRoots } from \"../../core/extensions/loader.js\";\nimport { pathExists } from \"../../core/fs/fs-utils.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { EXIT_CODE } from \"../../core/shared/constants.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport { resolvePmRoot } from \"../../core/store/paths.js\";\n\nconst execFileAsync = promisify(execFile);\nconst DEFAULT_CLI_PACKAGE = \"@unbrained/pm-cli\";\nconst DEFAULT_TAG = \"latest\";\n\nexport interface UpgradeCommandOptions {\n dryRun?: boolean;\n cliOnly?: boolean;\n packagesOnly?: boolean;\n project?: boolean;\n local?: boolean;\n global?: boolean;\n repair?: boolean;\n tag?: string;\n packageName?: string;\n commandRunner?: UpgradeCommandRunner;\n}\n\nexport interface UpgradeCommandRunnerResult {\n stdout: string;\n stderr: string;\n}\n\nexport type UpgradeCommandRunner = (\n command: string,\n args: string[],\n options?: { cwd?: string },\n) => Promise<UpgradeCommandRunnerResult>;\n\nexport interface UpgradeCliResult {\n requested: boolean;\n status: \"planned\" | \"updated\" | \"failed\" | \"skipped\";\n package: string;\n target: string;\n command: string[];\n before_version?: string;\n after_version?: string;\n repair: boolean;\n reason?: string;\n error?: string;\n}\n\nexport interface UpgradePackageResult {\n name: string;\n directory: string;\n scope: ExtensionScope;\n source: ManagedExtensionSource;\n status: \"planned\" | \"updated\" | \"failed\" | \"skipped\";\n command: string[];\n previous_version: string;\n installed_version?: string;\n reason?: string;\n error?: string;\n}\n\nexport interface UpgradeResult {\n ok: boolean;\n action: \"upgrade\";\n dry_run: boolean;\n scope: ExtensionScope;\n target?: string;\n cli: UpgradeCliResult;\n packages: UpgradePackageResult[];\n summary: {\n requested_cli: boolean;\n requested_packages: boolean;\n planned: number;\n updated: number;\n skipped: number;\n failed: number;\n };\n}\n\nfunction resolveScope(options: UpgradeCommandOptions): ExtensionScope {\n const projectLike = options.project === true || options.local === true;\n const global = options.global === true;\n if (projectLike && global) {\n throw new PmCliError('Options \"--project/--local\" and \"--global\" are mutually exclusive.', EXIT_CODE.USAGE);\n }\n return global ? \"global\" : \"project\";\n}\n\nfunction normalizeTarget(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction packageRecordMatchesTarget(record: ManagedExtensionRecord, target: string): boolean {\n const normalizedTarget = normalizeTarget(target);\n const values = [\n record.name,\n record.directory,\n record.source.input,\n record.source.location,\n record.source.package,\n record.source.repository,\n record.source.owner && record.source.repo ? `${record.source.owner}/${record.source.repo}` : undefined,\n ];\n return values.some((value) => typeof value === \"string\" && normalizeTarget(value) === normalizedTarget);\n}\n\nfunction resolveRoots(scope: ExtensionScope, global: GlobalOptions): {\n selected_root: string;\n} {\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n const roots = resolveExtensionRoots(pmRoot, process.cwd());\n return {\n selected_root: scope === \"global\" ? roots.global : roots.project,\n };\n}\n\nasync function defaultCommandRunner(\n command: string,\n args: string[],\n options?: { cwd?: string },\n): Promise<UpgradeCommandRunnerResult> {\n try {\n const result = await execFileAsync(command, args, {\n cwd: options?.cwd,\n encoding: \"utf8\",\n });\n return {\n stdout: result.stdout ?? \"\",\n stderr: result.stderr ?? \"\",\n };\n } catch (error: unknown) {\n const stderr = typeof error === \"object\" && error !== null && \"stderr\" in error\n ? String((error as { stderr?: unknown }).stderr ?? \"\")\n : \"\";\n const message = stderr.trim().length > 0 ? stderr.trim() : error instanceof Error ? error.message : String(error);\n throw new PmCliError(`Command failed: ${command} ${args.join(\" \")}\\n${message}`, EXIT_CODE.GENERIC_FAILURE);\n }\n}\n\nasync function readCurrentVersion(): Promise<string | undefined> {\n const packageJsonPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), \"../../..\", \"package.json\");\n try {\n const parsed = JSON.parse(await fs.readFile(packageJsonPath, \"utf8\")) as { version?: unknown };\n return typeof parsed.version === \"string\" ? parsed.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveTag(options: UpgradeCommandOptions): string {\n return typeof options.tag === \"string\" && options.tag.trim().length > 0 ? options.tag.trim() : DEFAULT_TAG;\n}\n\nfunction resolveCliPackage(options: UpgradeCommandOptions): string {\n return typeof options.packageName === \"string\" && options.packageName.trim().length > 0\n ? options.packageName.trim()\n : DEFAULT_CLI_PACKAGE;\n}\n\nasync function upgradeCli(options: UpgradeCommandOptions, dryRun: boolean): Promise<UpgradeCliResult> {\n const runner = options.commandRunner ?? defaultCommandRunner;\n const packageName = resolveCliPackage(options);\n const tag = resolveTag(options);\n const target = `${packageName}@${tag}`;\n const command = [\"npm\", \"install\", \"-g\", target];\n if (options.repair === true) {\n command.push(\"--force\");\n }\n const beforeVersion = await readCurrentVersion();\n const planned: UpgradeCliResult = {\n requested: true,\n status: \"planned\",\n package: packageName,\n target,\n command,\n before_version: beforeVersion,\n repair: options.repair === true,\n };\n if (dryRun) {\n return planned;\n }\n try {\n await runner(command[0]!, command.slice(1));\n const verified = await runner(\"pm\", [\"--version\"]);\n return {\n ...planned,\n status: \"updated\",\n after_version: verified.stdout.trim() || undefined,\n };\n } catch (error: unknown) {\n return {\n ...planned,\n status: \"failed\",\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nfunction isLocalNpmSpec(spec: string): boolean {\n return path.isAbsolute(spec) || spec.startsWith(\".\") || spec.startsWith(\"..\") || spec.startsWith(\"file:\");\n}\n\nfunction resolvePackageInstallSource(source: ManagedExtensionSource, tag: string): string {\n if (source.kind === \"npm\") {\n const rawSpec = source.input.startsWith(\"npm:\") ? source.input.slice(\"npm:\".length).trim() : source.input.trim();\n if (!isLocalNpmSpec(rawSpec) && source.package && source.package.trim().length > 0) {\n return `npm:${source.package.trim()}@${tag}`;\n }\n return source.input.startsWith(\"npm:\") ? source.input : `npm:${source.input}`;\n }\n return source.input;\n}\n\nasync function resolveRunnablePackageSource(source: ManagedExtensionSource, tag: string): Promise<string> {\n const installSource = resolvePackageInstallSource(source, tag);\n if (source.kind !== \"local\") {\n return installSource;\n }\n if (await pathExists(installSource)) {\n return installSource;\n }\n if (await pathExists(source.location)) {\n return source.location;\n }\n return installSource;\n}\n\nfunction packageCommandFor(source: ManagedExtensionSource, installSource: string, scope: ExtensionScope, ref?: string): string[] {\n const command = [\"pm\", \"install\", installSource, scope === \"global\" ? \"--global\" : \"--project\"];\n if (source.kind === \"github\" && ref && ref.trim().length > 0) {\n command.push(\"--ref\", ref.trim());\n }\n return command;\n}\n\nasync function readManagedRecords(scope: ExtensionScope, global: GlobalOptions): Promise<ManagedExtensionRecord[]> {\n const roots = resolveRoots(scope, global);\n const managedState = await readManagedExtensionState(roots.selected_root);\n return managedState.state.entries.filter((entry) => entry.scope === scope);\n}\n\nasync function refreshManagedRecord(\n scope: ExtensionScope,\n global: GlobalOptions,\n record: ManagedExtensionRecord,\n): Promise<ManagedExtensionRecord | undefined> {\n const records = await readManagedRecords(scope, global);\n return records.find((candidate) => packageRecordMatchesTarget(candidate, record.name)) ??\n records.find((candidate) => normalizeTarget(candidate.directory) === normalizeTarget(record.directory));\n}\n\nasync function upgradePackageRecord(\n record: ManagedExtensionRecord,\n options: UpgradeCommandOptions,\n global: GlobalOptions,\n scope: ExtensionScope,\n dryRun: boolean,\n): Promise<UpgradePackageResult> {\n const tag = resolveTag(options);\n const installSource = await resolveRunnablePackageSource(record.source, tag);\n const command = packageCommandFor(record.source, installSource, scope, record.source.ref);\n const planned: UpgradePackageResult = {\n name: record.name,\n directory: record.directory,\n scope,\n source: record.source,\n status: \"planned\",\n command,\n previous_version: record.manifest_version,\n };\n if (dryRun) {\n return planned;\n }\n try {\n await runExtension(\n installSource,\n {\n install: true,\n project: scope === \"project\",\n global: scope === \"global\",\n ref: record.source.kind === \"github\" ? record.source.ref : undefined,\n },\n global,\n );\n const refreshed = await refreshManagedRecord(scope, global, record);\n return {\n ...planned,\n status: \"updated\",\n installed_version: refreshed?.manifest_version,\n };\n } catch (error: unknown) {\n return {\n ...planned,\n status: \"failed\",\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nfunction summarize(\n cli: UpgradeCliResult,\n packages: UpgradePackageResult[],\n includeCli: boolean,\n includePackages: boolean,\n): UpgradeResult[\"summary\"] {\n const statuses = [includeCli ? cli.status : undefined, ...packages.map((entry) => entry.status)].filter(\n (value): value is UpgradeCliResult[\"status\"] => typeof value === \"string\",\n );\n return {\n requested_cli: includeCli,\n requested_packages: includePackages,\n planned: statuses.filter((status) => status === \"planned\").length,\n updated: statuses.filter((status) => status === \"updated\").length,\n skipped: statuses.filter((status) => status === \"skipped\").length,\n failed: statuses.filter((status) => status === \"failed\").length,\n };\n}\n\nexport async function runUpgrade(\n target: string | undefined,\n options: UpgradeCommandOptions,\n global: GlobalOptions,\n): Promise<UpgradeResult> {\n if (options.cliOnly === true && options.packagesOnly === true) {\n throw new PmCliError('Options \"--cli-only\" and \"--packages-only\" are mutually exclusive.', EXIT_CODE.USAGE);\n }\n\n const scope = resolveScope(options);\n const dryRun = options.dryRun === true;\n const normalizedTarget = typeof target === \"string\" && target.trim().length > 0 ? target.trim() : undefined;\n if (options.cliOnly === true && normalizedTarget) {\n throw new PmCliError('A package target cannot be used with \"--cli-only\".', EXIT_CODE.USAGE);\n }\n const includeCli = options.packagesOnly === true || normalizedTarget ? false : true;\n const includePackages = options.cliOnly === true ? false : true;\n const cli = includeCli\n ? await upgradeCli(options, dryRun)\n : {\n requested: false,\n status: \"skipped\",\n package: resolveCliPackage(options),\n target: `${resolveCliPackage(options)}@${resolveTag(options)}`,\n command: [\"npm\", \"install\", \"-g\", `${resolveCliPackage(options)}@${resolveTag(options)}`],\n repair: options.repair === true,\n reason: \"not_requested\",\n } as UpgradeCliResult;\n\n let packageRecords = includePackages ? await readManagedRecords(scope, global) : [];\n if (normalizedTarget) {\n packageRecords = packageRecords.filter((entry) => packageRecordMatchesTarget(entry, normalizedTarget));\n if (packageRecords.length === 0) {\n throw new PmCliError(`Managed package \"${normalizedTarget}\" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);\n }\n }\n\n const packages: UpgradePackageResult[] = [];\n for (const record of packageRecords) {\n packages.push(await upgradePackageRecord(record, options, global, scope, dryRun));\n }\n\n const summary = summarize(cli, packages, includeCli, includePackages);\n return {\n ok: summary.failed === 0,\n action: \"upgrade\",\n dry_run: dryRun,\n scope,\n target: normalizedTarget,\n cli,\n packages,\n summary,\n };\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { PmCliErrorContext } from "../core/shared/errors.js";
1
+ import type { PmCliErrorContext, PmCliErrorRecoveryPayload } from "../core/shared/errors.js";
2
2
  interface GuidanceMessage {
3
3
  code: string;
4
4
  type: string;
@@ -8,6 +8,7 @@ interface GuidanceMessage {
8
8
  why?: string;
9
9
  examples?: string[];
10
10
  nextSteps?: string[];
11
+ recovery?: PmCliErrorRecoveryPayload;
11
12
  }
12
13
  export interface JsonErrorEnvelope {
13
14
  type: string;
@@ -19,6 +20,7 @@ export interface JsonErrorEnvelope {
19
20
  why?: string;
20
21
  examples?: string[];
21
22
  next_steps?: string[];
23
+ recovery?: PmCliErrorRecoveryPayload;
22
24
  }
23
25
  export interface ErrorClassification {
24
26
  type: string;
@@ -29,10 +31,16 @@ export interface ErrorClassification {
29
31
  why?: string;
30
32
  examples?: string[];
31
33
  next_steps?: string[];
34
+ recovery?: PmCliErrorRecoveryPayload;
32
35
  }
33
36
  export interface CommanderGuidanceContext {
34
37
  unknownCommandExamples?: string[];
35
38
  unknownCommandNextSteps?: string[];
39
+ attemptedCommand?: string;
40
+ normalizedInvocationArgs?: string[];
41
+ providedOptionFlags?: string[];
42
+ unknownOptionSuggestions?: string[];
43
+ suggestedRetryCommand?: string;
36
44
  }
37
45
  export declare function renderGuidanceMessage(message: GuidanceMessage): string;
38
46
  export declare function formatPmCliErrorForDisplay(rawMessage: string, context?: PmCliErrorContext): string;
@@ -1,3 +1,4 @@
1
+ import { renderPmCommand } from "./argv-utils.js";
1
2
  function errorType(code) {
2
3
  return `urn:pm-cli:error:${code}`;
3
4
  }
@@ -13,6 +14,60 @@ function renderList(title, entries) {
13
14
  }
14
15
  return [title, ...entries.map((entry) => ` - ${entry}`)];
15
16
  }
17
+ function normalizeRecoveryPayload(payload) {
18
+ if (!payload || typeof payload !== "object") {
19
+ return undefined;
20
+ }
21
+ const normalized = {};
22
+ if (typeof payload.attempted_command === "string" && payload.attempted_command.trim().length > 0) {
23
+ normalized.attempted_command = payload.attempted_command.trim();
24
+ }
25
+ if (Array.isArray(payload.normalized_args)) {
26
+ const args = payload.normalized_args.map((entry) => entry.trim()).filter((entry) => entry.length > 0);
27
+ if (args.length > 0) {
28
+ normalized.normalized_args = args;
29
+ }
30
+ }
31
+ if (Array.isArray(payload.provided_fields)) {
32
+ const fields = payload.provided_fields.map((entry) => entry.trim()).filter((entry) => entry.length > 0);
33
+ if (fields.length > 0) {
34
+ normalized.provided_fields = fields;
35
+ }
36
+ }
37
+ if (Array.isArray(payload.missing)) {
38
+ const missing = payload.missing.map((entry) => entry.trim()).filter((entry) => entry.length > 0);
39
+ if (missing.length > 0) {
40
+ normalized.missing = missing;
41
+ }
42
+ }
43
+ if (typeof payload.suggested_retry === "string" && payload.suggested_retry.trim().length > 0) {
44
+ normalized.suggested_retry = payload.suggested_retry.trim();
45
+ }
46
+ return Object.keys(normalized).length > 0 ? normalized : undefined;
47
+ }
48
+ function renderRecoveryBundle(recovery) {
49
+ const normalized = normalizeRecoveryPayload(recovery);
50
+ if (!normalized) {
51
+ return [];
52
+ }
53
+ const lines = ["Recovery bundle:"];
54
+ if (normalized.attempted_command) {
55
+ lines.push(` attempted_command: ${normalized.attempted_command}`);
56
+ }
57
+ if (normalized.normalized_args && normalized.normalized_args.length > 0) {
58
+ lines.push(` normalized_args: ${normalized.normalized_args.join(" ")}`);
59
+ }
60
+ if (normalized.provided_fields && normalized.provided_fields.length > 0) {
61
+ lines.push(` provided_fields: ${normalized.provided_fields.join(", ")}`);
62
+ }
63
+ if (normalized.missing && normalized.missing.length > 0) {
64
+ lines.push(` missing: ${normalized.missing.join(", ")}`);
65
+ }
66
+ if (normalized.suggested_retry) {
67
+ lines.push(` suggested_retry: ${normalized.suggested_retry}`);
68
+ }
69
+ return lines;
70
+ }
16
71
  export function renderGuidanceMessage(message) {
17
72
  const lines = [
18
73
  `Error: ${message.title}`,
@@ -35,6 +90,11 @@ export function renderGuidanceMessage(message) {
35
90
  lines.push("");
36
91
  lines.push(...renderList("Next steps:", message.nextSteps));
37
92
  }
93
+ const recoveryLines = renderRecoveryBundle(message.recovery);
94
+ if (recoveryLines.length > 0) {
95
+ lines.push("");
96
+ lines.push(...recoveryLines);
97
+ }
38
98
  return lines.join("\n");
39
99
  }
40
100
  function guidanceToJsonEnvelope(message, exitCode) {
@@ -55,6 +115,9 @@ function guidanceToJsonEnvelope(message, exitCode) {
55
115
  if (message.nextSteps && message.nextSteps.length > 0) {
56
116
  payload.next_steps = message.nextSteps;
57
117
  }
118
+ if (message.recovery) {
119
+ payload.recovery = message.recovery;
120
+ }
58
121
  return payload;
59
122
  }
60
123
  function guidanceToClassification(message) {
@@ -74,6 +137,9 @@ function guidanceToClassification(message) {
74
137
  if (message.nextSteps && message.nextSteps.length > 0) {
75
138
  payload.next_steps = message.nextSteps;
76
139
  }
140
+ if (message.recovery) {
141
+ payload.recovery = message.recovery;
142
+ }
77
143
  return payload;
78
144
  }
79
145
  function normalizeMessage(message) {
@@ -106,6 +172,7 @@ function applyPmCliErrorContext(guidance, rawMessage, context) {
106
172
  const examples = normalizeContextList(context.examples) ?? guidance.examples;
107
173
  const nextSteps = normalizeContextList(context.nextSteps) ?? guidance.nextSteps;
108
174
  const fallbackTitle = guidance.code === "command_failed" && context.code ? buildFallbackTitleFromMessage(normalizedRawMessage) : undefined;
175
+ const recovery = normalizeRecoveryPayload(context.recovery) ?? guidance.recovery;
109
176
  return {
110
177
  ...guidance,
111
178
  code,
@@ -116,6 +183,7 @@ function applyPmCliErrorContext(guidance, rawMessage, context) {
116
183
  why: typeof context.why === "string" && context.why.trim().length > 0 ? context.why.trim() : guidance.why,
117
184
  examples,
118
185
  nextSteps,
186
+ recovery,
119
187
  };
120
188
  }
121
189
  function buildPmCliErrorGuidance(rawMessage, context) {
@@ -267,12 +335,65 @@ function commandExampleForRequiredOption(commandName, optionFlag, allowedTypes)
267
335
  }
268
336
  return [`pm ${commandName ?? "<command>"} --help`];
269
337
  }
338
+ function normalizeRequiredOptionLabel(rawValue) {
339
+ const normalized = rawValue.trim();
340
+ const firstLongFlag = normalized.match(/--[A-Za-z0-9][A-Za-z0-9_-]*/)?.[0];
341
+ return firstLongFlag ?? normalized;
342
+ }
343
+ function renderPmCommandFromArgs(argv) {
344
+ if (!Array.isArray(argv) || argv.length === 0) {
345
+ return undefined;
346
+ }
347
+ return renderPmCommand(argv);
348
+ }
349
+ function normalizeOptionFlags(values) {
350
+ if (!Array.isArray(values)) {
351
+ return undefined;
352
+ }
353
+ const normalized = values.map((value) => value.trim()).filter((value) => value.length > 0);
354
+ return normalized.length > 0 ? normalized : undefined;
355
+ }
356
+ function buildCommanderRecoveryPayload(context, overrides = {}) {
357
+ const providedFields = normalizeOptionFlags(context?.providedOptionFlags);
358
+ const normalizedArgs = Array.isArray(context?.normalizedInvocationArgs) && context?.normalizedInvocationArgs.length > 0
359
+ ? context.normalizedInvocationArgs
360
+ : undefined;
361
+ const attemptedCommand = typeof context?.attemptedCommand === "string" ? context.attemptedCommand : renderPmCommandFromArgs(normalizedArgs);
362
+ const retryCommand = typeof context?.suggestedRetryCommand === "string" ? context.suggestedRetryCommand : undefined;
363
+ return normalizeRecoveryPayload({
364
+ attempted_command: attemptedCommand,
365
+ normalized_args: normalizedArgs,
366
+ provided_fields: providedFields,
367
+ suggested_retry: retryCommand,
368
+ ...overrides,
369
+ });
370
+ }
371
+ function appendIfMissing(entries, value) {
372
+ if (!value || entries.includes(value)) {
373
+ return entries;
374
+ }
375
+ return [...entries, value];
376
+ }
270
377
  function buildCommanderErrorGuidance(rawMessage, commandName, allowedTypes, context) {
271
378
  const message = normalizeMessage(rawMessage);
272
379
  const requiredOption = message.match(/required option '([^']+)' not specified/);
273
380
  if (requiredOption) {
274
- const optionFlag = requiredOption[1];
381
+ const optionFlag = normalizeRequiredOptionLabel(requiredOption[1]);
275
382
  const isType = optionFlag.startsWith("--type");
383
+ const retryCommand = context?.suggestedRetryCommand;
384
+ const providedFlags = normalizeOptionFlags(context?.providedOptionFlags);
385
+ const missing = [optionFlag];
386
+ const examples = commandExampleForRequiredOption(commandName, optionFlag, allowedTypes);
387
+ const examplesWithRetry = retryCommand ? appendIfMissing(examples, retryCommand) : examples;
388
+ const nextStepsBase = isType
389
+ ? [`Allowed type values: ${allowedTypes}`, `Run "pm ${commandName ?? "create"} --help --type <value>" for type-aware policy details.`]
390
+ : [`Run "pm ${commandName ?? "<command>"} --help" for required option guidance.`];
391
+ const nextStepsWithRetry = retryCommand
392
+ ? appendIfMissing(nextStepsBase, `Replay with preserved arguments: ${retryCommand}`)
393
+ : nextStepsBase;
394
+ const nextSteps = providedFlags && providedFlags.length > 0
395
+ ? appendIfMissing(nextStepsWithRetry, `Already provided options: ${providedFlags.join(", ")}`)
396
+ : nextStepsWithRetry;
276
397
  return makeGuidanceMessage({
277
398
  code: "missing_required_option",
278
399
  title: `Missing required option ${optionFlag}`,
@@ -281,10 +402,9 @@ function buildCommanderErrorGuidance(rawMessage, commandName, allowedTypes, cont
281
402
  why: isType
282
403
  ? "--type selects item contract and policy routing, including required/disabled option rules."
283
404
  : "Required flags define mandatory command intent and prevent ambiguous execution.",
284
- examples: commandExampleForRequiredOption(commandName, optionFlag, allowedTypes),
285
- nextSteps: isType
286
- ? [`Allowed type values: ${allowedTypes}`, `Run "pm ${commandName ?? "create"} --help --type <value>" for type-aware policy details.`]
287
- : [`Run "pm ${commandName ?? "<command>"} --help" for required option guidance.`],
405
+ examples: examplesWithRetry,
406
+ nextSteps,
407
+ recovery: buildCommanderRecoveryPayload(context, { missing }),
288
408
  });
289
409
  }
290
410
  const missingArgument = message.match(/missing required argument '([^']+)'/);
@@ -297,11 +417,14 @@ function buildCommanderErrorGuidance(rawMessage, commandName, allowedTypes, cont
297
417
  required: `Provide ${argumentName} in the expected command position.`,
298
418
  why: "Positional arguments identify the target entity or action context for the command.",
299
419
  examples: [`pm ${commandName ?? "<command>"} --help`],
420
+ recovery: buildCommanderRecoveryPayload(context, { missing: [argumentName] }),
300
421
  });
301
422
  }
302
423
  const unknownOption = message.match(/unknown option '([^']+)'/);
303
424
  if (unknownOption) {
304
425
  const optionName = unknownOption[1];
426
+ const suggestions = normalizeOptionFlags(context?.unknownOptionSuggestions);
427
+ const retryCommand = context?.suggestedRetryCommand;
305
428
  if (commandName === "update" && (optionName === "--file" || optionName === "--doc")) {
306
429
  return makeGuidanceMessage({
307
430
  code: "unsupported_update_option",
@@ -314,15 +437,31 @@ function buildCommanderErrorGuidance(rawMessage, commandName, allowedTypes, cont
314
437
  'pm docs pm-a1b2 --add "path=README.md,scope=project,note=user-facing contract"',
315
438
  ],
316
439
  nextSteps: ['Run "pm files --help" and "pm docs --help" for add/remove payload formats.'],
440
+ recovery: buildCommanderRecoveryPayload(context, {
441
+ missing: suggestions,
442
+ }),
317
443
  });
318
444
  }
445
+ const nextSteps = [
446
+ "Run command help to confirm the exact option contracts for this command path.",
447
+ ...(suggestions && suggestions.length > 0 ? [`Nearest supported options: ${suggestions.join(", ")}`] : []),
448
+ ...(retryCommand ? [`Replay with suggested correction: ${retryCommand}`] : []),
449
+ ];
450
+ const examples = [
451
+ ...(retryCommand ? [retryCommand] : []),
452
+ `pm ${commandName ?? "<command>"} --help`,
453
+ ];
319
454
  return makeGuidanceMessage({
320
455
  code: "unknown_option",
321
456
  title: `Unknown option ${optionName}`,
322
457
  happened: `Commander does not recognize option ${optionName} for this command path.`,
323
458
  required: "Use supported options only, or move option to the correct subcommand.",
324
459
  why: "Option contracts are command-specific and intentionally validated.",
325
- examples: [`pm ${commandName ?? "<command>"} --help`],
460
+ examples,
461
+ nextSteps,
462
+ recovery: buildCommanderRecoveryPayload(context, {
463
+ missing: suggestions,
464
+ }),
326
465
  });
327
466
  }
328
467
  const unknownCommand = message.match(/unknown command '([^']+)'/);
@@ -338,6 +477,7 @@ function buildCommanderErrorGuidance(rawMessage, commandName, allowedTypes, cont
338
477
  why: "Command registry includes core commands plus active extension command handlers.",
339
478
  examples: runtimeExamples ?? ["pm --help"],
340
479
  nextSteps: runtimeNextSteps ?? ["Verify spelling and active extensions, then rerun."],
480
+ recovery: buildCommanderRecoveryPayload(context),
341
481
  });
342
482
  }
343
483
  return makeGuidanceMessage({
@@ -347,6 +487,7 @@ function buildCommanderErrorGuidance(rawMessage, commandName, allowedTypes, cont
347
487
  required: "Use the command with valid arguments and options.",
348
488
  why: "Commander validates CLI contracts before execution.",
349
489
  examples: ["pm --help", `pm ${commandName ?? "<command>"} --help`],
490
+ recovery: buildCommanderRecoveryPayload(context),
350
491
  });
351
492
  }
352
493
  export function formatPmCliErrorForDisplay(rawMessage, context) {