@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,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]="9dfba929-1fc6-569e-8311-91fc06f420bc")}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]="a8653cb8-6b5a-5e26-bf29-f20efd02a25b")}catch(e){}}();
3
3
  import { activateExtensions, loadExtensions, } from "../core/extensions/index.js";
4
4
  import { resolveItemTypeRegistry } from "../core/item/type-registry.js";
5
5
  import { resolveRuntimeStatusRegistry } from "../core/schema/runtime-schema.js";
@@ -23,7 +23,7 @@ export { isTimestampLiteral, nowIso } from "../core/shared/time.js";
23
23
  export { listAllFrontMatter, locateItem, readLocatedItem } from "../core/store/item-store.js";
24
24
  export { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from "../core/store/paths.js";
25
25
  export { readSettings } from "../core/store/settings.js";
26
- export { renderCalendarMarkdown, resolveCalendarOutputFormat, runCalendar, } from "../cli/commands/calendar.js";
26
+ export { renderCalendarMarkdown, renderCalendarToon, resolveCalendarOutputFormat, runCalendar, } from "../cli/commands/calendar.js";
27
27
  export { renderGuideMarkdown, resolveGuideOutputFormat, runGuide, } from "../cli/commands/guide.js";
28
28
  export { runCompletion } from "../cli/commands/completion.js";
29
29
  export { runCommentsAudit, } from "../cli/commands/comments-audit.js";
@@ -73,4 +73,4 @@ async function loadWorkspaceExtensionRegistrations(pmRoot, settings, cwd) {
73
73
  return activationResult.registrations;
74
74
  }
75
75
  //# sourceMappingURL=runtime.js.map
76
- //# debugId=9dfba929-1fc6-569e-8311-91fc06f420bc
76
+ //# debugId=a8653cb8-6b5a-5e26-bf29-f20efd02a25b
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sources":["sdk/runtime.ts"],"sourceRoot":"/","sourcesContent":["import {\n activateExtensions,\n loadExtensions,\n type ExtensionRegistrationRegistry,\n} from \"../core/extensions/index.js\";\nimport type { GlobalOptions } from \"../core/shared/command-types.js\";\nimport { resolveItemTypeRegistry } from \"../core/item/type-registry.js\";\nimport { resolveRuntimeStatusRegistry } from \"../core/schema/runtime-schema.js\";\nimport { readSettings } from \"../core/store/settings.js\";\nimport {\n runContracts,\n type ContractsCommandOptions,\n type ContractsResult,\n} from \"../cli/commands/contracts.js\";\n\nexport {\n getActiveExtensionRegistrations,\n runActiveOnReadHooks,\n runActiveOnWriteHooks,\n} from \"../core/extensions/index.js\";\nexport { pathExists, readFileIfExists, removeFileIfExists, writeFileAtomic } from \"../core/fs/fs-utils.js\";\nexport { appendHistoryEntry, createHistoryEntry } from \"../core/history/history.js\";\nexport { generateItemId, normalizeItemId, normalizeRawItemId } from \"../core/item/id.js\";\nexport { readBooleanOption, readCsvListOption, readStringOption } from \"./package-runtime-options.js\";\nexport {\n commitImportedItem,\n emptyImportedDocument,\n ensureTrackerInitialized,\n selectImportAuthor,\n toEstimatedMinutesValue,\n toImportPriority,\n toImportStatus,\n toImportTags,\n toNonEmptyImportString,\n type CommitImportedItemParams,\n type CommitImportedItemResult,\n} from \"./package-import-adapters.js\";\nexport {\n canonicalDocument,\n normalizeFrontMatter,\n serializeItemDocument,\n splitFrontMatter,\n} from \"../core/item/item-format.js\";\nexport { parseTags } from \"../core/item/parse.js\";\nexport { normalizeStatusInput } from \"../core/item/status.js\";\nexport { resolveItemTypeRegistry } from \"../core/item/type-registry.js\";\nexport { acquireLock } from \"../core/lock/lock.js\";\nexport { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry } from \"../core/schema/runtime-schema.js\";\nexport { EXIT_CODE } from \"../core/shared/constants.js\";\nexport { PmCliError } from \"../core/shared/errors.js\";\nexport { isTimestampLiteral, nowIso } from \"../core/shared/time.js\";\nexport { listAllFrontMatter, locateItem, readLocatedItem } from \"../core/store/item-store.js\";\nexport { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from \"../core/store/paths.js\";\nexport { readSettings } from \"../core/store/settings.js\";\nexport {\n renderCalendarMarkdown,\n resolveCalendarOutputFormat,\n runCalendar,\n type CalendarOptions,\n type CalendarResult,\n} from \"../cli/commands/calendar.js\";\nexport {\n renderGuideMarkdown,\n resolveGuideOutputFormat,\n runGuide,\n type GuideDepth,\n type GuideOptions,\n type GuideOutputFormat,\n type GuideResult,\n} from \"../cli/commands/guide.js\";\nexport { runCompletion, type CompletionResult, type CompletionShell } from \"../cli/commands/completion.js\";\nexport {\n runCommentsAudit,\n type CommentsAuditEntry,\n type CommentsAuditHistoryRow,\n type CommentsAuditOptions,\n type CommentsAuditResult,\n type CommentsAuditSummary,\n type CommentsAuditTypeSummary,\n} from \"../cli/commands/comments-audit.js\";\nexport {\n runDedupeAudit,\n type DedupeAuditCandidate,\n type DedupeAuditCluster,\n type DedupeAuditOptions,\n type DedupeAuditResult,\n} from \"../cli/commands/dedupe-audit.js\";\nexport { runNormalize, type NormalizeCommandOptions, type NormalizeResult } from \"../cli/commands/normalize.js\";\nexport { runReindex, type ReindexOptions, type ReindexResult } from \"../cli/commands/reindex.js\";\nexport { runSearch, type SearchOptions, type SearchResult } from \"../cli/commands/search.js\";\nexport {\n loadCreateTemplateOptions,\n runTemplatesList,\n runTemplatesSave,\n runTemplatesShow,\n type CreateTemplateOptions,\n type TemplatesListResult,\n type TemplatesSaveResult,\n type TemplatesShowResult,\n} from \"../cli/commands/templates.js\";\nexport {\n runTestRunsList,\n runTestRunsLogs,\n runTestRunsResume,\n runTestRunsStatus,\n runTestRunsStop,\n type TestRunsListCommandOptions,\n type TestRunsLogsCommandOptions,\n type TestRunsResumeCommandOptions,\n type TestRunsStopCommandOptions,\n} from \"../cli/commands/test-runs.js\";\nexport {\n CONFIDENCE_TEXT_VALUES,\n DEPENDENCY_KIND_VALUES,\n BUILTIN_ITEM_TYPE_VALUES,\n ISSUE_SEVERITY_VALUES,\n ITEM_TYPE_VALUES,\n RISK_VALUES,\n STATUS_VALUES,\n} from \"../types/index.js\";\nexport type { GlobalOptions } from \"../core/shared/command-types.js\";\nexport type {\n Dependency,\n ItemDocument,\n ItemMetadata,\n ItemStatus,\n ItemType,\n LinkedDoc,\n LinkedFile,\n LinkedTest,\n LogNote,\n PmSettings,\n} from \"../types/index.js\";\n\nexport interface GetContractsOptions extends ContractsCommandOptions {\n pmRoot?: string;\n cwd?: string;\n noExtensions?: boolean;\n quiet?: boolean;\n profile?: boolean;\n}\n\nexport interface WorkspaceContractsOptions {\n extensionRegistrations?: ExtensionRegistrationRegistry | null;\n noExtensions?: boolean;\n cwd?: string;\n}\n\nexport interface WorkspaceContracts {\n types: string[];\n statuses: string[];\n openStatus: string;\n closeStatus: string;\n canceledStatus: string;\n}\n\nexport async function getWorkspaceContracts(\n pmRoot: string,\n options: WorkspaceContractsOptions = {},\n): Promise<WorkspaceContracts> {\n const settings = await readSettings(pmRoot);\n const extensionRegistrations =\n options.extensionRegistrations ??\n (options.noExtensions === true ? null : await loadWorkspaceExtensionRegistrations(pmRoot, settings, options.cwd));\n const typeRegistry = resolveItemTypeRegistry(settings, extensionRegistrations);\n const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);\n\n return {\n types: [...typeRegistry.types],\n statuses: statusRegistry.definitions.map((definition) => definition.id),\n openStatus: statusRegistry.open_status,\n closeStatus: statusRegistry.close_status,\n canceledStatus: statusRegistry.canceled_status,\n };\n}\n\nexport async function getContracts(\n pmRootOrOptions?: string | GetContractsOptions,\n options: GetContractsOptions = {},\n): Promise<ContractsResult> {\n const resolvedOptions =\n typeof pmRootOrOptions === \"string\"\n ? { ...options, pmRoot: pmRootOrOptions }\n : (pmRootOrOptions ?? options);\n const global: GlobalOptions = {\n json: true,\n quiet: resolvedOptions.quiet ?? true,\n noExtensions: resolvedOptions.noExtensions ?? false,\n noPager: true,\n profile: resolvedOptions.profile ?? false,\n path: resolvedOptions.pmRoot,\n };\n\n return runContracts(resolvedOptions, global);\n}\n\nasync function loadWorkspaceExtensionRegistrations(\n pmRoot: string,\n settings: Awaited<ReturnType<typeof readSettings>>,\n cwd?: string,\n): Promise<ExtensionRegistrationRegistry | null> {\n const loadResult = await loadExtensions({\n pmRoot,\n settings,\n cwd: cwd ?? process.cwd(),\n noExtensions: false,\n });\n const activationResult = await activateExtensions(loadResult);\n return activationResult.registrations;\n}\n\nexport type { ContractsCommandOptions, ContractsResult };\n"],"names":[],"mappings":";;AAAA,OAAO,EACL,kBAAkB,EAClB,cAAc,GAEf,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EACL,YAAY,GAGb,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,+BAA+B,EAC/B,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC3G,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AACtG,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,sBAAsB,GAGvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,2BAA2B,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAC7G,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9F,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACrG,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,WAAW,GAGZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,QAAQ,GAKT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAA+C,MAAM,+BAA+B,CAAC;AAC3G,OAAO,EACL,gBAAgB,GAOjB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,cAAc,GAKf,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,YAAY,EAAsD,MAAM,8BAA8B,CAAC;AAChH,OAAO,EAAE,UAAU,EAA2C,MAAM,4BAA4B,CAAC;AACjG,OAAO,EAAE,SAAS,EAAyC,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GAKjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAKhB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,aAAa,GACd,MAAM,mBAAmB,CAAC;AAqC3B,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAc,EACd,UAAqC,EAAE;IAEvC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,sBAAsB,GAC1B,OAAO,CAAC,sBAAsB;QAC9B,CAAC,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,mCAAmC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACpH,MAAM,YAAY,GAAG,uBAAuB,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;IAC/E,MAAM,cAAc,GAAG,4BAA4B,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAErE,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC;QAC9B,QAAQ,EAAE,cAAc,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;QACvE,UAAU,EAAE,cAAc,CAAC,WAAW;QACtC,WAAW,EAAE,cAAc,CAAC,YAAY;QACxC,cAAc,EAAE,cAAc,CAAC,eAAe;KAC/C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,eAA8C,EAC9C,UAA+B,EAAE;IAEjC,MAAM,eAAe,GACnB,OAAO,eAAe,KAAK,QAAQ;QACjC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE;QACzC,CAAC,CAAC,CAAC,eAAe,IAAI,OAAO,CAAC,CAAC;IACnC,MAAM,MAAM,GAAkB;QAC5B,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,eAAe,CAAC,KAAK,IAAI,IAAI;QACpC,YAAY,EAAE,eAAe,CAAC,YAAY,IAAI,KAAK;QACnD,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,eAAe,CAAC,OAAO,IAAI,KAAK;QACzC,IAAI,EAAE,eAAe,CAAC,MAAM;KAC7B,CAAC;IAEF,OAAO,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,mCAAmC,CAChD,MAAc,EACd,QAAkD,EAClD,GAAY;IAEZ,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC;QACtC,MAAM;QACN,QAAQ;QACR,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;QACzB,YAAY,EAAE,KAAK;KACpB,CAAC,CAAC;IACH,MAAM,gBAAgB,GAAG,MAAM,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC9D,OAAO,gBAAgB,CAAC,aAAa,CAAC;AACxC,CAAC","debugId":"9dfba929-1fc6-569e-8311-91fc06f420bc"}
1
+ {"version":3,"file":"runtime.js","sources":["sdk/runtime.ts"],"sourceRoot":"/","sourcesContent":["import {\n activateExtensions,\n loadExtensions,\n type ExtensionRegistrationRegistry,\n} from \"../core/extensions/index.js\";\nimport type { GlobalOptions } from \"../core/shared/command-types.js\";\nimport { resolveItemTypeRegistry } from \"../core/item/type-registry.js\";\nimport { resolveRuntimeStatusRegistry } from \"../core/schema/runtime-schema.js\";\nimport { readSettings } from \"../core/store/settings.js\";\nimport {\n runContracts,\n type ContractsCommandOptions,\n type ContractsResult,\n} from \"../cli/commands/contracts.js\";\n\nexport {\n getActiveExtensionRegistrations,\n runActiveOnReadHooks,\n runActiveOnWriteHooks,\n} from \"../core/extensions/index.js\";\nexport { pathExists, readFileIfExists, removeFileIfExists, writeFileAtomic } from \"../core/fs/fs-utils.js\";\nexport { appendHistoryEntry, createHistoryEntry } from \"../core/history/history.js\";\nexport { generateItemId, normalizeItemId, normalizeRawItemId } from \"../core/item/id.js\";\nexport { readBooleanOption, readCsvListOption, readStringOption } from \"./package-runtime-options.js\";\nexport {\n commitImportedItem,\n emptyImportedDocument,\n ensureTrackerInitialized,\n selectImportAuthor,\n toEstimatedMinutesValue,\n toImportPriority,\n toImportStatus,\n toImportTags,\n toNonEmptyImportString,\n type CommitImportedItemParams,\n type CommitImportedItemResult,\n} from \"./package-import-adapters.js\";\nexport {\n canonicalDocument,\n normalizeFrontMatter,\n serializeItemDocument,\n splitFrontMatter,\n} from \"../core/item/item-format.js\";\nexport { parseTags } from \"../core/item/parse.js\";\nexport { normalizeStatusInput } from \"../core/item/status.js\";\nexport { resolveItemTypeRegistry } from \"../core/item/type-registry.js\";\nexport { acquireLock } from \"../core/lock/lock.js\";\nexport { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry } from \"../core/schema/runtime-schema.js\";\nexport { EXIT_CODE } from \"../core/shared/constants.js\";\nexport { PmCliError } from \"../core/shared/errors.js\";\nexport { isTimestampLiteral, nowIso } from \"../core/shared/time.js\";\nexport { listAllFrontMatter, locateItem, readLocatedItem } from \"../core/store/item-store.js\";\nexport { getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot } from \"../core/store/paths.js\";\nexport { readSettings } from \"../core/store/settings.js\";\nexport {\n renderCalendarMarkdown,\n renderCalendarToon,\n resolveCalendarOutputFormat,\n runCalendar,\n type CalendarOptions,\n type CalendarResult,\n} from \"../cli/commands/calendar.js\";\nexport {\n renderGuideMarkdown,\n resolveGuideOutputFormat,\n runGuide,\n type GuideDepth,\n type GuideOptions,\n type GuideOutputFormat,\n type GuideResult,\n} from \"../cli/commands/guide.js\";\nexport { runCompletion, type CompletionResult, type CompletionShell } from \"../cli/commands/completion.js\";\nexport {\n runCommentsAudit,\n type CommentsAuditEntry,\n type CommentsAuditHistoryRow,\n type CommentsAuditOptions,\n type CommentsAuditResult,\n type CommentsAuditSummary,\n type CommentsAuditTypeSummary,\n} from \"../cli/commands/comments-audit.js\";\nexport {\n runDedupeAudit,\n type DedupeAuditCandidate,\n type DedupeAuditCluster,\n type DedupeAuditOptions,\n type DedupeAuditResult,\n} from \"../cli/commands/dedupe-audit.js\";\nexport { runNormalize, type NormalizeCommandOptions, type NormalizeResult } from \"../cli/commands/normalize.js\";\nexport { runReindex, type ReindexOptions, type ReindexResult } from \"../cli/commands/reindex.js\";\nexport { runSearch, type SearchOptions, type SearchResult } from \"../cli/commands/search.js\";\nexport {\n loadCreateTemplateOptions,\n runTemplatesList,\n runTemplatesSave,\n runTemplatesShow,\n type CreateTemplateOptions,\n type TemplatesListResult,\n type TemplatesSaveResult,\n type TemplatesShowResult,\n} from \"../cli/commands/templates.js\";\nexport {\n runTestRunsList,\n runTestRunsLogs,\n runTestRunsResume,\n runTestRunsStatus,\n runTestRunsStop,\n type TestRunsListCommandOptions,\n type TestRunsLogsCommandOptions,\n type TestRunsResumeCommandOptions,\n type TestRunsStopCommandOptions,\n} from \"../cli/commands/test-runs.js\";\nexport {\n CONFIDENCE_TEXT_VALUES,\n DEPENDENCY_KIND_VALUES,\n BUILTIN_ITEM_TYPE_VALUES,\n ISSUE_SEVERITY_VALUES,\n ITEM_TYPE_VALUES,\n RISK_VALUES,\n STATUS_VALUES,\n} from \"../types/index.js\";\nexport type { GlobalOptions } from \"../core/shared/command-types.js\";\nexport type {\n Dependency,\n ItemDocument,\n ItemMetadata,\n ItemStatus,\n ItemType,\n LinkedDoc,\n LinkedFile,\n LinkedTest,\n LogNote,\n PmSettings,\n} from \"../types/index.js\";\n\nexport interface GetContractsOptions extends ContractsCommandOptions {\n pmRoot?: string;\n cwd?: string;\n noExtensions?: boolean;\n quiet?: boolean;\n profile?: boolean;\n}\n\nexport interface WorkspaceContractsOptions {\n extensionRegistrations?: ExtensionRegistrationRegistry | null;\n noExtensions?: boolean;\n cwd?: string;\n}\n\nexport interface WorkspaceContracts {\n types: string[];\n statuses: string[];\n openStatus: string;\n closeStatus: string;\n canceledStatus: string;\n}\n\nexport async function getWorkspaceContracts(\n pmRoot: string,\n options: WorkspaceContractsOptions = {},\n): Promise<WorkspaceContracts> {\n const settings = await readSettings(pmRoot);\n const extensionRegistrations =\n options.extensionRegistrations ??\n (options.noExtensions === true ? null : await loadWorkspaceExtensionRegistrations(pmRoot, settings, options.cwd));\n const typeRegistry = resolveItemTypeRegistry(settings, extensionRegistrations);\n const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);\n\n return {\n types: [...typeRegistry.types],\n statuses: statusRegistry.definitions.map((definition) => definition.id),\n openStatus: statusRegistry.open_status,\n closeStatus: statusRegistry.close_status,\n canceledStatus: statusRegistry.canceled_status,\n };\n}\n\nexport async function getContracts(\n pmRootOrOptions?: string | GetContractsOptions,\n options: GetContractsOptions = {},\n): Promise<ContractsResult> {\n const resolvedOptions =\n typeof pmRootOrOptions === \"string\"\n ? { ...options, pmRoot: pmRootOrOptions }\n : (pmRootOrOptions ?? options);\n const global: GlobalOptions = {\n json: true,\n quiet: resolvedOptions.quiet ?? true,\n noExtensions: resolvedOptions.noExtensions ?? false,\n noPager: true,\n profile: resolvedOptions.profile ?? false,\n path: resolvedOptions.pmRoot,\n };\n\n return runContracts(resolvedOptions, global);\n}\n\nasync function loadWorkspaceExtensionRegistrations(\n pmRoot: string,\n settings: Awaited<ReturnType<typeof readSettings>>,\n cwd?: string,\n): Promise<ExtensionRegistrationRegistry | null> {\n const loadResult = await loadExtensions({\n pmRoot,\n settings,\n cwd: cwd ?? process.cwd(),\n noExtensions: false,\n });\n const activationResult = await activateExtensions(loadResult);\n return activationResult.registrations;\n}\n\nexport type { ContractsCommandOptions, ContractsResult };\n"],"names":[],"mappings":"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","debugId":"a8653cb8-6b5a-5e26-bf29-f20efd02a25b"}
@@ -48,6 +48,13 @@ Priority accepts either numeric `0..4` or named aliases `critical`, `high`, `med
48
48
 
49
49
  Repeated singular/plural list flags accumulate, so `--tag a --tag b` is equivalent to `--tags a,b` (same for `--status` and `--fields` on read commands). You no longer have to pre-join values into one comma list.
50
50
 
51
+ `--tags` REPLACES the whole tag list. To edit tags without restating the full set, prefer `--add-tags <value>` (adds without replacing) and `--remove-tags <value>` (prunes) on `create`/`update`/`update-many` (both repeatable; CSV or JSON-array). `--remove-tags` is `update`/`update-many` only. Also note `--expected`/`--actual` are short aliases for `--expected-result`/`--actual-result` on these commands, matching `pm close`.
52
+
53
+ ```bash
54
+ pm update <item-id> --add-tags urgent,backend # keep existing tags, add two
55
+ pm update <item-id> --remove-tags stale # drop one, keep the rest
56
+ ```
57
+
51
58
  Create hierarchy from broad to narrow: `Epic` -> `Feature` -> `Task` or `Issue`. Use `--parent <id>` for child items.
52
59
 
53
60
  3. **Claim**
package/docs/COMMANDS.md CHANGED
@@ -129,6 +129,17 @@ pm create \
129
129
 
130
130
  Repeated singular/plural list flags now accumulate, so `--tag a --tag b` is equivalent to `--tags a,b` (the same holds for `--status` and `--fields` on read commands). Earlier versions silently kept only the last value.
131
131
 
132
+ `--tags` REPLACES the whole tag list. To edit tags without restating the full set, use the additive/subtractive flags on `create`/`update`/`update-many`:
133
+
134
+ - `--add-tags <value>` adds tags to the existing list without replacing it (repeatable; CSV or JSON-array values accepted).
135
+ - `--remove-tags <value>` prunes the given tags from the existing list (repeatable; CSV or JSON-array). Available on `update`/`update-many` only — `create` has no prior tags to remove.
136
+
137
+ ```bash
138
+ pm update pm-abc1 --add-tags urgent,backend # keeps existing tags, adds two
139
+ pm update pm-abc1 --remove-tags stale # drops "stale", keeps the rest
140
+ pm create "New backend task" --add-tags backend,p1
141
+ ```
142
+
132
143
  Update existing work:
133
144
 
134
145
  ```bash
@@ -138,6 +149,12 @@ pm update <id> --parent <parent-id>
138
149
  pm append <id> --body "Detailed implementation notes."
139
150
  ```
140
151
 
152
+ `--expected` and `--actual` are short aliases for `--expected-result` and `--actual-result` on `create`/`update`/`update-many`, matching the aliases `pm close` already accepts:
153
+
154
+ ```bash
155
+ pm update <id> --expected "Retry succeeds after backoff" --actual "Retry threw on first attempt"
156
+ ```
157
+
141
158
  Mutation commands (`create`/`update`/`close`/`append`/...) echo a `changed_fields` array. In high-volume agent loops that array is mostly redundant with the item echo above it, so pass the global `--no-changed-fields` flag to replace it with a compact `changed_field_count`:
142
159
 
143
160
  ```bash
@@ -142,6 +142,61 @@ pm reindex --mode hybrid --progress
142
142
  pm health --check-only
143
143
  ```
144
144
 
145
+ ### Custom search providers
146
+
147
+ pm supports any OpenAI-compatible API or Ollama-style provider via configuration. No code changes needed. Each leaf below can be set with `pm config <scope> set <key> <value>` (the corresponding `settings.json` dotted path is shown in parentheses).
148
+
149
+ **Ollama** (local, default for offline embedding):
150
+
151
+ ```bash
152
+ pm config project set ollama_base_url http://localhost:11434
153
+ pm config project set ollama_model nomic-embed-text
154
+ pm config project set search_provider ollama
155
+ ```
156
+
157
+ **OpenAI**:
158
+
159
+ ```bash
160
+ pm config project set openai_base_url https://api.openai.com/v1
161
+ pm config project set openai_api_key '<OPENAI_API_KEY>'
162
+ pm config project set openai_model text-embedding-3-small
163
+ pm config project set search_provider openai
164
+ ```
165
+
166
+ The base URL defaults to empty, so it must be set explicitly even for the canonical OpenAI endpoint.
167
+
168
+ **LM Studio (OpenAI-compatible)** — point pm at LM Studio's local OpenAI-compatible endpoint:
169
+
170
+ ```bash
171
+ pm config project set openai_base_url http://localhost:1234/v1
172
+ pm config project set openai_model nomic-embed-text-v1.5
173
+ pm config project set search_provider openai
174
+ ```
175
+
176
+ Set `openai_api_key` to any non-empty value if LM Studio is configured to require one.
177
+
178
+ **vLLM (OpenAI-compatible)** — point pm at a vLLM server serving an embedding model:
179
+
180
+ ```bash
181
+ pm config project set openai_base_url http://localhost:8000/v1
182
+ pm config project set openai_model BAAI/bge-large-en-v1.5
183
+ pm config project set search_provider openai
184
+ ```
185
+
186
+ **Vector store** — choose where vector embeddings live. LanceDB is file-backed and zero-setup; Qdrant runs as a service:
187
+
188
+ ```bash
189
+ pm config project set vector_store_adapter lancedb
190
+ pm config project set lancedb_path .agents/pm/search/lancedb
191
+
192
+ # or, with Qdrant:
193
+ pm config project set vector_store_adapter qdrant
194
+ pm config project set qdrant_url http://localhost:6333
195
+ pm config project set qdrant_api_key '<QDRANT_API_KEY>' # omit on unauthenticated dev servers
196
+ ```
197
+
198
+ After changing any of these, run `pm reindex --mode hybrid` so the vector index reflects the new provider/store. `pm search ... --mode semantic|hybrid` emits a `vector_index_stale` warning when items have been modified since the last reindex.
199
+
145
200
  ## Custom Item Types
146
201
 
147
202
  Custom item types can be defined in settings and by extensions. Runtime type resolution affects create/update validation, list/search/calendar filters, completions, and storage folders.
@@ -93,10 +93,13 @@ pm search "restore lock retry" --limit 10
93
93
  pm list-open --limit 20
94
94
  pm claim <item-id>
95
95
  pm update <item-id> --status in_progress --message "Start implementation"
96
+ pm update <item-id> --add-tags urgent,backend
96
97
  ```
97
98
 
98
99
  Do not create a duplicate item until `context`, `search`, and list commands show no relevant active item.
99
100
 
101
+ `--tags` replaces the whole tag list; use `--add-tags <value>` to add tags without replacing them and `--remove-tags <value>` to prune them (both on `update`/`update-many`; `create` supports `--add-tags`). On `create`/`update`/`update-many`, `--expected`/`--actual` are short aliases for `--expected-result`/`--actual-result`.
102
+
100
103
  ## Link Work Artifacts
101
104
 
102
105
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-cli",
3
- "version": "2026.5.28",
3
+ "version": "2026.5.29",
4
4
  "description": "Git-native project management CLI for humans and agents.",
5
5
  "type": "module",
6
6
  "author": "unbrained",
@@ -29,6 +29,7 @@ async function loadCalendarCoreModule() {
29
29
  if (
30
30
  typeof loaded.runCalendar === "function" &&
31
31
  typeof loaded.renderCalendarMarkdown === "function" &&
32
+ typeof loaded.renderCalendarToon === "function" &&
32
33
  typeof loaded.resolveCalendarOutputFormat === "function"
33
34
  ) {
34
35
  return loaded;
@@ -111,5 +112,9 @@ export function renderCalendarPackageOutput(context) {
111
112
  if (outputFormat === "json" || readPayloadFormat(context.payload) === "json") {
112
113
  return `${JSON.stringify(result, null, 2)}\n`;
113
114
  }
115
+ if (outputFormat === "toon") {
116
+ const rendered = calendarCore.renderCalendarToon(result);
117
+ return rendered.endsWith("\n") ? rendered : `${rendered}\n`;
118
+ }
114
119
  return null;
115
120
  }
@@ -8,6 +8,7 @@ const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
8
8
  interface CalendarCoreModule {
9
9
  runCalendar: (options: CalendarOptions, global: GlobalOptions) => Promise<CalendarResult>;
10
10
  renderCalendarMarkdown: (result: CalendarResult) => string;
11
+ renderCalendarToon: (result: CalendarResult) => string;
11
12
  resolveCalendarOutputFormat: (options: CalendarOptions, global: GlobalOptions) => "markdown" | "toon" | "json";
12
13
  }
13
14
 
@@ -38,6 +39,7 @@ async function loadCalendarCoreModule(): Promise<CalendarCoreModule> {
38
39
  if (
39
40
  typeof loaded.runCalendar === "function" &&
40
41
  typeof loaded.renderCalendarMarkdown === "function" &&
42
+ typeof loaded.renderCalendarToon === "function" &&
41
43
  typeof loaded.resolveCalendarOutputFormat === "function"
42
44
  ) {
43
45
  return loaded as CalendarCoreModule;
@@ -120,5 +122,9 @@ export function renderCalendarPackageOutput(context: ServiceOverrideContext): st
120
122
  if (outputFormat === "json" || readPayloadFormat(context.payload) === "json") {
121
123
  return `${JSON.stringify(result, null, 2)}\n`;
122
124
  }
125
+ if (outputFormat === "toon") {
126
+ const rendered = calendarCore.renderCalendarToon(result);
127
+ return rendered.endsWith("\n") ? rendered : `${rendered}\n`;
128
+ }
123
129
  return null;
124
130
  }