@unbrained/pm-cli 2026.5.18 → 2026.5.24
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 +60 -0
- package/README.md +2 -1
- package/dist/cli/commander-usage.js +16 -2
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/annotation-command.d.ts +49 -0
- package/dist/cli/commands/annotation-command.js +135 -0
- package/dist/cli/commands/annotation-command.js.map +1 -0
- package/dist/cli/commands/append.js +3 -7
- package/dist/cli/commands/append.js.map +1 -1
- package/dist/cli/commands/calendar.js +3 -6
- package/dist/cli/commands/calendar.js.map +1 -1
- package/dist/cli/commands/claim.js +12 -22
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.js +61 -9
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/comments.d.ts +5 -0
- package/dist/cli/commands/comments.js +27 -117
- package/dist/cli/commands/comments.js.map +1 -1
- package/dist/cli/commands/completion.js +102 -15
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/context.js +4 -10
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/contracts.js +168 -36
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/create.js +49 -44
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/dedupe-audit.js +7 -4
- package/dist/cli/commands/dedupe-audit.js.map +1 -1
- package/dist/cli/commands/delete.d.ts +3 -0
- package/dist/cli/commands/delete.js +9 -8
- package/dist/cli/commands/delete.js.map +1 -1
- package/dist/cli/commands/docs.d.ts +1 -0
- package/dist/cli/commands/docs.js +4 -8
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/event-validation-messages.d.ts +3 -0
- package/dist/cli/commands/event-validation-messages.js +44 -0
- package/dist/cli/commands/event-validation-messages.js.map +1 -0
- package/dist/cli/commands/extension.d.ts +1 -0
- package/dist/cli/commands/extension.js +138 -21
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/files.js +6 -13
- package/dist/cli/commands/files.js.map +1 -1
- package/dist/cli/commands/gc.js +17 -4
- package/dist/cli/commands/gc.js.map +1 -1
- package/dist/cli/commands/get.d.ts +3 -2
- package/dist/cli/commands/get.js +50 -8
- package/dist/cli/commands/get.js.map +1 -1
- package/dist/cli/commands/health.d.ts +10 -0
- package/dist/cli/commands/health.js +254 -75
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/history-redact.d.ts +8 -0
- package/dist/cli/commands/history-redact.js +14 -97
- package/dist/cli/commands/history-redact.js.map +1 -1
- package/dist/cli/commands/history-repair.d.ts +33 -0
- package/dist/cli/commands/history-repair.js +166 -0
- package/dist/cli/commands/history-repair.js.map +1 -0
- package/dist/cli/commands/history.d.ts +4 -4
- package/dist/cli/commands/history.js +10 -88
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/index.d.ts +3 -1
- package/dist/cli/commands/index.js +5 -3
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +28 -0
- package/dist/cli/commands/init.js +23 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/learnings.js +20 -119
- package/dist/cli/commands/learnings.js.map +1 -1
- package/dist/cli/commands/linked-test-entry.d.ts +3 -0
- package/dist/cli/commands/linked-test-entry.js +62 -0
- package/dist/cli/commands/linked-test-entry.js.map +1 -0
- package/dist/cli/commands/list.js +32 -22
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/notes.js +20 -119
- package/dist/cli/commands/notes.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +3 -0
- package/dist/cli/commands/plan.js +184 -22
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/restore.js +7 -50
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/schema.d.ts +31 -0
- package/dist/cli/commands/schema.js +98 -0
- package/dist/cli/commands/schema.js.map +1 -0
- package/dist/cli/commands/search.js +151 -40
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/templates.d.ts +4 -0
- package/dist/cli/commands/templates.js +89 -17
- package/dist/cli/commands/templates.js.map +1 -1
- package/dist/cli/commands/test-all.js +4 -8
- package/dist/cli/commands/test-all.js.map +1 -1
- package/dist/cli/commands/test.d.ts +1 -0
- package/dist/cli/commands/test.js +7 -10
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update-many.js +4 -8
- package/dist/cli/commands/update-many.js.map +1 -1
- package/dist/cli/commands/update.js +109 -51
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.d.ts +3 -1
- package/dist/cli/commands/validate.js +23 -71
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/error-guidance.js +96 -6
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/extension-command-help.d.ts +0 -1
- package/dist/cli/extension-command-help.js +2 -13
- package/dist/cli/extension-command-help.js.map +1 -1
- package/dist/cli/extension-command-options.d.ts +1 -0
- package/dist/cli/extension-command-options.js +106 -7
- package/dist/cli/extension-command-options.js.map +1 -1
- package/dist/cli/help-content.d.ts +0 -1
- package/dist/cli/help-content.js +13 -9
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/help-json-payload.d.ts +1 -0
- package/dist/cli/help-json-payload.js +33 -3
- package/dist/cli/help-json-payload.js.map +1 -1
- package/dist/cli/main.js +35 -29
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.d.ts +1 -1
- package/dist/cli/register-list-query.js +40 -17
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.d.ts +1 -1
- package/dist/cli/register-mutation.js +232 -64
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-operations.js +16 -11
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli/register-setup.js +26 -14
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/registration-helpers.d.ts +0 -2
- package/dist/cli/registration-helpers.js +13 -40
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli.js +23 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/extensions/index.d.ts +0 -1
- package/dist/core/extensions/index.js +2 -14
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.js +3 -9
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/fs/path-utils.d.ts +1 -0
- package/dist/core/fs/path-utils.js +12 -0
- package/dist/core/fs/path-utils.js.map +1 -0
- package/dist/core/history/drift-scan.d.ts +11 -0
- package/dist/core/history/drift-scan.js +67 -0
- package/dist/core/history/drift-scan.js.map +1 -0
- package/dist/core/history/replay.d.ts +82 -0
- package/dist/core/history/replay.js +249 -0
- package/dist/core/history/replay.js.map +1 -0
- package/dist/core/item/item-format.js +11 -8
- package/dist/core/item/item-format.js.map +1 -1
- package/dist/core/item/item-type-definition.d.ts +52 -0
- package/dist/core/item/item-type-definition.js +123 -0
- package/dist/core/item/item-type-definition.js.map +1 -0
- package/dist/core/item/parse.js +3 -2
- package/dist/core/item/parse.js.map +1 -1
- package/dist/core/item/priority.d.ts +23 -0
- package/dist/core/item/priority.js +55 -0
- package/dist/core/item/priority.js.map +1 -0
- package/dist/core/item/status.d.ts +14 -1
- package/dist/core/item/status.js +22 -2
- package/dist/core/item/status.js.map +1 -1
- package/dist/core/item/toon-decode.d.ts +19 -0
- package/dist/core/item/toon-decode.js +69 -0
- package/dist/core/item/toon-decode.js.map +1 -0
- package/dist/core/item/type-registry.js +13 -84
- package/dist/core/item/type-registry.js.map +1 -1
- package/dist/core/packages/manifest.js +3 -9
- package/dist/core/packages/manifest.js.map +1 -1
- package/dist/core/schema/item-types-file.d.ts +85 -0
- package/dist/core/schema/item-types-file.js +243 -0
- package/dist/core/schema/item-types-file.js.map +1 -0
- package/dist/core/schema/runtime-schema.d.ts +2 -1
- package/dist/core/schema/runtime-schema.js +11 -9
- package/dist/core/schema/runtime-schema.js.map +1 -1
- package/dist/core/search/semantic-defaults.js +3 -3
- package/dist/core/search/semantic-defaults.js.map +1 -1
- package/dist/core/shared/author.d.ts +1 -0
- package/dist/core/shared/author.js +9 -0
- package/dist/core/shared/author.js.map +1 -0
- package/dist/core/shared/lazy-module.d.ts +1 -0
- package/dist/core/shared/lazy-module.js +11 -0
- package/dist/core/shared/lazy-module.js.map +1 -0
- package/dist/core/shared/option-alias-visibility.d.ts +44 -0
- package/dist/core/shared/option-alias-visibility.js +76 -0
- package/dist/core/shared/option-alias-visibility.js.map +1 -0
- package/dist/core/shared/text-normalization.d.ts +0 -1
- package/dist/core/shared/text-normalization.js +2 -5
- package/dist/core/shared/text-normalization.js.map +1 -1
- package/dist/core/store/item-store.d.ts +2 -0
- package/dist/core/store/item-store.js +70 -39
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/core/store/settings-validator.d.ts +106 -0
- package/dist/core/store/settings-validator.js +279 -0
- package/dist/core/store/settings-validator.js.map +1 -0
- package/dist/core/store/settings.js +6 -343
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/runtime.js +5 -3
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/dist/mcp/server.js +64 -13
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +9 -2
- package/dist/sdk/cli-contracts.js +204 -13
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/runtime.d.ts +25 -1
- package/dist/sdk/runtime.js +46 -3
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.js +10 -2
- package/dist/types.js.map +1 -1
- package/docs/AGENT_GUIDE.md +7 -1
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/COMMANDS.md +39 -6
- package/docs/CONFIGURATION.md +1 -1
- package/docs/RELEASING.md +11 -7
- package/docs/SDK.md +11 -2
- package/package.json +12 -11
- package/packages/pm-calendar/README.md +3 -1
- package/packages/pm-calendar/extensions/calendar/index.js +21 -2
- package/packages/pm-calendar/extensions/calendar/index.ts +21 -2
- package/packages/pm-search-advanced/README.md +8 -0
- package/packages/pm-search-advanced/extensions/search-advanced/index.js +74 -0
- package/packages/pm-search-advanced/extensions/search-advanced/index.ts +74 -0
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +67 -9
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +67 -9
- package/packages/pm-templates/extensions/templates/runtime.js +11 -202
- package/packages/pm-templates/extensions/templates/runtime.ts +38 -230
- package/dist/core/output/command-aware.d.ts +0 -1
- package/dist/core/output/command-aware.js +0 -397
- package/dist/core/output/command-aware.js.map +0 -1
|
@@ -1,124 +1,25 @@
|
|
|
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]="
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
6
|
-
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
7
|
-
import { PmCliError } from "../../core/shared/errors.js";
|
|
8
|
-
import { nowIso } from "../../core/shared/time.js";
|
|
9
|
-
import { createStdinTokenResolver, parseCsvKv } from "../../core/item/parse.js";
|
|
10
|
-
import { locateItem, mutateItem, readLocatedItem } from "../../core/store/item-store.js";
|
|
11
|
-
import { getSettingsPath, resolvePmRoot } from "../../core/store/paths.js";
|
|
12
|
-
import { readSettings } from "../../core/store/settings.js";
|
|
13
|
-
import { parseLimit } from "../shared-parsers.js";
|
|
14
|
-
function resolveAuthor(candidate, fallback) {
|
|
15
|
-
const resolved = candidate ?? process.env.PM_AUTHOR ?? fallback;
|
|
16
|
-
const trimmed = resolved.trim();
|
|
17
|
-
return trimmed || "unknown";
|
|
18
|
-
}
|
|
19
|
-
function limitNotes(values, limit) {
|
|
20
|
-
if (limit === undefined)
|
|
21
|
-
return values;
|
|
22
|
-
if (limit === 0)
|
|
23
|
-
return [];
|
|
24
|
-
return values.slice(Math.max(0, values.length - limit));
|
|
25
|
-
}
|
|
26
|
-
function parseNoteTextInput(raw) {
|
|
27
|
-
const trimmed = raw.trim();
|
|
28
|
-
if (!trimmed) {
|
|
29
|
-
return "";
|
|
30
|
-
}
|
|
31
|
-
const looksStructured = /^(?:[-*+]\s*)?text\s*[:=]/im.test(trimmed) || trimmed.startsWith("```");
|
|
32
|
-
if (!looksStructured) {
|
|
33
|
-
return trimmed;
|
|
34
|
-
}
|
|
35
|
-
try {
|
|
36
|
-
const kv = parseCsvKv(trimmed, "--add");
|
|
37
|
-
const keys = Object.keys(kv).map((key) => key.trim().toLowerCase());
|
|
38
|
-
if (keys.some((key) => key !== "text")) {
|
|
39
|
-
return trimmed;
|
|
40
|
-
}
|
|
41
|
-
const text = kv.text?.trim();
|
|
42
|
-
return text || trimmed;
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
return trimmed;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
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]="60f1e397-2d8b-5ef9-a3e2-d4e20160ed6a")}catch(e){}}();
|
|
3
|
+
import { createStdinTokenResolver } from "../../core/item/parse.js";
|
|
4
|
+
import { parseAnnotationTextInput, runAnnotationCommand } from "./annotation-command.js";
|
|
48
5
|
export async function runNotes(id, options, global) {
|
|
49
6
|
const stdinResolver = createStdinTokenResolver();
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
notes,
|
|
67
|
-
count: notes.length,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
const author = resolveAuthor(options.author, settings.author_default);
|
|
71
|
-
const addInput = await stdinResolver.resolveValue(options.add, "--add");
|
|
72
|
-
const text = parseNoteTextInput(addInput ?? "");
|
|
73
|
-
if (!text) {
|
|
74
|
-
throw new PmCliError("--add text cannot be empty", EXIT_CODE.USAGE);
|
|
75
|
-
}
|
|
76
|
-
let result;
|
|
77
|
-
try {
|
|
78
|
-
result = await mutateItem({
|
|
79
|
-
pmRoot,
|
|
80
|
-
settings,
|
|
81
|
-
id,
|
|
82
|
-
op: "note_add",
|
|
83
|
-
author,
|
|
84
|
-
message: options.message,
|
|
85
|
-
force: options.force,
|
|
86
|
-
bypassAssigneeConflict: Boolean(options.allowAuditNote || options.allowAuditComment),
|
|
87
|
-
mutate(document) {
|
|
88
|
-
const notes = document.metadata.notes ?? [];
|
|
89
|
-
notes.push({
|
|
90
|
-
created_at: nowIso(),
|
|
91
|
-
author,
|
|
92
|
-
text,
|
|
93
|
-
});
|
|
94
|
-
document.metadata.notes = notes;
|
|
95
|
-
return { changedFields: ["notes"] };
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
if (error instanceof PmCliError &&
|
|
101
|
-
error.exitCode === EXIT_CODE.CONFLICT &&
|
|
102
|
-
error.message.includes("is assigned to") &&
|
|
103
|
-
error.message.includes("Use --force to override")) {
|
|
104
|
-
throw new PmCliError(error.message, error.exitCode, {
|
|
105
|
-
code: "ownership_conflict",
|
|
106
|
-
required: "For append-only note audits on another owner's item, prefer --allow-audit-note (legacy alias: --allow-audit-comment) before considering --force.",
|
|
107
|
-
examples: ['pm notes pm-a1b2 --add "audit note" --author "reviewer" --allow-audit-note'],
|
|
108
|
-
nextSteps: [
|
|
109
|
-
"Retry with --allow-audit-note (or legacy --allow-audit-comment) for append-only note audits that do not mutate item metadata beyond notes.",
|
|
110
|
-
"Use --force only when an ownership override is explicitly approved.",
|
|
111
|
-
],
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
throw error;
|
|
115
|
-
}
|
|
116
|
-
const notes = limitNotes(result.item.notes, limit);
|
|
117
|
-
return {
|
|
118
|
-
id: result.item.id,
|
|
119
|
-
notes,
|
|
120
|
-
count: notes.length,
|
|
121
|
-
};
|
|
7
|
+
const addInput = options.add === undefined ? undefined : await stdinResolver.resolveValue(options.add, "--add");
|
|
8
|
+
return runAnnotationCommand(id, options, global, {
|
|
9
|
+
input: options.add === undefined ? { mode: "list" } : { mode: "add", value: addInput ?? "", emptyFlag: "--add" },
|
|
10
|
+
collectionKey: "notes",
|
|
11
|
+
op: "note_add",
|
|
12
|
+
parseText: (raw) => parseAnnotationTextInput(raw),
|
|
13
|
+
allowAuditBypass: Boolean(options.allowAuditNote || options.allowAuditComment),
|
|
14
|
+
conflictGuidance: {
|
|
15
|
+
required: "For append-only note audits on another owner's item, prefer --allow-audit-note (legacy alias: --allow-audit-comment) before considering --force.",
|
|
16
|
+
examples: ['pm notes pm-a1b2 --add "audit note" --author "reviewer" --allow-audit-note'],
|
|
17
|
+
nextSteps: [
|
|
18
|
+
"Retry with --allow-audit-note (or legacy --allow-audit-comment) for append-only note audits that do not mutate item metadata beyond notes.",
|
|
19
|
+
"Use --force only when an ownership override is explicitly approved.",
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
});
|
|
122
23
|
}
|
|
123
24
|
//# sourceMappingURL=notes.js.map
|
|
124
|
-
//# debugId=
|
|
25
|
+
//# debugId=60f1e397-2d8b-5ef9-a3e2-d4e20160ed6a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notes.js","sources":["cli/commands/notes.ts"],"sourceRoot":"/","sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"notes.js","sources":["cli/commands/notes.ts"],"sourceRoot":"/","sourcesContent":["import type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { createStdinTokenResolver } from \"../../core/item/parse.js\";\nimport type { LogNote } from \"../../types/index.js\";\nimport { parseAnnotationTextInput, runAnnotationCommand } from \"./annotation-command.js\";\n\nexport interface NotesCommandOptions {\n add?: string;\n limit?: string;\n author?: string;\n message?: string;\n allowAuditNote?: boolean;\n allowAuditComment?: boolean;\n force?: boolean;\n}\n\nexport interface NotesResult {\n id: string;\n notes: LogNote[];\n count: number;\n}\n\nexport async function runNotes(id: string, options: NotesCommandOptions, global: GlobalOptions): Promise<NotesResult> {\n const stdinResolver = createStdinTokenResolver();\n const addInput = options.add === undefined ? undefined : await stdinResolver.resolveValue(options.add, \"--add\");\n\n return runAnnotationCommand<\"notes\", LogNote>(id, options, global, {\n input: options.add === undefined ? { mode: \"list\" } : { mode: \"add\", value: addInput ?? \"\", emptyFlag: \"--add\" },\n collectionKey: \"notes\",\n op: \"note_add\",\n parseText: (raw) => parseAnnotationTextInput(raw),\n allowAuditBypass: Boolean(options.allowAuditNote || options.allowAuditComment),\n conflictGuidance: {\n required:\n \"For append-only note audits on another owner's item, prefer --allow-audit-note (legacy alias: --allow-audit-comment) before considering --force.\",\n examples: ['pm notes pm-a1b2 --add \"audit note\" --author \"reviewer\" --allow-audit-note'],\n nextSteps: [\n \"Retry with --allow-audit-note (or legacy --allow-audit-comment) for append-only note audits that do not mutate item metadata beyond notes.\",\n \"Use --force only when an ownership override is explicitly approved.\",\n ],\n },\n });\n}\n"],"names":[],"mappings":";;AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAkBzF,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,EAAU,EAAE,OAA4B,EAAE,MAAqB;IAC5F,MAAM,aAAa,GAAG,wBAAwB,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEhH,OAAO,oBAAoB,CAAmB,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;QACjE,KAAK,EAAE,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,IAAI,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE;QAChH,aAAa,EAAE,OAAO;QACtB,EAAE,EAAE,UAAU;QACd,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC;QACjD,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC;QAC9E,gBAAgB,EAAE;YAChB,QAAQ,EACN,kJAAkJ;YACpJ,QAAQ,EAAE,CAAC,4EAA4E,CAAC;YACxF,SAAS,EAAE;gBACT,4IAA4I;gBAC5I,qEAAqE;aACtE;SACF;KACF,CAAC,CAAC;AACL,CAAC","debugId":"60f1e397-2d8b-5ef9-a3e2-d4e20160ed6a"}
|
|
@@ -37,10 +37,13 @@ export interface PlanCommandOptions {
|
|
|
37
37
|
test?: string | string[];
|
|
38
38
|
doc?: string | string[];
|
|
39
39
|
decisionText?: string;
|
|
40
|
+
decision?: string;
|
|
40
41
|
decisionRationale?: string;
|
|
41
42
|
decisionEvidence?: string;
|
|
42
43
|
discoveryText?: string;
|
|
44
|
+
discovery?: string;
|
|
43
45
|
validationText?: string;
|
|
46
|
+
validation?: string;
|
|
44
47
|
validationCommand?: string;
|
|
45
48
|
validationExpected?: string;
|
|
46
49
|
depth?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
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]="55dd5c6d-22e8-50d4-a39c-f08a7db05b06")}catch(e){}}();
|
|
3
3
|
import { pathExists } from "../../core/fs/fs-utils.js";
|
|
4
4
|
import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
|
|
5
5
|
import { resolveItemTypeRegistry, resolveTypeName } from "../../core/item/type-registry.js";
|
|
@@ -117,18 +117,53 @@ function parsePlanFields(raw) {
|
|
|
117
117
|
}
|
|
118
118
|
return fields;
|
|
119
119
|
}
|
|
120
|
+
const PLAN_FIELD_KEYS = new Set([
|
|
121
|
+
"id",
|
|
122
|
+
"title",
|
|
123
|
+
"status",
|
|
124
|
+
"mode",
|
|
125
|
+
"scope",
|
|
126
|
+
"harness",
|
|
127
|
+
"parent",
|
|
128
|
+
"resume_context",
|
|
129
|
+
"steps_summary",
|
|
130
|
+
"current_step",
|
|
131
|
+
"blocked_steps",
|
|
132
|
+
"steps",
|
|
133
|
+
"decisions",
|
|
134
|
+
"discoveries",
|
|
135
|
+
"validation",
|
|
136
|
+
"linked_items",
|
|
137
|
+
]);
|
|
120
138
|
function projectPlanForFields(plan, fields) {
|
|
121
139
|
const source = plan;
|
|
122
140
|
const projected = {};
|
|
141
|
+
const unknownFields = [];
|
|
123
142
|
for (const field of fields) {
|
|
124
143
|
const normalized = field.startsWith("plan.") ? field.slice("plan.".length) : field;
|
|
125
144
|
if (normalized.length === 0) {
|
|
126
145
|
continue;
|
|
127
146
|
}
|
|
147
|
+
if (!PLAN_FIELD_KEYS.has(normalized)) {
|
|
148
|
+
unknownFields.push(field);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
128
151
|
if (Object.prototype.hasOwnProperty.call(source, normalized)) {
|
|
129
152
|
projected[normalized] = source[normalized];
|
|
130
153
|
}
|
|
131
154
|
}
|
|
155
|
+
if (unknownFields.length > 0) {
|
|
156
|
+
throw new PmCliError(`Unknown Plan --fields value(s): ${unknownFields.join(", ")}`, EXIT_CODE.USAGE, {
|
|
157
|
+
nextSteps: [
|
|
158
|
+
`Use --fields ${[...PLAN_FIELD_KEYS].join(",")}`,
|
|
159
|
+
"Run pm plan show <id> --depth brief for compact default fields.",
|
|
160
|
+
],
|
|
161
|
+
recovery: {
|
|
162
|
+
provided_fields: unknownFields,
|
|
163
|
+
suggested_retry: `pm plan show <id> --fields ${[...PLAN_FIELD_KEYS].join(",")}`,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
}
|
|
132
167
|
return projected;
|
|
133
168
|
}
|
|
134
169
|
function parsePairList(raw, label) {
|
|
@@ -224,6 +259,38 @@ function resolveStepRef(steps, ref) {
|
|
|
224
259
|
}
|
|
225
260
|
throw new PmCliError(`Step "${ref}" not found in plan`, EXIT_CODE.NOT_FOUND);
|
|
226
261
|
}
|
|
262
|
+
function resolveMaterializeTargets(steps, refs) {
|
|
263
|
+
const allRefs = refs.filter((ref) => ref.trim().toLowerCase() === "all");
|
|
264
|
+
if (allRefs.length > 0) {
|
|
265
|
+
if (refs.length > allRefs.length) {
|
|
266
|
+
throw new PmCliError("pm plan materialize --steps all cannot be combined with other step refs", EXIT_CODE.USAGE);
|
|
267
|
+
}
|
|
268
|
+
return steps.slice().sort((left, right) => left.order - right.order);
|
|
269
|
+
}
|
|
270
|
+
const targets = [];
|
|
271
|
+
const seen = new Set();
|
|
272
|
+
for (const ref of refs) {
|
|
273
|
+
const step = resolveStepRef(steps, ref);
|
|
274
|
+
if (seen.has(step.id))
|
|
275
|
+
continue;
|
|
276
|
+
targets.push(step);
|
|
277
|
+
seen.add(step.id);
|
|
278
|
+
}
|
|
279
|
+
return targets;
|
|
280
|
+
}
|
|
281
|
+
function resolvePlanLogText(kind, options) {
|
|
282
|
+
const canonical = kind === "decision"
|
|
283
|
+
? options.decisionText
|
|
284
|
+
: kind === "discovery"
|
|
285
|
+
? options.discoveryText
|
|
286
|
+
: options.validationText;
|
|
287
|
+
const shorthand = kind === "decision"
|
|
288
|
+
? options.decision
|
|
289
|
+
: kind === "discovery"
|
|
290
|
+
? options.discovery
|
|
291
|
+
: options.validation;
|
|
292
|
+
return canonical?.trim() || shorthand?.trim() || undefined;
|
|
293
|
+
}
|
|
227
294
|
function findCurrentStep(steps) {
|
|
228
295
|
return steps.find((step) => step.status === "in_progress")
|
|
229
296
|
?? steps.find((step) => step.status === "pending");
|
|
@@ -285,7 +352,15 @@ function nextActionsFor(planId, plan) {
|
|
|
285
352
|
function ensurePlanItem(item) {
|
|
286
353
|
const normalizedType = (item.type ?? "").trim().toLowerCase();
|
|
287
354
|
if (normalizedType !== "plan") {
|
|
288
|
-
throw new PmCliError(`Item ${item.id} is type ${item.type}; pm plan commands require type=Plan. Use pm plan create or pm create --type Plan first.`, EXIT_CODE.USAGE
|
|
355
|
+
throw new PmCliError(`Item ${item.id} is type ${item.type}; pm plan commands require type=Plan. Use pm plan create or pm create --type Plan first.`, EXIT_CODE.USAGE, {
|
|
356
|
+
code: "wrong_item_type",
|
|
357
|
+
required: "Use pm plan commands only with items whose type is Plan.",
|
|
358
|
+
why: "Plan commands read and mutate Plan-specific step, decision, discovery, and validation fields.",
|
|
359
|
+
examples: [
|
|
360
|
+
`pm get ${item.id} --depth brief`,
|
|
361
|
+
'pm plan create --title "Execution plan" --scope "<goal>"',
|
|
362
|
+
],
|
|
363
|
+
});
|
|
289
364
|
}
|
|
290
365
|
}
|
|
291
366
|
async function loadContext(global) {
|
|
@@ -373,6 +448,91 @@ async function planCreate(options, global, ctx) {
|
|
|
373
448
|
},
|
|
374
449
|
});
|
|
375
450
|
let finalMetadata = seedResult.item;
|
|
451
|
+
let initialStep;
|
|
452
|
+
const initialValidationText = options.validationText?.trim();
|
|
453
|
+
const initialValidationCommand = options.validationCommand?.trim();
|
|
454
|
+
const initialValidationExpected = options.validationExpected?.trim();
|
|
455
|
+
const initialValidation = initialValidationText || initialValidationCommand || initialValidationExpected
|
|
456
|
+
? {
|
|
457
|
+
text: initialValidationText || initialValidationCommand || "Validation check",
|
|
458
|
+
command: initialValidationCommand || undefined,
|
|
459
|
+
expected: initialValidationExpected || undefined,
|
|
460
|
+
}
|
|
461
|
+
: undefined;
|
|
462
|
+
if (options.stepTitle?.trim()) {
|
|
463
|
+
const status = asStepStatus(options.stepStatus, "pending");
|
|
464
|
+
const linkedItems = buildLinkInputs(options, "depends_on");
|
|
465
|
+
const files = toSpecArray(options.file).map(parseStepFile);
|
|
466
|
+
const tests = toSpecArray(options.test).map(parseStepTest);
|
|
467
|
+
const docs = toSpecArray(options.doc).map(parseStepDoc);
|
|
468
|
+
const now = nowIso();
|
|
469
|
+
initialStep = {
|
|
470
|
+
id: "plan-step-001",
|
|
471
|
+
order: 1,
|
|
472
|
+
title: options.stepTitle.trim(),
|
|
473
|
+
body: options.stepBody?.trim() || undefined,
|
|
474
|
+
status,
|
|
475
|
+
owner: options.stepOwner?.trim() || undefined,
|
|
476
|
+
evidence: options.stepEvidence?.trim() || undefined,
|
|
477
|
+
blocked_reason: status === "blocked" ? options.stepBlockedReason?.trim() || "" : undefined,
|
|
478
|
+
linked_items: linkedItems.length > 0 ? linkedItems : undefined,
|
|
479
|
+
files: files.length > 0 ? files : undefined,
|
|
480
|
+
tests: tests.length > 0 ? tests : undefined,
|
|
481
|
+
docs: docs.length > 0 ? docs : undefined,
|
|
482
|
+
created_at: now,
|
|
483
|
+
updated_at: now,
|
|
484
|
+
completed_at: status === "completed" ? now : undefined,
|
|
485
|
+
};
|
|
486
|
+
const stepped = await mutateItem({
|
|
487
|
+
pmRoot: ctx.pmRoot,
|
|
488
|
+
settings: ctx.settings,
|
|
489
|
+
id: createResult.item.id,
|
|
490
|
+
op: "plan_create_initial_step",
|
|
491
|
+
author: resolveAuthor(options.author, ctx.settings.author_default),
|
|
492
|
+
message: `plan create initial step "${initialStep.title}"`,
|
|
493
|
+
mutate(doc) {
|
|
494
|
+
ensurePlanItem(doc.metadata);
|
|
495
|
+
doc.metadata.plan_steps = [initialStep];
|
|
496
|
+
if (initialValidation) {
|
|
497
|
+
doc.metadata.plan_validation = [...(doc.metadata.plan_validation ?? []), initialValidation];
|
|
498
|
+
}
|
|
499
|
+
return { changedFields: initialValidation ? ["plan_steps", "plan_validation"] : ["plan_steps"] };
|
|
500
|
+
},
|
|
501
|
+
});
|
|
502
|
+
finalMetadata = stepped.item;
|
|
503
|
+
}
|
|
504
|
+
else if (initialValidation) {
|
|
505
|
+
const validated = await mutateItem({
|
|
506
|
+
pmRoot: ctx.pmRoot,
|
|
507
|
+
settings: ctx.settings,
|
|
508
|
+
id: createResult.item.id,
|
|
509
|
+
op: "plan_create_initial_validation",
|
|
510
|
+
author: resolveAuthor(options.author, ctx.settings.author_default),
|
|
511
|
+
message: "plan create initial validation",
|
|
512
|
+
mutate(doc) {
|
|
513
|
+
ensurePlanItem(doc.metadata);
|
|
514
|
+
doc.metadata.plan_validation = [...(doc.metadata.plan_validation ?? []), initialValidation];
|
|
515
|
+
return { changedFields: ["plan_validation"] };
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
finalMetadata = validated.item;
|
|
519
|
+
}
|
|
520
|
+
else if (options.stepBody?.trim() ||
|
|
521
|
+
options.stepOwner?.trim() ||
|
|
522
|
+
options.stepStatus?.trim() ||
|
|
523
|
+
options.stepEvidence?.trim() ||
|
|
524
|
+
options.stepBlockedReason?.trim() ||
|
|
525
|
+
options.stepReplacement?.trim() ||
|
|
526
|
+
toArray(options.dependsOn).length > 0 ||
|
|
527
|
+
toArray(options.link).length > 0 ||
|
|
528
|
+
toSpecArray(options.file).length > 0 ||
|
|
529
|
+
toSpecArray(options.test).length > 0 ||
|
|
530
|
+
toSpecArray(options.doc).length > 0) {
|
|
531
|
+
throw new PmCliError("pm plan create step options require --step-title", EXIT_CODE.USAGE, {
|
|
532
|
+
code: "missing_required_option",
|
|
533
|
+
examples: ['pm plan create --title "Execution plan" --step-title "Read the code"'],
|
|
534
|
+
});
|
|
535
|
+
}
|
|
376
536
|
if (options.claim) {
|
|
377
537
|
const claimed = await mutateItem({
|
|
378
538
|
pmRoot: ctx.pmRoot,
|
|
@@ -392,6 +552,7 @@ async function planCreate(options, global, ctx) {
|
|
|
392
552
|
return {
|
|
393
553
|
action: "create",
|
|
394
554
|
plan,
|
|
555
|
+
step: initialStep,
|
|
395
556
|
next_actions: nextActionsFor(createResult.item.id, plan),
|
|
396
557
|
warnings: [...createResult.warnings],
|
|
397
558
|
generated_at: nowIso(),
|
|
@@ -401,7 +562,7 @@ async function planShow(id, options, ctx) {
|
|
|
401
562
|
const depth = asDepth(options.depth);
|
|
402
563
|
const fields = parsePlanFields(options.fields);
|
|
403
564
|
const { document, itemId } = await readPlanItem(ctx, id);
|
|
404
|
-
const fullPlan = projectPlan(document.metadata, depth);
|
|
565
|
+
const fullPlan = projectPlan(document.metadata, fields === null ? depth : "deep");
|
|
405
566
|
const plan = fields === null ? fullPlan : projectPlanForFields(fullPlan, fields);
|
|
406
567
|
return {
|
|
407
568
|
action: "show",
|
|
@@ -720,14 +881,20 @@ async function planUnlink(id, options, ctx, stepRef) {
|
|
|
720
881
|
};
|
|
721
882
|
}
|
|
722
883
|
async function planAppendLog(id, options, ctx, kind) {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
throw new PmCliError(
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
884
|
+
const logText = resolvePlanLogText(kind, options);
|
|
885
|
+
if (!logText) {
|
|
886
|
+
const canonical = `--${kind}-text`;
|
|
887
|
+
const shorthand = `--${kind}`;
|
|
888
|
+
throw new PmCliError(`pm plan ${kind} requires ${canonical}`, EXIT_CODE.USAGE, {
|
|
889
|
+
code: "missing_required_option",
|
|
890
|
+
examples: [
|
|
891
|
+
`pm plan ${kind} <plan-id> ${canonical} "..."`,
|
|
892
|
+
`pm plan ${kind} <plan-id> ${shorthand} "..."`,
|
|
893
|
+
],
|
|
894
|
+
recovery: {
|
|
895
|
+
suggested_retry: `pm plan ${kind} <plan-id> ${canonical} <value>`,
|
|
896
|
+
},
|
|
897
|
+
});
|
|
731
898
|
}
|
|
732
899
|
const author = resolveAuthor(options.author, ctx.settings.author_default);
|
|
733
900
|
const { document, itemId } = await mutatePlanSteps({
|
|
@@ -743,7 +910,7 @@ async function planAppendLog(id, options, ctx, kind) {
|
|
|
743
910
|
list.push({
|
|
744
911
|
ts: now,
|
|
745
912
|
author,
|
|
746
|
-
decision:
|
|
913
|
+
decision: logText,
|
|
747
914
|
rationale: options.decisionRationale?.trim() || undefined,
|
|
748
915
|
evidence: options.decisionEvidence?.trim() || undefined,
|
|
749
916
|
});
|
|
@@ -752,13 +919,13 @@ async function planAppendLog(id, options, ctx, kind) {
|
|
|
752
919
|
}
|
|
753
920
|
if (kind === "discovery") {
|
|
754
921
|
const list = doc.metadata.plan_discoveries ?? [];
|
|
755
|
-
list.push({ ts: now, author, text:
|
|
922
|
+
list.push({ ts: now, author, text: logText });
|
|
756
923
|
doc.metadata.plan_discoveries = list;
|
|
757
924
|
return { changedSteps: [] };
|
|
758
925
|
}
|
|
759
926
|
const list = doc.metadata.plan_validation ?? [];
|
|
760
927
|
list.push({
|
|
761
|
-
text:
|
|
928
|
+
text: logText,
|
|
762
929
|
command: options.validationCommand?.trim() || undefined,
|
|
763
930
|
expected: options.validationExpected?.trim() || undefined,
|
|
764
931
|
});
|
|
@@ -825,7 +992,7 @@ async function planApprove(id, options, ctx) {
|
|
|
825
992
|
async function planMaterialize(id, options, ctx) {
|
|
826
993
|
const stepRefs = toArray(options.steps);
|
|
827
994
|
if (stepRefs.length === 0) {
|
|
828
|
-
throw new PmCliError("pm plan materialize requires --steps <ids|orders>", EXIT_CODE.USAGE);
|
|
995
|
+
throw new PmCliError("pm plan materialize requires --steps <ids|orders|all>", EXIT_CODE.USAGE);
|
|
829
996
|
}
|
|
830
997
|
const targetType = options.materializeType?.trim() || "Task";
|
|
831
998
|
const typeRegistry = resolveItemTypeRegistry(ctx.settings, getActiveExtensionRegistrations());
|
|
@@ -837,7 +1004,7 @@ async function planMaterialize(id, options, ctx) {
|
|
|
837
1004
|
const tags = options.materializeTags;
|
|
838
1005
|
const planRead = await readPlanItem(ctx, id);
|
|
839
1006
|
const steps = (planRead.document.metadata.plan_steps ?? []).slice();
|
|
840
|
-
const targets =
|
|
1007
|
+
const targets = resolveMaterializeTargets(steps, stepRefs);
|
|
841
1008
|
if (targets.length === 0) {
|
|
842
1009
|
throw new PmCliError("No matching plan steps found for --steps", EXIT_CODE.NOT_FOUND);
|
|
843
1010
|
}
|
|
@@ -884,11 +1051,6 @@ async function planMaterialize(id, options, ctx) {
|
|
|
884
1051
|
step.linked_items = links;
|
|
885
1052
|
step.updated_at = nowIso();
|
|
886
1053
|
}
|
|
887
|
-
const deps = doc.metadata.dependencies ?? [];
|
|
888
|
-
for (const m of materialized) {
|
|
889
|
-
deps.push({ id: m.id, kind: "child", created_at: nowIso(), author: resolveAuthor(options.author, ctx.settings.author_default) });
|
|
890
|
-
}
|
|
891
|
-
doc.metadata.dependencies = deps;
|
|
892
1054
|
return { changedSteps: targets.map((entry) => entry.id) };
|
|
893
1055
|
},
|
|
894
1056
|
});
|
|
@@ -972,4 +1134,4 @@ export async function runPlan(input) {
|
|
|
972
1134
|
}
|
|
973
1135
|
}
|
|
974
1136
|
//# sourceMappingURL=plan.js.map
|
|
975
|
-
//# debugId=
|
|
1137
|
+
//# debugId=55dd5c6d-22e8-50d4-a39c-f08a7db05b06
|