@unbrained/pm-cli 2026.5.27 → 2026.5.28
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 +10 -0
- package/dist/cli/commands/close.d.ts +3 -0
- package/dist/cli/commands/close.js +24 -2
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/extension/scaffold.js +54 -21
- package/dist/cli/commands/extension/scaffold.js.map +1 -1
- package/dist/cli/commands/list.js +2 -3
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +5 -0
- package/dist/cli/commands/plan.js +56 -8
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/search.js +2 -6
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/test.js +3 -3
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update.js +23 -4
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.js +32 -12
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/register-mutation.js +51 -4
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/core/shared/levenshtein.js +23 -7
- package/dist/core/shared/levenshtein.js.map +1 -1
- package/dist/sdk/cli-contracts.js +9 -2
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4547acbc-0dcb-5ccd-9900-5384c6a1e956")}catch(e){}}();
|
|
3
3
|
import { Option } from "commander";
|
|
4
4
|
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
5
5
|
import { PmCliError } from "../core/shared/errors.js";
|
|
6
6
|
import { isPureSnakeCaseAlias } from "../core/shared/option-alias-visibility.js";
|
|
7
7
|
import { CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS, UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS, } from "../sdk/cli-contracts.js";
|
|
8
|
+
import { BUILTIN_ITEM_TYPE_VALUES } from "../types/index.js";
|
|
9
|
+
// Lowercase set of built-in type names ("epic", "feature", ...) used by the
|
|
10
|
+
// `pm create` positional guard (pm-edge #1, 2026-05-28): if the single
|
|
11
|
+
// positional exactly matches a known type AND no --title was given, we throw
|
|
12
|
+
// instead of silently creating a Task titled with the type name.
|
|
13
|
+
const BUILTIN_TYPE_NAME_LOOKUP = new Set(BUILTIN_ITEM_TYPE_VALUES.map((value) => value.toLowerCase()));
|
|
8
14
|
import { collect, extractUpdateManyMutationOptionSource, formatHookWarnings, getGlobalOptions, invalidateSearchCachesForMutation, normalizeCreateOptions, normalizeUpdateOptions, printError, printResult, writeStdout, } from "./registration-helpers.js";
|
|
9
15
|
import { createLazyModule } from "../core/shared/lazy-module.js";
|
|
10
16
|
const loadMutationCommandsModule = createLazyModule(() => import("./commands/index.js"));
|
|
@@ -82,6 +88,31 @@ export function registerMutationCommands(program) {
|
|
|
82
88
|
else if (typeof typeOrTitle === "string" && typeOrTitle.length > 0) {
|
|
83
89
|
positionalTitle = typeOrTitle;
|
|
84
90
|
}
|
|
91
|
+
// pm-edge #1 (2026-05-28): when the sole positional matches a known
|
|
92
|
+
// item type AND no --title was supplied, refuse early instead of
|
|
93
|
+
// silently creating a Task titled with the type name (e.g. `pm create
|
|
94
|
+
// Epic` would previously produce a Task literally titled "Epic"). The
|
|
95
|
+
// guard fires only for the ambiguous single-positional case so the
|
|
96
|
+
// documented `pm create <type> <title>` flow stays a never-block.
|
|
97
|
+
if (positionalType === undefined &&
|
|
98
|
+
typeof positionalTitle === "string" &&
|
|
99
|
+
positionalTitle.length > 0 &&
|
|
100
|
+
options.title === undefined &&
|
|
101
|
+
options.type === undefined &&
|
|
102
|
+
BUILTIN_TYPE_NAME_LOOKUP.has(positionalTitle.trim().toLowerCase())) {
|
|
103
|
+
const matchedType = positionalTitle.trim();
|
|
104
|
+
throw new PmCliError(`pm create needs a title — "${matchedType}" looks like an item type, not a title. Use either: pm create ${matchedType} "<title>" or pm create "<title>" --type ${matchedType}.`, EXIT_CODE.USAGE, {
|
|
105
|
+
code: "create_positional_type_without_title",
|
|
106
|
+
why: "Without this guard the single positional is used as the title and the type defaults to Task — so the command would silently create a Task literally titled \"" + matchedType + "\".",
|
|
107
|
+
examples: [
|
|
108
|
+
`pm create ${matchedType} "Wire up SSO for the agent harness"`,
|
|
109
|
+
`pm create "Wire up SSO for the agent harness" --type ${matchedType}`,
|
|
110
|
+
],
|
|
111
|
+
nextSteps: [
|
|
112
|
+
`Re-run with both type and title: pm create ${matchedType} "<title>"`,
|
|
113
|
+
],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
85
116
|
if (typeof positionalType === "string" && positionalType.length > 0 && options.type === undefined) {
|
|
86
117
|
options.type = positionalType;
|
|
87
118
|
}
|
|
@@ -287,7 +318,7 @@ export function registerMutationCommands(program) {
|
|
|
287
318
|
printError(`profile:command=update-many took_ms=${Date.now() - startedAt}`);
|
|
288
319
|
}
|
|
289
320
|
});
|
|
290
|
-
program
|
|
321
|
+
const closeCommand = program
|
|
291
322
|
.command("close")
|
|
292
323
|
.argument("<id>", "Item id")
|
|
293
324
|
.argument("[text]", "Close reason text (alias: --reason)")
|
|
@@ -296,8 +327,17 @@ export function registerMutationCommands(program) {
|
|
|
296
327
|
.option("--author <value>", "Mutation author")
|
|
297
328
|
.option("--message <value>", "History message")
|
|
298
329
|
.option("--validate-close [mode]", 'Validate closure metadata before close: "off", "warn", or "strict" (default: settings governance preset)')
|
|
330
|
+
.option("--resolution <value>", "Set the closure resolution summary inline (same field --validate-close strict checks; previously required a prior pm update)")
|
|
331
|
+
.option("--expected-result <value>", "Set the expected-result note inline (closure validation field)")
|
|
332
|
+
.option("--actual-result <value>", "Set the actual-result note inline (closure validation field)")
|
|
299
333
|
.option("--force", "Force ownership override")
|
|
300
|
-
.description("Close an item with a required reason.")
|
|
334
|
+
.description("Close an item with a required reason.");
|
|
335
|
+
// pm-fl0c #11 (2026-05-28): expose snake_case aliases alongside the canonical
|
|
336
|
+
// kebab-case so agents using --expected_result/--actual_result do not get an
|
|
337
|
+
// Unknown option error; the rendered help stays clean (aliases hidden).
|
|
338
|
+
addHiddenOption(closeCommand, "--expected_result <value>", "Alias for --expected-result", false);
|
|
339
|
+
addHiddenOption(closeCommand, "--actual_result <value>", "Alias for --actual-result", false);
|
|
340
|
+
closeCommand
|
|
301
341
|
.action(async (id, text, options, command) => {
|
|
302
342
|
const globalOptions = getGlobalOptions(command);
|
|
303
343
|
const startedAt = Date.now();
|
|
@@ -319,6 +359,10 @@ export function registerMutationCommands(program) {
|
|
|
319
359
|
],
|
|
320
360
|
});
|
|
321
361
|
}
|
|
362
|
+
const pickInlineString = (canonical, snake) => {
|
|
363
|
+
const value = typeof canonical === "string" ? canonical : typeof snake === "string" ? snake : undefined;
|
|
364
|
+
return value !== undefined ? value : undefined;
|
|
365
|
+
};
|
|
322
366
|
const result = await runClose(id, resolvedText, {
|
|
323
367
|
author: typeof options.author === "string" ? options.author : undefined,
|
|
324
368
|
message: typeof options.message === "string" ? options.message : undefined,
|
|
@@ -328,6 +372,9 @@ export function registerMutationCommands(program) {
|
|
|
328
372
|
? options.validateClose
|
|
329
373
|
: undefined,
|
|
330
374
|
force: Boolean(options.force),
|
|
375
|
+
resolution: typeof options.resolution === "string" ? options.resolution : undefined,
|
|
376
|
+
expectedResult: pickInlineString(options.expectedResult, options.expected_result),
|
|
377
|
+
actualResult: pickInlineString(options.actualResult, options.actual_result),
|
|
331
378
|
}, globalOptions);
|
|
332
379
|
await invalidateSearchCachesForMutation(globalOptions, result);
|
|
333
380
|
printResult(result, globalOptions);
|
|
@@ -1004,4 +1051,4 @@ export function registerMutationCommands(program) {
|
|
|
1004
1051
|
});
|
|
1005
1052
|
}
|
|
1006
1053
|
//# sourceMappingURL=register-mutation.js.map
|
|
1007
|
-
//# debugId=
|
|
1054
|
+
//# debugId=4547acbc-0dcb-5ccd-9900-5384c6a1e956
|