@unbrained/pm-cli 2026.5.28 → 2026.5.29

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 (83) hide show
  1. package/CHANGELOG.md +100 -83
  2. package/dist/cli/commander-usage.js +8 -8
  3. package/dist/cli/commander-usage.js.map +1 -1
  4. package/dist/cli/commands/aggregate.js +4 -3
  5. package/dist/cli/commands/aggregate.js.map +1 -1
  6. package/dist/cli/commands/calendar.d.ts +8 -0
  7. package/dist/cli/commands/calendar.js +13 -2
  8. package/dist/cli/commands/calendar.js.map +1 -1
  9. package/dist/cli/commands/completion.js +34 -2
  10. package/dist/cli/commands/completion.js.map +1 -1
  11. package/dist/cli/commands/config.d.ts +11 -1
  12. package/dist/cli/commands/config.js +68 -6
  13. package/dist/cli/commands/config.js.map +1 -1
  14. package/dist/cli/commands/create.d.ts +1 -0
  15. package/dist/cli/commands/create.js +40 -4
  16. package/dist/cli/commands/create.js.map +1 -1
  17. package/dist/cli/commands/extension/bundled-catalog.js +4 -3
  18. package/dist/cli/commands/extension/bundled-catalog.js.map +1 -1
  19. package/dist/cli/commands/health.js +3 -11
  20. package/dist/cli/commands/health.js.map +1 -1
  21. package/dist/cli/commands/linked-test-parsers.js +5 -4
  22. package/dist/cli/commands/linked-test-parsers.js.map +1 -1
  23. package/dist/cli/commands/plan.js +5 -4
  24. package/dist/cli/commands/plan.js.map +1 -1
  25. package/dist/cli/commands/search.js +45 -2
  26. package/dist/cli/commands/search.js.map +1 -1
  27. package/dist/cli/commands/update-many.js +35 -6
  28. package/dist/cli/commands/update-many.js.map +1 -1
  29. package/dist/cli/commands/update.d.ts +2 -0
  30. package/dist/cli/commands/update.js +38 -6
  31. package/dist/cli/commands/update.js.map +1 -1
  32. package/dist/cli/help-json-payload.d.ts +1 -11
  33. package/dist/cli/help-json-payload.js +12 -12
  34. package/dist/cli/help-json-payload.js.map +1 -1
  35. package/dist/cli/register-mutation.js +20 -8
  36. package/dist/cli/register-mutation.js.map +1 -1
  37. package/dist/cli/register-setup.js +4 -2
  38. package/dist/cli/register-setup.js.map +1 -1
  39. package/dist/cli/registration-helpers.d.ts +2 -6
  40. package/dist/cli/registration-helpers.js +9 -6
  41. package/dist/cli/registration-helpers.js.map +1 -1
  42. package/dist/core/config/nested-settings.d.ts +86 -0
  43. package/dist/core/config/nested-settings.js +258 -0
  44. package/dist/core/config/nested-settings.js.map +1 -0
  45. package/dist/core/item/parse.d.ts +19 -0
  46. package/dist/core/item/parse.js +76 -2
  47. package/dist/core/item/parse.js.map +1 -1
  48. package/dist/core/item/priority.d.ts +2 -1
  49. package/dist/core/item/priority.js +12 -2
  50. package/dist/core/item/priority.js.map +1 -1
  51. package/dist/core/search/providers.js +25 -5
  52. package/dist/core/search/providers.js.map +1 -1
  53. package/dist/core/search/staleness.d.ts +23 -0
  54. package/dist/core/search/staleness.js +34 -0
  55. package/dist/core/search/staleness.js.map +1 -0
  56. package/dist/core/search/vector-stores.js +12 -3
  57. package/dist/core/search/vector-stores.js.map +1 -1
  58. package/dist/core/shared/html-entity-decode.d.ts +21 -0
  59. package/dist/core/shared/html-entity-decode.js +122 -0
  60. package/dist/core/shared/html-entity-decode.js.map +1 -0
  61. package/dist/core/shared/split-comma-list.d.ts +20 -0
  62. package/dist/core/shared/split-comma-list.js +29 -0
  63. package/dist/core/shared/split-comma-list.js.map +1 -0
  64. package/dist/mcp/server.js +10 -3
  65. package/dist/mcp/server.js.map +1 -1
  66. package/dist/sdk/cli-contracts/commander-mutation-options.js +47 -11
  67. package/dist/sdk/cli-contracts/commander-mutation-options.js.map +1 -1
  68. package/dist/sdk/cli-contracts/tool-option-contracts.js +5 -2
  69. package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -1
  70. package/dist/sdk/cli-contracts/tool-parameter-tables.js +12 -2
  71. package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
  72. package/dist/sdk/cli-contracts.js +25 -4
  73. package/dist/sdk/cli-contracts.js.map +1 -1
  74. package/dist/sdk/runtime.d.ts +1 -1
  75. package/dist/sdk/runtime.js +3 -3
  76. package/dist/sdk/runtime.js.map +1 -1
  77. package/docs/AGENT_GUIDE.md +7 -0
  78. package/docs/COMMANDS.md +17 -0
  79. package/docs/CONFIGURATION.md +55 -0
  80. package/docs/QUICKSTART.md +3 -0
  81. package/package.json +1 -1
  82. package/packages/pm-calendar/extensions/calendar/runtime.js +5 -0
  83. package/packages/pm-calendar/extensions/calendar/runtime.ts +6 -0
@@ -1,16 +1,17 @@
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]="10f962f6-810b-5b40-a073-b763d0b0d8b0")}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]="8e1bfe68-8472-50a9-949d-d6429ca8ff20")}catch(e){}}();
3
3
  import { pathExists, removeFileIfExists, writeFileAtomic } from "../../core/fs/fs-utils.js";
4
4
  import { appendHistoryEntry, createHistoryEntry } from "../../core/history/history.js";
5
5
  import { generateItemId, normalizeItemId } from "../../core/item/id.js";
6
6
  import { canonicalDocument, normalizeFrontMatter, serializeItemDocument } from "../../core/item/item-format.js";
7
7
  import { normalizeParentReferenceValue, validateMissingParentReference, } from "../../core/item/parent-reference-policy.js";
8
8
  import { validateSprintOrReleaseValue } from "../../core/item/sprint-release-format.js";
9
- import { createStdinTokenResolver, parseCsvKv, parseOptionalNumber, parseTags } from "../../core/item/parse.js";
9
+ import { createStdinTokenResolver, mergeAdditiveTags, parseCsvKv, parseOptionalNumber, parseTags } from "../../core/item/parse.js";
10
10
  import { resolvePriority } from "../../core/item/priority.js";
11
11
  import { normalizeStatusInput } from "../../core/item/status.js";
12
12
  import { canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, } from "../../core/item/type-registry.js";
13
13
  import { acquireLock } from "../../core/lock/lock.js";
14
+ import { printError } from "../../core/output/output.js";
14
15
  import { buildInvalidTypeError } from "../../core/schema/item-types-file.js";
15
16
  import { collectRuntimeCreateFieldValues } from "../../core/schema/runtime-field-values.js";
16
17
  import { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, } from "../../core/schema/runtime-schema.js";
@@ -711,6 +712,14 @@ function requireCreateOptionByType(typeDefinition, options, createMode, clearOpt
711
712
  typeOption: options.typeOption,
712
713
  };
713
714
  const hasOptionValue = (optionKey) => {
715
+ // `--add-tags` mutates the same `tags` field as `--tags`, so it must count
716
+ // toward the `tags` command_option_policy (both the disabled guard and the
717
+ // required check) — otherwise `--add-tags` would bypass a rule disabling
718
+ // tags, or fail to satisfy a rule requiring them even though the created
719
+ // item ends up tagged.
720
+ if (optionKey === "tags") {
721
+ return scalarValues.tags !== undefined || (Array.isArray(options.addTags) && options.addTags.length > 0);
722
+ }
714
723
  if (optionKey in scalarValues) {
715
724
  return scalarValues[optionKey] !== undefined;
716
725
  }
@@ -1212,11 +1221,20 @@ export async function runCreate(options, global) {
1212
1221
  const id = await generateItemId(pmRoot, settings.id_prefix);
1213
1222
  let status = resolvedOptions.status !== undefined ? parseStatusValue(resolvedOptions.status, statusRegistry) : statusRegistry.open_status;
1214
1223
  const priority = resolvedOptions.priority !== undefined ? ensurePriority(resolvedOptions.priority) : 2;
1215
- const tags = unsetTargets.frontMatterKeys.has("tags")
1224
+ // `--unset tags` clears the field; combining it with `--add-tags` is the same
1225
+ // contradiction that `--unset tags --tags ...` already rejects, so reject it
1226
+ // here rather than silently letting the additions win over the clear.
1227
+ if (unsetTargets.frontMatterKeys.has("tags") &&
1228
+ Array.isArray(resolvedOptions.addTags) &&
1229
+ resolvedOptions.addTags.length > 0) {
1230
+ throw new PmCliError("Cannot combine --unset tags with --add-tags", EXIT_CODE.USAGE);
1231
+ }
1232
+ const baseTags = unsetTargets.frontMatterKeys.has("tags")
1216
1233
  ? []
1217
1234
  : resolvedOptions.tags !== undefined
1218
1235
  ? parseTags(resolvedOptions.tags)
1219
1236
  : [];
1237
+ const tags = mergeAdditiveTags(baseTags, resolvedOptions.addTags);
1220
1238
  const deadline = unsetTargets.frontMatterKeys.has("deadline")
1221
1239
  ? undefined
1222
1240
  : resolvedOptions.deadline === undefined
@@ -1288,6 +1306,16 @@ export async function runCreate(options, global) {
1288
1306
  if (type.toLowerCase() === "event" && (events.values === undefined || events.values.length === 0)) {
1289
1307
  validationWarnings.push(`event_without_schedule:${id}:no_time_set`);
1290
1308
  }
1309
+ // Calendar-relevant types (Milestone, Meeting, Reminder, Event) with NO deadline AND no
1310
+ // reminders AND no events are invisible on `pm calendar`. Warn (never block) so the agent
1311
+ // can attach a schedule via `pm update`.
1312
+ const calendarRelevantTypes = new Set(["milestone", "meeting", "reminder", "event"]);
1313
+ const hasDeadline = deadline !== undefined;
1314
+ const hasReminders = reminders.values !== undefined && reminders.values.length > 0;
1315
+ const hasEvents = events.values !== undefined && events.values.length > 0;
1316
+ if (calendarRelevantTypes.has(type.toLowerCase()) && !hasDeadline && !hasReminders && !hasEvents) {
1317
+ validationWarnings.push(`calendar_item_without_schedule:${id}:no_deadline_or_reminder_or_event`);
1318
+ }
1291
1319
  if (parent !== undefined) {
1292
1320
  parent = normalizeParentReferenceValue(parent);
1293
1321
  const parentLocated = await locateItem(pmRoot, parent, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);
@@ -1497,6 +1525,14 @@ export async function runCreate(options, global) {
1497
1525
  }
1498
1526
  const changedFields = buildChangedFields(frontMatter, body, explicitUnsetKeys);
1499
1527
  const outputItem = structuredClone(frontMatter);
1528
+ // After the create has committed (so the ID is real and shows up in the suggestion),
1529
+ // emit a single non-blocking stderr hint when the new item would be invisible on `pm
1530
+ // calendar`. The structured `calendar_item_without_schedule:*` warning above is what
1531
+ // automation reads; this stderr line is the human/agent-facing version with a
1532
+ // copy-pasteable `pm update` recipe.
1533
+ if (calendarRelevantTypes.has(type.toLowerCase()) && !hasDeadline && !hasReminders && !hasEvents) {
1534
+ printError(`[pm] warning: ${type} '${id}' has no deadline/reminder/event — it will not appear on the calendar. Add one via 'pm update ${id} --deadline <ISO>' or 'pm update ${id} --event "title|start|end"'.`);
1535
+ }
1500
1536
  return {
1501
1537
  item: outputItem,
1502
1538
  changed_fields: changedFields,
@@ -1504,4 +1540,4 @@ export async function runCreate(options, global) {
1504
1540
  };
1505
1541
  }
1506
1542
  //# sourceMappingURL=create.js.map
1507
- //# debugId=10f962f6-810b-5b40-a073-b763d0b0d8b0
1543
+ //# debugId=8e1bfe68-8472-50a9-949d-d6429ca8ff20