@unbrained/pm-cli 2026.10.30 → 2026.10.31

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 (235) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +32 -0
  3. package/dist/cli/commander-usage.js +2 -2
  4. package/dist/cli/error-guidance.d.ts +45 -5
  5. package/dist/cli/error-guidance.js +5 -3
  6. package/dist/cli/extension-command-help.d.ts +1 -0
  7. package/dist/cli/extension-command-help.js +2 -2
  8. package/dist/cli/main.d.ts +1 -5
  9. package/dist/cli/main.js +5 -5
  10. package/dist/cli/migration-gates.d.ts +1 -1
  11. package/dist/cli/migration-gates.js +1 -1
  12. package/dist/cli/preflight-warnings.d.ts +11 -0
  13. package/dist/cli/preflight-warnings.js +4 -0
  14. package/dist/cli/register-mutation.js +2 -2
  15. package/dist/cli-bundle/bundle-manifest.json +1 -1
  16. package/dist/cli-bundle/chunks/chunk-24J6TNYE.js +8 -0
  17. package/dist/cli-bundle/chunks/{chunk-EHBGHX55.js → chunk-2AHSPMKJ.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-MVL27TAH.js → chunk-35Q2B2GJ.js} +2 -2
  19. package/dist/cli-bundle/chunks/chunk-43R7UTWV.js +2 -0
  20. package/dist/cli-bundle/chunks/chunk-6PSDQ7T7.js +8 -0
  21. package/dist/cli-bundle/chunks/{chunk-UUQX3PFD.js → chunk-BS2KXT24.js} +70 -70
  22. package/dist/cli-bundle/chunks/{chunk-Y6NC3X3E.js → chunk-GMBDZID5.js} +3 -3
  23. package/dist/cli-bundle/chunks/chunk-HSBTITO4.js +3 -0
  24. package/dist/cli-bundle/chunks/{chunk-LWW4F4G2.js → chunk-MRUA2Z43.js} +2 -2
  25. package/dist/cli-bundle/chunks/chunk-P3LNMWL2.js +2 -0
  26. package/dist/cli-bundle/chunks/{chunk-S2U7ECUJ.js → chunk-PT7TS6E7.js} +2 -2
  27. package/dist/cli-bundle/chunks/{chunk-TH5KPAN4.js → chunk-SBVX5CMV.js} +2 -2
  28. package/dist/cli-bundle/chunks/{chunk-4BQD5SW2.js → chunk-TL3O5GZA.js} +30 -30
  29. package/dist/cli-bundle/chunks/chunk-U7JXZMU5.js +6 -0
  30. package/dist/cli-bundle/chunks/{chunk-GRABKNFL.js → chunk-V6EWBTNH.js} +2 -2
  31. package/dist/cli-bundle/chunks/chunk-VC7TA67O.js +20 -0
  32. package/dist/cli-bundle/chunks/chunk-WNF6FOL7.js +31 -0
  33. package/dist/cli-bundle/chunks/chunk-WRXQAW7Q.js +114 -0
  34. package/dist/cli-bundle/chunks/{chunk-RZQNFHXO.js → chunk-WX25MU4N.js} +3 -3
  35. package/dist/cli-bundle/chunks/chunk-XDDPSWIW.js +2 -0
  36. package/dist/cli-bundle/chunks/chunk-YT5D5HNG.js +2 -0
  37. package/dist/cli-bundle/chunks/chunk-ZTJVOBDU.js +128 -0
  38. package/dist/cli-bundle/chunks/{indexed-receipt-blobs-LHLE7PSG.js → indexed-receipt-blobs-KGMJVFH2.js} +2 -2
  39. package/dist/cli-bundle/chunks/item-transaction-UWV6UNSV.js +2 -0
  40. package/dist/cli-bundle/chunks/{mutation-admission-TRGAVS7N.js → mutation-admission-I4RHIT3Q.js} +2 -2
  41. package/dist/cli-bundle/chunks/{register-list-query-BH4F6M7Z.js → register-list-query-MVDL5EXG.js} +3 -3
  42. package/dist/cli-bundle/chunks/register-mutation-GAF7LXRB.js +20 -0
  43. package/dist/cli-bundle/chunks/register-operations-JLFRL36Q.js +2 -0
  44. package/dist/cli-bundle/chunks/{register-setup-QPWSVHFZ.js → register-setup-MZN6ONB3.js} +2 -2
  45. package/dist/cli-bundle/chunks/{settlement-hook-MN3Y7LVX.js → settlement-hook-YWSWFOZY.js} +2 -2
  46. package/dist/cli-bundle/chunks/{stage-RTB6RAAO.js → stage-2ZORTOF6.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/{chunk-S23ZUASN.js → chunk-2J7T2UCH.js} +2 -2
  48. package/dist/cli-bundle/focused-chunks/chunk-4QPGJO2G.js +26 -0
  49. package/dist/cli-bundle/focused-chunks/{chunk-YU7QOYYV.js → chunk-57HPXGOQ.js} +3 -3
  50. package/dist/cli-bundle/focused-chunks/chunk-5MCGYBOQ.js +91 -0
  51. package/dist/cli-bundle/focused-chunks/chunk-6F6APBCX.js +3 -0
  52. package/dist/cli-bundle/focused-chunks/chunk-AFVN2KCP.js +44 -0
  53. package/dist/cli-bundle/focused-chunks/{chunk-RKPUQDWF.js → chunk-DFUTCKUF.js} +2 -2
  54. package/dist/cli-bundle/focused-chunks/chunk-EA65HVBO.js +12 -0
  55. package/dist/cli-bundle/focused-chunks/chunk-GP2WU43K.js +26 -0
  56. package/dist/cli-bundle/focused-chunks/{chunk-YQUZL2CK.js → chunk-HPWT3RBG.js} +3 -3
  57. package/dist/cli-bundle/focused-chunks/chunk-HSAEEWSI.js +2 -0
  58. package/dist/cli-bundle/focused-chunks/{chunk-BPE6JTKL.js → chunk-JLXGRDTG.js} +3 -3
  59. package/dist/cli-bundle/focused-chunks/{chunk-FRFNGMAK.js → chunk-JNKRUCVZ.js} +2 -2
  60. package/dist/cli-bundle/focused-chunks/{chunk-BCIUAEWX.js → chunk-KH5QJXY7.js} +2 -2
  61. package/dist/cli-bundle/focused-chunks/chunk-KKRIFBSL.js +2 -0
  62. package/dist/cli-bundle/focused-chunks/{chunk-RGQEJFXO.js → chunk-MW77Q3AQ.js} +2 -2
  63. package/dist/cli-bundle/focused-chunks/chunk-NOKG4RFN.js +22 -0
  64. package/dist/cli-bundle/focused-chunks/{chunk-POJPJX64.js → chunk-NRBUMDLF.js} +2 -2
  65. package/dist/cli-bundle/focused-chunks/{chunk-3SRX77ES.js → chunk-PC3R5CJV.js} +2 -2
  66. package/dist/cli-bundle/focused-chunks/{chunk-RYEZSZJ7.js → chunk-PFBQOZPK.js} +2 -2
  67. package/dist/cli-bundle/focused-chunks/{chunk-SAT7IAEB.js → chunk-QFMJGQGO.js} +3 -3
  68. package/dist/cli-bundle/focused-chunks/{chunk-VFWCSQAG.js → chunk-SFQKCA5K.js} +2 -2
  69. package/dist/cli-bundle/focused-chunks/chunk-WHIE2C6Q.js +2 -0
  70. package/dist/cli-bundle/focused-chunks/chunk-Y6UYRMVG.js +6 -0
  71. package/dist/cli-bundle/focused-chunks/{indexed-receipt-blobs-VK2363JB.js → indexed-receipt-blobs-KHWT44EK.js} +2 -2
  72. package/dist/cli-bundle/focused-chunks/item-transaction-LU75EG7D.js +2 -0
  73. package/dist/cli-bundle/focused-chunks/{mutation-admission-7VUODEPJ.js → mutation-admission-KDJ7SCPA.js} +2 -2
  74. package/dist/cli-bundle/focused-chunks/{settlement-hook-OK6A7PG2.js → settlement-hook-SJV52ZTV.js} +2 -2
  75. package/dist/cli-bundle/focused-chunks/{stage-S5RP5SZH.js → stage-R4KEBO37.js} +2 -2
  76. package/dist/cli-bundle/main.js +26 -22
  77. package/dist/cli-bundle/sdk-authoring.js +1 -1
  78. package/dist/cli-bundle/sdk-contracts.js +4 -4
  79. package/dist/cli-bundle/sdk-core.js +1 -1
  80. package/dist/cli-bundle/sdk-governance.js +1 -1
  81. package/dist/cli-bundle/sdk-graph.js +1 -1
  82. package/dist/cli-bundle/sdk-merge.js +57 -57
  83. package/dist/cli-bundle/sdk-query.js +1 -1
  84. package/dist/cli-bundle/sdk-runtime.js +1 -1
  85. package/dist/cli-bundle/sdk-testing.js +1 -1
  86. package/dist/cli-bundle/sdk.js +11 -11
  87. package/dist/core/config/nested-settings.js +1 -1
  88. package/dist/core/extensions/extension-hook-runtime.js +1 -1
  89. package/dist/core/extensions/extension-types.d.ts +4 -0
  90. package/dist/core/extensions/extension-types.js +1 -1
  91. package/dist/core/extensions/loader.js +1 -1
  92. package/dist/core/lock/lock.js +4 -4
  93. package/dist/core/output/output.js +2 -2
  94. package/dist/core/schema/fields-file.js +1 -1
  95. package/dist/core/sentry/helpers.d.ts +6 -0
  96. package/dist/core/sentry/helpers.js +1 -1
  97. package/dist/core/sentry/instrument.d.ts +1 -1
  98. package/dist/core/sentry/instrument.js +1 -1
  99. package/dist/core/shared/constants.js +1 -1
  100. package/dist/core/shared/errors.d.ts +6 -0
  101. package/dist/core/shared/errors.js +1 -1
  102. package/dist/core/shared/output-unicode.d.ts +10 -0
  103. package/dist/core/shared/output-unicode.js +2 -0
  104. package/dist/core/store/settings-validator.d.ts +1 -0
  105. package/dist/core/store/settings-validator.js +1 -1
  106. package/dist/core/store/settings.js +1 -1
  107. package/dist/core/telemetry/policy.d.ts +8 -0
  108. package/dist/core/telemetry/policy.js +1 -1
  109. package/dist/core/telemetry/runtime.js +3 -3
  110. package/dist/sdk/agent/command-recovery.d.ts +15 -0
  111. package/dist/sdk/agent/command-recovery.js +1 -1
  112. package/dist/sdk/cli-bootstrap.js +1 -1
  113. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +28 -0
  114. package/dist/sdk/cli-contracts/agent-output-contracts.js +2 -2
  115. package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1
  116. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  117. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
  118. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -1
  119. package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -1
  120. package/dist/sdk/cli-contracts.d.ts +1 -1
  121. package/dist/sdk/cli-contracts.js +1 -1
  122. package/dist/sdk/completion/fish.js +4 -4
  123. package/dist/sdk/completion/zsh.js +3 -3
  124. package/dist/sdk/config.d.ts +1 -0
  125. package/dist/sdk/config.js +1 -1
  126. package/dist/sdk/core.d.ts +1 -0
  127. package/dist/sdk/core.js +1 -1
  128. package/dist/sdk/error-runtime.d.ts +9 -0
  129. package/dist/sdk/error-runtime.js +1 -1
  130. package/dist/sdk/errors.js +1 -1
  131. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  132. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  133. package/dist/sdk/index.d.ts +2 -2
  134. package/dist/sdk/index.js +1 -1
  135. package/dist/sdk/lifecycle/claim.js +1 -1
  136. package/dist/sdk/lifecycle/close.js +1 -1
  137. package/dist/sdk/lifecycle/create.js +1 -1
  138. package/dist/sdk/lifecycle/plan.d.ts +2 -3
  139. package/dist/sdk/lifecycle/plan.js +1 -1
  140. package/dist/sdk/lifecycle/repeated-terminal-state.d.ts +45 -0
  141. package/dist/sdk/lifecycle/repeated-terminal-state.js +2 -0
  142. package/dist/sdk/lifecycle/shared-unset-fields.d.ts +9 -0
  143. package/dist/sdk/lifecycle/shared-unset-fields.js +1 -1
  144. package/dist/sdk/lifecycle/update-many.d.ts +0 -1
  145. package/dist/sdk/lifecycle/update-many.js +1 -1
  146. package/dist/sdk/lifecycle/update.d.ts +29 -1
  147. package/dist/sdk/lifecycle/update.js +2 -2
  148. package/dist/sdk/output/table-rows.d.ts +7 -1
  149. package/dist/sdk/output/table-rows.js +1 -1
  150. package/dist/sdk/output.d.ts +1 -0
  151. package/dist/sdk/output.js +2 -2
  152. package/dist/sdk/ownership-source.d.ts +18 -0
  153. package/dist/sdk/ownership-source.js +1 -1
  154. package/dist/sdk/public-surface.json +1 -1
  155. package/dist/sdk/query/get.d.ts +1 -1
  156. package/dist/sdk/query/get.js +1 -1
  157. package/dist/sdk/query/next-ranking-policy.d.ts +35 -0
  158. package/dist/sdk/query/next-ranking-policy.js +2 -0
  159. package/dist/sdk/query/next.d.ts +12 -2
  160. package/dist/sdk/query/next.js +2 -2
  161. package/dist/sdk/query/projection-contracts.d.ts +4 -0
  162. package/dist/sdk/query/projection-contracts.js +1 -1
  163. package/dist/sdk/read-output/surfaces.d.ts +27 -0
  164. package/dist/sdk/read-output/surfaces.js +2 -0
  165. package/dist/sdk/read-output-contracts.js +1 -1
  166. package/dist/sdk/runtime-primitives.d.ts +1 -0
  167. package/dist/sdk/runtime-primitives.js +1 -1
  168. package/dist/sdk/runtime.js +1 -1
  169. package/dist/sdk/test/execution-receipts.d.ts +25 -0
  170. package/dist/sdk/test/execution-receipts.js +2 -2
  171. package/dist/sdk/test/execution.d.ts +5 -0
  172. package/dist/sdk/test/execution.js +2 -2
  173. package/dist/types.d.ts +2 -0
  174. package/dist/types.js +1 -1
  175. package/docs/AGENT_GUIDE.md +1 -1
  176. package/docs/AGENT_OUTPUT_ENCODINGS.md +12 -0
  177. package/docs/AGENT_UX_CONTRACTS.md +2 -1
  178. package/docs/COMMANDS.md +58 -5
  179. package/docs/CONFIGURATION.md +48 -1
  180. package/docs/DEVELOPMENT_DEPENDENCY_SECURITY.md +26 -0
  181. package/docs/PACKED_FIRST_RUN.md +2 -1
  182. package/docs/READ_OUTPUT_CONTRACTS.md +24 -6
  183. package/docs/SDK.md +73 -2
  184. package/docs/TESTING.md +38 -2
  185. package/docs/agent-task-token-baseline.json +1 -1
  186. package/marketplace.json +1 -1
  187. package/package.json +1 -1
  188. package/packages/pm-beads/package.json +1 -1
  189. package/packages/pm-calendar/extensions/calendar/index.ts +1 -0
  190. package/packages/pm-calendar/package.json +1 -1
  191. package/packages/pm-command-kit/package.json +1 -1
  192. package/packages/pm-digital-twin/package.json +1 -1
  193. package/packages/pm-governance-audit/package.json +1 -1
  194. package/packages/pm-guide-shell/package.json +1 -1
  195. package/packages/pm-kanban/package.json +1 -1
  196. package/packages/pm-lifecycle-hooks/package.json +1 -1
  197. package/packages/pm-linked-test-adapters/package.json +1 -1
  198. package/packages/pm-search-advanced/package.json +1 -1
  199. package/packages/pm-templates/package.json +1 -1
  200. package/packages/pm-todos/package.json +1 -1
  201. package/packages/pm-vcs/package.json +1 -1
  202. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  203. package/plugins/pm-claude/package.json +1 -1
  204. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  205. package/plugins/pm-codex/package.json +1 -1
  206. package/plugins/pm-codex/plugin.json +1 -1
  207. package/runtime-dependencies.json +1 -1
  208. package/dist/cli-bundle/chunks/chunk-34MP7WKK.js +0 -6
  209. package/dist/cli-bundle/chunks/chunk-3KMYHYJV.js +0 -2
  210. package/dist/cli-bundle/chunks/chunk-42BHHNTL.js +0 -128
  211. package/dist/cli-bundle/chunks/chunk-I5O3XZOA.js +0 -2
  212. package/dist/cli-bundle/chunks/chunk-LEIVUGDH.js +0 -8
  213. package/dist/cli-bundle/chunks/chunk-OH7WPD42.js +0 -114
  214. package/dist/cli-bundle/chunks/chunk-OOD2A7AF.js +0 -20
  215. package/dist/cli-bundle/chunks/chunk-Q5V7P6NM.js +0 -2
  216. package/dist/cli-bundle/chunks/chunk-QLPFYBXN.js +0 -2
  217. package/dist/cli-bundle/chunks/chunk-SA5NYLPE.js +0 -8
  218. package/dist/cli-bundle/chunks/chunk-VHLAVTJN.js +0 -31
  219. package/dist/cli-bundle/chunks/chunk-XAOVJG52.js +0 -3
  220. package/dist/cli-bundle/chunks/chunk-XPQ4RTSF.js +0 -2
  221. package/dist/cli-bundle/chunks/item-transaction-WIOBZW4E.js +0 -2
  222. package/dist/cli-bundle/chunks/register-mutation-5V2NANIS.js +0 -20
  223. package/dist/cli-bundle/chunks/register-operations-XSFRMUFX.js +0 -2
  224. package/dist/cli-bundle/focused-chunks/chunk-2V6NMNYN.js +0 -26
  225. package/dist/cli-bundle/focused-chunks/chunk-ASHGXMX4.js +0 -3
  226. package/dist/cli-bundle/focused-chunks/chunk-CKBN2D42.js +0 -12
  227. package/dist/cli-bundle/focused-chunks/chunk-I642DXOT.js +0 -22
  228. package/dist/cli-bundle/focused-chunks/chunk-K7DKG5HM.js +0 -91
  229. package/dist/cli-bundle/focused-chunks/chunk-NMQBXU7N.js +0 -44
  230. package/dist/cli-bundle/focused-chunks/chunk-PGM3ENGZ.js +0 -2
  231. package/dist/cli-bundle/focused-chunks/chunk-QFNV4JTA.js +0 -6
  232. package/dist/cli-bundle/focused-chunks/chunk-QVJCQMZY.js +0 -26
  233. package/dist/cli-bundle/focused-chunks/chunk-R2TPPPVU.js +0 -2
  234. package/dist/cli-bundle/focused-chunks/chunk-VJVJ2ZX2.js +0 -2
  235. package/dist/cli-bundle/focused-chunks/item-transaction-ZFDKJIP7.js +0 -2
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @module sdk/lifecycle/repeated-terminal-state
3
+ *
4
+ * An update that names the close status for an item that already holds that
5
+ * status with the same reason is not a transition. Routing it to the closure
6
+ * writer re-stamped `closed_at` and `updated_at` on every retry (GH-1628)
7
+ * while the same payload on an open item was a no-op. These helpers detect
8
+ * the repeated state and apply only the remaining fields.
9
+ */
10
+ import { type GlobalOptions,type RuntimeStatusRegistry } from "../runtime-primitives.js";
11
+ import type { ItemMetadata } from "../../types/index.js";
12
+ import type { CloseRouteContext,UpdateCommandOptions,UpdateResult } from "./update.js";
13
+ /** Receipt for an update that repeats the item's current terminal state, so no closure clock is re-stamped (GH-1628). */
14
+ export declare const TERMINAL_STATE_UNCHANGED_WARNING = "terminal_state_unchanged";
15
+ /**
16
+ * Refuse, before any write, a close-status update that unsets the close
17
+ * reason without supplying a new one while `governance.require_close_reason`
18
+ * is enabled. Neither route may run first: the repeated-state path would
19
+ * persist the unset as a no-op closure, and the ordinary route applies its
20
+ * field pre-update before the closure writer's own refusal.
21
+ */
22
+ export declare function assertRoutedCloseKeepsRequiredReason(context:CloseRouteContext):void;
23
+ /**
24
+ * True when the requested close status, reason and completion time already
25
+ * describe the stored item. Such an update is not a transition: routing it to
26
+ * the closure writer would re-stamp `closed_at` and `updated_at` on every
27
+ * retry (GH-1628), while the same identical payload on an open item is a
28
+ * no-op. A blank reason under `governance.require_close_reason` is not a
29
+ * repetition either: the closure writer must refuse it exactly as it would on
30
+ * an open item.
31
+ */
32
+ export declare function describesCurrentTerminalState(metadata:ItemMetadata,options:UpdateCommandOptions,statusRegistry:RuntimeStatusRegistry,requireCloseReason?:boolean):boolean;
33
+ /** Read the stored metadata of the item an update is routing, refusing with the shared not-found guidance. */
34
+ export declare function readRoutedItemMetadata(context:CloseRouteContext):Promise<ItemMetadata>;
35
+ /**
36
+ * Apply the non-terminal fields of an update whose close status, reason and
37
+ * completion time already match the stored item. The closure clocks and the
38
+ * terminal history stay untouched; the remaining fields take the ordinary
39
+ * update path, which skips the write when nothing changes. The classification
40
+ * read holds no item lock, so when the locked write returns an item another
41
+ * writer has reopened, or whose reason or completion time changed meanwhile,
42
+ * the request no longer repeats the stored state and `closeReopened` hands it
43
+ * to the closure writer instead of reporting it unchanged.
44
+ */
45
+ export declare function applyRepeatedTerminalStateUpdate(context:CloseRouteContext,metadata:ItemMetadata,otherFieldKeys:readonly string[],runUpdate:(id:string,options:UpdateCommandOptions,global:GlobalOptions) => Promise<UpdateResult>,closeReopened:(fieldUpdate:UpdateResult) => Promise<UpdateResult>):Promise<UpdateResult>;
@@ -0,0 +1,2 @@
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d510588a-e45d-54ba-b9c0-153940bb6677")}catch{}})();import{buildItemNotFoundError,locateItem,normalizeStatusInput,readLocatedItem,resolveIsoOrRelative,toItemRecord,transferMutationStdinTokenPolicy}from"../runtime-primitives.js";import{requireTerminalReason}from"../lifecycle-policy.js";import{CLOSE_REASON_UNSET_ALIASES,expandUnsetFieldTokens}from"./shared-unset-fields.js";const TERMINAL_STATE_UNCHANGED_WARNING="terminal_state_unchanged";function normalizeTerminalReasonInput(value){const trimmed=value?.trim();return trimmed!==void 0&&trimmed.length>0?trimmed:void 0}function isCloseStatus(status,statusRegistry){return normalizeStatusInput(status,statusRegistry)===statusRegistry.close_status}function unsetsCloseReason(options){const isCloseReasonAlias=entry=>CLOSE_REASON_UNSET_ALIASES.includes(entry.trim().toLowerCase());return expandUnsetFieldTokens(options.unset??[],isCloseReasonAlias).some(isCloseReasonAlias)}function assertRoutedCloseKeepsRequiredReason(context){!context.settings.governance.require_close_reason||!unsetsCloseReason(context.options)||requireTerminalReason({explicit:context.options.closeReason},!0)}function describesCurrentTerminalState(metadata,options,statusRegistry,requireCloseReason=!1){if(!isCloseStatus(metadata.status,statusRegistry))return!1;const requestedReason=normalizeTerminalReasonInput(options.closeReason);return requireCloseReason&&options.closeReason!==void 0&&requestedReason===void 0||requestedReason!==void 0&&requestedReason!==normalizeTerminalReasonInput(metadata.close_reason)?!1:options.completedAt===void 0||resolveIsoOrRelative(options.completedAt,new Date,"completed-at")===metadata.completed_at}async function readRoutedItemMetadata(context){const located=await locateItem(context.pmRoot,context.id,context.settings.id_prefix,context.settings.item_format,context.typeRegistry.type_to_folder);if(!located)throw await buildItemNotFoundError(context.pmRoot,context.id,context.settings.id_prefix,context.typeRegistry.type_to_folder);const{document}=await readLocatedItem(located,{schema:context.settings.schema});return document.metadata}async function applyRepeatedTerminalStateUpdate(context,metadata,otherFieldKeys,runUpdate,closeReopened){if(otherFieldKeys.length===0)return{item:toItemRecord(metadata),changed_fields:[],warnings:[...context.workflowTransitionWarnings,TERMINAL_STATE_UNCHANGED_WARNING]};const remainingOptions=transferMutationStdinTokenPolicy(context.options,{...context.options,status:void 0,closeReason:void 0,completedAt:void 0}),result=await runUpdate(context.id,remainingOptions,context.global);return describesCurrentTerminalState(result.item,context.options,context.statusRegistry,context.settings.governance.require_close_reason)?{item:result.item,changed_fields:result.changed_fields,warnings:[...context.workflowTransitionWarnings,...result.warnings,TERMINAL_STATE_UNCHANGED_WARNING]}:closeReopened(result)}export{TERMINAL_STATE_UNCHANGED_WARNING,applyRepeatedTerminalStateUpdate,assertRoutedCloseKeepsRequiredReason,describesCurrentTerminalState,readRoutedItemMetadata};
2
+ //# sourceMappingURL=repeated-terminal-state.js.map
@@ -15,6 +15,8 @@ optionKey:string;
15
15
  /** Value that configures or reports item metadata key for this contract. */
16
16
  metadataKey:string;
17
17
  }
18
+ /** `--unset` spellings that clear `close_reason`, shared by the update parser and the routed-close governance guard. */
19
+ export declare const CLOSE_REASON_UNSET_ALIASES:readonly string[];
18
20
  /** Public contract for common unset field definitions before close reason, shared by SDK and presentation-layer consumers. */
19
21
  export declare const COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON:readonly CommandUnsetFieldDefinition[];
20
22
  /** Public contract for common unset field definitions after close reason before author, shared by SDK and presentation-layer consumers. */
@@ -39,6 +41,13 @@ optionKeys:Set<string>;
39
41
  }
40
42
  /** Resolve one normalized `--unset` token to a item-metadata/option pair. */
41
43
  export type CommandUnsetTargetResolver = (trimmedToken:string) => RuntimeUnsetFieldDefinition | undefined;
44
+ /**
45
+ * Expand repeated and comma-separated `--unset` values into one token per
46
+ * field. An entry that resolves as a whole is kept intact first, so a legacy
47
+ * field key registered with a comma (before schema add-field refused them)
48
+ * stays clearable; only unresolved entries split on commas.
49
+ */
50
+ export declare function expandUnsetFieldTokens(raw:readonly string[],resolvesWhole:(entry:string) => boolean):string[];
42
51
  /** Parse and validate common command `--unset` tokens while preserving command-specific field resolution. */
43
52
  export declare function parseCommandUnsetTargets(options:{
44
53
  readonly raw:readonly string[] | undefined;
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1ffee31a-c272-5494-a04a-01a17b78dd2d")}catch{}})();import{EXIT_CODE,PmCliError}from"../runtime-primitives.js";import{isLegacyNoneToken}from"./legacy-none-tokens.js";const COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON=[{canonical:"tags",aliases:["tags"],optionKey:"tags",metadataKey:"tags"}],COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR=[{canonical:"deadline",aliases:["deadline"],optionKey:"deadline",metadataKey:"deadline"},{canonical:"estimate",aliases:["estimate","estimated_minutes","estimated-minutes"],optionKey:"estimatedMinutes",metadataKey:"estimated_minutes"},{canonical:"acceptance-criteria",aliases:["acceptance_criteria","acceptance-criteria","ac"],optionKey:"acceptanceCriteria",metadataKey:"acceptance_criteria"},{canonical:"definition-of-ready",aliases:["definition_of_ready","definition-of-ready"],optionKey:"definitionOfReady",metadataKey:"definition_of_ready"},{canonical:"order",aliases:["order","rank"],optionKey:"order",metadataKey:"order"},{canonical:"goal",aliases:["goal"],optionKey:"goal",metadataKey:"goal"},{canonical:"objective",aliases:["objective"],optionKey:"objective",metadataKey:"objective"},{canonical:"value",aliases:["value"],optionKey:"value",metadataKey:"value"},{canonical:"impact",aliases:["impact"],optionKey:"impact",metadataKey:"impact"},{canonical:"outcome",aliases:["outcome"],optionKey:"outcome",metadataKey:"outcome"},{canonical:"why-now",aliases:["why_now","why-now"],optionKey:"whyNow",metadataKey:"why_now"}],COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_AUTHOR=[...COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON,...COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR],COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR=[{canonical:"assignee",aliases:["assignee"],optionKey:"assignee",metadataKey:"assignee"},{canonical:"parent",aliases:["parent"],optionKey:"parent",metadataKey:"parent"},{canonical:"reviewer",aliases:["reviewer"],optionKey:"reviewer",metadataKey:"reviewer"},{canonical:"risk",aliases:["risk"],optionKey:"risk",metadataKey:"risk"},{canonical:"confidence",aliases:["confidence"],optionKey:"confidence",metadataKey:"confidence"},{canonical:"sprint",aliases:["sprint"],optionKey:"sprint",metadataKey:"sprint"},{canonical:"release",aliases:["release"],optionKey:"release",metadataKey:"release"},{canonical:"blocked-by",aliases:["blocked_by","blocked-by"],optionKey:"blockedBy",metadataKey:"blocked_by"},{canonical:"blocked-reason",aliases:["blocked_reason","blocked-reason"],optionKey:"blockedReason",metadataKey:"blocked_reason"},{canonical:"unblock-note",aliases:["unblock_note","unblock-note"],optionKey:"unblockNote",metadataKey:"unblock_note"},{canonical:"reporter",aliases:["reporter"],optionKey:"reporter",metadataKey:"reporter"},{canonical:"severity",aliases:["severity"],optionKey:"severity",metadataKey:"severity"},{canonical:"environment",aliases:["environment"],optionKey:"environment",metadataKey:"environment"},{canonical:"repro-steps",aliases:["repro_steps","repro-steps"],optionKey:"reproSteps",metadataKey:"repro_steps"},{canonical:"resolution",aliases:["resolution"],optionKey:"resolution",metadataKey:"resolution"},{canonical:"expected-result",aliases:["expected_result","expected-result"],optionKey:"expectedResult",metadataKey:"expected_result"},{canonical:"actual-result",aliases:["actual_result","actual-result"],optionKey:"actualResult",metadataKey:"actual_result"},{canonical:"affected-version",aliases:["affected_version","affected-version"],optionKey:"affectedVersion",metadataKey:"affected_version"},{canonical:"fixed-version",aliases:["fixed_version","fixed-version"],optionKey:"fixedVersion",metadataKey:"fixed_version"},{canonical:"component",aliases:["component"],optionKey:"component",metadataKey:"component"},{canonical:"regression",aliases:["regression"],optionKey:"regression",metadataKey:"regression"},{canonical:"customer-impact",aliases:["customer_impact","customer-impact"],optionKey:"customerImpact",metadataKey:"customer_impact"}];function parseCommandUnsetTargets(options){const metadataKeys=new Set,optionKeys=new Set;if(!options.raw||options.raw.length===0)return{metadataKeys,optionKeys};for(const entry of options.raw){const trimmed=entry.trim().toLowerCase();if(!trimmed)throw new PmCliError("--unset values must not be empty",EXIT_CODE.USAGE);if(isLegacyNoneToken(trimmed))throw new PmCliError('--unset no longer accepts "none" or "null". Specify concrete field names such as --unset deadline',EXIT_CODE.USAGE);const definition=options.resolveDefinition(trimmed);if(!definition)throw new PmCliError(`Unsupported --unset field "${entry}". Supported fields: ${options.supportedFields}`,EXIT_CODE.USAGE);metadataKeys.add(definition.metadataKey),optionKeys.add(definition.optionKey)}return{metadataKeys,optionKeys}}function resolveRuntimeUnsetFieldDefinition(token,command,runtimeFieldRegistry){const normalizedToken=token.trim().toLowerCase();if(!runtimeFieldRegistry)return;const definitions=runtimeFieldRegistry.command_to_fields?.get(command)??[];for(const definition of definitions){if(definition.allow_unset===!1)continue;const candidates=new Set;if(typeof definition.key=="string"&&definition.key.length>0&&candidates.add(definition.key.toLowerCase()),typeof definition.metadata_key=="string"&&definition.metadata_key.length>0&&candidates.add(definition.metadata_key.toLowerCase()),typeof definition.cli_flag=="string"&&definition.cli_flag.length>0&&(candidates.add(definition.cli_flag.replaceAll("-","_").toLowerCase()),candidates.add(definition.cli_flag.toLowerCase())),Array.isArray(definition.cli_aliases))for(const alias of definition.cli_aliases)typeof alias!="string"||alias.length===0||(candidates.add(alias.replaceAll("-","_").toLowerCase()),candidates.add(alias.toLowerCase()));if(candidates.has(normalizedToken))return{optionKey:definition.key,metadataKey:definition.metadata_key}}}export{COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR,COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR,COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_AUTHOR,COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON,parseCommandUnsetTargets,resolveRuntimeUnsetFieldDefinition};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="528a6201-58cb-544b-a831-5ce3bff3bbc2")}catch{}})();import{EXIT_CODE,PmCliError}from"../runtime-primitives.js";import{isLegacyNoneToken}from"./legacy-none-tokens.js";const CLOSE_REASON_UNSET_ALIASES=["close_reason","close-reason"],COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON=[{canonical:"tags",aliases:["tags"],optionKey:"tags",metadataKey:"tags"}],COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR=[{canonical:"deadline",aliases:["deadline"],optionKey:"deadline",metadataKey:"deadline"},{canonical:"estimate",aliases:["estimate","estimated_minutes","estimated-minutes"],optionKey:"estimatedMinutes",metadataKey:"estimated_minutes"},{canonical:"acceptance-criteria",aliases:["acceptance_criteria","acceptance-criteria","ac"],optionKey:"acceptanceCriteria",metadataKey:"acceptance_criteria"},{canonical:"definition-of-ready",aliases:["definition_of_ready","definition-of-ready"],optionKey:"definitionOfReady",metadataKey:"definition_of_ready"},{canonical:"order",aliases:["order","rank"],optionKey:"order",metadataKey:"order"},{canonical:"goal",aliases:["goal"],optionKey:"goal",metadataKey:"goal"},{canonical:"objective",aliases:["objective"],optionKey:"objective",metadataKey:"objective"},{canonical:"value",aliases:["value"],optionKey:"value",metadataKey:"value"},{canonical:"impact",aliases:["impact"],optionKey:"impact",metadataKey:"impact"},{canonical:"outcome",aliases:["outcome"],optionKey:"outcome",metadataKey:"outcome"},{canonical:"why-now",aliases:["why_now","why-now"],optionKey:"whyNow",metadataKey:"why_now"}],COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_AUTHOR=[...COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON,...COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR],COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR=[{canonical:"assignee",aliases:["assignee"],optionKey:"assignee",metadataKey:"assignee"},{canonical:"parent",aliases:["parent"],optionKey:"parent",metadataKey:"parent"},{canonical:"reviewer",aliases:["reviewer"],optionKey:"reviewer",metadataKey:"reviewer"},{canonical:"risk",aliases:["risk"],optionKey:"risk",metadataKey:"risk"},{canonical:"confidence",aliases:["confidence"],optionKey:"confidence",metadataKey:"confidence"},{canonical:"sprint",aliases:["sprint"],optionKey:"sprint",metadataKey:"sprint"},{canonical:"release",aliases:["release"],optionKey:"release",metadataKey:"release"},{canonical:"blocked-by",aliases:["blocked_by","blocked-by"],optionKey:"blockedBy",metadataKey:"blocked_by"},{canonical:"blocked-reason",aliases:["blocked_reason","blocked-reason"],optionKey:"blockedReason",metadataKey:"blocked_reason"},{canonical:"unblock-note",aliases:["unblock_note","unblock-note"],optionKey:"unblockNote",metadataKey:"unblock_note"},{canonical:"reporter",aliases:["reporter"],optionKey:"reporter",metadataKey:"reporter"},{canonical:"severity",aliases:["severity"],optionKey:"severity",metadataKey:"severity"},{canonical:"environment",aliases:["environment"],optionKey:"environment",metadataKey:"environment"},{canonical:"repro-steps",aliases:["repro_steps","repro-steps"],optionKey:"reproSteps",metadataKey:"repro_steps"},{canonical:"resolution",aliases:["resolution"],optionKey:"resolution",metadataKey:"resolution"},{canonical:"expected-result",aliases:["expected_result","expected-result"],optionKey:"expectedResult",metadataKey:"expected_result"},{canonical:"actual-result",aliases:["actual_result","actual-result"],optionKey:"actualResult",metadataKey:"actual_result"},{canonical:"affected-version",aliases:["affected_version","affected-version"],optionKey:"affectedVersion",metadataKey:"affected_version"},{canonical:"fixed-version",aliases:["fixed_version","fixed-version"],optionKey:"fixedVersion",metadataKey:"fixed_version"},{canonical:"component",aliases:["component"],optionKey:"component",metadataKey:"component"},{canonical:"regression",aliases:["regression"],optionKey:"regression",metadataKey:"regression"},{canonical:"customer-impact",aliases:["customer_impact","customer-impact"],optionKey:"customerImpact",metadataKey:"customer_impact"}];function expandUnsetFieldTokens(raw,resolvesWhole){return raw.flatMap(entry=>entry.includes(",")&&resolvesWhole(entry)?[entry]:entry.split(","))}function parseCommandUnsetTargets(options){const metadataKeys=new Set,optionKeys=new Set;if(!options.raw||options.raw.length===0)return{metadataKeys,optionKeys};const tokens=expandUnsetFieldTokens(options.raw,entry=>options.resolveDefinition(entry.trim().toLowerCase())!==void 0);for(const entry of tokens){const trimmed=entry.trim().toLowerCase();if(!trimmed)throw new PmCliError("--unset values must not be empty; name each field once, for example --unset parent,release",EXIT_CODE.USAGE);if(isLegacyNoneToken(trimmed))throw new PmCliError('--unset no longer accepts "none" or "null". Specify concrete field names such as --unset deadline',EXIT_CODE.USAGE);const definition=options.resolveDefinition(trimmed);if(!definition)throw new PmCliError(`Unsupported --unset field "${entry}". Supported fields: ${options.supportedFields}`,EXIT_CODE.USAGE);metadataKeys.add(definition.metadataKey),optionKeys.add(definition.optionKey)}return{metadataKeys,optionKeys}}function resolveRuntimeUnsetFieldDefinition(token,command,runtimeFieldRegistry){const normalizedToken=token.trim().toLowerCase();if(!runtimeFieldRegistry)return;const definitions=runtimeFieldRegistry.command_to_fields?.get(command)??[];for(const definition of definitions){if(definition.allow_unset===!1)continue;const candidates=new Set;if(typeof definition.key=="string"&&definition.key.length>0&&candidates.add(definition.key.toLowerCase()),typeof definition.metadata_key=="string"&&definition.metadata_key.length>0&&candidates.add(definition.metadata_key.toLowerCase()),typeof definition.cli_flag=="string"&&definition.cli_flag.length>0&&(candidates.add(definition.cli_flag.replaceAll("-","_").toLowerCase()),candidates.add(definition.cli_flag.toLowerCase())),Array.isArray(definition.cli_aliases))for(const alias of definition.cli_aliases)typeof alias!="string"||alias.length===0||(candidates.add(alias.replaceAll("-","_").toLowerCase()),candidates.add(alias.toLowerCase()));if(candidates.has(normalizedToken))return{optionKey:definition.key,metadataKey:definition.metadata_key}}}export{CLOSE_REASON_UNSET_ALIASES,COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR,COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR,COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_AUTHOR,COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON,expandUnsetFieldTokens,parseCommandUnsetTargets,resolveRuntimeUnsetFieldDefinition};
2
2
  //# sourceMappingURL=shared-unset-fields.js.map
@@ -99,7 +99,6 @@ hasListFilters:typeof hasListFilters;
99
99
  normalizeStatusFilter:(value:string | undefined,statusRegistry:RuntimeStatusRegistry) => ItemStatus[] | undefined;
100
100
  normalizeCollectionBeforeValue:(field:string,value:unknown) => unknown;
101
101
  normalizeExistingTags:(value:unknown) => string[];
102
- normalizeUnsetField:(rawField:string) => string;
103
102
  rejectBlankIdsFilter:(list:ListOptions | undefined) => void;
104
103
  sanitizeUpdateOptionsForSummary:(options:UpdateCommandOptions) => Record<string,unknown>;
105
104
  toComparablePreviewValue:(optionKey:keyof UpdateCommandOptions,value:unknown) => unknown;
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="24a00d2b-9dd4-51cf-9281-99e9ef09e9fb")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{withCheckpointMutation}from"../../core/checkpoint/mutation-context.js";import{resolveCheckpointRollbackId}from"../../core/checkpoint/mutation-checkpoint.js";import{rollbackMutationCheckpoint}from"./checkpoint-rollback.js";import{createCheckpointId,loadMutationCheckpoint,writeMutationCheckpoint,toItemRecord,applyAcceptanceCriteriaMutations,applyTagRemovals,mergeAdditiveTags,parseOptionalNonNegativeInteger,parseTags,splitAcceptanceCriteria,resolvePriority,normalizeStatusInput,resolveItemTypeRegistry,resolveTypeName,collectRuntimeUpdateFieldValues,buildInvalidTypeError,resolveItemTypesFilePath,resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,PmCliError,toErrorMessage,stableValueEquals,nowIso,preserveMutationStdinTokenLiterals,transferMutationStdinTokenPolicy,resolveIsoOrRelative,getActiveExtensionRegistrations,resolvePmRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{assertDependencyTargetsResolvable}from"../dependency-flag-validation.js";import{parseStatusFilterCsv}from"../../core/item/status-filter.js";import{hasListFilters}from"../query/list-filter-shared.js";import{runList}from"../query/list.js";import{assertUpdateMutationOptionCombinations,parseDependencyAdditions,resolveUpdateTransportOptions,runUpdate}from"./update.js";import{derivePmBulkMutationEffect}from"../cli-contracts/command-exit-contracts.js";const UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION=2,UPDATE_MANY_CHECKPOINT_SUBDIR="update-many",NON_MUTATION_UPDATE_OPTION_KEYS=new Set(["author","message","force","ownershipMetadataBypass","ownershipDependencyBypass","allowUnresolvedDeps"]),UPDATE_MANY_MUTATION_FLAG_GUIDANCE=["--status","--priority","--type","--tags","--description","--body","--deadline","--estimate","--assignee","--dep","--dep-remove","--comment","--note","--learning","--file","--test","--doc","--replace-deps","--replace-tests","--replace-files","--replace-docs","--unset","--clear-*"].join(", "),UPDATE_OPTION_TO_ITEM_KEY={title:"title",description:"description",body:"body",status:"status",closeReason:"close_reason",priority:"priority",type:"type",deadline:"deadline",estimatedMinutes:"estimated_minutes",acceptanceCriteria:"acceptance_criteria",definitionOfReady:"definition_of_ready",order:"order",goal:"goal",objective:"objective",value:"value",impact:"impact",outcome:"outcome",whyNow:"why_now",assignee:"assignee",parent:"parent",reviewer:"reviewer",risk:"risk",confidence:"confidence",sprint:"sprint",release:"release",blockedBy:"blocked_by",blockedReason:"blocked_reason",unblockNote:"unblock_note",reporter:"reporter",severity:"severity",environment:"environment",reproSteps:"repro_steps",resolution:"resolution",expectedResult:"expected_result",actualResult:"actual_result",affectedVersion:"affected_version",fixedVersion:"fixed_version",component:"component",regression:"regression",customerImpact:"customer_impact"},COLLECTION_MUTATION_PLAN_DEFINITIONS=[{field:"dependencies",addKey:"dep",removeKey:"depRemove",clearKey:"clearDeps",replaceKey:"replaceDeps"},{field:"comments",addKey:"comment",clearKey:"clearComments"},{field:"notes",addKey:"note",clearKey:"clearNotes"},{field:"learnings",addKey:"learning",clearKey:"clearLearnings"},{field:"files",addKey:"file",clearKey:"clearFiles",replaceKey:"replaceFiles"},{field:"tests",addKey:"test",clearKey:"clearTests",replaceKey:"replaceTests"},{field:"docs",addKey:"doc",clearKey:"clearDocs",replaceKey:"replaceDocs"},{field:"reminders",addKey:"reminder",clearKey:"clearReminders"},{field:"events",addKey:"event",clearKey:"clearEvents"},{field:"type_options",addKey:"typeOption",clearKey:"clearTypeOptions"}],UNSET_FIELD_ALIASES={close_reason:"close_reason","close-reason":"close_reason",deadline:"deadline",estimate:"estimated_minutes",estimated_minutes:"estimated_minutes","estimated-minutes":"estimated_minutes",acceptance_criteria:"acceptance_criteria","acceptance-criteria":"acceptance_criteria",ac:"acceptance_criteria",definition_of_ready:"definition_of_ready","definition-of-ready":"definition_of_ready",order:"order",rank:"order",goal:"goal",objective:"objective",value:"value",impact:"impact",outcome:"outcome",why_now:"why_now","why-now":"why_now",assignee:"assignee",parent:"parent",reviewer:"reviewer",risk:"risk",confidence:"confidence",sprint:"sprint",release:"release",blocked_by:"blocked_by","blocked-by":"blocked_by",blocked_reason:"blocked_reason","blocked-reason":"blocked_reason",unblock_note:"unblock_note","unblock-note":"unblock_note",reporter:"reporter",severity:"severity",environment:"environment",repro_steps:"repro_steps","repro-steps":"repro_steps",resolution:"resolution",expected_result:"expected_result","expected-result":"expected_result",actual_result:"actual_result","actual-result":"actual_result",affected_version:"affected_version","affected-version":"affected_version",fixed_version:"fixed_version","fixed-version":"fixed_version",component:"component",regression:"regression",customer_impact:"customer_impact","customer-impact":"customer_impact",type_options:"type_options","type-options":"type_options",tags:"tags"},sanitizeUpdateOptionsForSummary=options=>{const summary={};for(const[key,value]of Object.entries(options))NON_MUTATION_UPDATE_OPTION_KEYS.has(key)||value!==void 0&&(summary[key]=value);return summary},hasAnyUpdateMutationInput=options=>Object.keys(sanitizeUpdateOptionsForSummary(options)).length>0,trimPreviewValue=value=>typeof value=="string"?value.trim():value,normalizeIntegerPreviewValue=value=>{const trimmed=String(value).trim(),parsed=Number(trimmed);return Number.isInteger(parsed)?parsed:trimmed},normalizeNumericPreviewValue=value=>{const trimmed=String(value).trim(),parsed=Number(trimmed);return Number.isFinite(parsed)?parsed:trimmed},normalizeRegressionPreviewValue=value=>{const normalized=String(value).trim().toLowerCase();return new Map([["true",!0],["1",!0],["false",!1],["0",!1]]).get(normalized)??trimPreviewValue(value)},PREVIEW_VALUE_NORMALIZERS={priority:normalizeIntegerPreviewValue,estimatedMinutes:normalizeNumericPreviewValue,order:normalizeNumericPreviewValue,rank:normalizeNumericPreviewValue,regression:normalizeRegressionPreviewValue},toComparablePreviewValue=(optionKey,value)=>{if(value!==void 0)return(PREVIEW_VALUE_NORMALIZERS[optionKey]??trimPreviewValue)(value)},normalizeUnsetField=rawField=>{const normalized=rawField.trim().toLowerCase().replaceAll("-","_");return UNSET_FIELD_ALIASES[normalized]??normalized},areValuesEqual=(left,right)=>stableValueEquals(left,right),normalizeCollectionBeforeValue=(field,value)=>value!==void 0?value:field==="type_options"?{}:[],collectionValueCount=(field,value)=>Array.isArray(value)?value.length:field==="type_options"&&value&&typeof value=="object"?Object.keys(value).length:0,resolveCollectionMutationOperation=params=>params.replace?"replace":params.clear?"clear_or_reset":params.removeCount>0?"merge_remove":"append",readOptionalUpdateValue=(update,key)=>key===void 0?void 0:update[key],updateArrayValueCount=value=>Array.isArray(value)?value.length:0,buildCollectionMutationPlan=(definition,row,update)=>{const addValues=update[definition.addKey],removeValues=readOptionalUpdateValue(update,definition.removeKey),addCount=updateArrayValueCount(addValues),removeCount=updateArrayValueCount(removeValues),clear=update[definition.clearKey]===!0,replace=readOptionalUpdateValue(update,definition.replaceKey)===!0;if(![clear,replace,addCount>0,removeCount>0].includes(!0))return;const before=normalizeCollectionBeforeValue(definition.field,row[definition.field]);return{field:definition.field,before,after:{operation:resolveCollectionMutationOperation({replace,clear,removeCount}),clear,replace,add_count:addCount,remove_count:removeCount,before_count:collectionValueCount(definition.field,before)}}},buildCollectionMutationPlans=(row,update)=>{const changes=[];for(const definition of COLLECTION_MUTATION_PLAN_DEFINITIONS){const plan=buildCollectionMutationPlan(definition,row,update);plan!==void 0&&changes.push(plan)}return changes},normalizeExistingTags=value=>Array.isArray(value)?value.filter(tag=>typeof tag=="string"):[],buildTagMutationPlan=(row,update)=>{if(![update.tags!==void 0,updateArrayValueCount(update.addTags)>0,updateArrayValueCount(update.removeTags)>0].includes(!0))return;const existing=normalizeExistingTags(row.tags),baseTags=update.tags===void 0?existing:parseTags(update.tags),withAdditions=mergeAdditiveTags(baseTags,update.addTags),after=applyTagRemovals(withAdditions,update.removeTags).slice().sort((a,b)=>a.localeCompare(b)),before=existing.slice().sort((a,b)=>a.localeCompare(b));if(!areValuesEqual(before,after))return{field:"tags",before:existing,after}},buildAcceptanceCriteriaMutationPlan=(row,update)=>{const before=row.acceptance_criteria,mutation=applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(before),update.addAc,update.removeAc);if(mutation.unmatchedRemovals.length>0)throw new PmCliError(`Acceptance criteria removal did not match: ${mutation.unmatchedRemovals.join(", ")}`,EXIT_CODE.NOT_FOUND,{code:"acceptance_criteria_remove_unmatched",reason:"exact_match_not_found",field:"acceptance_criteria",unmatched:mutation.unmatchedRemovals});const after=mutation.criteria.join("; ");if(!areValuesEqual(typeof before=="string"?before:"",after))return{field:"acceptance_criteria",before,after}},appendScalarMutationPlans=(changes,row,update)=>{for(const[optionKey,itemKey]of Object.entries(UPDATE_OPTION_TO_ITEM_KEY)){const candidate=update[optionKey];if(candidate===void 0)continue;const before=row[itemKey],after=toComparablePreviewValue(optionKey,candidate);areValuesEqual(before,after)||changes.push({field:itemKey,before,after})}},appendRuntimeFieldMutationPlans=(changes,row,update,runtimeFieldRegistry)=>{const runtimeFieldUpdates=collectRuntimeUpdateFieldValues(update,runtimeFieldRegistry,["update_many"]);for(const[field,after]of Object.entries(runtimeFieldUpdates)){const before=row[field];areValuesEqual(before,after)||changes.push({field,before,after})}},appendUnsetMutationPlans=(changes,row,unset)=>{for(const rawUnsetField of unset??[]){const field=normalizeUnsetField(rawUnsetField),before=row[field];before!==void 0&&changes.push({field,before,after:null})}},buildPlannedItemDiff=(item,runtimeFieldRegistry,update={})=>{const row=toItemRecord(item),changes=[],tagPlan=buildTagMutationPlan(row,update);if(tagPlan&&changes.push(tagPlan),appendScalarMutationPlans(changes,row,update),updateArrayValueCount(update.addAc)>0||updateArrayValueCount(update.removeAc)>0){const acceptanceCriteriaChange=buildAcceptanceCriteriaMutationPlan(row,update);acceptanceCriteriaChange!==void 0&&changes.push(acceptanceCriteriaChange)}return changes.push(...buildCollectionMutationPlans(row,update)),appendRuntimeFieldMutationPlans(changes,row,update,runtimeFieldRegistry),appendUnsetMutationPlans(changes,row,update.unset),{id:item.id,changes}},normalizeStatusFilter=(value,statusRegistry)=>parseStatusFilterCsv(value,statusRegistry,{strict:!0,flagLabel:"--filter-status"}),rejectBlankIdsFilter=list=>{if(list?.ids!=null&&String(list.ids).trim().length===0)throw new PmCliError("--ids requires at least one non-empty item ID",EXIT_CODE.USAGE)},PLANNED_UPDATE_VALIDATORS=[({update})=>{update.priority!==void 0&&resolvePriority(update.priority)},({update,settings,pmRoot})=>{if(update.type===void 0)return;const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());if(!resolveTypeName(update.type,typeRegistry))throw new PmCliError(buildInvalidTypeError(update.type,typeRegistry.types,resolveItemTypesFilePath(pmRoot,settings.schema)),EXIT_CODE.USAGE)},({update,statusRegistry})=>{if(update.status!==void 0&&!normalizeStatusInput(update.status,statusRegistry)){const allowedStatuses=statusRegistry.definitions.map(definition=>definition.id);throw new PmCliError(`Invalid status value "${update.status}". Allowed: ${allowedStatuses.join(", ")}`,EXIT_CODE.USAGE,{code:"invalid_argument_value",field:"status",value:update.status,allowed:allowedStatuses})}},({update})=>{update.deadline!==void 0&&resolveIsoOrRelative(update.deadline,new Date,"deadline")},({update})=>{update.estimatedMinutes!==void 0&&parseOptionalNonNegativeInteger(update.estimatedMinutes,"estimated-minutes")}],assertPlannedUpdateValuesValid=(update,settings,statusRegistry,pmRoot)=>{const context={update,settings,statusRegistry,pmRoot};for(const validate of PLANNED_UPDATE_VALIDATORS)validate(context)},runUpdateManyRollback=async params=>{const checkpoint=await loadMutationCheckpoint(params.pmRoot,UPDATE_MANY_CHECKPOINT_SUBDIR,params.rollbackId,UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION),restoreMessage=params.options.update?.message??`Rollback update-many checkpoint ${checkpoint.id}`,rollback=await rollbackMutationCheckpoint(params.pmRoot,checkpoint,{author:params.options.update?.author,message:restoreMessage,force:params.options.update?.force}),skipped=rollback.rows.filter(row=>row.status==="skipped").length;return{...derivePmBulkMutationEffect({applied:rollback.restored_ids.length,skipped,failed:rollback.failed_count,unmatched:0}),mode:"rollback",matched_count:checkpoint.items.length,dry_run:!1,rollback_checkpoint_id:checkpoint.id,checkpoint:{id:checkpoint.id,created_at:checkpoint.created_at,path:checkpoint.path,rollback_command:`pm update-many --rollback ${checkpoint.id}`},restored_count:rollback.restored_ids.length,skipped_count:skipped,failed_count:rollback.failed_count,rows:rollback.rows,ids:rollback.restored_ids}},writeUpdateManyCheckpoint=async params=>{const checkpointPayload={schema_version:UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION,rollback_strategy:"guarded_inverse",id:params.checkpointId,created_at:params.nowValue,author:resolveAuthor(params.options.update?.author,"unknown"),status_filter:params.statusFilter??null,list_filters:params.filters,update_options:params.updateSummary,items:params.checkpointItems},checkpointPath=await writeMutationCheckpoint(params.pmRoot,UPDATE_MANY_CHECKPOINT_SUBDIR,params.checkpointId,checkpointPayload);return{id:params.checkpointId,created_at:params.nowValue,path:checkpointPath,rollback_command:`pm update-many --rollback ${params.checkpointId}`}},collectUnmatchedRequestedIds=(rawIds,existingItems)=>{if(rawIds==null)return;const requested=[...new Set(String(rawIds).split(",").map(entry=>entry.trim()).filter(entry=>entry.length>0))],existing=new Set(existingItems.map(item=>item.id));return requested.filter(id=>!existing.has(id))},buildUnmatchedIdFields=plan=>plan.unmatchedIds===void 0?{}:{unmatched_ids:plan.unmatchedIds,unmatched_count:plan.unmatchedIds.length},loadUpdateManyRuntimeContext=async global2=>{const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);return{pmRoot,settings,statusRegistry:resolveRuntimeStatusRegistry(settings.schema),runtimeFieldRegistry:resolveRuntimeFieldRegistry(settings.schema)}},runRequestedUpdateManyRollback=params=>{if(params.options.dryRun===!0)throw new PmCliError("--dry-run cannot be combined with --rollback",EXIT_CODE.USAGE);if(hasListFilters(params.options.list,params.options.status))throw new PmCliError("Rollback mode does not accept filter options",EXIT_CODE.USAGE);if(Object.keys(params.updateSummary).length>0)throw new PmCliError("Rollback mode does not accept update mutation flags",EXIT_CODE.USAGE);return runUpdateManyRollback({pmRoot:params.runtime.pmRoot,rollbackId:params.rollbackId,options:params.options,global:params.global})},buildUpdateManyPlan=async params=>{normalizeStatusFilter(params.options.status,params.runtime.statusRegistry);const listed=await runList(void 0,{...params.options.list,status:params.options.status,compact:void 0,brief:void 0,fields:void 0,includeBody:!0,full:!0},params.global),planned=listed.items.map(item=>{const diff=buildPlannedItemDiff(item,params.runtime.runtimeFieldRegistry,params.options.update);return params.dependencyWarnings.length===0?diff:{...diff,warnings:[...params.dependencyWarnings]}}),existenceItems=params.options.list?.ids==null?[]:(await runList(void 0,{ids:params.options.list.ids,noTruncate:!0,full:!0},params.global)).items;return{listed,planned,actionable:planned.filter(row=>row.changes.length>0),updateSummary:params.updateSummary,unmatchedIds:collectUnmatchedRequestedIds(params.options.list?.ids,existenceItems)}},buildUpdateManyDryRunResult=plan=>({outcome:"effect",exit_code:EXIT_CODE.SUCCESS,mode:"dry_run",matched_count:plan.listed.items.length,dry_run:!0,filters:plan.listed.filters,planned_update_options:plan.updateSummary,item_plans:plan.planned,ids:[],...buildUnmatchedIdFields(plan)}),buildUpdateManyNoopResult=plan=>({...derivePmBulkMutationEffect({applied:0,skipped:plan.listed.items.length,failed:0,unmatched:plan.unmatchedIds?.length??0}),mode:"apply",matched_count:plan.listed.items.length,dry_run:!1,filters:plan.listed.filters,planned_update_options:plan.updateSummary,updated_count:0,skipped_count:plan.listed.items.length,failed_count:0,rows:plan.planned.map(row=>({id:row.id,status:"skipped"})),ids:[],...buildUnmatchedIdFields(plan)}),applyUpdateManyRows=async params=>{const rows=[],updatedIds=[],updateMessage=params.options.update.message??`update-many apply ${params.checkpointId}`,actionableById=new Set(params.plans.filter(row=>row.changes.length>0).map(row=>row.id));for(const item of params.items){if(!actionableById.has(item.id)){rows.push({id:item.id,status:"skipped"});continue}try{const rowUpdateOptions=preserveMutationStdinTokenLiterals(transferMutationStdinTokenPolicy(params.options.update,{...params.options.update,message:updateMessage,runtimeFieldCommands:["update_many"]})),result=await withCheckpointMutation({pmRoot:params.pmRoot,itemId:item.id,checkpointId:params.checkpointId},()=>runUpdate(item.id,rowUpdateOptions,params.global));rows.push({id:item.id,status:"updated",changed_fields:result.changed_fields,warnings:result.warnings}),updatedIds.push(item.id)}catch(error){rows.push({id:item.id,status:"failed",error:toErrorMessage(error)})}}return{rows,updatedIds}},applyUpdateManyPlan=async params=>{if(params.plan.actionable.length===0)return buildUpdateManyNoopResult(params.plan);const nowValue=nowIso(),checkpointId=createCheckpointId(UPDATE_MANY_CHECKPOINT_SUBDIR,nowValue),actionableById=new Set(params.plan.actionable.map(row=>row.id)),checkpointItems=params.plan.listed.items.filter(item=>actionableById.has(item.id)).map(item=>({id:item.id,target_updated_at:item.updated_at})),checkpointInfo=params.options.checkpoint===!1?void 0:await writeUpdateManyCheckpoint({pmRoot:params.runtime.pmRoot,checkpointId,nowValue,options:params.options,statusFilter:params.options.status,filters:params.plan.listed.filters,updateSummary:params.plan.updateSummary,checkpointItems}),applied=await applyUpdateManyRows({pmRoot:params.runtime.pmRoot,items:params.plan.listed.items,plans:params.plan.planned,options:params.options,global:params.global,checkpointId}),countStatus=status=>applied.rows.filter(row=>row.status===status).length,updatedCount=countStatus("updated"),skippedCount=countStatus("skipped"),failedCount=countStatus("failed");return{...derivePmBulkMutationEffect({applied:updatedCount,skipped:skippedCount,failed:failedCount,unmatched:params.plan.unmatchedIds?.length??0}),mode:"apply",matched_count:params.plan.listed.items.length,dry_run:!1,filters:params.plan.listed.filters,planned_update_options:params.plan.updateSummary,...checkpointInfo?{checkpoint:checkpointInfo}:{},updated_count:updatedCount,skipped_count:skippedCount,failed_count:failedCount,rows:applied.rows,ids:applied.updatedIds,...buildUnmatchedIdFields(params.plan)}},runUpdateMany=async(options,global2)=>{const rollbackId=resolveCheckpointRollbackId(options.rollback),runtime=await loadUpdateManyRuntimeContext(global2);rollbackId===void 0&&(options={...options,update:preserveMutationStdinTokenLiterals(await resolveUpdateTransportOptions(options.update))});const updateSummary=sanitizeUpdateOptionsForSummary(options.update);if(rejectBlankIdsFilter(options.list),rollbackId!==void 0)return runRequestedUpdateManyRollback({runtime,rollbackId,options,global:global2,updateSummary});if(!hasAnyUpdateMutationInput(options.update)&&options.dryRun!==!0)throw new PmCliError(`No update-many mutation flags provided. Add at least one mutation flag (for example: ${UPDATE_MANY_MUTATION_FLAG_GUIDANCE}), or pass --dry-run for a filter-only preview.`,EXIT_CODE.USAGE);assertPlannedUpdateValuesValid(options.update,runtime.settings,runtime.statusRegistry,runtime.pmRoot),assertUpdateMutationOptionCombinations(options.update);const dependencyWarnings=await assertDependencyTargetsResolvable({pmRoot:runtime.pmRoot,dependencies:parseDependencyAdditions(options.update.dep,runtime.settings.id_prefix,nowIso(),resolveAuthor(options.update.author,runtime.settings.author_default)).additions,idPrefix:runtime.settings.id_prefix,itemFormat:runtime.settings.item_format,typeToFolder:resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()).type_to_folder,allowUnresolved:options.update.allowUnresolvedDeps}),plan=await buildUpdateManyPlan({options,global:global2,runtime,updateSummary,dependencyWarnings});return await assertDependencyTargetsResolvable({pmRoot:runtime.pmRoot,dependencies:parseDependencyAdditions(options.update.dep,runtime.settings.id_prefix,nowIso(),resolveAuthor(options.update.author,runtime.settings.author_default)).additions,idPrefix:runtime.settings.id_prefix,itemFormat:runtime.settings.item_format,typeToFolder:resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()).type_to_folder,allowUnresolved:options.update.allowUnresolvedDeps,holders:plan.listed.items.map(item=>({id:item.id,createdAt:item.created_at})),schema:runtime.settings.schema}),options.dryRun===!0?buildUpdateManyDryRunResult(plan):applyUpdateManyPlan({runtime,options,global:global2,plan})},_testOnlyUpdateManyCommand={assertPlannedUpdateValuesValid,buildCollectionMutationPlans,buildPlannedItemDiff,buildTagMutationPlan,collectionValueCount,hasAnyUpdateMutationInput,hasListFilters,normalizeStatusFilter,normalizeCollectionBeforeValue,normalizeExistingTags,normalizeUnsetField,rejectBlankIdsFilter,sanitizeUpdateOptionsForSummary,toComparablePreviewValue};export{_testOnlyUpdateManyCommand,runUpdateMany};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="86acbe76-ed18-52be-b561-4819c648e88e")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{withCheckpointMutation}from"../../core/checkpoint/mutation-context.js";import{resolveCheckpointRollbackId}from"../../core/checkpoint/mutation-checkpoint.js";import{rollbackMutationCheckpoint}from"./checkpoint-rollback.js";import{createCheckpointId,loadMutationCheckpoint,writeMutationCheckpoint,toItemRecord,applyAcceptanceCriteriaMutations,applyTagRemovals,mergeAdditiveTags,parseOptionalNonNegativeInteger,parseTags,splitAcceptanceCriteria,resolvePriority,normalizeStatusInput,resolveItemTypeRegistry,resolveTypeName,collectRuntimeUpdateFieldValues,buildInvalidTypeError,resolveItemTypesFilePath,resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,PmCliError,toErrorMessage,stableValueEquals,nowIso,preserveMutationStdinTokenLiterals,transferMutationStdinTokenPolicy,resolveIsoOrRelative,getActiveExtensionRegistrations,collectRegisteredItemFieldNames,resolvePmRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{assertDependencyTargetsResolvable}from"../dependency-flag-validation.js";import{parseStatusFilterCsv}from"../../core/item/status-filter.js";import{hasListFilters}from"../query/list-filter-shared.js";import{runList}from"../query/list.js";import{assertUpdateMutationOptionCombinations,assertUpdateUnsetFieldsSupported,parseDependencyAdditions,resolveUpdateTransportOptions,runUpdate}from"./update.js";import{derivePmBulkMutationEffect}from"../cli-contracts/command-exit-contracts.js";const UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION=2,UPDATE_MANY_CHECKPOINT_SUBDIR="update-many",NON_MUTATION_UPDATE_OPTION_KEYS=new Set(["author","message","force","ownershipMetadataBypass","ownershipDependencyBypass","allowUnresolvedDeps"]),UPDATE_MANY_MUTATION_FLAG_GUIDANCE=["--status","--priority","--type","--tags","--description","--body","--deadline","--estimate","--assignee","--dep","--dep-remove","--comment","--note","--learning","--file","--test","--doc","--replace-deps","--replace-tests","--replace-files","--replace-docs","--unset","--clear-*"].join(", "),UPDATE_OPTION_TO_ITEM_KEY={title:"title",description:"description",body:"body",status:"status",closeReason:"close_reason",priority:"priority",type:"type",deadline:"deadline",estimatedMinutes:"estimated_minutes",acceptanceCriteria:"acceptance_criteria",definitionOfReady:"definition_of_ready",order:"order",goal:"goal",objective:"objective",value:"value",impact:"impact",outcome:"outcome",whyNow:"why_now",assignee:"assignee",parent:"parent",reviewer:"reviewer",risk:"risk",confidence:"confidence",sprint:"sprint",release:"release",blockedBy:"blocked_by",blockedReason:"blocked_reason",unblockNote:"unblock_note",reporter:"reporter",severity:"severity",environment:"environment",reproSteps:"repro_steps",resolution:"resolution",expectedResult:"expected_result",actualResult:"actual_result",affectedVersion:"affected_version",fixedVersion:"fixed_version",component:"component",regression:"regression",customerImpact:"customer_impact"},COLLECTION_MUTATION_PLAN_DEFINITIONS=[{field:"dependencies",addKey:"dep",removeKey:"depRemove",clearKey:"clearDeps",replaceKey:"replaceDeps"},{field:"comments",addKey:"comment",clearKey:"clearComments"},{field:"notes",addKey:"note",clearKey:"clearNotes"},{field:"learnings",addKey:"learning",clearKey:"clearLearnings"},{field:"files",addKey:"file",clearKey:"clearFiles",replaceKey:"replaceFiles"},{field:"tests",addKey:"test",clearKey:"clearTests",replaceKey:"replaceTests"},{field:"docs",addKey:"doc",clearKey:"clearDocs",replaceKey:"replaceDocs"},{field:"reminders",addKey:"reminder",clearKey:"clearReminders"},{field:"events",addKey:"event",clearKey:"clearEvents"},{field:"type_options",addKey:"typeOption",clearKey:"clearTypeOptions"}],sanitizeUpdateOptionsForSummary=options=>{const summary={};for(const[key,value]of Object.entries(options))NON_MUTATION_UPDATE_OPTION_KEYS.has(key)||value!==void 0&&(summary[key]=value);return summary},hasAnyUpdateMutationInput=options=>Object.keys(sanitizeUpdateOptionsForSummary(options)).length>0,trimPreviewValue=value=>typeof value=="string"?value.trim():value,normalizeIntegerPreviewValue=value=>{const trimmed=String(value).trim(),parsed=Number(trimmed);return Number.isInteger(parsed)?parsed:trimmed},normalizeNumericPreviewValue=value=>{const trimmed=String(value).trim(),parsed=Number(trimmed);return Number.isFinite(parsed)?parsed:trimmed},normalizeRegressionPreviewValue=value=>{const normalized=String(value).trim().toLowerCase();return new Map([["true",!0],["1",!0],["false",!1],["0",!1]]).get(normalized)??trimPreviewValue(value)},PREVIEW_VALUE_NORMALIZERS={priority:normalizeIntegerPreviewValue,estimatedMinutes:normalizeNumericPreviewValue,order:normalizeNumericPreviewValue,rank:normalizeNumericPreviewValue,regression:normalizeRegressionPreviewValue},toComparablePreviewValue=(optionKey,value)=>{if(value!==void 0)return(PREVIEW_VALUE_NORMALIZERS[optionKey]??trimPreviewValue)(value)},areValuesEqual=(left,right)=>stableValueEquals(left,right),normalizeCollectionBeforeValue=(field,value)=>value!==void 0?value:field==="type_options"?{}:[],collectionValueCount=(field,value)=>Array.isArray(value)?value.length:field==="type_options"&&value&&typeof value=="object"?Object.keys(value).length:0,resolveCollectionMutationOperation=params=>params.replace?"replace":params.clear?"clear_or_reset":params.removeCount>0?"merge_remove":"append",readOptionalUpdateValue=(update,key)=>key===void 0?void 0:update[key],updateArrayValueCount=value=>Array.isArray(value)?value.length:0,buildCollectionMutationPlan=(definition,row,update)=>{const addValues=update[definition.addKey],removeValues=readOptionalUpdateValue(update,definition.removeKey),addCount=updateArrayValueCount(addValues),removeCount=updateArrayValueCount(removeValues),clear=update[definition.clearKey]===!0,replace=readOptionalUpdateValue(update,definition.replaceKey)===!0;if(![clear,replace,addCount>0,removeCount>0].includes(!0))return;const before=normalizeCollectionBeforeValue(definition.field,row[definition.field]);return{field:definition.field,before,after:{operation:resolveCollectionMutationOperation({replace,clear,removeCount}),clear,replace,add_count:addCount,remove_count:removeCount,before_count:collectionValueCount(definition.field,before)}}},buildCollectionMutationPlans=(row,update)=>{const changes=[];for(const definition of COLLECTION_MUTATION_PLAN_DEFINITIONS){const plan=buildCollectionMutationPlan(definition,row,update);plan!==void 0&&changes.push(plan)}return changes},normalizeExistingTags=value=>Array.isArray(value)?value.filter(tag=>typeof tag=="string"):[],buildTagMutationPlan=(row,update)=>{if(![update.tags!==void 0,updateArrayValueCount(update.addTags)>0,updateArrayValueCount(update.removeTags)>0].includes(!0))return;const existing=normalizeExistingTags(row.tags),baseTags=update.tags===void 0?existing:parseTags(update.tags),withAdditions=mergeAdditiveTags(baseTags,update.addTags),after=applyTagRemovals(withAdditions,update.removeTags).slice().sort((a,b)=>a.localeCompare(b)),before=existing.slice().sort((a,b)=>a.localeCompare(b));if(!areValuesEqual(before,after))return{field:"tags",before:existing,after}},buildAcceptanceCriteriaMutationPlan=(row,update)=>{const before=row.acceptance_criteria,mutation=applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(before),update.addAc,update.removeAc);if(mutation.unmatchedRemovals.length>0)throw new PmCliError(`Acceptance criteria removal did not match: ${mutation.unmatchedRemovals.join(", ")}`,EXIT_CODE.NOT_FOUND,{code:"acceptance_criteria_remove_unmatched",reason:"exact_match_not_found",field:"acceptance_criteria",unmatched:mutation.unmatchedRemovals});const after=mutation.criteria.join("; ");if(!areValuesEqual(typeof before=="string"?before:"",after))return{field:"acceptance_criteria",before,after}},appendScalarMutationPlans=(changes,row,update)=>{for(const[optionKey,itemKey]of Object.entries(UPDATE_OPTION_TO_ITEM_KEY)){const candidate=update[optionKey];if(candidate===void 0)continue;const before=row[itemKey],after=toComparablePreviewValue(optionKey,candidate);areValuesEqual(before,after)||changes.push({field:itemKey,before,after})}},appendRuntimeFieldMutationPlans=(changes,row,update,runtimeFieldRegistry)=>{const runtimeFieldUpdates=collectRuntimeUpdateFieldValues(update,runtimeFieldRegistry,["update_many"]);for(const[field,after]of Object.entries(runtimeFieldUpdates)){const before=row[field];areValuesEqual(before,after)||changes.push({field,before,after})}},appendUnsetMutationPlans=(changes,row,unset,runtimeFieldRegistry)=>{if(unset===void 0||unset.length===0)return;const fields=assertUpdateUnsetFieldsSupported(unset,runtimeFieldRegistry,collectRegisteredItemFieldNames(getActiveExtensionRegistrations()),["update_many"]);for(const field of fields){const before=row[field];before!==void 0&&changes.push({field,before,after:null})}},buildPlannedItemDiff=(item,runtimeFieldRegistry,update={})=>{const row=toItemRecord(item),changes=[],tagPlan=buildTagMutationPlan(row,update);if(tagPlan&&changes.push(tagPlan),appendScalarMutationPlans(changes,row,update),updateArrayValueCount(update.addAc)>0||updateArrayValueCount(update.removeAc)>0){const acceptanceCriteriaChange=buildAcceptanceCriteriaMutationPlan(row,update);acceptanceCriteriaChange!==void 0&&changes.push(acceptanceCriteriaChange)}return changes.push(...buildCollectionMutationPlans(row,update)),appendRuntimeFieldMutationPlans(changes,row,update,runtimeFieldRegistry),appendUnsetMutationPlans(changes,row,update.unset,runtimeFieldRegistry),{id:item.id,changes}},normalizeStatusFilter=(value,statusRegistry)=>parseStatusFilterCsv(value,statusRegistry,{strict:!0,flagLabel:"--filter-status"}),rejectBlankIdsFilter=list=>{if(list?.ids!=null&&String(list.ids).trim().length===0)throw new PmCliError("--ids requires at least one non-empty item ID",EXIT_CODE.USAGE)},PLANNED_UPDATE_VALIDATORS=[({update})=>{update.priority!==void 0&&resolvePriority(update.priority)},({update,settings})=>{update.unset!==void 0&&update.unset.length>0&&assertUpdateUnsetFieldsSupported(update.unset,resolveRuntimeFieldRegistry(settings.schema),collectRegisteredItemFieldNames(getActiveExtensionRegistrations()),["update_many"])},({update,settings,pmRoot})=>{if(update.type===void 0)return;const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());if(!resolveTypeName(update.type,typeRegistry))throw new PmCliError(buildInvalidTypeError(update.type,typeRegistry.types,resolveItemTypesFilePath(pmRoot,settings.schema)),EXIT_CODE.USAGE)},({update,statusRegistry})=>{if(update.status!==void 0&&!normalizeStatusInput(update.status,statusRegistry)){const allowedStatuses=statusRegistry.definitions.map(definition=>definition.id);throw new PmCliError(`Invalid status value "${update.status}". Allowed: ${allowedStatuses.join(", ")}`,EXIT_CODE.USAGE,{code:"invalid_argument_value",field:"status",value:update.status,allowed:allowedStatuses})}},({update})=>{update.deadline!==void 0&&resolveIsoOrRelative(update.deadline,new Date,"deadline")},({update})=>{update.estimatedMinutes!==void 0&&parseOptionalNonNegativeInteger(update.estimatedMinutes,"estimated-minutes")}],assertPlannedUpdateValuesValid=(update,settings,statusRegistry,pmRoot)=>{const context={update,settings,statusRegistry,pmRoot};for(const validate of PLANNED_UPDATE_VALIDATORS)validate(context)},runUpdateManyRollback=async params=>{const checkpoint=await loadMutationCheckpoint(params.pmRoot,UPDATE_MANY_CHECKPOINT_SUBDIR,params.rollbackId,UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION),restoreMessage=params.options.update?.message??`Rollback update-many checkpoint ${checkpoint.id}`,rollback=await rollbackMutationCheckpoint(params.pmRoot,checkpoint,{author:params.options.update?.author,message:restoreMessage,force:params.options.update?.force}),skipped=rollback.rows.filter(row=>row.status==="skipped").length;return{...derivePmBulkMutationEffect({applied:rollback.restored_ids.length,skipped,failed:rollback.failed_count,unmatched:0}),mode:"rollback",matched_count:checkpoint.items.length,dry_run:!1,rollback_checkpoint_id:checkpoint.id,checkpoint:{id:checkpoint.id,created_at:checkpoint.created_at,path:checkpoint.path,rollback_command:`pm update-many --rollback ${checkpoint.id}`},restored_count:rollback.restored_ids.length,skipped_count:skipped,failed_count:rollback.failed_count,rows:rollback.rows,ids:rollback.restored_ids}},writeUpdateManyCheckpoint=async params=>{const checkpointPayload={schema_version:UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION,rollback_strategy:"guarded_inverse",id:params.checkpointId,created_at:params.nowValue,author:resolveAuthor(params.options.update?.author,"unknown"),status_filter:params.statusFilter??null,list_filters:params.filters,update_options:params.updateSummary,items:params.checkpointItems},checkpointPath=await writeMutationCheckpoint(params.pmRoot,UPDATE_MANY_CHECKPOINT_SUBDIR,params.checkpointId,checkpointPayload);return{id:params.checkpointId,created_at:params.nowValue,path:checkpointPath,rollback_command:`pm update-many --rollback ${params.checkpointId}`}},collectUnmatchedRequestedIds=(rawIds,existingItems)=>{if(rawIds==null)return;const requested=[...new Set(String(rawIds).split(",").map(entry=>entry.trim()).filter(entry=>entry.length>0))],existing=new Set(existingItems.map(item=>item.id));return requested.filter(id=>!existing.has(id))},buildUnmatchedIdFields=plan=>plan.unmatchedIds===void 0?{}:{unmatched_ids:plan.unmatchedIds,unmatched_count:plan.unmatchedIds.length},loadUpdateManyRuntimeContext=async global2=>{const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);return{pmRoot,settings,statusRegistry:resolveRuntimeStatusRegistry(settings.schema),runtimeFieldRegistry:resolveRuntimeFieldRegistry(settings.schema)}},runRequestedUpdateManyRollback=params=>{if(params.options.dryRun===!0)throw new PmCliError("--dry-run cannot be combined with --rollback",EXIT_CODE.USAGE);if(hasListFilters(params.options.list,params.options.status))throw new PmCliError("Rollback mode does not accept filter options",EXIT_CODE.USAGE);if(Object.keys(params.updateSummary).length>0)throw new PmCliError("Rollback mode does not accept update mutation flags",EXIT_CODE.USAGE);return runUpdateManyRollback({pmRoot:params.runtime.pmRoot,rollbackId:params.rollbackId,options:params.options,global:params.global})},buildUpdateManyPlan=async params=>{normalizeStatusFilter(params.options.status,params.runtime.statusRegistry);const listed=await runList(void 0,{...params.options.list,status:params.options.status,compact:void 0,brief:void 0,fields:void 0,includeBody:!0,full:!0},params.global),planned=listed.items.map(item=>{const diff=buildPlannedItemDiff(item,params.runtime.runtimeFieldRegistry,params.options.update);return params.dependencyWarnings.length===0?diff:{...diff,warnings:[...params.dependencyWarnings]}}),existenceItems=params.options.list?.ids==null?[]:(await runList(void 0,{ids:params.options.list.ids,noTruncate:!0,full:!0},params.global)).items;return{listed,planned,actionable:planned.filter(row=>row.changes.length>0),updateSummary:params.updateSummary,unmatchedIds:collectUnmatchedRequestedIds(params.options.list?.ids,existenceItems)}},buildUpdateManyDryRunResult=plan=>({outcome:"effect",exit_code:EXIT_CODE.SUCCESS,mode:"dry_run",matched_count:plan.listed.items.length,dry_run:!0,filters:plan.listed.filters,planned_update_options:plan.updateSummary,item_plans:plan.planned,ids:[],...buildUnmatchedIdFields(plan)}),buildUpdateManyNoopResult=plan=>({...derivePmBulkMutationEffect({applied:0,skipped:plan.listed.items.length,failed:0,unmatched:plan.unmatchedIds?.length??0}),mode:"apply",matched_count:plan.listed.items.length,dry_run:!1,filters:plan.listed.filters,planned_update_options:plan.updateSummary,updated_count:0,skipped_count:plan.listed.items.length,failed_count:0,rows:plan.planned.map(row=>({id:row.id,status:"skipped"})),ids:[],...buildUnmatchedIdFields(plan)}),applyUpdateManyRows=async params=>{const rows=[],updatedIds=[],updateMessage=params.options.update.message??`update-many apply ${params.checkpointId}`,actionableById=new Set(params.plans.filter(row=>row.changes.length>0).map(row=>row.id));for(const item of params.items){if(!actionableById.has(item.id)){rows.push({id:item.id,status:"skipped"});continue}try{const rowUpdateOptions=preserveMutationStdinTokenLiterals(transferMutationStdinTokenPolicy(params.options.update,{...params.options.update,message:updateMessage,runtimeFieldCommands:["update_many"]})),result=await withCheckpointMutation({pmRoot:params.pmRoot,itemId:item.id,checkpointId:params.checkpointId},()=>runUpdate(item.id,rowUpdateOptions,params.global));rows.push({id:item.id,status:"updated",changed_fields:result.changed_fields,warnings:result.warnings}),updatedIds.push(item.id)}catch(error){rows.push({id:item.id,status:"failed",error:toErrorMessage(error)})}}return{rows,updatedIds}},applyUpdateManyPlan=async params=>{if(params.plan.actionable.length===0)return buildUpdateManyNoopResult(params.plan);const nowValue=nowIso(),checkpointId=createCheckpointId(UPDATE_MANY_CHECKPOINT_SUBDIR,nowValue),actionableById=new Set(params.plan.actionable.map(row=>row.id)),checkpointItems=params.plan.listed.items.filter(item=>actionableById.has(item.id)).map(item=>({id:item.id,target_updated_at:item.updated_at})),checkpointInfo=params.options.checkpoint===!1?void 0:await writeUpdateManyCheckpoint({pmRoot:params.runtime.pmRoot,checkpointId,nowValue,options:params.options,statusFilter:params.options.status,filters:params.plan.listed.filters,updateSummary:params.plan.updateSummary,checkpointItems}),applied=await applyUpdateManyRows({pmRoot:params.runtime.pmRoot,items:params.plan.listed.items,plans:params.plan.planned,options:params.options,global:params.global,checkpointId}),countStatus=status=>applied.rows.filter(row=>row.status===status).length,updatedCount=countStatus("updated"),skippedCount=countStatus("skipped"),failedCount=countStatus("failed");return{...derivePmBulkMutationEffect({applied:updatedCount,skipped:skippedCount,failed:failedCount,unmatched:params.plan.unmatchedIds?.length??0}),mode:"apply",matched_count:params.plan.listed.items.length,dry_run:!1,filters:params.plan.listed.filters,planned_update_options:params.plan.updateSummary,...checkpointInfo?{checkpoint:checkpointInfo}:{},updated_count:updatedCount,skipped_count:skippedCount,failed_count:failedCount,rows:applied.rows,ids:applied.updatedIds,...buildUnmatchedIdFields(params.plan)}},runUpdateMany=async(options,global2)=>{const rollbackId=resolveCheckpointRollbackId(options.rollback),runtime=await loadUpdateManyRuntimeContext(global2);rollbackId===void 0&&(options={...options,update:preserveMutationStdinTokenLiterals(await resolveUpdateTransportOptions(options.update))});const updateSummary=sanitizeUpdateOptionsForSummary(options.update);if(rejectBlankIdsFilter(options.list),rollbackId!==void 0)return runRequestedUpdateManyRollback({runtime,rollbackId,options,global:global2,updateSummary});if(!hasAnyUpdateMutationInput(options.update)&&options.dryRun!==!0)throw new PmCliError(`No update-many mutation flags provided. Add at least one mutation flag (for example: ${UPDATE_MANY_MUTATION_FLAG_GUIDANCE}), or pass --dry-run for a filter-only preview.`,EXIT_CODE.USAGE);assertPlannedUpdateValuesValid(options.update,runtime.settings,runtime.statusRegistry,runtime.pmRoot),assertUpdateMutationOptionCombinations(options.update);const dependencyWarnings=await assertDependencyTargetsResolvable({pmRoot:runtime.pmRoot,dependencies:parseDependencyAdditions(options.update.dep,runtime.settings.id_prefix,nowIso(),resolveAuthor(options.update.author,runtime.settings.author_default)).additions,idPrefix:runtime.settings.id_prefix,itemFormat:runtime.settings.item_format,typeToFolder:resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()).type_to_folder,allowUnresolved:options.update.allowUnresolvedDeps}),plan=await buildUpdateManyPlan({options,global:global2,runtime,updateSummary,dependencyWarnings});return await assertDependencyTargetsResolvable({pmRoot:runtime.pmRoot,dependencies:parseDependencyAdditions(options.update.dep,runtime.settings.id_prefix,nowIso(),resolveAuthor(options.update.author,runtime.settings.author_default)).additions,idPrefix:runtime.settings.id_prefix,itemFormat:runtime.settings.item_format,typeToFolder:resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()).type_to_folder,allowUnresolved:options.update.allowUnresolvedDeps,holders:plan.listed.items.map(item=>({id:item.id,createdAt:item.created_at})),schema:runtime.settings.schema}),options.dryRun===!0?buildUpdateManyDryRunResult(plan):applyUpdateManyPlan({runtime,options,global:global2,plan})},_testOnlyUpdateManyCommand={assertPlannedUpdateValuesValid,buildCollectionMutationPlans,buildPlannedItemDiff,buildTagMutationPlan,collectionValueCount,hasAnyUpdateMutationInput,hasListFilters,normalizeStatusFilter,normalizeCollectionBeforeValue,normalizeExistingTags,rejectBlankIdsFilter,sanitizeUpdateOptionsForSummary,toComparablePreviewValue};export{_testOnlyUpdateManyCommand,runUpdateMany};
2
2
  //# sourceMappingURL=update-many.js.map
@@ -94,7 +94,14 @@ export interface ReopenUpdateResult extends UpdateResult {
94
94
  lifecycle_transition:ReopenUpdateReceipt;
95
95
  }
96
96
  declare function normalizeLegacyNoneUpdateOptions(options:UpdateCommandOptions):UpdateCommandOptions;
97
- declare function parseUpdateUnsetTargets(raw:string[] | undefined,runtimeFieldRegistry?:RuntimeFieldRegistry,extensionFieldNames?:readonly string[]):{
97
+ /**
98
+ * Refuse unsupported or empty `--unset` field names before a bulk plan can
99
+ * skip items silently, returning the stored metadata keys they resolve to so
100
+ * planning checks the same fields validation accepted.
101
+ */
102
+ export declare function assertUpdateUnsetFieldsSupported(raw:readonly string[],runtimeFieldRegistry:RuntimeFieldRegistry,extensionFieldNames:readonly string[],commands?:UpdateCommandOptions["runtimeFieldCommands"]):string[];
103
+ /** Resolve `--unset` tokens; runtime fields resolve under the invoking command scope (`update` or `update_many`). */
104
+ declare function parseUpdateUnsetTargets(raw:string[] | undefined,runtimeFieldRegistry?:RuntimeFieldRegistry,extensionFieldNames?:readonly string[],commands?:UpdateCommandOptions["runtimeFieldCommands"]):{
98
105
  metadataKeys:Set<string>;
99
106
  optionKeys:Set<string>;
100
107
  };
@@ -152,6 +159,27 @@ nowIso:string;
152
159
  author:string;
153
160
  pmRoot:string;
154
161
  }
162
+ /** Inputs shared by the close-status routing of an update and its repeated-terminal-state check. */
163
+ export interface CloseRouteContext {
164
+ /** Normalized update options of the invocation. */
165
+ options:UpdateCommandOptions;
166
+ /** Which update fields the invocation set, keyed by option name. */
167
+ fieldFlags:Record<string,boolean>;
168
+ /** Runtime status registry that names the configured close status. */
169
+ statusRegistry:RuntimeStatusRegistry;
170
+ /** Workflow transition warnings collected before routing. */
171
+ workflowTransitionWarnings:readonly string[];
172
+ /** Global CLI options forwarded to nested commands. */
173
+ global:GlobalOptions;
174
+ /** Target item id. */
175
+ id:string;
176
+ /** Resolved tracker root. */
177
+ pmRoot:string;
178
+ /** Tracker settings in effect. */
179
+ settings:Awaited<ReturnType<typeof readSettings>>;
180
+ /** Item type registry used to locate the item document. */
181
+ typeRegistry:ReturnType<typeof resolveItemTypeRegistry>;
182
+ }
155
183
  /** Resolve update stdin tokens once while preserving transport-marked literals. */
156
184
  export declare function resolveUpdateTransportOptions(options:UpdateCommandOptions):Promise<UpdateCommandOptions>;
157
185
  /** Validate mutually exclusive and required update mutation option combinations. */