@unbrained/pm-cli 2026.5.18 → 2026.5.27

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 (369) hide show
  1. package/CHANGELOG.md +953 -472
  2. package/README.md +4 -11
  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 +147 -10
  7. package/dist/cli/commander-usage.js.map +1 -1
  8. package/dist/cli/commands/annotation-command.d.ts +49 -0
  9. package/dist/cli/commands/annotation-command.js +135 -0
  10. package/dist/cli/commands/annotation-command.js.map +1 -0
  11. package/dist/cli/commands/append.js +5 -8
  12. package/dist/cli/commands/append.js.map +1 -1
  13. package/dist/cli/commands/calendar.js +3 -6
  14. package/dist/cli/commands/calendar.js.map +1 -1
  15. package/dist/cli/commands/claim.js +15 -24
  16. package/dist/cli/commands/claim.js.map +1 -1
  17. package/dist/cli/commands/close.js +63 -10
  18. package/dist/cli/commands/close.js.map +1 -1
  19. package/dist/cli/commands/comments.d.ts +5 -0
  20. package/dist/cli/commands/comments.js +27 -117
  21. package/dist/cli/commands/comments.js.map +1 -1
  22. package/dist/cli/commands/completion.d.ts +2 -2
  23. package/dist/cli/commands/completion.js +203 -63
  24. package/dist/cli/commands/completion.js.map +1 -1
  25. package/dist/cli/commands/config.d.ts +1 -1
  26. package/dist/cli/commands/config.js +82 -4
  27. package/dist/cli/commands/config.js.map +1 -1
  28. package/dist/cli/commands/context.js +4 -10
  29. package/dist/cli/commands/context.js.map +1 -1
  30. package/dist/cli/commands/contracts.js +168 -36
  31. package/dist/cli/commands/contracts.js.map +1 -1
  32. package/dist/cli/commands/create.js +53 -313
  33. package/dist/cli/commands/create.js.map +1 -1
  34. package/dist/cli/commands/dedupe-audit.js +7 -4
  35. package/dist/cli/commands/dedupe-audit.js.map +1 -1
  36. package/dist/cli/commands/delete.d.ts +3 -0
  37. package/dist/cli/commands/delete.js +11 -9
  38. package/dist/cli/commands/delete.js.map +1 -1
  39. package/dist/cli/commands/docs.d.ts +2 -12
  40. package/dist/cli/commands/docs.js +8 -316
  41. package/dist/cli/commands/docs.js.map +1 -1
  42. package/dist/cli/commands/event-validation-messages.d.ts +3 -0
  43. package/dist/cli/commands/event-validation-messages.js +44 -0
  44. package/dist/cli/commands/event-validation-messages.js.map +1 -0
  45. package/dist/cli/commands/extension/bundled-catalog.d.ts +14 -0
  46. package/dist/cli/commands/extension/bundled-catalog.js +268 -0
  47. package/dist/cli/commands/extension/bundled-catalog.js.map +1 -0
  48. package/dist/cli/commands/extension/doctor.d.ts +31 -0
  49. package/dist/cli/commands/extension/doctor.js +345 -0
  50. package/dist/cli/commands/extension/doctor.js.map +1 -0
  51. package/dist/cli/commands/extension/install-sources.d.ts +37 -0
  52. package/dist/cli/commands/extension/install-sources.js +384 -0
  53. package/dist/cli/commands/extension/install-sources.js.map +1 -0
  54. package/dist/cli/commands/extension/managed-state.d.ts +48 -0
  55. package/dist/cli/commands/extension/managed-state.js +172 -0
  56. package/dist/cli/commands/extension/managed-state.js.map +1 -0
  57. package/dist/cli/commands/extension/scaffold.d.ts +14 -0
  58. package/dist/cli/commands/extension/scaffold.js +169 -0
  59. package/dist/cli/commands/extension/scaffold.js.map +1 -0
  60. package/dist/cli/commands/extension/shared.d.ts +14 -0
  61. package/dist/cli/commands/extension/shared.js +106 -0
  62. package/dist/cli/commands/extension/shared.js.map +1 -0
  63. package/dist/cli/commands/extension.d.ts +37 -68
  64. package/dist/cli/commands/extension.js +157 -1319
  65. package/dist/cli/commands/extension.js.map +1 -1
  66. package/dist/cli/commands/files.d.ts +1 -12
  67. package/dist/cli/commands/files.js +14 -318
  68. package/dist/cli/commands/files.js.map +1 -1
  69. package/dist/cli/commands/gc.js +17 -4
  70. package/dist/cli/commands/gc.js.map +1 -1
  71. package/dist/cli/commands/get.d.ts +3 -2
  72. package/dist/cli/commands/get.js +52 -9
  73. package/dist/cli/commands/get.js.map +1 -1
  74. package/dist/cli/commands/health.d.ts +10 -0
  75. package/dist/cli/commands/health.js +269 -76
  76. package/dist/cli/commands/health.js.map +1 -1
  77. package/dist/cli/commands/history-redact.d.ts +8 -0
  78. package/dist/cli/commands/history-redact.js +35 -113
  79. package/dist/cli/commands/history-redact.js.map +1 -1
  80. package/dist/cli/commands/history-repair.d.ts +33 -0
  81. package/dist/cli/commands/history-repair.js +172 -0
  82. package/dist/cli/commands/history-repair.js.map +1 -0
  83. package/dist/cli/commands/history.d.ts +4 -4
  84. package/dist/cli/commands/history.js +10 -88
  85. package/dist/cli/commands/history.js.map +1 -1
  86. package/dist/cli/commands/index.d.ts +3 -1
  87. package/dist/cli/commands/index.js +5 -3
  88. package/dist/cli/commands/index.js.map +1 -1
  89. package/dist/cli/commands/init.d.ts +28 -0
  90. package/dist/cli/commands/init.js +23 -2
  91. package/dist/cli/commands/init.js.map +1 -1
  92. package/dist/cli/commands/learnings.js +20 -119
  93. package/dist/cli/commands/learnings.js.map +1 -1
  94. package/dist/cli/commands/legacy-none-tokens.d.ts +3 -0
  95. package/dist/cli/commands/legacy-none-tokens.js +39 -0
  96. package/dist/cli/commands/legacy-none-tokens.js.map +1 -0
  97. package/dist/cli/commands/linked-artifacts.d.ts +96 -0
  98. package/dist/cli/commands/linked-artifacts.js +335 -0
  99. package/dist/cli/commands/linked-artifacts.js.map +1 -0
  100. package/dist/cli/commands/linked-test-entry.d.ts +3 -0
  101. package/dist/cli/commands/linked-test-entry.js +62 -0
  102. package/dist/cli/commands/linked-test-entry.js.map +1 -0
  103. package/dist/cli/commands/linked-test-parsers.d.ts +28 -0
  104. package/dist/cli/commands/linked-test-parsers.js +192 -0
  105. package/dist/cli/commands/linked-test-parsers.js.map +1 -0
  106. package/dist/cli/commands/list.js +49 -24
  107. package/dist/cli/commands/list.js.map +1 -1
  108. package/dist/cli/commands/normalize.js +4 -3
  109. package/dist/cli/commands/normalize.js.map +1 -1
  110. package/dist/cli/commands/notes.js +20 -119
  111. package/dist/cli/commands/notes.js.map +1 -1
  112. package/dist/cli/commands/plan.d.ts +3 -0
  113. package/dist/cli/commands/plan.js +184 -22
  114. package/dist/cli/commands/plan.js.map +1 -1
  115. package/dist/cli/commands/recurrence-parsers.d.ts +26 -0
  116. package/dist/cli/commands/recurrence-parsers.js +98 -0
  117. package/dist/cli/commands/recurrence-parsers.js.map +1 -0
  118. package/dist/cli/commands/restore.js +24 -56
  119. package/dist/cli/commands/restore.js.map +1 -1
  120. package/dist/cli/commands/schema.d.ts +31 -0
  121. package/dist/cli/commands/schema.js +98 -0
  122. package/dist/cli/commands/schema.js.map +1 -0
  123. package/dist/cli/commands/search.js +154 -42
  124. package/dist/cli/commands/search.js.map +1 -1
  125. package/dist/cli/commands/templates.d.ts +4 -0
  126. package/dist/cli/commands/templates.js +89 -17
  127. package/dist/cli/commands/templates.js.map +1 -1
  128. package/dist/cli/commands/test/linked-command-detection.d.ts +37 -0
  129. package/dist/cli/commands/test/linked-command-detection.js +200 -0
  130. package/dist/cli/commands/test/linked-command-detection.js.map +1 -0
  131. package/dist/cli/commands/test-all.js +4 -8
  132. package/dist/cli/commands/test-all.js.map +1 -1
  133. package/dist/cli/commands/test.d.ts +2 -2
  134. package/dist/cli/commands/test.js +12 -357
  135. package/dist/cli/commands/test.js.map +1 -1
  136. package/dist/cli/commands/update-many.js +6 -9
  137. package/dist/cli/commands/update-many.js.map +1 -1
  138. package/dist/cli/commands/update.js +167 -401
  139. package/dist/cli/commands/update.js.map +1 -1
  140. package/dist/cli/commands/validate.d.ts +3 -1
  141. package/dist/cli/commands/validate.js +23 -71
  142. package/dist/cli/commands/validate.js.map +1 -1
  143. package/dist/cli/error-guidance.d.ts +1 -0
  144. package/dist/cli/error-guidance.js +100 -6
  145. package/dist/cli/error-guidance.js.map +1 -1
  146. package/dist/cli/extension-command-help.d.ts +0 -1
  147. package/dist/cli/extension-command-help.js +2 -13
  148. package/dist/cli/extension-command-help.js.map +1 -1
  149. package/dist/cli/extension-command-options.d.ts +1 -0
  150. package/dist/cli/extension-command-options.js +106 -7
  151. package/dist/cli/extension-command-options.js.map +1 -1
  152. package/dist/cli/help-content.d.ts +0 -1
  153. package/dist/cli/help-content.js +13 -9
  154. package/dist/cli/help-content.js.map +1 -1
  155. package/dist/cli/help-json-payload.d.ts +1 -0
  156. package/dist/cli/help-json-payload.js +33 -3
  157. package/dist/cli/help-json-payload.js.map +1 -1
  158. package/dist/cli/main.d.ts +11 -0
  159. package/dist/cli/main.js +109 -55
  160. package/dist/cli/main.js.map +1 -1
  161. package/dist/cli/register-list-query.d.ts +5 -2
  162. package/dist/cli/register-list-query.js +254 -192
  163. package/dist/cli/register-list-query.js.map +1 -1
  164. package/dist/cli/register-mutation.d.ts +1 -1
  165. package/dist/cli/register-mutation.js +247 -64
  166. package/dist/cli/register-mutation.js.map +1 -1
  167. package/dist/cli/register-operations.js +17 -12
  168. package/dist/cli/register-operations.js.map +1 -1
  169. package/dist/cli/register-setup.js +33 -16
  170. package/dist/cli/register-setup.js.map +1 -1
  171. package/dist/cli/registration-helpers.d.ts +0 -2
  172. package/dist/cli/registration-helpers.js +14 -40
  173. package/dist/cli/registration-helpers.js.map +1 -1
  174. package/dist/cli.js +25 -4
  175. package/dist/cli.js.map +1 -1
  176. package/dist/core/config/positional-value.d.ts +44 -0
  177. package/dist/core/config/positional-value.js +109 -0
  178. package/dist/core/config/positional-value.js.map +1 -0
  179. package/dist/core/extensions/extension-capability-aliases.d.ts +14 -0
  180. package/dist/core/extensions/extension-capability-aliases.js +159 -0
  181. package/dist/core/extensions/extension-capability-aliases.js.map +1 -0
  182. package/dist/core/extensions/extension-hook-runtime.d.ts +13 -0
  183. package/dist/core/extensions/extension-hook-runtime.js +414 -0
  184. package/dist/core/extensions/extension-hook-runtime.js.map +1 -0
  185. package/dist/core/extensions/extension-policy.d.ts +69 -0
  186. package/dist/core/extensions/extension-policy.js +481 -0
  187. package/dist/core/extensions/extension-policy.js.map +1 -0
  188. package/dist/core/extensions/extension-registries.d.ts +8 -0
  189. package/dist/core/extensions/extension-registries.js +52 -0
  190. package/dist/core/extensions/extension-registries.js.map +1 -0
  191. package/dist/core/extensions/extension-runtime-helpers.d.ts +6 -0
  192. package/dist/core/extensions/extension-runtime-helpers.js +29 -0
  193. package/dist/core/extensions/extension-runtime-helpers.js.map +1 -0
  194. package/dist/core/extensions/extension-types.d.ts +13 -39
  195. package/dist/core/extensions/extension-types.js +34 -2
  196. package/dist/core/extensions/extension-types.js.map +1 -1
  197. package/dist/core/extensions/index.d.ts +7 -1
  198. package/dist/core/extensions/index.js +11 -14
  199. package/dist/core/extensions/index.js.map +1 -1
  200. package/dist/core/extensions/loader.d.ts +4 -22
  201. package/dist/core/extensions/loader.js +23 -1146
  202. package/dist/core/extensions/loader.js.map +1 -1
  203. package/dist/core/fs/path-utils.d.ts +1 -0
  204. package/dist/core/fs/path-utils.js +12 -0
  205. package/dist/core/fs/path-utils.js.map +1 -0
  206. package/dist/core/history/drift-scan.d.ts +22 -0
  207. package/dist/core/history/drift-scan.js +149 -0
  208. package/dist/core/history/drift-scan.js.map +1 -0
  209. package/dist/core/history/history-rewrite.d.ts +43 -0
  210. package/dist/core/history/history-rewrite.js +48 -0
  211. package/dist/core/history/history-rewrite.js.map +1 -0
  212. package/dist/core/history/history.js +5 -4
  213. package/dist/core/history/history.js.map +1 -1
  214. package/dist/core/history/replay.d.ts +82 -0
  215. package/dist/core/history/replay.js +250 -0
  216. package/dist/core/history/replay.js.map +1 -0
  217. package/dist/core/item/item-format.js +11 -8
  218. package/dist/core/item/item-format.js.map +1 -1
  219. package/dist/core/item/item-record.d.ts +19 -0
  220. package/dist/core/item/item-record.js +24 -0
  221. package/dist/core/item/item-record.js.map +1 -0
  222. package/dist/core/item/item-type-definition.d.ts +52 -0
  223. package/dist/core/item/item-type-definition.js +123 -0
  224. package/dist/core/item/item-type-definition.js.map +1 -0
  225. package/dist/core/item/parse.js +3 -2
  226. package/dist/core/item/parse.js.map +1 -1
  227. package/dist/core/item/priority.d.ts +23 -0
  228. package/dist/core/item/priority.js +55 -0
  229. package/dist/core/item/priority.js.map +1 -0
  230. package/dist/core/item/status.d.ts +14 -1
  231. package/dist/core/item/status.js +22 -2
  232. package/dist/core/item/status.js.map +1 -1
  233. package/dist/core/item/toon-decode.d.ts +19 -0
  234. package/dist/core/item/toon-decode.js +69 -0
  235. package/dist/core/item/toon-decode.js.map +1 -0
  236. package/dist/core/item/type-registry.js +13 -84
  237. package/dist/core/item/type-registry.js.map +1 -1
  238. package/dist/core/output/mutation-projection.d.ts +31 -0
  239. package/dist/core/output/mutation-projection.js +103 -0
  240. package/dist/core/output/mutation-projection.js.map +1 -0
  241. package/dist/core/output/output.d.ts +2 -0
  242. package/dist/core/output/output.js +5 -3
  243. package/dist/core/output/output.js.map +1 -1
  244. package/dist/core/packages/manifest.js +3 -9
  245. package/dist/core/packages/manifest.js.map +1 -1
  246. package/dist/core/schema/item-types-file.d.ts +85 -0
  247. package/dist/core/schema/item-types-file.js +243 -0
  248. package/dist/core/schema/item-types-file.js.map +1 -0
  249. package/dist/core/schema/runtime-schema.d.ts +2 -1
  250. package/dist/core/schema/runtime-schema.js +17 -45
  251. package/dist/core/schema/runtime-schema.js.map +1 -1
  252. package/dist/core/search/semantic-defaults.js +3 -3
  253. package/dist/core/search/semantic-defaults.js.map +1 -1
  254. package/dist/core/search/vector-stores.js +46 -9
  255. package/dist/core/search/vector-stores.js.map +1 -1
  256. package/dist/core/sentry/helpers.d.ts +1 -1
  257. package/dist/core/sentry/helpers.js +20 -3
  258. package/dist/core/sentry/helpers.js.map +1 -1
  259. package/dist/core/shared/author.d.ts +1 -0
  260. package/dist/core/shared/author.js +9 -0
  261. package/dist/core/shared/author.js.map +1 -0
  262. package/dist/core/shared/command-types.d.ts +1 -0
  263. package/dist/core/shared/command-types.js +2 -2
  264. package/dist/core/shared/command-types.js.map +1 -1
  265. package/dist/core/shared/constants.d.ts +10 -1
  266. package/dist/core/shared/constants.js +56 -58
  267. package/dist/core/shared/constants.js.map +1 -1
  268. package/dist/core/shared/lazy-module.d.ts +1 -0
  269. package/dist/core/shared/lazy-module.js +11 -0
  270. package/dist/core/shared/lazy-module.js.map +1 -0
  271. package/dist/core/shared/option-alias-visibility.d.ts +44 -0
  272. package/dist/core/shared/option-alias-visibility.js +76 -0
  273. package/dist/core/shared/option-alias-visibility.js.map +1 -0
  274. package/dist/core/shared/primitives.d.ts +23 -0
  275. package/dist/core/shared/primitives.js +39 -2
  276. package/dist/core/shared/primitives.js.map +1 -1
  277. package/dist/core/shared/text-normalization.d.ts +0 -1
  278. package/dist/core/shared/text-normalization.js +2 -5
  279. package/dist/core/shared/text-normalization.js.map +1 -1
  280. package/dist/core/store/front-matter-cache.d.ts +16 -2
  281. package/dist/core/store/front-matter-cache.js +99 -33
  282. package/dist/core/store/front-matter-cache.js.map +1 -1
  283. package/dist/core/store/item-store.d.ts +2 -0
  284. package/dist/core/store/item-store.js +76 -110
  285. package/dist/core/store/item-store.js.map +1 -1
  286. package/dist/core/store/settings-validator.d.ts +106 -0
  287. package/dist/core/store/settings-validator.js +279 -0
  288. package/dist/core/store/settings-validator.js.map +1 -0
  289. package/dist/core/store/settings.js +6 -343
  290. package/dist/core/store/settings.js.map +1 -1
  291. package/dist/core/telemetry/runtime.js +5 -3
  292. package/dist/core/telemetry/runtime.js.map +1 -1
  293. package/dist/mcp/server.js +138 -39
  294. package/dist/mcp/server.js.map +1 -1
  295. package/dist/sdk/cli-contracts/enum-contracts.d.ts +20 -0
  296. package/dist/sdk/cli-contracts/enum-contracts.js +156 -0
  297. package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -0
  298. package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +14 -0
  299. package/dist/sdk/cli-contracts/tool-option-contracts.js +243 -0
  300. package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -0
  301. package/dist/sdk/cli-contracts/tool-parameter-tables.d.ts +11 -0
  302. package/dist/sdk/cli-contracts/tool-parameter-tables.js +901 -0
  303. package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -0
  304. package/dist/sdk/cli-contracts.d.ts +18 -33
  305. package/dist/sdk/cli-contracts.js +96 -1238
  306. package/dist/sdk/cli-contracts.js.map +1 -1
  307. package/dist/sdk/package-import-adapters.d.ts +74 -0
  308. package/dist/sdk/package-import-adapters.js +186 -0
  309. package/dist/sdk/package-import-adapters.js.map +1 -0
  310. package/dist/sdk/package-runtime-options.d.ts +26 -0
  311. package/dist/sdk/package-runtime-options.js +71 -0
  312. package/dist/sdk/package-runtime-options.js.map +1 -0
  313. package/dist/sdk/runtime.d.ts +27 -1
  314. package/dist/sdk/runtime.js +48 -3
  315. package/dist/sdk/runtime.js.map +1 -1
  316. package/dist/types.d.ts +6 -0
  317. package/dist/types.js +10 -2
  318. package/dist/types.js.map +1 -1
  319. package/docs/AGENT_GUIDE.md +13 -11
  320. package/docs/ARCHITECTURE.md +1 -1
  321. package/docs/CLAUDE_CODE_PLUGIN.md +5 -28
  322. package/docs/CODEX_PLUGIN.md +5 -5
  323. package/docs/COMMANDS.md +58 -9
  324. package/docs/CONFIGURATION.md +16 -1
  325. package/docs/EXTENSIONS.md +4 -63
  326. package/docs/RELEASING.md +12 -8
  327. package/docs/SDK.md +11 -2
  328. package/marketplace.json +7 -3
  329. package/package.json +18 -14
  330. package/packages/pm-beads/extensions/beads/index.js +2 -49
  331. package/packages/pm-beads/extensions/beads/index.ts +2 -54
  332. package/packages/pm-beads/extensions/beads/runtime-loader.js +86 -0
  333. package/packages/pm-beads/extensions/beads/runtime-loader.ts +88 -0
  334. package/packages/pm-beads/extensions/beads/runtime.js +26 -115
  335. package/packages/pm-beads/extensions/beads/runtime.ts +33 -132
  336. package/packages/pm-calendar/README.md +3 -1
  337. package/packages/pm-calendar/extensions/calendar/index.js +66 -2
  338. package/packages/pm-calendar/extensions/calendar/index.ts +71 -2
  339. package/packages/pm-calendar/extensions/calendar/runtime.js +1 -0
  340. package/packages/pm-calendar/extensions/calendar/runtime.ts +1 -0
  341. package/packages/pm-governance-audit/extensions/governance-audit/runtime.js +14 -41
  342. package/packages/pm-governance-audit/extensions/governance-audit/runtime.ts +25 -41
  343. package/packages/pm-guide-shell/extensions/guide-shell/runtime.js +10 -50
  344. package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +17 -50
  345. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.js +8 -40
  346. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.ts +10 -40
  347. package/packages/pm-search-advanced/README.md +8 -0
  348. package/packages/pm-search-advanced/extensions/search-advanced/index.js +75 -1
  349. package/packages/pm-search-advanced/extensions/search-advanced/index.ts +74 -0
  350. package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +58 -33
  351. package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +60 -33
  352. package/packages/pm-templates/extensions/templates/runtime.js +11 -202
  353. package/packages/pm-templates/extensions/templates/runtime.ts +38 -230
  354. package/packages/pm-todos/extensions/todos/index.js +3 -50
  355. package/packages/pm-todos/extensions/todos/index.ts +3 -55
  356. package/packages/pm-todos/extensions/todos/runtime-loader.js +86 -0
  357. package/packages/pm-todos/extensions/todos/runtime-loader.ts +88 -0
  358. package/packages/pm-todos/extensions/todos/runtime.js +24 -117
  359. package/packages/pm-todos/extensions/todos/runtime.ts +32 -129
  360. package/plugins/pm-claude/README.md +2 -2
  361. package/plugins/pm-claude/commands/pm-planner.md +1 -15
  362. package/plugins/pm-claude/scripts/pm-mcp-server.mjs +5 -2
  363. package/plugins/pm-claude/skills/pm-planner/SKILL.md +3 -21
  364. package/plugins/pm-codex/scripts/pm-mcp-server.mjs +15 -6
  365. package/plugins/pm-codex/skills/pm-native/SKILL.md +1 -13
  366. package/PRD.md +0 -1734
  367. package/dist/core/output/command-aware.d.ts +0 -1
  368. package/dist/core/output/command-aware.js +0 -397
  369. package/dist/core/output/command-aware.js.map +0 -1
@@ -8,6 +8,8 @@ const {
8
8
  PmCliError,
9
9
  runSearch,
10
10
  runReindex,
11
+ readStringOption,
12
+ readBooleanOption,
11
13
  } = sdk;
12
14
 
13
15
  async function loadSearchSdkModule() {
@@ -24,6 +26,8 @@ async function loadSearchSdkModule() {
24
26
  typeof loaded.runSearch === "function" &&
25
27
  typeof loaded.runReindex === "function" &&
26
28
  typeof loaded.PmCliError === "function" &&
29
+ typeof loaded.readStringOption === "function" &&
30
+ typeof loaded.readBooleanOption === "function" &&
27
31
  typeof loaded.EXIT_CODE === "object" &&
28
32
  loaded.EXIT_CODE !== null
29
33
  ) {
@@ -37,58 +41,79 @@ async function loadSearchSdkModule() {
37
41
  );
38
42
  }
39
43
 
40
- function readStringOption(options, key, aliases = []) {
41
- const keys = [key, ...aliases];
42
- for (const candidate of keys) {
43
- const value = options[candidate];
44
- if (typeof value === "string" && value.trim().length > 0) {
45
- return value;
46
- }
47
- }
48
- return undefined;
49
- }
44
+ const SEARCH_VALUE_FLAGS = new Set([
45
+ "--mode",
46
+ "--type",
47
+ "--tag",
48
+ "--priority",
49
+ "--deadline-before",
50
+ "--deadline_before",
51
+ "--deadline-after",
52
+ "--deadline_after",
53
+ "--limit",
54
+ "--fields",
55
+ ]);
50
56
 
51
- function readBooleanOption(options, key, aliases = []) {
52
- const keys = [key, ...aliases];
53
- for (const candidate of keys) {
54
- const value = options[candidate];
55
- if (value === undefined) {
57
+ const SEARCH_BOOLEAN_FLAGS = new Set([
58
+ "--semantic",
59
+ "--hybrid",
60
+ "--include-linked",
61
+ "--include_linked",
62
+ "--title-exact",
63
+ "--title_exact",
64
+ "--phrase-exact",
65
+ "--phrase_exact",
66
+ "--compact",
67
+ "--full",
68
+ "--json",
69
+ ]);
70
+
71
+ function stripSearchOptionTokens(args) {
72
+ const queryTokens = [];
73
+ for (let index = 0; index < args.length; index += 1) {
74
+ const token = args[index]?.trim() ?? "";
75
+ const equalsIndex = token.indexOf("=");
76
+ const flagName = equalsIndex > 0 ? token.slice(0, equalsIndex) : token;
77
+ if (SEARCH_VALUE_FLAGS.has(flagName)) {
78
+ if (equalsIndex < 0) {
79
+ index += 1;
80
+ }
56
81
  continue;
57
82
  }
58
- if (typeof value === "boolean") {
59
- return value;
83
+ if (SEARCH_BOOLEAN_FLAGS.has(flagName)) {
84
+ continue;
60
85
  }
61
- if (typeof value === "string") {
62
- const normalized = value.trim().toLowerCase();
63
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
64
- return true;
65
- }
66
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
67
- return false;
68
- }
86
+ if (token.length > 0) {
87
+ queryTokens.push(token);
69
88
  }
70
89
  }
71
- return undefined;
90
+ return queryTokens;
72
91
  }
73
92
 
74
93
  function resolveSearchQuery(args) {
75
- const query = args
76
- .map((value) => value.trim())
77
- .filter((value) => value.length > 0)
78
- .join(" ");
94
+ const query = stripSearchOptionTokens(args).join(" ");
79
95
  if (query.length === 0) {
80
96
  throw new PmCliError("Search query must not be empty", EXIT_CODE.USAGE);
81
97
  }
82
98
  return query;
83
99
  }
84
100
 
85
- function normalizeAdvancedSearchOptions(rawOptions) {
101
+ function normalizeAdvancedSearchOptions(rawOptions, args) {
86
102
  const fields = readStringOption(rawOptions, "fields");
87
103
  const compactRequested = readBooleanOption(rawOptions, "compact") === true;
88
104
  const fullRequested = readBooleanOption(rawOptions, "full") === true;
89
105
  const defaultCompact = !compactRequested && !fullRequested && fields === undefined;
106
+ const explicitMode = readStringOption(rawOptions, "mode");
107
+ const argFlags = new Set(args.map((value) => value?.trim() ?? ""));
108
+ const mode =
109
+ explicitMode ??
110
+ (readBooleanOption(rawOptions, "semantic") === true || argFlags.has("--semantic")
111
+ ? "semantic"
112
+ : readBooleanOption(rawOptions, "hybrid") === true || argFlags.has("--hybrid")
113
+ ? "hybrid"
114
+ : "keyword");
90
115
  return {
91
- mode: readStringOption(rawOptions, "mode"),
116
+ mode,
92
117
  includeLinked: readBooleanOption(rawOptions, "includeLinked", ["include_linked"]) === true ? true : undefined,
93
118
  titleExact: readBooleanOption(rawOptions, "titleExact", ["title_exact"]) === true ? true : undefined,
94
119
  phraseExact: readBooleanOption(rawOptions, "phraseExact", ["phrase_exact"]) === true ? true : undefined,
@@ -112,7 +137,7 @@ function normalizeReindexOptions(rawOptions) {
112
137
  }
113
138
 
114
139
  export async function runAdvancedSearchPackage(args, rawOptions, global) {
115
- return runSearch(resolveSearchQuery(args), normalizeAdvancedSearchOptions(rawOptions), global);
140
+ return runSearch(resolveSearchQuery(args), normalizeAdvancedSearchOptions(rawOptions, args), global);
116
141
  }
117
142
 
118
143
  export async function runAdvancedReindexPackage(rawOptions, global) {
@@ -17,6 +17,8 @@ interface SearchRuntimeSdkModule {
17
17
  PmCliError: new (message: string, exitCode?: number) => Error;
18
18
  runSearch: (query: string, options: SearchOptions, global: GlobalOptions) => Promise<SearchResult>;
19
19
  runReindex: (options: ReindexOptions, global: GlobalOptions) => Promise<ReindexResult>;
20
+ readStringOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => string | undefined;
21
+ readBooleanOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => boolean | undefined;
20
22
  }
21
23
 
22
24
  const sdk = await loadSearchSdkModule();
@@ -25,6 +27,8 @@ const {
25
27
  PmCliError,
26
28
  runSearch,
27
29
  runReindex,
30
+ readStringOption,
31
+ readBooleanOption,
28
32
  } = sdk;
29
33
 
30
34
  async function loadSearchSdkModule(): Promise<SearchRuntimeSdkModule> {
@@ -41,6 +45,8 @@ async function loadSearchSdkModule(): Promise<SearchRuntimeSdkModule> {
41
45
  typeof loaded.runSearch === "function" &&
42
46
  typeof loaded.runReindex === "function" &&
43
47
  typeof loaded.PmCliError === "function" &&
48
+ typeof loaded.readStringOption === "function" &&
49
+ typeof loaded.readBooleanOption === "function" &&
44
50
  typeof loaded.EXIT_CODE === "object" &&
45
51
  loaded.EXIT_CODE !== null
46
52
  ) {
@@ -54,58 +60,79 @@ async function loadSearchSdkModule(): Promise<SearchRuntimeSdkModule> {
54
60
  );
55
61
  }
56
62
 
57
- function readStringOption(options: Record<string, unknown>, key: string, aliases: string[] = []): string | undefined {
58
- const keys = [key, ...aliases];
59
- for (const candidate of keys) {
60
- const value = options[candidate];
61
- if (typeof value === "string" && value.trim().length > 0) {
62
- return value;
63
- }
64
- }
65
- return undefined;
66
- }
63
+ const SEARCH_VALUE_FLAGS = new Set([
64
+ "--mode",
65
+ "--type",
66
+ "--tag",
67
+ "--priority",
68
+ "--deadline-before",
69
+ "--deadline_before",
70
+ "--deadline-after",
71
+ "--deadline_after",
72
+ "--limit",
73
+ "--fields",
74
+ ]);
67
75
 
68
- function readBooleanOption(options: Record<string, unknown>, key: string, aliases: string[] = []): boolean | undefined {
69
- const keys = [key, ...aliases];
70
- for (const candidate of keys) {
71
- const value = options[candidate];
72
- if (value === undefined) {
76
+ const SEARCH_BOOLEAN_FLAGS = new Set([
77
+ "--semantic",
78
+ "--hybrid",
79
+ "--include-linked",
80
+ "--include_linked",
81
+ "--title-exact",
82
+ "--title_exact",
83
+ "--phrase-exact",
84
+ "--phrase_exact",
85
+ "--compact",
86
+ "--full",
87
+ "--json",
88
+ ]);
89
+
90
+ function stripSearchOptionTokens(args: string[]): string[] {
91
+ const queryTokens: string[] = [];
92
+ for (let index = 0; index < args.length; index += 1) {
93
+ const token = args[index]?.trim() ?? "";
94
+ const equalsIndex = token.indexOf("=");
95
+ const flagName = equalsIndex > 0 ? token.slice(0, equalsIndex) : token;
96
+ if (SEARCH_VALUE_FLAGS.has(flagName)) {
97
+ if (equalsIndex < 0) {
98
+ index += 1;
99
+ }
73
100
  continue;
74
101
  }
75
- if (typeof value === "boolean") {
76
- return value;
102
+ if (SEARCH_BOOLEAN_FLAGS.has(flagName)) {
103
+ continue;
77
104
  }
78
- if (typeof value === "string") {
79
- const normalized = value.trim().toLowerCase();
80
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
81
- return true;
82
- }
83
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
84
- return false;
85
- }
105
+ if (token.length > 0) {
106
+ queryTokens.push(token);
86
107
  }
87
108
  }
88
- return undefined;
109
+ return queryTokens;
89
110
  }
90
111
 
91
112
  function resolveSearchQuery(args: string[]): string {
92
- const query = args
93
- .map((value) => value.trim())
94
- .filter((value) => value.length > 0)
95
- .join(" ");
113
+ const query = stripSearchOptionTokens(args).join(" ");
96
114
  if (query.length === 0) {
97
115
  throw new PmCliError("Search query must not be empty", EXIT_CODE.USAGE);
98
116
  }
99
117
  return query;
100
118
  }
101
119
 
102
- function normalizeAdvancedSearchOptions(rawOptions: Record<string, unknown>): SearchOptions {
120
+ function normalizeAdvancedSearchOptions(rawOptions: Record<string, unknown>, args: string[]): SearchOptions {
103
121
  const fields = readStringOption(rawOptions, "fields");
104
122
  const compactRequested = readBooleanOption(rawOptions, "compact") === true;
105
123
  const fullRequested = readBooleanOption(rawOptions, "full") === true;
106
124
  const defaultCompact = !compactRequested && !fullRequested && fields === undefined;
125
+ const explicitMode = readStringOption(rawOptions, "mode");
126
+ const argFlags = new Set(args.map((value) => value?.trim() ?? ""));
127
+ const mode =
128
+ explicitMode ??
129
+ (readBooleanOption(rawOptions, "semantic") === true || argFlags.has("--semantic")
130
+ ? "semantic"
131
+ : readBooleanOption(rawOptions, "hybrid") === true || argFlags.has("--hybrid")
132
+ ? "hybrid"
133
+ : "keyword");
107
134
  return {
108
- mode: readStringOption(rawOptions, "mode"),
135
+ mode,
109
136
  includeLinked: readBooleanOption(rawOptions, "includeLinked", ["include_linked"]) === true ? true : undefined,
110
137
  titleExact: readBooleanOption(rawOptions, "titleExact", ["title_exact"]) === true ? true : undefined,
111
138
  phraseExact: readBooleanOption(rawOptions, "phraseExact", ["phrase_exact"]) === true ? true : undefined,
@@ -133,7 +160,7 @@ export async function runAdvancedSearchPackage(
133
160
  rawOptions: Record<string, unknown>,
134
161
  global: GlobalOptions,
135
162
  ): Promise<SearchResult> {
136
- return runSearch(resolveSearchQuery(args), normalizeAdvancedSearchOptions(rawOptions), global);
163
+ return runSearch(resolveSearchQuery(args), normalizeAdvancedSearchOptions(rawOptions, args), global);
137
164
  }
138
165
 
139
166
  export async function runAdvancedReindexPackage(
@@ -1,226 +1,35 @@
1
- import fs from "node:fs/promises";
2
1
  import path from "node:path";
3
2
  import { pathToFileURL } from "node:url";
4
-
5
3
  const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
6
4
  const sdk = await loadTemplatesSdkModule();
7
- const {
8
- CREATE_COMMANDER_REPEATABLE_OPTION_CONTRACTS,
9
- EXIT_CODE,
10
- PmCliError,
11
- getSettingsPath,
12
- nowIso,
13
- pathExists,
14
- readFileIfExists,
15
- resolvePmRoot,
16
- writeFileAtomic,
17
- } = sdk;
18
-
19
5
  async function loadTemplatesSdkModule() {
20
6
  const envRoot = process.env[PM_PACKAGE_ROOT_ENV];
21
7
  if (typeof envRoot !== "string" || envRoot.trim().length === 0) {
22
- throw new Error(
23
- `builtin-templates requires ${PM_PACKAGE_ROOT_ENV} to locate core SDK runtime exports.`,
24
- );
8
+ throw new Error(`builtin-templates requires ${PM_PACKAGE_ROOT_ENV} to locate core SDK runtime exports.`);
25
9
  }
26
10
  const modulePath = path.join(path.resolve(envRoot.trim()), "dist", "sdk", "index.js");
27
11
  try {
28
12
  const loaded = await import(pathToFileURL(modulePath).href);
29
- if (
30
- typeof loaded.resolvePmRoot === "function" &&
31
- typeof loaded.pathExists === "function" &&
32
- typeof loaded.PmCliError === "function" &&
33
- Array.isArray(loaded.CREATE_COMMANDER_REPEATABLE_OPTION_CONTRACTS)
34
- ) {
13
+ if (typeof loaded.loadCreateTemplateOptions === "function" &&
14
+ typeof loaded.runTemplatesList === "function" &&
15
+ typeof loaded.runTemplatesSave === "function" &&
16
+ typeof loaded.runTemplatesShow === "function") {
35
17
  return loaded;
36
18
  }
37
19
  } catch {
38
20
  // Fall through to deterministic failure message below.
39
21
  }
40
- throw new Error(
41
- `builtin-templates failed to load SDK runtime exports from ${modulePath}.`,
42
- );
22
+ throw new Error(`builtin-templates failed to load template runtime exports from ${modulePath}.`);
43
23
  }
44
-
45
- const TEMPLATE_DIRECTORY_NAME = "templates";
46
- const TEMPLATE_FILE_EXTENSION = ".json";
47
- const TEMPLATE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
48
- const TEMPLATE_OPTION_REPEATABLE_KEY_SET = new Set(CREATE_COMMANDER_REPEATABLE_OPTION_CONTRACTS.map((entry) => entry.target));
49
-
50
- function normalizeTemplateName(rawName) {
51
- const name = rawName.trim();
52
- if (!TEMPLATE_NAME_PATTERN.test(name)) {
53
- throw new PmCliError(
54
- `Invalid template name "${rawName}". Expected 1-64 characters matching [A-Za-z0-9][A-Za-z0-9._-]*.`,
55
- EXIT_CODE.USAGE,
56
- );
57
- }
58
- return name;
59
- }
60
-
61
- function templatesDirectory(pmRoot) {
62
- return path.join(pmRoot, TEMPLATE_DIRECTORY_NAME);
63
- }
64
-
65
- function templatePath(pmRoot, normalizedName) {
66
- return path.join(templatesDirectory(pmRoot), `${normalizedName}${TEMPLATE_FILE_EXTENSION}`);
67
- }
68
-
69
- async function ensureTrackerInitialized(pmRoot) {
70
- if (!(await pathExists(getSettingsPath(pmRoot)))) {
71
- throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
72
- }
73
- }
74
-
75
- function sortTemplateOptions(options) {
76
- return Object.fromEntries(Object.entries(options).sort(([left], [right]) => left.localeCompare(right)));
77
- }
78
-
79
- function extractTemplateOptions(rawOptions) {
80
- const next = {};
81
- for (const [key, value] of Object.entries(rawOptions)) {
82
- if (value === undefined) {
83
- continue;
84
- }
85
- if (TEMPLATE_OPTION_REPEATABLE_KEY_SET.has(key)) {
86
- if (typeof value === "string") {
87
- next[key] = [value];
88
- continue;
89
- }
90
- if (!Array.isArray(value)) {
91
- continue;
92
- }
93
- const values = value.filter((entry) => typeof entry === "string");
94
- if (values.length > 0) {
95
- next[key] = values;
96
- }
97
- continue;
98
- }
99
- if (typeof value === "string") {
100
- next[key] = value;
101
- continue;
102
- }
103
- if (Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
104
- next[key] = [...value];
105
- }
106
- }
107
- return sortTemplateOptions(next);
108
- }
109
-
110
- function parseStoredTemplateOptions(rawOptions, templateName) {
111
- if (typeof rawOptions !== "object" || rawOptions === null || Array.isArray(rawOptions)) {
112
- throw new PmCliError(`Template "${templateName}" has invalid options payload.`, EXIT_CODE.GENERIC_FAILURE);
113
- }
114
- const normalized = {};
115
- for (const [key, value] of Object.entries(rawOptions)) {
116
- const normalizedKey = key.trim();
117
- if (normalizedKey.length === 0) {
118
- throw new PmCliError(`Template "${templateName}" contains an empty option key.`, EXIT_CODE.GENERIC_FAILURE);
119
- }
120
- if (typeof value === "string") {
121
- normalized[normalizedKey] = value;
122
- continue;
123
- }
124
- if (Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
125
- normalized[normalizedKey] = [...value];
126
- continue;
127
- }
128
- throw new PmCliError(`Template "${templateName}" contains invalid value for option "${normalizedKey}".`, EXIT_CODE.GENERIC_FAILURE);
129
- }
130
- return sortTemplateOptions(normalized);
131
- }
132
-
133
- function parseStoredTemplateDocument(raw, normalizedName) {
134
- let parsed;
135
- try {
136
- parsed = JSON.parse(raw);
137
- } catch {
138
- throw new PmCliError(`Template "${normalizedName}" contains invalid JSON.`, EXIT_CODE.GENERIC_FAILURE);
139
- }
140
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
141
- throw new PmCliError(`Template "${normalizedName}" has invalid document shape.`, EXIT_CODE.GENERIC_FAILURE);
142
- }
143
- const options = parseStoredTemplateOptions(parsed.options, normalizedName);
144
- const now = nowIso();
145
- return {
146
- name: typeof parsed.name === "string" && parsed.name.trim().length > 0 ? parsed.name.trim() : normalizedName,
147
- created_at: typeof parsed.created_at === "string" ? parsed.created_at : now,
148
- updated_at: typeof parsed.updated_at === "string" ? parsed.updated_at : now,
149
- options,
150
- };
151
- }
152
-
153
- async function readStoredTemplateDocument(pmRoot, normalizedName) {
154
- const raw = await readFileIfExists(templatePath(pmRoot, normalizedName));
155
- if (raw === null) {
156
- throw new PmCliError(`Template "${normalizedName}" not found`, EXIT_CODE.NOT_FOUND);
157
- }
158
- return parseStoredTemplateDocument(raw, normalizedName);
24
+ export async function loadCreateTemplateOptions(pmRoot, rawTemplateName) {
25
+ return sdk.loadCreateTemplateOptions(pmRoot, rawTemplateName);
159
26
  }
160
-
161
27
  export async function runTemplatesSave(rawTemplateName, options, global) {
162
- const pmRoot = resolvePmRoot(process.cwd(), global.path);
163
- await ensureTrackerInitialized(pmRoot);
164
- const normalizedName = normalizeTemplateName(rawTemplateName);
165
- const nextOptions = extractTemplateOptions(options);
166
- if (Object.keys(nextOptions).length === 0) {
167
- throw new PmCliError("templates save requires at least one create option flag", EXIT_CODE.USAGE);
168
- }
169
-
170
- const now = nowIso();
171
- const storedPath = templatePath(pmRoot, normalizedName);
172
- let createdAt = now;
173
- if (await pathExists(storedPath)) {
174
- const existing = await readStoredTemplateDocument(pmRoot, normalizedName);
175
- createdAt = existing.created_at;
176
- }
177
-
178
- const document = {
179
- name: normalizedName,
180
- created_at: createdAt,
181
- updated_at: now,
182
- options: nextOptions,
183
- };
184
- await fs.mkdir(templatesDirectory(pmRoot), { recursive: true });
185
- await writeFileAtomic(storedPath, `${JSON.stringify(document, null, 2)}\n`);
186
- return {
187
- name: document.name,
188
- created_at: document.created_at,
189
- updated_at: document.updated_at,
190
- path: storedPath,
191
- options: document.options,
192
- };
28
+ return sdk.runTemplatesSave(rawTemplateName, options, global);
193
29
  }
194
-
195
30
  export async function runTemplatesList(global) {
196
- const pmRoot = resolvePmRoot(process.cwd(), global.path);
197
- await ensureTrackerInitialized(pmRoot);
198
- const dirPath = templatesDirectory(pmRoot);
199
- if (!(await pathExists(dirPath))) {
200
- return { templates: [], count: 0 };
201
- }
202
- const entries = await fs.readdir(dirPath);
203
- const templates = entries
204
- .filter((entry) => entry.toLowerCase().endsWith(TEMPLATE_FILE_EXTENSION))
205
- .map((entry) => entry.slice(0, -TEMPLATE_FILE_EXTENSION.length))
206
- .filter((entry) => TEMPLATE_NAME_PATTERN.test(entry))
207
- .sort((left, right) => left.localeCompare(right));
208
- return {
209
- templates,
210
- count: templates.length,
211
- };
31
+ return sdk.runTemplatesList(global);
212
32
  }
213
-
214
33
  export async function runTemplatesShow(rawTemplateName, global) {
215
- const pmRoot = resolvePmRoot(process.cwd(), global.path);
216
- await ensureTrackerInitialized(pmRoot);
217
- const normalizedName = normalizeTemplateName(rawTemplateName);
218
- const stored = await readStoredTemplateDocument(pmRoot, normalizedName);
219
- return {
220
- name: stored.name,
221
- created_at: stored.created_at,
222
- updated_at: stored.updated_at,
223
- path: templatePath(pmRoot, normalizedName),
224
- options: stored.options,
225
- };
34
+ return sdk.runTemplatesShow(rawTemplateName, global);
226
35
  }