@unbrained/pm-cli 2026.5.24 → 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.
Files changed (246) hide show
  1. package/CHANGELOG.md +953 -522
  2. package/README.md +2 -10
  3. package/dist/cli/bootstrap-args.d.ts +18 -1
  4. package/dist/cli/bootstrap-args.js +143 -3
  5. package/dist/cli/bootstrap-args.js.map +1 -1
  6. package/dist/cli/commander-usage.js +134 -11
  7. package/dist/cli/commander-usage.js.map +1 -1
  8. package/dist/cli/commands/append.js +4 -3
  9. package/dist/cli/commands/append.js.map +1 -1
  10. package/dist/cli/commands/claim.js +5 -4
  11. package/dist/cli/commands/claim.js.map +1 -1
  12. package/dist/cli/commands/close.d.ts +3 -0
  13. package/dist/cli/commands/close.js +26 -3
  14. package/dist/cli/commands/close.js.map +1 -1
  15. package/dist/cli/commands/completion.d.ts +2 -2
  16. package/dist/cli/commands/completion.js +109 -56
  17. package/dist/cli/commands/completion.js.map +1 -1
  18. package/dist/cli/commands/config.d.ts +1 -1
  19. package/dist/cli/commands/config.js +82 -4
  20. package/dist/cli/commands/config.js.map +1 -1
  21. package/dist/cli/commands/create.js +7 -272
  22. package/dist/cli/commands/create.js.map +1 -1
  23. package/dist/cli/commands/delete.js +4 -3
  24. package/dist/cli/commands/delete.js.map +1 -1
  25. package/dist/cli/commands/docs.d.ts +1 -12
  26. package/dist/cli/commands/docs.js +8 -312
  27. package/dist/cli/commands/docs.js.map +1 -1
  28. package/dist/cli/commands/extension/bundled-catalog.d.ts +14 -0
  29. package/dist/cli/commands/extension/bundled-catalog.js +268 -0
  30. package/dist/cli/commands/extension/bundled-catalog.js.map +1 -0
  31. package/dist/cli/commands/extension/doctor.d.ts +31 -0
  32. package/dist/cli/commands/extension/doctor.js +345 -0
  33. package/dist/cli/commands/extension/doctor.js.map +1 -0
  34. package/dist/cli/commands/extension/install-sources.d.ts +37 -0
  35. package/dist/cli/commands/extension/install-sources.js +384 -0
  36. package/dist/cli/commands/extension/install-sources.js.map +1 -0
  37. package/dist/cli/commands/extension/managed-state.d.ts +48 -0
  38. package/dist/cli/commands/extension/managed-state.js +172 -0
  39. package/dist/cli/commands/extension/managed-state.js.map +1 -0
  40. package/dist/cli/commands/extension/scaffold.d.ts +14 -0
  41. package/dist/cli/commands/extension/scaffold.js +202 -0
  42. package/dist/cli/commands/extension/scaffold.js.map +1 -0
  43. package/dist/cli/commands/extension/shared.d.ts +14 -0
  44. package/dist/cli/commands/extension/shared.js +106 -0
  45. package/dist/cli/commands/extension/shared.js.map +1 -0
  46. package/dist/cli/commands/extension.d.ts +36 -68
  47. package/dist/cli/commands/extension.js +143 -1422
  48. package/dist/cli/commands/extension.js.map +1 -1
  49. package/dist/cli/commands/files.d.ts +1 -12
  50. package/dist/cli/commands/files.js +11 -308
  51. package/dist/cli/commands/files.js.map +1 -1
  52. package/dist/cli/commands/get.js +4 -3
  53. package/dist/cli/commands/get.js.map +1 -1
  54. package/dist/cli/commands/health.js +17 -3
  55. package/dist/cli/commands/health.js.map +1 -1
  56. package/dist/cli/commands/history-redact.js +23 -18
  57. package/dist/cli/commands/history-redact.js.map +1 -1
  58. package/dist/cli/commands/history-repair.js +24 -18
  59. package/dist/cli/commands/history-repair.js.map +1 -1
  60. package/dist/cli/commands/legacy-none-tokens.d.ts +3 -0
  61. package/dist/cli/commands/legacy-none-tokens.js +39 -0
  62. package/dist/cli/commands/legacy-none-tokens.js.map +1 -0
  63. package/dist/cli/commands/linked-artifacts.d.ts +96 -0
  64. package/dist/cli/commands/linked-artifacts.js +335 -0
  65. package/dist/cli/commands/linked-artifacts.js.map +1 -0
  66. package/dist/cli/commands/linked-test-parsers.d.ts +28 -0
  67. package/dist/cli/commands/linked-test-parsers.js +192 -0
  68. package/dist/cli/commands/linked-test-parsers.js.map +1 -0
  69. package/dist/cli/commands/list.js +19 -5
  70. package/dist/cli/commands/list.js.map +1 -1
  71. package/dist/cli/commands/normalize.js +4 -3
  72. package/dist/cli/commands/normalize.js.map +1 -1
  73. package/dist/cli/commands/plan.d.ts +5 -0
  74. package/dist/cli/commands/plan.js +56 -8
  75. package/dist/cli/commands/plan.js.map +1 -1
  76. package/dist/cli/commands/recurrence-parsers.d.ts +26 -0
  77. package/dist/cli/commands/recurrence-parsers.js +98 -0
  78. package/dist/cli/commands/recurrence-parsers.js.map +1 -0
  79. package/dist/cli/commands/restore.js +19 -8
  80. package/dist/cli/commands/restore.js.map +1 -1
  81. package/dist/cli/commands/search.js +5 -8
  82. package/dist/cli/commands/search.js.map +1 -1
  83. package/dist/cli/commands/test/linked-command-detection.d.ts +37 -0
  84. package/dist/cli/commands/test/linked-command-detection.js +200 -0
  85. package/dist/cli/commands/test/linked-command-detection.js.map +1 -0
  86. package/dist/cli/commands/test.d.ts +1 -2
  87. package/dist/cli/commands/test.js +8 -350
  88. package/dist/cli/commands/test.js.map +1 -1
  89. package/dist/cli/commands/update-many.js +4 -3
  90. package/dist/cli/commands/update-many.js.map +1 -1
  91. package/dist/cli/commands/update.js +83 -356
  92. package/dist/cli/commands/update.js.map +1 -1
  93. package/dist/cli/commands/validate.js +32 -12
  94. package/dist/cli/commands/validate.js.map +1 -1
  95. package/dist/cli/error-guidance.d.ts +1 -0
  96. package/dist/cli/error-guidance.js +6 -2
  97. package/dist/cli/error-guidance.js.map +1 -1
  98. package/dist/cli/main.d.ts +11 -0
  99. package/dist/cli/main.js +76 -28
  100. package/dist/cli/main.js.map +1 -1
  101. package/dist/cli/register-list-query.d.ts +4 -1
  102. package/dist/cli/register-list-query.js +242 -203
  103. package/dist/cli/register-list-query.js.map +1 -1
  104. package/dist/cli/register-mutation.js +73 -11
  105. package/dist/cli/register-mutation.js.map +1 -1
  106. package/dist/cli/register-operations.js +3 -3
  107. package/dist/cli/register-operations.js.map +1 -1
  108. package/dist/cli/register-setup.js +12 -7
  109. package/dist/cli/register-setup.js.map +1 -1
  110. package/dist/cli/registration-helpers.js +3 -2
  111. package/dist/cli/registration-helpers.js.map +1 -1
  112. package/dist/cli.js +4 -3
  113. package/dist/cli.js.map +1 -1
  114. package/dist/core/config/positional-value.d.ts +44 -0
  115. package/dist/core/config/positional-value.js +109 -0
  116. package/dist/core/config/positional-value.js.map +1 -0
  117. package/dist/core/extensions/extension-capability-aliases.d.ts +14 -0
  118. package/dist/core/extensions/extension-capability-aliases.js +159 -0
  119. package/dist/core/extensions/extension-capability-aliases.js.map +1 -0
  120. package/dist/core/extensions/extension-hook-runtime.d.ts +13 -0
  121. package/dist/core/extensions/extension-hook-runtime.js +414 -0
  122. package/dist/core/extensions/extension-hook-runtime.js.map +1 -0
  123. package/dist/core/extensions/extension-policy.d.ts +69 -0
  124. package/dist/core/extensions/extension-policy.js +481 -0
  125. package/dist/core/extensions/extension-policy.js.map +1 -0
  126. package/dist/core/extensions/extension-registries.d.ts +8 -0
  127. package/dist/core/extensions/extension-registries.js +52 -0
  128. package/dist/core/extensions/extension-registries.js.map +1 -0
  129. package/dist/core/extensions/extension-runtime-helpers.d.ts +6 -0
  130. package/dist/core/extensions/extension-runtime-helpers.js +29 -0
  131. package/dist/core/extensions/extension-runtime-helpers.js.map +1 -0
  132. package/dist/core/extensions/extension-types.d.ts +13 -39
  133. package/dist/core/extensions/extension-types.js +34 -2
  134. package/dist/core/extensions/extension-types.js.map +1 -1
  135. package/dist/core/extensions/index.d.ts +7 -0
  136. package/dist/core/extensions/index.js +11 -2
  137. package/dist/core/extensions/index.js.map +1 -1
  138. package/dist/core/extensions/loader.d.ts +4 -22
  139. package/dist/core/extensions/loader.js +22 -1139
  140. package/dist/core/extensions/loader.js.map +1 -1
  141. package/dist/core/history/drift-scan.d.ts +11 -0
  142. package/dist/core/history/drift-scan.js +114 -32
  143. package/dist/core/history/drift-scan.js.map +1 -1
  144. package/dist/core/history/history-rewrite.d.ts +43 -0
  145. package/dist/core/history/history-rewrite.js +48 -0
  146. package/dist/core/history/history-rewrite.js.map +1 -0
  147. package/dist/core/history/history.js +5 -4
  148. package/dist/core/history/history.js.map +1 -1
  149. package/dist/core/history/replay.js +4 -3
  150. package/dist/core/history/replay.js.map +1 -1
  151. package/dist/core/item/item-record.d.ts +19 -0
  152. package/dist/core/item/item-record.js +24 -0
  153. package/dist/core/item/item-record.js.map +1 -0
  154. package/dist/core/output/mutation-projection.d.ts +31 -0
  155. package/dist/core/output/mutation-projection.js +103 -0
  156. package/dist/core/output/mutation-projection.js.map +1 -0
  157. package/dist/core/output/output.d.ts +2 -0
  158. package/dist/core/output/output.js +5 -3
  159. package/dist/core/output/output.js.map +1 -1
  160. package/dist/core/schema/runtime-schema.js +8 -38
  161. package/dist/core/schema/runtime-schema.js.map +1 -1
  162. package/dist/core/search/vector-stores.js +46 -9
  163. package/dist/core/search/vector-stores.js.map +1 -1
  164. package/dist/core/sentry/helpers.d.ts +1 -1
  165. package/dist/core/sentry/helpers.js +20 -3
  166. package/dist/core/sentry/helpers.js.map +1 -1
  167. package/dist/core/shared/command-types.d.ts +1 -0
  168. package/dist/core/shared/command-types.js +2 -2
  169. package/dist/core/shared/command-types.js.map +1 -1
  170. package/dist/core/shared/constants.d.ts +10 -1
  171. package/dist/core/shared/constants.js +56 -58
  172. package/dist/core/shared/constants.js.map +1 -1
  173. package/dist/core/shared/levenshtein.js +23 -7
  174. package/dist/core/shared/levenshtein.js.map +1 -1
  175. package/dist/core/shared/primitives.d.ts +23 -0
  176. package/dist/core/shared/primitives.js +39 -2
  177. package/dist/core/shared/primitives.js.map +1 -1
  178. package/dist/core/store/front-matter-cache.d.ts +16 -2
  179. package/dist/core/store/front-matter-cache.js +99 -33
  180. package/dist/core/store/front-matter-cache.js.map +1 -1
  181. package/dist/core/store/item-store.js +8 -73
  182. package/dist/core/store/item-store.js.map +1 -1
  183. package/dist/mcp/server.js +76 -28
  184. package/dist/mcp/server.js.map +1 -1
  185. package/dist/sdk/cli-contracts/enum-contracts.d.ts +20 -0
  186. package/dist/sdk/cli-contracts/enum-contracts.js +156 -0
  187. package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -0
  188. package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +14 -0
  189. package/dist/sdk/cli-contracts/tool-option-contracts.js +243 -0
  190. package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -0
  191. package/dist/sdk/cli-contracts/tool-parameter-tables.d.ts +11 -0
  192. package/dist/sdk/cli-contracts/tool-parameter-tables.js +901 -0
  193. package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -0
  194. package/dist/sdk/cli-contracts.d.ts +11 -33
  195. package/dist/sdk/cli-contracts.js +30 -1356
  196. package/dist/sdk/cli-contracts.js.map +1 -1
  197. package/dist/sdk/package-import-adapters.d.ts +74 -0
  198. package/dist/sdk/package-import-adapters.js +186 -0
  199. package/dist/sdk/package-import-adapters.js.map +1 -0
  200. package/dist/sdk/package-runtime-options.d.ts +26 -0
  201. package/dist/sdk/package-runtime-options.js +71 -0
  202. package/dist/sdk/package-runtime-options.js.map +1 -0
  203. package/dist/sdk/runtime.d.ts +2 -0
  204. package/dist/sdk/runtime.js +4 -2
  205. package/dist/sdk/runtime.js.map +1 -1
  206. package/docs/AGENT_GUIDE.md +6 -10
  207. package/docs/CLAUDE_CODE_PLUGIN.md +5 -28
  208. package/docs/CODEX_PLUGIN.md +5 -5
  209. package/docs/COMMANDS.md +19 -3
  210. package/docs/CONFIGURATION.md +15 -0
  211. package/docs/EXTENSIONS.md +4 -63
  212. package/docs/RELEASING.md +4 -4
  213. package/marketplace.json +7 -3
  214. package/package.json +9 -6
  215. package/packages/pm-beads/extensions/beads/index.js +2 -49
  216. package/packages/pm-beads/extensions/beads/index.ts +2 -54
  217. package/packages/pm-beads/extensions/beads/runtime-loader.js +86 -0
  218. package/packages/pm-beads/extensions/beads/runtime-loader.ts +88 -0
  219. package/packages/pm-beads/extensions/beads/runtime.js +26 -115
  220. package/packages/pm-beads/extensions/beads/runtime.ts +33 -132
  221. package/packages/pm-calendar/extensions/calendar/index.js +47 -2
  222. package/packages/pm-calendar/extensions/calendar/index.ts +52 -2
  223. package/packages/pm-calendar/extensions/calendar/runtime.js +1 -0
  224. package/packages/pm-calendar/extensions/calendar/runtime.ts +1 -0
  225. package/packages/pm-governance-audit/extensions/governance-audit/runtime.js +14 -41
  226. package/packages/pm-governance-audit/extensions/governance-audit/runtime.ts +25 -41
  227. package/packages/pm-guide-shell/extensions/guide-shell/runtime.js +10 -50
  228. package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +17 -50
  229. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.js +8 -40
  230. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.ts +10 -40
  231. package/packages/pm-search-advanced/extensions/search-advanced/index.js +1 -1
  232. package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +4 -37
  233. package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +6 -37
  234. package/packages/pm-todos/extensions/todos/index.js +3 -50
  235. package/packages/pm-todos/extensions/todos/index.ts +3 -55
  236. package/packages/pm-todos/extensions/todos/runtime-loader.js +86 -0
  237. package/packages/pm-todos/extensions/todos/runtime-loader.ts +88 -0
  238. package/packages/pm-todos/extensions/todos/runtime.js +24 -117
  239. package/packages/pm-todos/extensions/todos/runtime.ts +32 -129
  240. package/plugins/pm-claude/README.md +2 -2
  241. package/plugins/pm-claude/commands/pm-planner.md +1 -15
  242. package/plugins/pm-claude/scripts/pm-mcp-server.mjs +5 -2
  243. package/plugins/pm-claude/skills/pm-planner/SKILL.md +3 -21
  244. package/plugins/pm-codex/scripts/pm-mcp-server.mjs +15 -6
  245. package/plugins/pm-codex/skills/pm-native/SKILL.md +1 -13
  246. package/PRD.md +0 -1734
@@ -1,8 +1,9 @@
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]="689e9580-d7f6-5b07-be3d-28c381d20260")}catch(e){}}();
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]="b4271a85-6407-5151-876e-6b38c7881b67")}catch(e){}}();
3
3
  import { pathExists } from "../../core/fs/fs-utils.js";
4
4
  import { canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, } from "../../core/item/type-registry.js";
5
5
  import { normalizeItemId } from "../../core/item/id.js";
6
+ import { toItemRecord } from "../../core/item/item-record.js";
6
7
  import { buildInvalidTypeError } from "../../core/schema/item-types-file.js";
7
8
  import { normalizeParentReferenceValue, validateMissingParentReference, } from "../../core/item/parent-reference-policy.js";
8
9
  import { validateSprintOrReleaseValue } from "../../core/item/sprint-release-format.js";
@@ -22,9 +23,10 @@ import { readSettings } from "../../core/store/settings.js";
22
23
  import { runClose } from "./close.js";
23
24
  import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
24
25
  import { resolveEventEndAt } from "./event-validation-messages.js";
25
- import { DEPENDENCY_KIND_VALUES, ISSUE_SEVERITY_VALUES, RECURRENCE_FREQUENCY_VALUES, RECURRENCE_WEEKDAY_VALUES, RISK_VALUES, weekdayOrderIndex, } from "../../types/index.js";
26
+ import { assertNoLegacyNoneToken, assertNoLegacyNoneTokens, isLegacyNoneToken } from "./legacy-none-tokens.js";
27
+ import { ensureEnumValue as ensureEnum, parseEventBoolean, parseRecurrenceRule } from "./recurrence-parsers.js";
28
+ import { DEPENDENCY_KIND_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES, } from "../../types/index.js";
26
29
  import { parseDocs, parseFiles, parseLogSeed, parseTests } from "./create.js";
27
- const LEGACY_NONE_TOKENS = new Set(["none", "null"]);
28
30
  const UPDATE_UNSET_FIELD_DEFINITIONS = [
29
31
  { canonical: "tags", aliases: ["tags"], optionKey: "tags", frontMatterKey: "tags" },
30
32
  { canonical: "close-reason", aliases: ["close_reason", "close-reason"], optionKey: "closeReason", frontMatterKey: "close_reason" },
@@ -170,30 +172,6 @@ function toAuthor(candidate, defaultAuthor) {
170
172
  const trimmed = resolved.trim();
171
173
  return trimmed || "unknown";
172
174
  }
173
- function isLegacyNoneToken(value) {
174
- if (value === undefined) {
175
- return false;
176
- }
177
- return LEGACY_NONE_TOKENS.has(value.trim().toLowerCase());
178
- }
179
- function assertNoLegacyNoneToken(value, flag, replacementHint) {
180
- if (!isLegacyNoneToken(value)) {
181
- return;
182
- }
183
- const suffix = replacementHint ? ` ${replacementHint}` : "";
184
- throw new PmCliError(`${flag} no longer accepts "none" or "null".${suffix}`.trim(), EXIT_CODE.USAGE);
185
- }
186
- function assertNoLegacyNoneTokens(values, flag, replacementHint) {
187
- if (!values || values.length === 0) {
188
- return;
189
- }
190
- const hasLegacyToken = values.some((value) => isLegacyNoneToken(value));
191
- if (!hasLegacyToken) {
192
- return;
193
- }
194
- const suffix = replacementHint ? ` ${replacementHint}` : "";
195
- throw new PmCliError(`${flag} no longer accepts "none" or "null".${suffix}`.trim(), EXIT_CODE.USAGE);
196
- }
197
175
  const UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS = [
198
176
  { optionKey: "dep", clearFlagKey: "clearDeps", valueFlag: "--dep", clearFlag: "--clear-deps", disableReplaceFlagKey: "replaceDeps" },
199
177
  { optionKey: "comment", clearFlagKey: "clearComments", valueFlag: "--comment", clearFlag: "--clear-comments" },
@@ -481,12 +459,6 @@ function enforceAllowAuditUpdateScope(options, clearFrontMatterKeys) {
481
459
  throw new PmCliError(`--allow-audit-update only supports non-lifecycle metadata fields. Remove restricted options: ${disallowedFlags.join(", ")}`, EXIT_CODE.USAGE);
482
460
  }
483
461
  }
484
- function ensureEnum(value, allowed, label) {
485
- if (!allowed.includes(value)) {
486
- throw new PmCliError(`Invalid ${label} value "${value}". Allowed: ${allowed.join(", ")}`, EXIT_CODE.USAGE);
487
- }
488
- return value;
489
- }
490
462
  function parseStatus(value, statusRegistry) {
491
463
  const normalized = normalizeStatusInput(value, statusRegistry);
492
464
  if (!normalized) {
@@ -509,75 +481,6 @@ function parseReminderEntries(raw, nowValue) {
509
481
  };
510
482
  });
511
483
  }
512
- function parseEventBoolean(value, flag) {
513
- const normalized = value.trim().toLowerCase();
514
- if (normalized === "true" || normalized === "1" || normalized === "yes") {
515
- return true;
516
- }
517
- if (normalized === "false" || normalized === "0" || normalized === "no") {
518
- return false;
519
- }
520
- throw new PmCliError(`${flag} must be one of true|false|1|0|yes|no`, EXIT_CODE.USAGE);
521
- }
522
- function parseDelimitedList(raw) {
523
- if (!raw) {
524
- return [];
525
- }
526
- return raw
527
- .split("|")
528
- .map((value) => value.trim())
529
- .filter((value) => value.length > 0);
530
- }
531
- function parseRecurrenceRule(kv, startAt, nowValue) {
532
- const freqRaw = kv.recur_freq?.trim();
533
- const intervalRaw = kv.recur_interval?.trim();
534
- const countRaw = kv.recur_count?.trim();
535
- const untilRaw = kv.recur_until?.trim();
536
- const byWeekdayRaw = kv.recur_by_weekday?.trim();
537
- const byMonthDayRaw = kv.recur_by_month_day?.trim();
538
- const exdatesRaw = kv.recur_exdates?.trim();
539
- const recurrenceInputsProvided = [freqRaw, intervalRaw, countRaw, untilRaw, byWeekdayRaw, byMonthDayRaw, exdatesRaw].some((value) => value !== undefined);
540
- if (!recurrenceInputsProvided) {
541
- return undefined;
542
- }
543
- if (!freqRaw) {
544
- throw new PmCliError("--event recurrence fields require recur_freq=<daily|weekly|monthly|yearly>", EXIT_CODE.USAGE);
545
- }
546
- const freq = ensureEnum(freqRaw.toLowerCase(), RECURRENCE_FREQUENCY_VALUES, "event recurrence frequency");
547
- const interval = intervalRaw ? parseOptionalNumber(intervalRaw, "event recur_interval") : undefined;
548
- if (interval !== undefined && (!Number.isInteger(interval) || interval < 1)) {
549
- throw new PmCliError("--event recur_interval must be an integer >= 1", EXIT_CODE.USAGE);
550
- }
551
- const count = countRaw ? parseOptionalNumber(countRaw, "event recur_count") : undefined;
552
- if (count !== undefined && (!Number.isInteger(count) || count < 1)) {
553
- throw new PmCliError("--event recur_count must be an integer >= 1", EXIT_CODE.USAGE);
554
- }
555
- const until = untilRaw ? resolveIsoOrRelative(untilRaw, nowValue, "event.recur_until") : undefined;
556
- if (until && until < startAt) {
557
- throw new PmCliError("--event recur_until must be at or after start", EXIT_CODE.USAGE);
558
- }
559
- const byWeekday = Array.from(new Set(parseDelimitedList(byWeekdayRaw)
560
- .map((value) => ensureEnum(value.toLowerCase(), RECURRENCE_WEEKDAY_VALUES, "event weekday")))).sort((left, right) => weekdayOrderIndex(left) -
561
- weekdayOrderIndex(right));
562
- const byMonthDay = Array.from(new Set(parseDelimitedList(byMonthDayRaw)
563
- .map((value) => {
564
- const day = parseOptionalNumber(value, "event recur_by_month_day");
565
- if (!Number.isInteger(day) || day < 1 || day > 31) {
566
- throw new PmCliError("--event recur_by_month_day values must be integers 1..31", EXIT_CODE.USAGE);
567
- }
568
- return day;
569
- }))).sort((left, right) => left - right);
570
- const exdates = Array.from(new Set(parseDelimitedList(exdatesRaw).map((value) => resolveIsoOrRelative(value, nowValue, "event.recur_exdates")))).sort((left, right) => left.localeCompare(right));
571
- return {
572
- freq,
573
- interval,
574
- count,
575
- until,
576
- by_weekday: byWeekday.length > 0 ? byWeekday : undefined,
577
- by_month_day: byMonthDay.length > 0 ? byMonthDay : undefined,
578
- exdates: exdates.length > 0 ? exdates : undefined,
579
- };
580
- }
581
484
  function parseEventEntries(raw, nowValue) {
582
485
  return raw.map((entry) => {
583
486
  const kv = parseCsvKv(entry, "--event");
@@ -610,7 +513,7 @@ function parseEventEntries(raw, nowValue) {
610
513
  throw new PmCliError("--event timezone must not be empty", EXIT_CODE.USAGE);
611
514
  }
612
515
  const allDayRaw = kv.all_day?.trim();
613
- const recurrence = parseRecurrenceRule(kv, startAt, nowValue);
516
+ const recurrence = parseRecurrenceRule(kv, startAt, nowValue, "truthy");
614
517
  return {
615
518
  start_at: startAt,
616
519
  end_at: endAt,
@@ -683,6 +586,25 @@ function looksLikeStructuredDependencyEntry(raw) {
683
586
  }
684
587
  return /^(?:[-*+]\s+)?(?:id|kind|author|created_at|source_kind)\s*[:=]/i.test(raw);
685
588
  }
589
+ // pm-fl0c #4 (2026-05-28): `pm plan` accepts `depends_on` as a link kind
590
+ // (`PLAN_STEP_LINK_KIND_VALUES`) but `pm update --dep kind=depends_on` rejected
591
+ // it because `DEPENDENCY_KIND_VALUES` only lists `blocked_by`. The two terms
592
+ // are semantically identical from this side ("X depends on Y" === "X blocked
593
+ // by Y"), so we normalize input here rather than expanding the persisted enum
594
+ // — the stored kind stays canonical (`blocked_by`) and downstream consumers
595
+ // (closing logic, dependency graphs, blockers views) keep working unchanged.
596
+ const DEPENDENCY_KIND_INPUT_ALIASES = {
597
+ depends_on: "blocked_by",
598
+ "depends-on": "blocked_by",
599
+ };
600
+ function normalizeDependencyKindInput(raw) {
601
+ if (typeof raw !== "string") {
602
+ return raw;
603
+ }
604
+ const trimmed = raw.trim();
605
+ const alias = DEPENDENCY_KIND_INPUT_ALIASES[trimmed.toLowerCase()];
606
+ return alias ?? trimmed;
607
+ }
686
608
  function parseDependencyAdditions(raw, prefix, nowIso) {
687
609
  if (!raw) {
688
610
  return { additions: [] };
@@ -692,7 +614,7 @@ function parseDependencyAdditions(raw, prefix, nowIso) {
692
614
  const trimmedEntry = entry.trim();
693
615
  const kv = looksLikeStructuredDependencyEntry(trimmedEntry) ? parseCsvKv(entry, "--dep") : { id: trimmedEntry, kind: "related" };
694
616
  const id = kv.id?.trim();
695
- const kind = kv.kind?.trim();
617
+ const kind = normalizeDependencyKindInput(kv.kind?.trim());
696
618
  if (!id || !kind) {
697
619
  throw new PmCliError("--dep requires id and kind, or a bare item id to add a related dependency", EXIT_CODE.USAGE);
698
620
  }
@@ -729,7 +651,7 @@ function parseDependencyRemovals(raw, prefix) {
729
651
  if (idRaw.toLowerCase() === "undefined") {
730
652
  throw new PmCliError(`--dep-remove id must not use placeholder token "${idRaw}"`, EXIT_CODE.USAGE);
731
653
  }
732
- const kindRaw = parseOptionalDependencyString(kv.kind);
654
+ const kindRaw = normalizeDependencyKindInput(parseOptionalDependencyString(kv.kind));
733
655
  const sourceKind = parseOptionalDependencyString(kv.source_kind);
734
656
  return {
735
657
  id: normalizeItemId(idRaw, prefix),
@@ -1268,7 +1190,7 @@ export async function runUpdate(id, options, global) {
1268
1190
  }
1269
1191
  const { document } = await readLocatedItem(located, { schema: settings.schema });
1270
1192
  return {
1271
- item: document.metadata,
1193
+ item: toItemRecord(document.metadata),
1272
1194
  changed_fields: [],
1273
1195
  warnings: ["noop_no_update_fields"],
1274
1196
  };
@@ -1329,6 +1251,27 @@ export async function runUpdate(id, options, global) {
1329
1251
  const changedFields = [];
1330
1252
  const warnings = [];
1331
1253
  let activeTypeName = resolveTypeName(document.metadata.type, typeRegistry) ?? document.metadata.type;
1254
+ // Declarative set-or-clear helpers for the many string scalar fields that
1255
+ // share an identical shape: set from `--flag` (optionally transformed) or
1256
+ // delete when `--unset <field>` was requested, then record the change.
1257
+ // Each call is placed in the same position the inline block occupied so
1258
+ // the order of `changedFields` is preserved exactly (pm-why9).
1259
+ const metadataRecord = toItemRecord(document.metadata);
1260
+ const setOrClearScalar = (optionValue, metadataKey, transform) => {
1261
+ if (optionValue === undefined && !clearFrontMatterKeys.has(metadataKey)) {
1262
+ return;
1263
+ }
1264
+ if (clearFrontMatterKeys.has(metadataKey)) {
1265
+ delete metadataRecord[metadataKey];
1266
+ }
1267
+ else {
1268
+ metadataRecord[metadataKey] = transform(optionValue);
1269
+ }
1270
+ changedFields.push(metadataKey);
1271
+ };
1272
+ const setOrClearTrimScalar = (optionValue, metadataKey) => {
1273
+ setOrClearScalar(optionValue, metadataKey, (value) => value.trim());
1274
+ };
1332
1275
  if (options.title !== undefined) {
1333
1276
  document.metadata.title = options.title;
1334
1277
  changedFields.push("title");
@@ -1538,42 +1481,10 @@ export async function runUpdate(id, options, global) {
1538
1481
  document.metadata.tags = clearFrontMatterKeys.has("tags") ? [] : parseTags(options.tags);
1539
1482
  changedFields.push("tags");
1540
1483
  }
1541
- if (options.deadline !== undefined || clearFrontMatterKeys.has("deadline")) {
1542
- if (clearFrontMatterKeys.has("deadline")) {
1543
- delete document.metadata.deadline;
1544
- }
1545
- else {
1546
- document.metadata.deadline = resolveIsoOrRelative(options.deadline, new Date(), "deadline");
1547
- }
1548
- changedFields.push("deadline");
1549
- }
1550
- if (options.estimatedMinutes !== undefined || clearFrontMatterKeys.has("estimated_minutes")) {
1551
- if (clearFrontMatterKeys.has("estimated_minutes")) {
1552
- delete document.metadata.estimated_minutes;
1553
- }
1554
- else {
1555
- document.metadata.estimated_minutes = parseOptionalNumber(options.estimatedMinutes, "estimated-minutes");
1556
- }
1557
- changedFields.push("estimated_minutes");
1558
- }
1559
- if (options.acceptanceCriteria !== undefined || clearFrontMatterKeys.has("acceptance_criteria")) {
1560
- if (clearFrontMatterKeys.has("acceptance_criteria")) {
1561
- delete document.metadata.acceptance_criteria;
1562
- }
1563
- else {
1564
- document.metadata.acceptance_criteria = options.acceptanceCriteria;
1565
- }
1566
- changedFields.push("acceptance_criteria");
1567
- }
1568
- if (options.definitionOfReady !== undefined || clearFrontMatterKeys.has("definition_of_ready")) {
1569
- if (clearFrontMatterKeys.has("definition_of_ready")) {
1570
- delete document.metadata.definition_of_ready;
1571
- }
1572
- else {
1573
- document.metadata.definition_of_ready = options.definitionOfReady.trim();
1574
- }
1575
- changedFields.push("definition_of_ready");
1576
- }
1484
+ setOrClearScalar(options.deadline, "deadline", (value) => resolveIsoOrRelative(value, nowValue, "deadline"));
1485
+ setOrClearScalar(options.estimatedMinutes, "estimated_minutes", (value) => parseOptionalNumber(value, "estimated-minutes"));
1486
+ setOrClearScalar(options.acceptanceCriteria, "acceptance_criteria", (value) => value);
1487
+ setOrClearTrimScalar(options.definitionOfReady, "definition_of_ready");
1577
1488
  const orderRaw = options.order ?? options.rank;
1578
1489
  if (orderRaw !== undefined || clearFrontMatterKeys.has("order")) {
1579
1490
  if (clearFrontMatterKeys.has("order")) {
@@ -1588,60 +1499,12 @@ export async function runUpdate(id, options, global) {
1588
1499
  }
1589
1500
  changedFields.push("order");
1590
1501
  }
1591
- if (options.goal !== undefined || clearFrontMatterKeys.has("goal")) {
1592
- if (clearFrontMatterKeys.has("goal")) {
1593
- delete document.metadata.goal;
1594
- }
1595
- else {
1596
- document.metadata.goal = options.goal.trim();
1597
- }
1598
- changedFields.push("goal");
1599
- }
1600
- if (options.objective !== undefined || clearFrontMatterKeys.has("objective")) {
1601
- if (clearFrontMatterKeys.has("objective")) {
1602
- delete document.metadata.objective;
1603
- }
1604
- else {
1605
- document.metadata.objective = options.objective.trim();
1606
- }
1607
- changedFields.push("objective");
1608
- }
1609
- if (options.value !== undefined || clearFrontMatterKeys.has("value")) {
1610
- if (clearFrontMatterKeys.has("value")) {
1611
- delete document.metadata.value;
1612
- }
1613
- else {
1614
- document.metadata.value = options.value.trim();
1615
- }
1616
- changedFields.push("value");
1617
- }
1618
- if (options.impact !== undefined || clearFrontMatterKeys.has("impact")) {
1619
- if (clearFrontMatterKeys.has("impact")) {
1620
- delete document.metadata.impact;
1621
- }
1622
- else {
1623
- document.metadata.impact = options.impact.trim();
1624
- }
1625
- changedFields.push("impact");
1626
- }
1627
- if (options.outcome !== undefined || clearFrontMatterKeys.has("outcome")) {
1628
- if (clearFrontMatterKeys.has("outcome")) {
1629
- delete document.metadata.outcome;
1630
- }
1631
- else {
1632
- document.metadata.outcome = options.outcome.trim();
1633
- }
1634
- changedFields.push("outcome");
1635
- }
1636
- if (options.whyNow !== undefined || clearFrontMatterKeys.has("why_now")) {
1637
- if (clearFrontMatterKeys.has("why_now")) {
1638
- delete document.metadata.why_now;
1639
- }
1640
- else {
1641
- document.metadata.why_now = options.whyNow.trim();
1642
- }
1643
- changedFields.push("why_now");
1644
- }
1502
+ setOrClearTrimScalar(options.goal, "goal");
1503
+ setOrClearTrimScalar(options.objective, "objective");
1504
+ setOrClearTrimScalar(options.value, "value");
1505
+ setOrClearTrimScalar(options.impact, "impact");
1506
+ setOrClearTrimScalar(options.outcome, "outcome");
1507
+ setOrClearTrimScalar(options.whyNow, "why_now");
1645
1508
  if (options.assignee !== undefined || clearFrontMatterKeys.has("assignee")) {
1646
1509
  if (clearFrontMatterKeys.has("assignee")) {
1647
1510
  delete document.metadata.assignee;
@@ -1663,33 +1526,9 @@ export async function runUpdate(id, options, global) {
1663
1526
  }
1664
1527
  changedFields.push("parent");
1665
1528
  }
1666
- if (options.reviewer !== undefined || clearFrontMatterKeys.has("reviewer")) {
1667
- if (clearFrontMatterKeys.has("reviewer")) {
1668
- delete document.metadata.reviewer;
1669
- }
1670
- else {
1671
- document.metadata.reviewer = options.reviewer.trim();
1672
- }
1673
- changedFields.push("reviewer");
1674
- }
1675
- if (options.risk !== undefined || clearFrontMatterKeys.has("risk")) {
1676
- if (clearFrontMatterKeys.has("risk")) {
1677
- delete document.metadata.risk;
1678
- }
1679
- else {
1680
- document.metadata.risk = ensureEnum(normalizeRiskInput(options.risk), RISK_VALUES, "risk");
1681
- }
1682
- changedFields.push("risk");
1683
- }
1684
- if (options.confidence !== undefined || clearFrontMatterKeys.has("confidence")) {
1685
- if (clearFrontMatterKeys.has("confidence")) {
1686
- delete document.metadata.confidence;
1687
- }
1688
- else {
1689
- document.metadata.confidence = parseConfidenceInput(options.confidence);
1690
- }
1691
- changedFields.push("confidence");
1692
- }
1529
+ setOrClearTrimScalar(options.reviewer, "reviewer");
1530
+ setOrClearScalar(options.risk, "risk", (value) => ensureEnum(normalizeRiskInput(value), RISK_VALUES, "risk"));
1531
+ setOrClearScalar(options.confidence, "confidence", (value) => parseConfidenceInput(value));
1693
1532
  if (options.sprint !== undefined || clearFrontMatterKeys.has("sprint")) {
1694
1533
  if (clearFrontMatterKeys.has("sprint")) {
1695
1534
  delete document.metadata.sprint;
@@ -1723,132 +1562,20 @@ export async function runUpdate(id, options, global) {
1723
1562
  // pm-kyd6: keep the dependency graph in sync with the blocked_by scalar.
1724
1563
  applyBlockedByDependencyEdge(document.metadata, resolvedBlockedByDependencyId, nowIso, author, changedFields);
1725
1564
  }
1726
- if (options.blockedReason !== undefined || clearFrontMatterKeys.has("blocked_reason")) {
1727
- if (clearFrontMatterKeys.has("blocked_reason")) {
1728
- delete document.metadata.blocked_reason;
1729
- }
1730
- else {
1731
- document.metadata.blocked_reason = options.blockedReason.trim();
1732
- }
1733
- changedFields.push("blocked_reason");
1734
- }
1735
- if (options.unblockNote !== undefined || clearFrontMatterKeys.has("unblock_note")) {
1736
- if (clearFrontMatterKeys.has("unblock_note")) {
1737
- delete document.metadata.unblock_note;
1738
- }
1739
- else {
1740
- document.metadata.unblock_note = options.unblockNote.trim();
1741
- }
1742
- changedFields.push("unblock_note");
1743
- }
1744
- if (options.reporter !== undefined || clearFrontMatterKeys.has("reporter")) {
1745
- if (clearFrontMatterKeys.has("reporter")) {
1746
- delete document.metadata.reporter;
1747
- }
1748
- else {
1749
- document.metadata.reporter = options.reporter.trim();
1750
- }
1751
- changedFields.push("reporter");
1752
- }
1753
- if (options.severity !== undefined || clearFrontMatterKeys.has("severity")) {
1754
- if (clearFrontMatterKeys.has("severity")) {
1755
- delete document.metadata.severity;
1756
- }
1757
- else {
1758
- document.metadata.severity = ensureEnum(normalizeSeverityInput(options.severity), ISSUE_SEVERITY_VALUES, "severity");
1759
- }
1760
- changedFields.push("severity");
1761
- }
1762
- if (options.environment !== undefined || clearFrontMatterKeys.has("environment")) {
1763
- if (clearFrontMatterKeys.has("environment")) {
1764
- delete document.metadata.environment;
1765
- }
1766
- else {
1767
- document.metadata.environment = options.environment.trim();
1768
- }
1769
- changedFields.push("environment");
1770
- }
1771
- if (options.reproSteps !== undefined || clearFrontMatterKeys.has("repro_steps")) {
1772
- if (clearFrontMatterKeys.has("repro_steps")) {
1773
- delete document.metadata.repro_steps;
1774
- }
1775
- else {
1776
- document.metadata.repro_steps = options.reproSteps.trim();
1777
- }
1778
- changedFields.push("repro_steps");
1779
- }
1780
- if (options.resolution !== undefined || clearFrontMatterKeys.has("resolution")) {
1781
- if (clearFrontMatterKeys.has("resolution")) {
1782
- delete document.metadata.resolution;
1783
- }
1784
- else {
1785
- document.metadata.resolution = options.resolution.trim();
1786
- }
1787
- changedFields.push("resolution");
1788
- }
1789
- if (options.expectedResult !== undefined || clearFrontMatterKeys.has("expected_result")) {
1790
- if (clearFrontMatterKeys.has("expected_result")) {
1791
- delete document.metadata.expected_result;
1792
- }
1793
- else {
1794
- document.metadata.expected_result = options.expectedResult.trim();
1795
- }
1796
- changedFields.push("expected_result");
1797
- }
1798
- if (options.actualResult !== undefined || clearFrontMatterKeys.has("actual_result")) {
1799
- if (clearFrontMatterKeys.has("actual_result")) {
1800
- delete document.metadata.actual_result;
1801
- }
1802
- else {
1803
- document.metadata.actual_result = options.actualResult.trim();
1804
- }
1805
- changedFields.push("actual_result");
1806
- }
1807
- if (options.affectedVersion !== undefined || clearFrontMatterKeys.has("affected_version")) {
1808
- if (clearFrontMatterKeys.has("affected_version")) {
1809
- delete document.metadata.affected_version;
1810
- }
1811
- else {
1812
- document.metadata.affected_version = options.affectedVersion.trim();
1813
- }
1814
- changedFields.push("affected_version");
1815
- }
1816
- if (options.fixedVersion !== undefined || clearFrontMatterKeys.has("fixed_version")) {
1817
- if (clearFrontMatterKeys.has("fixed_version")) {
1818
- delete document.metadata.fixed_version;
1819
- }
1820
- else {
1821
- document.metadata.fixed_version = options.fixedVersion.trim();
1822
- }
1823
- changedFields.push("fixed_version");
1824
- }
1825
- if (options.component !== undefined || clearFrontMatterKeys.has("component")) {
1826
- if (clearFrontMatterKeys.has("component")) {
1827
- delete document.metadata.component;
1828
- }
1829
- else {
1830
- document.metadata.component = options.component.trim();
1831
- }
1832
- changedFields.push("component");
1833
- }
1834
- if (options.regression !== undefined || clearFrontMatterKeys.has("regression")) {
1835
- if (clearFrontMatterKeys.has("regression")) {
1836
- delete document.metadata.regression;
1837
- }
1838
- else {
1839
- document.metadata.regression = parseRegressionInput(options.regression);
1840
- }
1841
- changedFields.push("regression");
1842
- }
1843
- if (options.customerImpact !== undefined || clearFrontMatterKeys.has("customer_impact")) {
1844
- if (clearFrontMatterKeys.has("customer_impact")) {
1845
- delete document.metadata.customer_impact;
1846
- }
1847
- else {
1848
- document.metadata.customer_impact = options.customerImpact.trim();
1849
- }
1850
- changedFields.push("customer_impact");
1851
- }
1565
+ setOrClearTrimScalar(options.blockedReason, "blocked_reason");
1566
+ setOrClearTrimScalar(options.unblockNote, "unblock_note");
1567
+ setOrClearTrimScalar(options.reporter, "reporter");
1568
+ setOrClearScalar(options.severity, "severity", (value) => ensureEnum(normalizeSeverityInput(value), ISSUE_SEVERITY_VALUES, "severity"));
1569
+ setOrClearTrimScalar(options.environment, "environment");
1570
+ setOrClearTrimScalar(options.reproSteps, "repro_steps");
1571
+ setOrClearTrimScalar(options.resolution, "resolution");
1572
+ setOrClearTrimScalar(options.expectedResult, "expected_result");
1573
+ setOrClearTrimScalar(options.actualResult, "actual_result");
1574
+ setOrClearTrimScalar(options.affectedVersion, "affected_version");
1575
+ setOrClearTrimScalar(options.fixedVersion, "fixed_version");
1576
+ setOrClearTrimScalar(options.component, "component");
1577
+ setOrClearScalar(options.regression, "regression", (value) => parseRegressionInput(value));
1578
+ setOrClearTrimScalar(options.customerImpact, "customer_impact");
1852
1579
  if (options.reminder !== undefined || clearFrontMatterKeys.has("reminders")) {
1853
1580
  if (clearFrontMatterKeys.has("reminders")) {
1854
1581
  delete document.metadata.reminders;
@@ -1871,10 +1598,10 @@ export async function runUpdate(id, options, global) {
1871
1598
  if (!clearFrontMatterKeys.has(definition.metadata_key)) {
1872
1599
  continue;
1873
1600
  }
1874
- if (document.metadata[definition.metadata_key] === undefined) {
1601
+ if (metadataRecord[definition.metadata_key] === undefined) {
1875
1602
  continue;
1876
1603
  }
1877
- delete document.metadata[definition.metadata_key];
1604
+ delete metadataRecord[definition.metadata_key];
1878
1605
  changedFields.push(definition.metadata_key);
1879
1606
  }
1880
1607
  const runtimeFieldUpdates = collectRuntimeUpdateFieldValues(options, runtimeFieldRegistry);
@@ -1882,14 +1609,14 @@ export async function runUpdate(id, options, global) {
1882
1609
  if (clearFrontMatterKeys.has(fieldKey)) {
1883
1610
  continue;
1884
1611
  }
1885
- if (JSON.stringify(document.metadata[fieldKey]) === JSON.stringify(fieldValue)) {
1612
+ if (JSON.stringify(metadataRecord[fieldKey]) === JSON.stringify(fieldValue)) {
1886
1613
  continue;
1887
1614
  }
1888
- document.metadata[fieldKey] = fieldValue;
1615
+ metadataRecord[fieldKey] = fieldValue;
1889
1616
  changedFields.push(fieldKey);
1890
1617
  }
1891
1618
  try {
1892
- applyRegisteredItemFieldDefaultsAndValidation(document.metadata, getActiveExtensionRegistrations());
1619
+ applyRegisteredItemFieldDefaultsAndValidation(metadataRecord, getActiveExtensionRegistrations());
1893
1620
  }
1894
1621
  catch (error) {
1895
1622
  throw new PmCliError(error instanceof Error ? error.message : "Invalid extension item field values", EXIT_CODE.USAGE);
@@ -1898,11 +1625,11 @@ export async function runUpdate(id, options, global) {
1898
1625
  },
1899
1626
  });
1900
1627
  return {
1901
- item: result.item,
1628
+ item: toItemRecord(result.item),
1902
1629
  changed_fields: result.changedFields,
1903
1630
  warnings: [...parentReferenceWarnings, ...result.warnings],
1904
1631
  ...(options.allowAuditUpdate === true || options.allowAuditDepUpdate === true ? { audit_update: true } : {}),
1905
1632
  };
1906
1633
  }
1907
1634
  //# sourceMappingURL=update.js.map
1908
- //# debugId=689e9580-d7f6-5b07-be3d-28c381d20260
1635
+ //# debugId=b4271a85-6407-5151-876e-6b38c7881b67