@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
@@ -4,36 +4,31 @@ import {
4
4
  DEPENDENCY_KIND_VALUES,
5
5
  EXIT_CODE,
6
6
  PmCliError,
7
- acquireLock,
8
- appendHistoryEntry,
9
7
  canonicalDocument,
10
- createHistoryEntry,
8
+ commitImportedItem,
11
9
  generateItemId,
12
10
  getActiveExtensionRegistrations,
13
- getHistoryPath,
14
11
  getItemPath,
15
- getSettingsPath,
16
12
  isTimestampLiteral,
17
13
  locateItem,
18
14
  normalizeFrontMatter,
19
15
  normalizeItemId,
20
16
  normalizeRawItemId,
21
- normalizeStatusInput,
22
17
  nowIso,
23
- parseTags,
24
18
  pathExists,
25
19
  readSettings,
26
- removeFileIfExists,
27
20
  resolveItemTypeRegistry,
28
21
  resolvePmRoot,
29
22
  runActiveOnReadHooks,
30
- runActiveOnWriteHooks,
31
- serializeItemDocument,
32
- writeFileAtomic,
23
+ ensureTrackerInitialized,
24
+ selectImportAuthor,
25
+ toEstimatedMinutesValue,
26
+ toImportPriority,
27
+ toImportStatus,
28
+ toImportTags,
29
+ toNonEmptyImportString,
33
30
  type Dependency,
34
31
  type GlobalOptions,
35
- type ItemDocument,
36
- type ItemMetadata,
37
32
  type ItemStatus,
38
33
  type ItemType,
39
34
  type LinkedDoc,
@@ -102,13 +97,13 @@ interface BeadsRecord extends Record<string, unknown> {
102
97
  docs?: unknown;
103
98
  }
104
99
 
105
- function toNonEmptyString(value: unknown): string | undefined {
106
- if (typeof value !== "string") {
107
- return undefined;
108
- }
109
- const trimmed = value.trim();
110
- return trimmed.length > 0 ? trimmed : undefined;
111
- }
100
+ // Shared, behavior-identical value coercers are sourced from the SDK adapter
101
+ // surface; package-specific mappings (timestamps, item types, dependencies,
102
+ // linked artifacts) stay local below.
103
+ const toNonEmptyString = toNonEmptyImportString;
104
+ const toEstimatedMinutes = toEstimatedMinutesValue;
105
+ const toPriority = toImportPriority;
106
+ const toTags = toImportTags;
112
107
 
113
108
  function toIsoString(value: unknown): string | undefined {
114
109
  const raw = toNonEmptyString(value);
@@ -121,47 +116,6 @@ function toIsoString(value: unknown): string | undefined {
121
116
  return raw;
122
117
  }
123
118
 
124
- function toEstimatedMinutes(value: unknown): number | undefined {
125
- if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
126
- return value;
127
- }
128
- if (typeof value === "string" && value.trim().length > 0) {
129
- const parsed = Number(value);
130
- if (Number.isFinite(parsed) && parsed >= 0) {
131
- return parsed;
132
- }
133
- }
134
- return undefined;
135
- }
136
-
137
- function toPriority(value: unknown): 0 | 1 | 2 | 3 | 4 {
138
- const fallback: 0 | 1 | 2 | 3 | 4 = 2;
139
- if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 4) {
140
- return value as 0 | 1 | 2 | 3 | 4;
141
- }
142
- if (typeof value === "string" && value.trim().length > 0) {
143
- const parsed = Number(value);
144
- if (Number.isInteger(parsed) && parsed >= 0 && parsed <= 4) {
145
- return parsed as 0 | 1 | 2 | 3 | 4;
146
- }
147
- }
148
- return fallback;
149
- }
150
-
151
- function toTags(value: unknown): string[] {
152
- if (Array.isArray(value)) {
153
- const tags = value
154
- .filter((entry): entry is string => typeof entry === "string")
155
- .map((entry) => entry.trim().toLowerCase())
156
- .filter((entry) => entry.length > 0);
157
- return Array.from(new Set(tags)).sort((left, right) => left.localeCompare(right));
158
- }
159
- if (typeof value === "string") {
160
- return parseTags(value);
161
- }
162
- return [];
163
- }
164
-
165
119
  function toItemType(value: unknown): { type: ItemType; sourceType?: string } {
166
120
  const raw = toNonEmptyString(value);
167
121
  const normalized = raw?.toLowerCase();
@@ -185,16 +139,7 @@ function toItemType(value: unknown): { type: ItemType; sourceType?: string } {
185
139
  }
186
140
  }
187
141
 
188
- function toStatus(value: unknown): ItemStatus {
189
- const normalized = toNonEmptyString(value);
190
- if (normalized) {
191
- const canonical = normalizeStatusInput(normalized);
192
- if (canonical) {
193
- return canonical;
194
- }
195
- }
196
- return "open";
197
- }
142
+ const toStatus: (value: unknown) => ItemStatus = toImportStatus;
198
143
 
199
144
  function toDependencyKind(value: unknown): { kind: Dependency["kind"]; sourceKind?: string } {
200
145
  const raw = toNonEmptyString(value);
@@ -452,26 +397,8 @@ function toLinkedDocs(value: unknown): LinkedDoc[] | undefined {
452
397
  return docs.length > 0 ? docs : undefined;
453
398
  }
454
399
 
455
- function selectAuthor(explicitAuthor: string | undefined, settingsAuthor: string): string {
456
- const candidate = explicitAuthor ?? process.env.PM_AUTHOR ?? settingsAuthor;
457
- const trimmed = candidate.trim();
458
- return trimmed.length > 0 ? trimmed : "unknown";
459
- }
460
-
461
- function ensureInitHasRun(pmRoot: string): Promise<void> {
462
- return pathExists(getSettingsPath(pmRoot)).then((exists) => {
463
- if (!exists) {
464
- throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
465
- }
466
- });
467
- }
468
-
469
- function emptyDocument(): ItemDocument {
470
- return {
471
- metadata: {} as ItemMetadata,
472
- body: "",
473
- };
474
- }
400
+ const selectAuthor = selectImportAuthor;
401
+ const ensureInitHasRun = ensureTrackerInitialized;
475
402
 
476
403
  function resolveInputPath(rawPath: string): string {
477
404
  return path.isAbsolute(rawPath) ? rawPath : path.resolve(process.cwd(), rawPath);
@@ -667,48 +594,22 @@ export async function runBeadsImport(options: BeadsImportOptions, global: Global
667
594
  }
668
595
  const itemPath = getItemPath(pmRoot, type, id, "toon", typeRegistry.type_to_folder);
669
596
 
670
- const historyPath = getHistoryPath(pmRoot, id);
671
- try {
672
- const releaseLock = await acquireLock(pmRoot, id, settings.locks.ttl_seconds, author);
673
- try {
674
- await writeFileAtomic(itemPath, serializeItemDocument(afterDocument, { format: "toon" }));
675
- try {
676
- const entry = createHistoryEntry({
677
- nowIso: nowIso(),
678
- author,
679
- op: "import",
680
- before: emptyDocument(),
681
- after: afterDocument,
682
- message,
683
- });
684
- await appendHistoryEntry(historyPath, entry);
685
- warnings.push(
686
- ...(await runActiveOnWriteHooks({
687
- path: itemPath,
688
- scope: "project",
689
- op: "import",
690
- })),
691
- ...(await runActiveOnWriteHooks({
692
- path: historyPath,
693
- scope: "project",
694
- op: "import:history",
695
- })),
696
- );
697
- } catch (error: unknown) {
698
- await removeFileIfExists(itemPath);
699
- throw error;
700
- }
701
- } finally {
702
- await releaseLock();
703
- }
704
- } catch (error: unknown) {
705
- if (error instanceof PmCliError && error.exitCode === EXIT_CODE.CONFLICT) {
706
- warnings.push(`beads_import_lock_conflict:${id}`);
707
- skipped += 1;
708
- continue;
709
- }
710
- throw error;
597
+ const commit = await commitImportedItem({
598
+ pmRoot,
599
+ id,
600
+ itemPath,
601
+ document: afterDocument,
602
+ author,
603
+ message,
604
+ settings,
605
+ conflictWarningPrefix: "beads_import_lock_conflict",
606
+ });
607
+ if (!commit.committed) {
608
+ warnings.push(commit.conflictWarning);
609
+ skipped += 1;
610
+ continue;
711
611
  }
612
+ warnings.push(...commit.writeWarnings);
712
613
 
713
614
  ids.push(id);
714
615
  imported += 1;
@@ -3,7 +3,9 @@
3
3
  `@unbrained/pm-calendar` provides agenda and calendar views as an installable pm package.
4
4
 
5
5
  ```bash
6
- pm install calendar
6
+ pm install calendar --project
7
+ # Or bootstrap all bundled package commands in a new project:
8
+ pm init --defaults --with-packages
7
9
  pm calendar --view week --full-period
8
10
  pm cal --json --view agenda --include reminders,events
9
11
  ```
@@ -1,5 +1,19 @@
1
1
  import { renderCalendarPackageOutput, runCalendarPackage } from "./runtime.js";
2
2
 
3
+ const CALENDAR_VIEW_NAMES = ["agenda", "day", "week", "month"];
4
+
5
+ // Standalone error class so the package stays self-contained when installed
6
+ // outside the pm-cli source tree. The class name "PmCliError" lines up with
7
+ // the Sentry beforeSend filter (isExpectedCliErrorEvent) so usage errors do
8
+ // not leak into Sentry as crashes.
9
+ class PmCliError extends Error {
10
+ constructor(message, exitCode) {
11
+ super(message);
12
+ this.name = "PmCliError";
13
+ this.exitCode = exitCode;
14
+ }
15
+ }
16
+
3
17
  export const manifest = {
4
18
  name: "builtin-calendar",
5
19
  version: "0.1.0",
@@ -23,7 +37,7 @@ const calendarFlags = [
23
37
  { long: "--assignee-filter", value_name: "value", value_type: "string", description: "Filter assignee presence." },
24
38
  { long: "--sprint", value_name: "value", value_type: "string", description: "Filter by sprint." },
25
39
  { long: "--release", value_name: "value", value_type: "string", description: "Filter by release." },
26
- { long: "--include", value_name: "value", value_type: "string", description: "Include sources: deadlines|reminders|events|all." },
40
+ { long: "--include", value_name: "value", value_type: "string", description: "Include sources: deadlines|reminders|events|scheduled|all." },
27
41
  { long: "--recurrence-lookahead-days", value_name: "n", value_type: "string", description: "Bound open-ended recurrence lookahead days." },
28
42
  { long: "--recurrence-lookback-days", value_name: "n", value_type: "string", description: "Bound open-ended recurrence lookback days." },
29
43
  { long: "--occurrence-limit", value_name: "n", value_type: "string", description: "Cap generated occurrences per recurring event." },
@@ -31,13 +45,63 @@ const calendarFlags = [
31
45
  { long: "--format", value_name: "value", value_type: "string", description: "Calendar output override: markdown|toon|json." },
32
46
  ];
33
47
 
48
+ // The runtime lowercases `view` before validating (src/cli/commands/calendar.ts),
49
+ // so the unknown-alias / recovery-hint logic must match views case-insensitively
50
+ // or `pm calendar DAY ...` would wrongly flag DAY as unknown.
51
+ function normalizeCalendarView(arg) {
52
+ const normalized = arg.toLowerCase();
53
+ return CALENDAR_VIEW_NAMES.includes(normalized) ? normalized : null;
54
+ }
55
+
56
+ function buildPositionalViewError(positionalArgs) {
57
+ const received = positionalArgs.map((arg) => arg.trim()).filter((arg) => arg.length > 0);
58
+ const receivedList = received.join(", ");
59
+ // Check every received positional, not just the tail, so an invalid first
60
+ // positional (e.g. `pm calendar totally-bogus week`) is still surfaced.
61
+ const extras = received.filter((arg) => normalizeCalendarView(arg) === null);
62
+ // Fall back to the first valid view from `received` (normalized to canonical
63
+ // lowercase) for the recovery hint; recommend `agenda` only when none of the
64
+ // positionals are valid view names.
65
+ const recoveryView = received.map(normalizeCalendarView).find((view) => view !== null) ?? "agenda";
66
+ const hintLines = [`Calendar accepts at most one positional view (agenda|day|week|month), but received: ${receivedList}.`];
67
+ if (extras.length > 0) {
68
+ hintLines.push(`Unknown view alias(es): ${extras.join(", ")}.`);
69
+ }
70
+ hintLines.push("Use a single view, or pass extra arguments via flags:");
71
+ hintLines.push(` pm calendar ${recoveryView}`);
72
+ hintLines.push(` pm calendar --view ${recoveryView} --date +7d`);
73
+ return new PmCliError(hintLines.join("\n"), 2);
74
+ }
75
+
34
76
  function calendarCommand(name) {
35
77
  return {
36
78
  name,
37
79
  action: "calendar",
38
80
  description: "Show deadline, reminder, and scheduled event calendar views.",
81
+ arguments: [{ name: "view", required: false, description: "Calendar view: agenda|day|week|month." }],
39
82
  flags: [...calendarFlags],
40
- run: async (context) => runCalendarPackage(context.options, context.global),
83
+ run: async (context) => {
84
+ // Extension flags are parsed loosely, so context.args still contains flag
85
+ // tokens (e.g. ["day", "--date", "+7d"]). Only the leading non-flag tokens
86
+ // are true positionals, so a positional view combined with --date/--from/etc.
87
+ // must not be mistaken for multiple positional views.
88
+ const firstFlagIndex = context.args.findIndex((arg) => arg.startsWith("-"));
89
+ const rawPositionalArgs = firstFlagIndex === -1 ? context.args : context.args.slice(0, firstFlagIndex);
90
+ // Drop empty/whitespace-only positionals (e.g. from `pm calendar agenda ""`
91
+ // when a shell variable is unset) so the count check stays meaningful.
92
+ const positionalArgs = rawPositionalArgs.filter((arg) => arg.trim().length > 0);
93
+ const positionalView = positionalArgs[0]?.trim();
94
+ if (positionalArgs.length > 1) {
95
+ throw buildPositionalViewError(positionalArgs);
96
+ }
97
+ return runCalendarPackage(
98
+ {
99
+ ...context.options,
100
+ ...(positionalView && context.options.view === undefined ? { view: positionalView } : {}),
101
+ },
102
+ context.global,
103
+ );
104
+ },
41
105
  };
42
106
  }
43
107
 
@@ -6,6 +6,21 @@ import type {
6
6
  import type { CalendarOptions } from "../../../../src/sdk/runtime.js";
7
7
  import { renderCalendarPackageOutput, runCalendarPackage } from "./runtime.js";
8
8
 
9
+ const CALENDAR_VIEW_NAMES = ["agenda", "day", "week", "month"] as const;
10
+
11
+ // Standalone error class so the package stays self-contained when installed
12
+ // outside the pm-cli source tree. The class name "PmCliError" lines up with
13
+ // the Sentry beforeSend filter (isExpectedCliErrorEvent) so usage errors do
14
+ // not leak into Sentry as crashes.
15
+ class PmCliError extends Error {
16
+ exitCode: number;
17
+ constructor(message: string, exitCode: number) {
18
+ super(message);
19
+ this.name = "PmCliError";
20
+ this.exitCode = exitCode;
21
+ }
22
+ }
23
+
9
24
  export const manifest = {
10
25
  name: "builtin-calendar",
11
26
  version: "0.1.0",
@@ -29,7 +44,7 @@ const calendarFlags = [
29
44
  { long: "--assignee-filter", value_name: "value", value_type: "string", description: "Filter assignee presence." },
30
45
  { long: "--sprint", value_name: "value", value_type: "string", description: "Filter by sprint." },
31
46
  { long: "--release", value_name: "value", value_type: "string", description: "Filter by release." },
32
- { long: "--include", value_name: "value", value_type: "string", description: "Include sources: deadlines|reminders|events|all." },
47
+ { long: "--include", value_name: "value", value_type: "string", description: "Include sources: deadlines|reminders|events|scheduled|all." },
33
48
  { long: "--recurrence-lookahead-days", value_name: "n", value_type: "string", description: "Bound open-ended recurrence lookahead days." },
34
49
  { long: "--recurrence-lookback-days", value_name: "n", value_type: "string", description: "Bound open-ended recurrence lookback days." },
35
50
  { long: "--occurrence-limit", value_name: "n", value_type: "string", description: "Cap generated occurrences per recurring event." },
@@ -37,13 +52,67 @@ const calendarFlags = [
37
52
  { long: "--format", value_name: "value", value_type: "string", description: "Calendar output override: markdown|toon|json." },
38
53
  ] as const;
39
54
 
55
+ // The runtime lowercases `view` before validating (src/cli/commands/calendar.ts),
56
+ // so the unknown-alias / recovery-hint logic must match views case-insensitively
57
+ // or `pm calendar DAY ...` would wrongly flag DAY as unknown.
58
+ function normalizeCalendarView(arg: string): (typeof CALENDAR_VIEW_NAMES)[number] | null {
59
+ const normalized = arg.toLowerCase();
60
+ return (CALENDAR_VIEW_NAMES as readonly string[]).includes(normalized)
61
+ ? (normalized as (typeof CALENDAR_VIEW_NAMES)[number])
62
+ : null;
63
+ }
64
+
65
+ function buildPositionalViewError(positionalArgs: readonly string[]): PmCliError {
66
+ const received = positionalArgs.map((arg) => arg.trim()).filter((arg) => arg.length > 0);
67
+ const receivedList = received.join(", ");
68
+ // Check every received positional, not just the tail, so an invalid first
69
+ // positional (e.g. `pm calendar totally-bogus week`) is still surfaced.
70
+ const extras = received.filter((arg) => normalizeCalendarView(arg) === null);
71
+ // Fall back to the first valid view from `received` (normalized to canonical
72
+ // lowercase) for the recovery hint; recommend `agenda` only when none of the
73
+ // positionals are valid view names.
74
+ const recoveryView =
75
+ received.map(normalizeCalendarView).find((view): view is (typeof CALENDAR_VIEW_NAMES)[number] => view !== null) ??
76
+ "agenda";
77
+ const hintLines = [`Calendar accepts at most one positional view (agenda|day|week|month), but received: ${receivedList}.`];
78
+ if (extras.length > 0) {
79
+ hintLines.push(`Unknown view alias(es): ${extras.join(", ")}.`);
80
+ }
81
+ hintLines.push("Use a single view, or pass extra arguments via flags:");
82
+ hintLines.push(` pm calendar ${recoveryView}`);
83
+ hintLines.push(` pm calendar --view ${recoveryView} --date +7d`);
84
+ return new PmCliError(hintLines.join("\n"), 2);
85
+ }
86
+
40
87
  function calendarCommand(name: "calendar" | "cal"): CommandDefinition {
41
88
  return {
42
89
  name,
43
90
  action: "calendar",
44
91
  description: "Show deadline, reminder, and scheduled event calendar views.",
92
+ arguments: [{ name: "view", required: false, description: "Calendar view: agenda|day|week|month." }],
45
93
  flags: [...calendarFlags],
46
- run: async (context) => runCalendarPackage(context.options as CalendarOptions, context.global),
94
+ run: async (context) => {
95
+ // Extension flags are parsed loosely, so context.args still contains flag
96
+ // tokens (e.g. ["day", "--date", "+7d"]). Only the leading non-flag tokens
97
+ // are true positionals, so a positional view combined with --date/--from/etc.
98
+ // must not be mistaken for multiple positional views.
99
+ const firstFlagIndex = context.args.findIndex((arg) => arg.startsWith("-"));
100
+ const rawPositionalArgs = firstFlagIndex === -1 ? context.args : context.args.slice(0, firstFlagIndex);
101
+ // Drop empty/whitespace-only positionals (e.g. from `pm calendar agenda ""`
102
+ // when a shell variable is unset) so the count check stays meaningful.
103
+ const positionalArgs = rawPositionalArgs.filter((arg) => arg.trim().length > 0);
104
+ const positionalView = positionalArgs[0]?.trim();
105
+ if (positionalArgs.length > 1) {
106
+ throw buildPositionalViewError(positionalArgs);
107
+ }
108
+ return runCalendarPackage(
109
+ {
110
+ ...(context.options as CalendarOptions),
111
+ ...(positionalView && (context.options as CalendarOptions).view === undefined ? { view: positionalView } : {}),
112
+ },
113
+ context.global,
114
+ );
115
+ },
47
116
  };
48
117
  }
49
118
 
@@ -90,6 +90,7 @@ function readPayloadGlobalOptions(payload) {
90
90
 
91
91
  export async function runCalendarPackage(options, global) {
92
92
  const loaded = await ensureCalendarCoreModule();
93
+ loaded.resolveCalendarOutputFormat(options, global);
93
94
  return loaded.runCalendar(options, global);
94
95
  }
95
96
 
@@ -99,6 +99,7 @@ function readPayloadGlobalOptions(payload: unknown): GlobalOptions {
99
99
 
100
100
  export async function runCalendarPackage(options: CalendarOptions, global: GlobalOptions): Promise<CalendarResult> {
101
101
  const loaded = await ensureCalendarCoreModule();
102
+ loaded.resolveCalendarOutputFormat(options, global);
102
103
  return loaded.runCalendar(options, global);
103
104
  }
104
105
 
@@ -29,7 +29,9 @@ async function loadGovernanceModule() {
29
29
  if (
30
30
  typeof loaded.runDedupeAudit === "function" &&
31
31
  typeof loaded.runCommentsAudit === "function" &&
32
- typeof loaded.runNormalize === "function"
32
+ typeof loaded.runNormalize === "function" &&
33
+ typeof loaded.readStringOption === "function" &&
34
+ typeof loaded.readBooleanOption === "function"
33
35
  ) {
34
36
  return loaded;
35
37
  }
@@ -41,41 +43,8 @@ async function loadGovernanceModule() {
41
43
  );
42
44
  }
43
45
 
44
- function readStringOption(options, key, aliases = []) {
45
- const keys = [key, ...aliases];
46
- for (const candidate of keys) {
47
- const value = options[candidate];
48
- if (typeof value === "string" && value.trim().length > 0) {
49
- return value;
50
- }
51
- }
52
- return undefined;
53
- }
54
-
55
- function readBooleanOption(options, key, aliases = []) {
56
- const keys = [key, ...aliases];
57
- for (const candidate of keys) {
58
- const value = options[candidate];
59
- if (value === undefined) {
60
- continue;
61
- }
62
- if (typeof value === "boolean") {
63
- return value;
64
- }
65
- if (typeof value === "string") {
66
- const normalized = value.trim().toLowerCase();
67
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
68
- return true;
69
- }
70
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
71
- return false;
72
- }
73
- }
74
- }
75
- return undefined;
76
- }
77
-
78
- function normalizeDedupeAuditOptions(raw) {
46
+ function normalizeDedupeAuditOptions(sdk, raw) {
47
+ const readStringOption = sdk.readStringOption;
79
48
  return {
80
49
  mode: readStringOption(raw, "mode"),
81
50
  status: readStringOption(raw, "status"),
@@ -94,7 +63,9 @@ function normalizeDedupeAuditOptions(raw) {
94
63
  };
95
64
  }
96
65
 
97
- function normalizeCommentsAuditOptions(raw) {
66
+ function normalizeCommentsAuditOptions(sdk, raw) {
67
+ const readStringOption = sdk.readStringOption;
68
+ const readBooleanOption = sdk.readBooleanOption;
98
69
  return {
99
70
  status: readStringOption(raw, "status"),
100
71
  type: readStringOption(raw, "type"),
@@ -112,7 +83,9 @@ function normalizeCommentsAuditOptions(raw) {
112
83
  };
113
84
  }
114
85
 
115
- function normalizeNormalizeOptions(raw) {
86
+ function normalizeNormalizeOptions(sdk, raw) {
87
+ const readStringOption = sdk.readStringOption;
88
+ const readBooleanOption = sdk.readBooleanOption;
116
89
  return {
117
90
  status: readStringOption(raw, "filterStatus", ["filter_status", "status"]),
118
91
  list: {
@@ -145,15 +118,15 @@ function normalizeNormalizeOptions(raw) {
145
118
 
146
119
  export async function runDedupeAuditPackage(options, global) {
147
120
  const module = await ensureGovernanceModule();
148
- return module.runDedupeAudit(normalizeDedupeAuditOptions(options), global);
121
+ return module.runDedupeAudit(normalizeDedupeAuditOptions(module, options), global);
149
122
  }
150
123
 
151
124
  export async function runCommentsAuditPackage(options, global) {
152
125
  const module = await ensureGovernanceModule();
153
- return module.runCommentsAudit(normalizeCommentsAuditOptions(options), global);
126
+ return module.runCommentsAudit(normalizeCommentsAuditOptions(module, options), global);
154
127
  }
155
128
 
156
129
  export async function runNormalizePackage(options, global) {
157
130
  const module = await ensureGovernanceModule();
158
- return module.runNormalize(normalizeNormalizeOptions(options), global);
131
+ return module.runNormalize(normalizeNormalizeOptions(module, options), global);
159
132
  }
@@ -8,6 +8,8 @@ interface GovernanceRuntimeSdkModule {
8
8
  runDedupeAudit: (options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
9
9
  runCommentsAudit: (options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
10
10
  runNormalize: (options: Record<string, unknown>, global: GlobalOptions) => Promise<unknown>;
11
+ readStringOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => string | undefined;
12
+ readBooleanOption: (options: Record<string, unknown>, key: string, aliases?: string[]) => boolean | undefined;
11
13
  }
12
14
 
13
15
  let governanceModule: GovernanceRuntimeSdkModule | null = null;
@@ -37,7 +39,9 @@ async function loadGovernanceModule(): Promise<GovernanceRuntimeSdkModule> {
37
39
  if (
38
40
  typeof loaded.runDedupeAudit === "function" &&
39
41
  typeof loaded.runCommentsAudit === "function" &&
40
- typeof loaded.runNormalize === "function"
42
+ typeof loaded.runNormalize === "function" &&
43
+ typeof loaded.readStringOption === "function" &&
44
+ typeof loaded.readBooleanOption === "function"
41
45
  ) {
42
46
  return loaded as GovernanceRuntimeSdkModule;
43
47
  }
@@ -49,41 +53,11 @@ async function loadGovernanceModule(): Promise<GovernanceRuntimeSdkModule> {
49
53
  );
50
54
  }
51
55
 
52
- function readStringOption(options: Record<string, unknown>, key: string, aliases: string[] = []): string | undefined {
53
- const keys = [key, ...aliases];
54
- for (const candidate of keys) {
55
- const value = options[candidate];
56
- if (typeof value === "string" && value.trim().length > 0) {
57
- return value;
58
- }
59
- }
60
- return undefined;
61
- }
62
-
63
- function readBooleanOption(options: Record<string, unknown>, key: string, aliases: string[] = []): boolean | undefined {
64
- const keys = [key, ...aliases];
65
- for (const candidate of keys) {
66
- const value = options[candidate];
67
- if (value === undefined) {
68
- continue;
69
- }
70
- if (typeof value === "boolean") {
71
- return value;
72
- }
73
- if (typeof value === "string") {
74
- const normalized = value.trim().toLowerCase();
75
- if (normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on") {
76
- return true;
77
- }
78
- if (normalized === "false" || normalized === "0" || normalized === "no" || normalized === "off") {
79
- return false;
80
- }
81
- }
82
- }
83
- return undefined;
84
- }
85
-
86
- function normalizeDedupeAuditOptions(raw: Record<string, unknown>): Record<string, unknown> {
56
+ function normalizeDedupeAuditOptions(
57
+ sdk: GovernanceRuntimeSdkModule,
58
+ raw: Record<string, unknown>,
59
+ ): Record<string, unknown> {
60
+ const readStringOption = sdk.readStringOption;
87
61
  return {
88
62
  mode: readStringOption(raw, "mode"),
89
63
  status: readStringOption(raw, "status"),
@@ -102,7 +76,12 @@ function normalizeDedupeAuditOptions(raw: Record<string, unknown>): Record<strin
102
76
  };
103
77
  }
104
78
 
105
- function normalizeCommentsAuditOptions(raw: Record<string, unknown>): Record<string, unknown> {
79
+ function normalizeCommentsAuditOptions(
80
+ sdk: GovernanceRuntimeSdkModule,
81
+ raw: Record<string, unknown>,
82
+ ): Record<string, unknown> {
83
+ const readStringOption = sdk.readStringOption;
84
+ const readBooleanOption = sdk.readBooleanOption;
106
85
  return {
107
86
  status: readStringOption(raw, "status"),
108
87
  type: readStringOption(raw, "type"),
@@ -120,7 +99,12 @@ function normalizeCommentsAuditOptions(raw: Record<string, unknown>): Record<str
120
99
  };
121
100
  }
122
101
 
123
- function normalizeNormalizeOptions(raw: Record<string, unknown>): Record<string, unknown> {
102
+ function normalizeNormalizeOptions(
103
+ sdk: GovernanceRuntimeSdkModule,
104
+ raw: Record<string, unknown>,
105
+ ): Record<string, unknown> {
106
+ const readStringOption = sdk.readStringOption;
107
+ const readBooleanOption = sdk.readBooleanOption;
124
108
  return {
125
109
  status: readStringOption(raw, "filterStatus", ["filter_status", "status"]),
126
110
  list: {
@@ -156,7 +140,7 @@ export async function runDedupeAuditPackage(
156
140
  global: GlobalOptions,
157
141
  ): Promise<unknown> {
158
142
  const module = await ensureGovernanceModule();
159
- return module.runDedupeAudit(normalizeDedupeAuditOptions(options), global);
143
+ return module.runDedupeAudit(normalizeDedupeAuditOptions(module, options), global);
160
144
  }
161
145
 
162
146
  export async function runCommentsAuditPackage(
@@ -164,7 +148,7 @@ export async function runCommentsAuditPackage(
164
148
  global: GlobalOptions,
165
149
  ): Promise<unknown> {
166
150
  const module = await ensureGovernanceModule();
167
- return module.runCommentsAudit(normalizeCommentsAuditOptions(options), global);
151
+ return module.runCommentsAudit(normalizeCommentsAuditOptions(module, options), global);
168
152
  }
169
153
 
170
154
  export async function runNormalizePackage(
@@ -172,5 +156,5 @@ export async function runNormalizePackage(
172
156
  global: GlobalOptions,
173
157
  ): Promise<unknown> {
174
158
  const module = await ensureGovernanceModule();
175
- return module.runNormalize(normalizeNormalizeOptions(options), global);
159
+ return module.runNormalize(normalizeNormalizeOptions(module, options), global);
176
160
  }