@unbrained/pm-cli 2026.9.7 → 2026.9.9

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 (746) hide show
  1. package/.agents/skills/pm-developer/SKILL.md +12 -4
  2. package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +19 -10
  3. package/.agents/skills/pm-extensions/SKILL.md +6 -0
  4. package/.agents/skills/pm-sdk/SKILL.md +11 -2
  5. package/.agents/skills/pm-user/SKILL.md +7 -2
  6. package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
  7. package/.claude-plugin/marketplace.json +2 -2
  8. package/CHANGELOG.md +231 -182
  9. package/dist/cli/after-command-context-usage.js +1 -48
  10. package/dist/cli/argv-utils.js +1 -40
  11. package/dist/cli/bootstrap-args.js +1 -9
  12. package/dist/cli/bundle-integrity.js +2 -110
  13. package/dist/cli/commander-usage.js +11 -771
  14. package/dist/cli/commands/activity.js +1 -9
  15. package/dist/cli/commands/aggregate.js +1 -5
  16. package/dist/cli/commands/append.js +1 -5
  17. package/dist/cli/commands/claim.js +1 -5
  18. package/dist/cli/commands/close-many.js +1 -5
  19. package/dist/cli/commands/close.js +1 -9
  20. package/dist/cli/commands/comments.js +1 -5
  21. package/dist/cli/commands/config.js +1 -9
  22. package/dist/cli/commands/context.js +1 -9
  23. package/dist/cli/commands/contracts.js +1 -5
  24. package/dist/cli/commands/copy.js +1 -9
  25. package/dist/cli/commands/create.js +1 -9
  26. package/dist/cli/commands/delete.js +1 -9
  27. package/dist/cli/commands/deps.js +1 -9
  28. package/dist/cli/commands/docs.js +1 -9
  29. package/dist/cli/commands/duplicates.js +1 -9
  30. package/dist/cli/commands/eval.js +1 -9
  31. package/dist/cli/commands/extension/describe.js +1 -5
  32. package/dist/cli/commands/extension/scaffold.js +1 -5
  33. package/dist/cli/commands/extension/shared.js +1 -5
  34. package/dist/cli/commands/extension.js +1 -9
  35. package/dist/cli/commands/files.js +1 -9
  36. package/dist/cli/commands/focus.js +1 -9
  37. package/dist/cli/commands/gc.js +1 -9
  38. package/dist/cli/commands/get.js +1 -9
  39. package/dist/cli/commands/graph.js +1 -10
  40. package/dist/cli/commands/health.js +1 -9
  41. package/dist/cli/commands/history-compact.js +1 -10
  42. package/dist/cli/commands/history-redact.js +1 -11
  43. package/dist/cli/commands/history-repair.js +1 -10
  44. package/dist/cli/commands/history.js +1 -5
  45. package/dist/cli/commands/index.js +1 -58
  46. package/dist/cli/commands/init-agent-guidance.js +1 -9
  47. package/dist/cli/commands/init.js +1 -9
  48. package/dist/cli/commands/learnings.js +1 -5
  49. package/dist/cli/commands/lifecycle-transitions.js +1 -5
  50. package/dist/cli/commands/list.js +1 -9
  51. package/dist/cli/commands/merge.js +1 -11
  52. package/dist/cli/commands/next.js +1 -9
  53. package/dist/cli/commands/notes.js +1 -5
  54. package/dist/cli/commands/plan.js +1 -9
  55. package/dist/cli/commands/profile.js +1 -9
  56. package/dist/cli/commands/restore.js +1 -9
  57. package/dist/cli/commands/scheduling-shortcuts.js +1 -9
  58. package/dist/cli/commands/schema.js +1 -10
  59. package/dist/cli/commands/search.js +1 -9
  60. package/dist/cli/commands/stats.js +1 -9
  61. package/dist/cli/commands/telemetry.js +1 -9
  62. package/dist/cli/commands/test-all.js +1 -9
  63. package/dist/cli/commands/test-runs.js +1 -9
  64. package/dist/cli/commands/test.js +1 -9
  65. package/dist/cli/commands/update-many.js +1 -5
  66. package/dist/cli/commands/update.js +1 -9
  67. package/dist/cli/commands/upgrade.js +1 -5
  68. package/dist/cli/commands/validate.js +1 -15
  69. package/dist/cli/context-intent-invocation.js +1 -20
  70. package/dist/cli/description-stdin.js +1 -17
  71. package/dist/cli/error-guidance.js +1 -1353
  72. package/dist/cli/extension-command-help.js +5 -636
  73. package/dist/cli/extension-command-options.js +1 -427
  74. package/dist/cli/extension-recovery.js +1 -126
  75. package/dist/cli/help-content.js +2 -1001
  76. package/dist/cli/help-json-payload.js +4 -570
  77. package/dist/cli/main.d.ts +4 -0
  78. package/dist/cli/main.js +5 -2573
  79. package/dist/cli/migration-gates.js +1 -289
  80. package/dist/cli/public.js +1 -20
  81. package/dist/cli/register-annotations.js +1 -270
  82. package/dist/cli/register-assurance.js +1 -62
  83. package/dist/cli/register-files-lookup.js +1 -56
  84. package/dist/cli/register-history-activity.d.ts +8 -0
  85. package/dist/cli/register-history-activity.js +2 -0
  86. package/dist/cli/register-history-author.js +1 -38
  87. package/dist/cli/register-history-maintenance.d.ts +9 -0
  88. package/dist/cli/register-history-maintenance.js +2 -0
  89. package/dist/cli/register-list-query.js +10 -943
  90. package/dist/cli/register-mutation-options.js +1 -9
  91. package/dist/cli/register-mutation.d.ts +0 -5
  92. package/dist/cli/register-mutation.js +19 -1893
  93. package/dist/cli/register-operations.js +1 -920
  94. package/dist/cli/register-setup.js +1 -716
  95. package/dist/cli/register-structured-mutation.js +1 -196
  96. package/dist/cli/registration-helpers.js +1 -5
  97. package/dist/cli/runtime-compatibility-boundary.js +4 -42
  98. package/dist/cli/schema-registration-helpers.js +1 -73
  99. package/dist/cli/search-refresh.js +1 -13
  100. package/dist/cli/stats-analytics-json.js +1 -68
  101. package/dist/cli/telemetry-flush.js +1 -10
  102. package/dist/cli-bundle/bundle-manifest.json +164 -156
  103. package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-3IPRM75M.js} +3 -3
  104. package/dist/cli-bundle/chunks/chunk-4VL5P22L.js +2 -0
  105. package/dist/cli-bundle/chunks/chunk-AAFBV3U3.js +29 -0
  106. package/dist/cli-bundle/chunks/chunk-D3YVILJJ.js +20 -0
  107. package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
  108. package/dist/cli-bundle/chunks/chunk-ECBLPN7B.js +3 -0
  109. package/dist/cli-bundle/chunks/chunk-J6ERHBV2.js +235 -0
  110. package/dist/cli-bundle/chunks/chunk-JUNJ5EKI.js +2 -0
  111. package/dist/cli-bundle/chunks/chunk-L5RCDKQ2.js +2 -0
  112. package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
  113. package/dist/cli-bundle/chunks/chunk-OHNLSGGV.js +79 -0
  114. package/dist/cli-bundle/chunks/chunk-WQKMSFBV.js +5 -0
  115. package/dist/cli-bundle/chunks/{chunk-BAX2BYUW.js → chunk-XZ6T7YPP.js} +256 -150
  116. package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-Z3XVXUVF.js} +4 -4
  117. package/dist/cli-bundle/chunks/register-list-query-UIHRCS6D.js +11 -0
  118. package/dist/cli-bundle/chunks/register-mutation-WHWMGRVX.js +20 -0
  119. package/dist/cli-bundle/chunks/register-operations-64YZYTC5.js +2 -0
  120. package/dist/cli-bundle/chunks/register-setup-PERI45EM.js +2 -0
  121. package/dist/cli-bundle/focused-chunks/chunk-2W4XIYOB.js +2 -0
  122. package/dist/cli-bundle/focused-chunks/chunk-2WSBXIGF.js +12 -0
  123. package/dist/cli-bundle/focused-chunks/chunk-5FHTCOHS.js +3 -0
  124. package/dist/cli-bundle/focused-chunks/chunk-7N6DOREF.js +26 -0
  125. package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-7PC4R5QB.js} +2 -2
  126. package/dist/cli-bundle/focused-chunks/chunk-BUCJUZVG.js +6 -0
  127. package/dist/cli-bundle/focused-chunks/chunk-FE3BABLJ.js +2 -0
  128. package/dist/cli-bundle/focused-chunks/chunk-IWITF53W.js +2 -0
  129. package/dist/cli-bundle/focused-chunks/chunk-OQUGRHKV.js +10 -0
  130. package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-PNKIANFZ.js} +2 -2
  131. package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-QQQ4SAUO.js} +3 -3
  132. package/dist/cli-bundle/focused-chunks/chunk-TTYXF5YD.js +177 -0
  133. package/dist/cli-bundle/focused-chunks/chunk-XNR3DM6J.js +2 -0
  134. package/dist/cli-bundle/focused-chunks/chunk-XSS3APUF.js +9 -0
  135. package/dist/cli-bundle/focused-chunks/chunk-YCDQ2N23.js +8 -0
  136. package/dist/cli-bundle/focused-chunks/chunk-YJUXGS57.js +20 -0
  137. package/dist/cli-bundle/focused-chunks/chunk-ZTCE4UO6.js +58 -0
  138. package/dist/cli-bundle/main.js +20 -20
  139. package/dist/cli-bundle/sdk-authoring.js +1 -1
  140. package/dist/cli-bundle/sdk-contracts.js +2 -2
  141. package/dist/cli-bundle/sdk-core.js +37 -37
  142. package/dist/cli-bundle/sdk-governance.js +1 -1
  143. package/dist/cli-bundle/sdk-graph.js +1 -1
  144. package/dist/cli-bundle/sdk-merge.js +42 -42
  145. package/dist/cli-bundle/sdk-query.js +1 -1
  146. package/dist/cli-bundle/sdk-runtime.js +1 -1
  147. package/dist/cli-bundle/sdk-testing.js +1 -1
  148. package/dist/cli-bundle/sdk.js +11 -11
  149. package/dist/cli.js +1 -104
  150. package/dist/core/checkpoint/checkpoint-gc.js +1 -169
  151. package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
  152. package/dist/core/config/nested-settings.js +1 -534
  153. package/dist/core/config/positional-value.js +1 -109
  154. package/dist/core/diagnostics/remediation.js +1 -506
  155. package/dist/core/extensions/activation-summary-markdown.js +2 -145
  156. package/dist/core/extensions/activation-summary.js +1 -92
  157. package/dist/core/extensions/activation-transaction.js +1 -46
  158. package/dist/core/extensions/capability-usage.js +1 -173
  159. package/dist/core/extensions/command-hook-context.js +1 -13
  160. package/dist/core/extensions/command-metadata-contract.js +1 -22
  161. package/dist/core/extensions/command-visibility-tier.js +1 -29
  162. package/dist/core/extensions/contribution-inventory.js +1 -173
  163. package/dist/core/extensions/exporter-output-contract.js +1 -66
  164. package/dist/core/extensions/extension-candidate.js +1 -18
  165. package/dist/core/extensions/extension-capability-aliases.js +1 -158
  166. package/dist/core/extensions/extension-hook-runtime.js +1 -699
  167. package/dist/core/extensions/extension-policy.js +1 -599
  168. package/dist/core/extensions/extension-registries.js +1 -62
  169. package/dist/core/extensions/extension-runtime-helpers.js +1 -33
  170. package/dist/core/extensions/extension-types.js +1 -102
  171. package/dist/core/extensions/flag-definition-validation.js +1 -52
  172. package/dist/core/extensions/flag-value-types.js +1 -64
  173. package/dist/core/extensions/index.js +1 -526
  174. package/dist/core/extensions/item-field-types.js +1 -39
  175. package/dist/core/extensions/item-fields.js +1 -261
  176. package/dist/core/extensions/loader.js +1 -2223
  177. package/dist/core/extensions/manifest-schema.js +1 -69
  178. package/dist/core/extensions/module-graph-snapshot.js +1 -33
  179. package/dist/core/extensions/preflight-ownership.js +1 -41
  180. package/dist/core/extensions/registration-validation.js +1 -82
  181. package/dist/core/extensions/registration-values.js +1 -209
  182. package/dist/core/extensions/reserved-host-flags.js +1 -36
  183. package/dist/core/extensions/runtime-registrations.js +1 -67
  184. package/dist/core/extensions/service-ownership.js +1 -19
  185. package/dist/core/extensions/version-compat.js +1 -216
  186. package/dist/core/fs/fs-utils.js +2 -158
  187. package/dist/core/fs/host-environment-errors.js +1 -141
  188. package/dist/core/fs/index.js +1 -9
  189. package/dist/core/fs/path-utils.js +1 -17
  190. package/dist/core/governance/content-fields.js +1 -160
  191. package/dist/core/governance/issue-codes.js +1 -151
  192. package/dist/core/governance/metadata-coverage.js +1 -358
  193. package/dist/core/history/drift-cache.js +3 -72
  194. package/dist/core/history/drift-scan.js +1 -342
  195. package/dist/core/history/event-classification.js +1 -109
  196. package/dist/core/history/event-index.js +8 -784
  197. package/dist/core/history/history-compact-bulk.js +1 -104
  198. package/dist/core/history/history-diff.js +1 -158
  199. package/dist/core/history/history-rewrite.d.ts +6 -1
  200. package/dist/core/history/history-rewrite.js +1 -107
  201. package/dist/core/history/history-storage-stats.js +1 -102
  202. package/dist/core/history/history-stream-policy.js +1 -62
  203. package/dist/core/history/history.js +2 -617
  204. package/dist/core/history/identity.js +1 -30
  205. package/dist/core/history/index.js +1 -9
  206. package/dist/core/history/projection.js +1 -196
  207. package/dist/core/history/read.d.ts +9 -0
  208. package/dist/core/history/read.js +1 -57
  209. package/dist/core/history/replay.js +2 -439
  210. package/dist/core/history/version-address.js +1 -32
  211. package/dist/core/history/workspace-history.js +2 -433
  212. package/dist/core/io/body-file.js +1 -62
  213. package/dist/core/io/bulk-ids-input.js +1 -112
  214. package/dist/core/item/actionability.js +1 -327
  215. package/dist/core/item/dependency-reference.js +1 -20
  216. package/dist/core/item/id.js +1 -112
  217. package/dist/core/item/index.js +1 -12
  218. package/dist/core/item/item-format-version.js +1 -78
  219. package/dist/core/item/item-format.js +5 -1473
  220. package/dist/core/item/item-record.js +1 -23
  221. package/dist/core/item/item-type-definition.js +1 -133
  222. package/dist/core/item/parent-reference-policy.js +1 -57
  223. package/dist/core/item/parse.js +2 -603
  224. package/dist/core/item/plan-lifecycle.js +1 -19
  225. package/dist/core/item/priority.js +1 -61
  226. package/dist/core/item/sprint-release-format.js +1 -38
  227. package/dist/core/item/status-filter.js +1 -115
  228. package/dist/core/item/status.js +1 -43
  229. package/dist/core/item/toon-decode.js +1 -29
  230. package/dist/core/item/type-registry.js +1 -715
  231. package/dist/core/item/type-synonyms.js +1 -38
  232. package/dist/core/lock/index.js +1 -9
  233. package/dist/core/lock/lock-gc.js +1 -240
  234. package/dist/core/lock/lock.js +3 -590
  235. package/dist/core/output/mutation-projection.js +1 -217
  236. package/dist/core/output/output-control.js +1 -25
  237. package/dist/core/output/output.js +11 -494
  238. package/dist/core/output/query-summary.js +1 -58
  239. package/dist/core/output/tabular.js +1 -77
  240. package/dist/core/packages/manifest.js +1 -244
  241. package/dist/core/packages/root.js +1 -84
  242. package/dist/core/policy/workflow-policy-schema.d.ts +312 -0
  243. package/dist/core/policy/workflow-policy-schema.js +2 -0
  244. package/dist/core/policy/workflow-policy-store.d.ts +24 -0
  245. package/dist/core/policy/workflow-policy-store.js +2 -0
  246. package/dist/core/policy/workflow-policy.d.ts +139 -0
  247. package/dist/core/policy/workflow-policy.js +2 -0
  248. package/dist/core/profile/profile-describe.js +1 -83
  249. package/dist/core/profile/profile-lint.js +1 -415
  250. package/dist/core/profile/profile-plan.js +0 -0
  251. package/dist/core/profile/profile-presets.js +1 -370
  252. package/dist/core/reproducibility/context.js +1 -82
  253. package/dist/core/schema/fields-file.js +2 -288
  254. package/dist/core/schema/item-types-file.js +2 -296
  255. package/dist/core/schema/runtime-field-filters.js +1 -49
  256. package/dist/core/schema/runtime-field-values.js +1 -313
  257. package/dist/core/schema/runtime-schema.js +2 -826
  258. package/dist/core/schema/status-defs-file.js +2 -227
  259. package/dist/core/schema/status-token.js +1 -31
  260. package/dist/core/schema/type-inference.js +1 -95
  261. package/dist/core/schema/type-presets.js +1 -87
  262. package/dist/core/schema/type-workflows.js +1 -104
  263. package/dist/core/search/background-refresh.js +2 -286
  264. package/dist/core/search/bm25.js +1 -146
  265. package/dist/core/search/cache.js +2 -534
  266. package/dist/core/search/corpus.js +1 -311
  267. package/dist/core/search/embedding-batches.js +1 -163
  268. package/dist/core/search/eval.js +1 -225
  269. package/dist/core/search/http-client.js +1 -75
  270. package/dist/core/search/providers.js +1 -242
  271. package/dist/core/search/relevance.js +1 -244
  272. package/dist/core/search/semantic-defaults.js +1 -199
  273. package/dist/core/search/staleness.js +1 -30
  274. package/dist/core/search/vector-stores.js +2 -664
  275. package/dist/core/search/vectorization-metadata.js +1 -81
  276. package/dist/core/sentry/helpers.js +1 -272
  277. package/dist/core/sentry/instrument.js +1 -387
  278. package/dist/core/session/session-state.js +1 -260
  279. package/dist/core/shared/agent-session-context.js +1 -133
  280. package/dist/core/shared/author.js +1 -1172
  281. package/dist/core/shared/command-types.js +1 -4
  282. package/dist/core/shared/conflict-markers.js +1 -31
  283. package/dist/core/shared/constants.js +1 -405
  284. package/dist/core/shared/errors.js +1 -20
  285. package/dist/core/shared/html-entity-decode.js +1 -131
  286. package/dist/core/shared/index.js +1 -12
  287. package/dist/core/shared/item-metadata-contract.js +1 -89
  288. package/dist/core/shared/lazy-module.js +1 -16
  289. package/dist/core/shared/levenshtein.js +1 -61
  290. package/dist/core/shared/memo.js +1 -19
  291. package/dist/core/shared/numeric-parsers.js +1 -20
  292. package/dist/core/shared/option-alias-visibility.js +1 -67
  293. package/dist/core/shared/primitives.js +1 -127
  294. package/dist/core/shared/serial-queue.js +1 -79
  295. package/dist/core/shared/serialization.js +1 -210
  296. package/dist/core/shared/split-comma-list.js +1 -30
  297. package/dist/core/shared/text-normalization.js +1 -38
  298. package/dist/core/shared/time.js +1 -306
  299. package/dist/core/store/index.js +1 -12
  300. package/dist/core/store/item-format-migration.js +1 -125
  301. package/dist/core/store/item-metadata-cache.js +1 -1116
  302. package/dist/core/store/item-metadata-query-index.js +9 -394
  303. package/dist/core/store/item-metadata-read-work.js +1 -43
  304. package/dist/core/store/item-store.js +1 -693
  305. package/dist/core/store/paths.d.ts +1 -1
  306. package/dist/core/store/paths.js +1 -214
  307. package/dist/core/store/settings-read-cache.js +1 -85
  308. package/dist/core/store/settings-validator.d.ts +1 -0
  309. package/dist/core/store/settings-validator.js +1 -421
  310. package/dist/core/store/settings.js +3 -1309
  311. package/dist/core/store/tracker-preflight.js +1 -141
  312. package/dist/core/telemetry/consent.js +5 -108
  313. package/dist/core/telemetry/observability.js +1 -246
  314. package/dist/core/telemetry/runtime.js +4 -1988
  315. package/dist/core/test/background-runs.js +4 -945
  316. package/dist/core/test/item-test-run-tracking.js +1 -63
  317. package/dist/core/test/run-selectors.js +1 -120
  318. package/dist/core/validate/estimate-defaults.js +1 -89
  319. package/dist/core/validate/fix-planning.js +1 -189
  320. package/dist/core/validate/linked-artifact-reference.js +1 -36
  321. package/dist/core/validate/missing-by-type.js +1 -34
  322. package/dist/core/validate/missing-link-owners.js +1 -95
  323. package/dist/core/validate/stale-file-classification.js +1 -82
  324. package/dist/mcp/http-server.js +5 -448
  325. package/dist/mcp/legacy-adapter.js +1 -77
  326. package/dist/mcp/runtime-capabilities.js +1 -200
  327. package/dist/mcp/server.js +4 -1233
  328. package/dist/mcp/tool-definitions.js +1 -804
  329. package/dist/sdk/actionability.js +1 -13
  330. package/dist/sdk/agent/closed-domain-contracts.js +1 -161
  331. package/dist/sdk/agent/command-recovery.js +1 -59
  332. package/dist/sdk/agent/command-suggestions.js +1 -66
  333. package/dist/sdk/agent/create-option-policy.js +1 -31
  334. package/dist/sdk/agent/identity-config.js +1 -106
  335. package/dist/sdk/agent/item-addressing.js +1 -207
  336. package/dist/sdk/agent/refusal-closure-census.js +1 -151
  337. package/dist/sdk/agent/refusal-closure.js +1 -133
  338. package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
  339. package/dist/sdk/agent/refusal-reachability.js +1 -593
  340. package/dist/sdk/agent/subcommand-recovery.js +1 -83
  341. package/dist/sdk/agent/task-transcript-contracts.js +1 -197
  342. package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
  343. package/dist/sdk/agent-capability-contracts.js +1 -428
  344. package/dist/sdk/agent-session-context.js +1 -9
  345. package/dist/sdk/annotations.js +1 -448
  346. package/dist/sdk/author-attribution.js +1 -468
  347. package/dist/sdk/authoring.js +1 -20
  348. package/dist/sdk/cli-bootstrap.js +1 -838
  349. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
  350. package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
  351. package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
  352. package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
  353. package/dist/sdk/cli-contracts/command-aliases.js +1 -107
  354. package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
  355. package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
  356. package/dist/sdk/cli-contracts/commander-types.js +1 -159
  357. package/dist/sdk/cli-contracts/completeness.js +1 -393
  358. package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
  359. package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
  360. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
  361. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
  362. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
  363. package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
  364. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
  365. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
  366. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
  367. package/dist/sdk/cli-contracts/string-lists.js +1 -16
  368. package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
  369. package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
  370. package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
  371. package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
  372. package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
  373. package/dist/sdk/cli-contracts.d.ts +1 -1
  374. package/dist/sdk/cli-contracts.js +1 -17
  375. package/dist/sdk/cli-program.js +1 -49
  376. package/dist/sdk/command-line.d.ts +2 -5
  377. package/dist/sdk/command-line.js +1 -78
  378. package/dist/sdk/comments.js +1 -133
  379. package/dist/sdk/compile-cache.js +1 -73
  380. package/dist/sdk/completion.js +174 -839
  381. package/dist/sdk/compose.js +1 -1090
  382. package/dist/sdk/config.js +1 -1204
  383. package/dist/sdk/context/recency.js +1 -33
  384. package/dist/sdk/context/semantic-session-attribution.js +1 -82
  385. package/dist/sdk/context/usage-egress.js +1 -29
  386. package/dist/sdk/context/usage-ledger.js +3 -185
  387. package/dist/sdk/context-intent-contracts.js +1 -709
  388. package/dist/sdk/context-intent-runtime.js +1 -115
  389. package/dist/sdk/context-packing.js +1 -218
  390. package/dist/sdk/context-relevance.js +1 -503
  391. package/dist/sdk/context-signal-store.js +2 -426
  392. package/dist/sdk/context-usage.js +1 -367
  393. package/dist/sdk/contracts.js +1 -23
  394. package/dist/sdk/core-governance.js +1 -14
  395. package/dist/sdk/core.js +1 -14
  396. package/dist/sdk/corpus-shape.js +1 -401
  397. package/dist/sdk/define.js +1 -220
  398. package/dist/sdk/dependencies.js +1 -718
  399. package/dist/sdk/dependency-flag-validation.js +1 -156
  400. package/dist/sdk/dependency-provenance.js +1 -135
  401. package/dist/sdk/docs.js +1 -14
  402. package/dist/sdk/duplicates.js +1 -40
  403. package/dist/sdk/environment/agent-environment.js +1 -466
  404. package/dist/sdk/environment/host-environment-errors.js +1 -8
  405. package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
  406. package/dist/sdk/environment/source-context.js +1 -28
  407. package/dist/sdk/environment/tracker-preflight.js +1 -9
  408. package/dist/sdk/error-code-catalog.js +1 -153
  409. package/dist/sdk/error-runtime.js +1 -58
  410. package/dist/sdk/errors.js +1 -58
  411. package/dist/sdk/eval.js +1 -190
  412. package/dist/sdk/extension/author-manifest.js +1 -92
  413. package/dist/sdk/extension/bundled-catalog.js +1 -332
  414. package/dist/sdk/extension/concurrency.js +1 -25
  415. package/dist/sdk/extension/copy-scope.d.ts +2 -0
  416. package/dist/sdk/extension/copy-scope.js +2 -0
  417. package/dist/sdk/extension/custom-field-collisions.js +1 -30
  418. package/dist/sdk/extension/describe.js +3 -189
  419. package/dist/sdk/extension/doctor.js +1 -606
  420. package/dist/sdk/extension/install-plan.d.ts +69 -0
  421. package/dist/sdk/extension/install-plan.js +2 -0
  422. package/dist/sdk/extension/install-receipts.d.ts +7 -0
  423. package/dist/sdk/extension/install-receipts.js +2 -0
  424. package/dist/sdk/extension/install-runtime.js +3 -313
  425. package/dist/sdk/extension/install-snapshot.js +1 -66
  426. package/dist/sdk/extension/install-sources.js +5 -1057
  427. package/dist/sdk/extension/managed-state.js +2 -252
  428. package/dist/sdk/extension/migrations.js +2 -174
  429. package/dist/sdk/extension/output-ownership.js +1 -25
  430. package/dist/sdk/extension/runtime-summary.js +1 -18
  431. package/dist/sdk/extension/scaffold.js +4 -2308
  432. package/dist/sdk/extension/shared.js +1 -147
  433. package/dist/sdk/extension/source-resolution.js +1 -65
  434. package/dist/sdk/extension/update-check.js +1 -67
  435. package/dist/sdk/extension-command-context.js +1 -44
  436. package/dist/sdk/extension-contracts.js +1 -73
  437. package/dist/sdk/extension.d.ts +7 -2
  438. package/dist/sdk/extension.js +1 -2196
  439. package/dist/sdk/files.js +1 -535
  440. package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
  441. package/dist/sdk/flag-invocation-contracts.js +1 -344
  442. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
  443. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
  444. package/dist/sdk/generated-error-code-catalog.js +1 -16
  445. package/dist/sdk/governance/assurance-action-contracts.js +1 -4
  446. package/dist/sdk/governance/assurance-action.js +1 -411
  447. package/dist/sdk/governance/assurance-limits.js +1 -10
  448. package/dist/sdk/governance/assurance-mutation-error.js +1 -81
  449. package/dist/sdk/governance/assurance-presets.js +1 -135
  450. package/dist/sdk/governance/assurance-runtime.js +1 -238
  451. package/dist/sdk/governance/assurance.js +4 -1182
  452. package/dist/sdk/governance/boundary-fixtures.js +1 -200
  453. package/dist/sdk/governance/coverage-assurance.js +1 -60
  454. package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
  455. package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
  456. package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
  457. package/dist/sdk/governance/defect-recurrence.js +1 -623
  458. package/dist/sdk/governance/extension-host-version.js +1 -115
  459. package/dist/sdk/governance/gc.js +1 -368
  460. package/dist/sdk/governance/health.js +1 -2367
  461. package/dist/sdk/governance/hierarchy-validation.js +1 -108
  462. package/dist/sdk/governance/linked-file-report.js +1 -71
  463. package/dist/sdk/governance/merge-receipt-history.js +1 -206
  464. package/dist/sdk/governance/provenance-health.js +1 -282
  465. package/dist/sdk/governance/reindex.js +4 -761
  466. package/dist/sdk/governance/stale-work.js +1 -82
  467. package/dist/sdk/governance/status-role-diagnostics.js +1 -35
  468. package/dist/sdk/governance/storage-integrity.js +1 -280
  469. package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
  470. package/dist/sdk/governance/upgrade.js +2 -327
  471. package/dist/sdk/governance/validate-history-drift.js +1 -81
  472. package/dist/sdk/governance/validate-item-reader.js +1 -17
  473. package/dist/sdk/governance/validate-normalization.js +1 -36
  474. package/dist/sdk/governance/validate.d.ts +3 -1
  475. package/dist/sdk/governance/validate.js +1 -2261
  476. package/dist/sdk/governance/workflow-completeness.d.ts +32 -0
  477. package/dist/sdk/governance/workflow-completeness.js +2 -0
  478. package/dist/sdk/governance/workflow-policy.d.ts +47 -0
  479. package/dist/sdk/governance/workflow-policy.js +4 -0
  480. package/dist/sdk/governance/workspace-position.js +1 -163
  481. package/dist/sdk/governance.d.ts +2 -0
  482. package/dist/sdk/governance.js +1 -31
  483. package/dist/sdk/graph/adapter.js +1 -181
  484. package/dist/sdk/graph/analytics.js +1 -474
  485. package/dist/sdk/graph/assembly.js +1 -377
  486. package/dist/sdk/graph/cache.js +1 -160
  487. package/dist/sdk/graph/centrality.js +1 -258
  488. package/dist/sdk/graph/conformance.js +1 -130
  489. package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
  490. package/dist/sdk/graph/deadline-scheduling.js +2 -0
  491. package/dist/sdk/graph/durable-cache.d.ts +1 -1
  492. package/dist/sdk/graph/durable-cache.js +1 -361
  493. package/dist/sdk/graph/governance-contracts.js +1 -34
  494. package/dist/sdk/graph/governance.d.ts +13 -1
  495. package/dist/sdk/graph/governance.js +1 -735
  496. package/dist/sdk/graph/hierarchy-integrity.js +1 -310
  497. package/dist/sdk/graph/index.d.ts +3 -2
  498. package/dist/sdk/graph/index.js +1 -26
  499. package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
  500. package/dist/sdk/graph/lifecycle-coverage.js +2 -0
  501. package/dist/sdk/graph/mutation-advisory.js +1 -176
  502. package/dist/sdk/graph/remediation.js +1 -197
  503. package/dist/sdk/graph/run.d.ts +15 -1
  504. package/dist/sdk/graph/run.js +1 -768
  505. package/dist/sdk/graph/scheduling.js +1 -124
  506. package/dist/sdk/graph/traversal.js +1 -284
  507. package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
  508. package/dist/sdk/graph.js +1 -15
  509. package/dist/sdk/guide-topics.js +1 -707
  510. package/dist/sdk/guide.js +1 -279
  511. package/dist/sdk/history/maintenance.d.ts +71 -0
  512. package/dist/sdk/history/maintenance.js +2 -0
  513. package/dist/sdk/history/salvage.js +2 -247
  514. package/dist/sdk/history/subject.d.ts +19 -0
  515. package/dist/sdk/history/subject.js +2 -0
  516. package/dist/sdk/history-analytics.js +1 -282
  517. package/dist/sdk/history-compact.js +1 -527
  518. package/dist/sdk/history-mcp.js +1 -68
  519. package/dist/sdk/history-provenance.js +1 -182
  520. package/dist/sdk/history-read.js +1 -96
  521. package/dist/sdk/history-redact.d.ts +1 -14
  522. package/dist/sdk/history-redact.js +1 -643
  523. package/dist/sdk/history-repair.d.ts +5 -0
  524. package/dist/sdk/history-repair.js +1 -657
  525. package/dist/sdk/improvement-ledger-validation.js +1 -62
  526. package/dist/sdk/improvement-ledger.js +2 -257
  527. package/dist/sdk/index.d.ts +4 -1
  528. package/dist/sdk/index.js +1 -183
  529. package/dist/sdk/init-agent-guidance.js +2 -496
  530. package/dist/sdk/init.js +2 -820
  531. package/dist/sdk/invocation-author.js +1 -39
  532. package/dist/sdk/item-children.js +1 -90
  533. package/dist/sdk/item-metadata-index.js +1 -15
  534. package/dist/sdk/item-schedule.js +1 -27
  535. package/dist/sdk/item-transaction.js +1 -396
  536. package/dist/sdk/learnings.js +1 -29
  537. package/dist/sdk/lifecycle/append.js +2 -53
  538. package/dist/sdk/lifecycle/claim.d.ts +2 -0
  539. package/dist/sdk/lifecycle/claim.js +1 -242
  540. package/dist/sdk/lifecycle/close-many.js +1 -438
  541. package/dist/sdk/lifecycle/close.js +1 -468
  542. package/dist/sdk/lifecycle/copy.js +1 -212
  543. package/dist/sdk/lifecycle/create.js +1 -1949
  544. package/dist/sdk/lifecycle/delete.js +1 -45
  545. package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
  546. package/dist/sdk/lifecycle/focus.js +1 -91
  547. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
  548. package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
  549. package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
  550. package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
  551. package/dist/sdk/lifecycle/mcp-actions.js +1 -51
  552. package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
  553. package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
  554. package/dist/sdk/lifecycle/plan.js +1 -1606
  555. package/dist/sdk/lifecycle/recurrence-parsers.d.ts +1 -1
  556. package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
  557. package/dist/sdk/lifecycle/reopen.js +1 -68
  558. package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
  559. package/dist/sdk/lifecycle/restore.d.ts +1 -0
  560. package/dist/sdk/lifecycle/restore.js +1 -330
  561. package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
  562. package/dist/sdk/lifecycle/update-many.js +1 -861
  563. package/dist/sdk/lifecycle/update.js +1 -2136
  564. package/dist/sdk/lifecycle-completion.js +1 -92
  565. package/dist/sdk/lifecycle-policy.js +1 -120
  566. package/dist/sdk/linked-artifacts.js +1 -530
  567. package/dist/sdk/mcp/apps.js +4 -133
  568. package/dist/sdk/mcp/authorization.js +1 -404
  569. package/dist/sdk/mcp/discovery.js +1 -494
  570. package/dist/sdk/mcp/interactions.js +1 -336
  571. package/dist/sdk/mcp/protocol.d.ts +7 -0
  572. package/dist/sdk/mcp/protocol.js +1 -184
  573. package/dist/sdk/mcp/skills.js +1 -389
  574. package/dist/sdk/mcp/subscriptions.js +1 -211
  575. package/dist/sdk/mcp/tasks.js +2 -430
  576. package/dist/sdk/mcp/transport.js +1 -260
  577. package/dist/sdk/merge/abandoned-receipts.js +1 -46
  578. package/dist/sdk/merge/driver.js +1 -212
  579. package/dist/sdk/merge/index.js +1 -16
  580. package/dist/sdk/merge/install.js +3 -561
  581. package/dist/sdk/merge/receipt-file-boundary.js +1 -46
  582. package/dist/sdk/merge/receipt-operation.js +1 -96
  583. package/dist/sdk/merge/receipt-schema.js +1 -397
  584. package/dist/sdk/merge/receipts.js +4 -525
  585. package/dist/sdk/merge/reconcile.js +1 -352
  586. package/dist/sdk/merge/three-way.js +3 -775
  587. package/dist/sdk/merge.js +1 -10
  588. package/dist/sdk/mutation-events.js +1 -292
  589. package/dist/sdk/mutation-guard.js +1 -216
  590. package/dist/sdk/notes.js +1 -139
  591. package/dist/sdk/output-contracts.js +1 -172
  592. package/dist/sdk/output-projection.js +1 -430
  593. package/dist/sdk/output-token-accounting.js +1 -140
  594. package/dist/sdk/output.js +1 -64
  595. package/dist/sdk/ownership-source.js +1 -21
  596. package/dist/sdk/package-import-adapters.js +1 -442
  597. package/dist/sdk/package-migrations.js +1 -20
  598. package/dist/sdk/package-runtime-options.js +1 -80
  599. package/dist/sdk/pagination.js +1 -162
  600. package/dist/sdk/profile.js +1 -454
  601. package/dist/sdk/provenance.js +1 -258
  602. package/dist/sdk/public-surface.json +1 -1
  603. package/dist/sdk/query/activity.js +1 -401
  604. package/dist/sdk/query/aggregate.d.ts +16 -0
  605. package/dist/sdk/query/aggregate.js +1 -390
  606. package/dist/sdk/query/calendar.js +1 -964
  607. package/dist/sdk/query/complete-list.js +1 -215
  608. package/dist/sdk/query/context.js +1 -1702
  609. package/dist/sdk/query/duplicate-candidates.js +1 -70
  610. package/dist/sdk/query/get.js +1 -450
  611. package/dist/sdk/query/history.js +1 -186
  612. package/dist/sdk/query/item-filter-options.js +1 -9
  613. package/dist/sdk/query/light-metadata.js +1 -18
  614. package/dist/sdk/query/list-filter-shared.js +1 -81
  615. package/dist/sdk/query/list.js +1 -1304
  616. package/dist/sdk/query/multi-value-filters.js +1 -78
  617. package/dist/sdk/query/next.js +1 -513
  618. package/dist/sdk/query/parsers.js +1 -44
  619. package/dist/sdk/query/projection-contracts.js +1 -184
  620. package/dist/sdk/query/search-contracts.d.ts +27 -0
  621. package/dist/sdk/query/search-contracts.js +1 -230
  622. package/dist/sdk/query/search-pagination.js +1 -35
  623. package/dist/sdk/query/search-rendering.js +1 -105
  624. package/dist/sdk/query/search.d.ts +6 -4
  625. package/dist/sdk/query/search.js +2 -1987
  626. package/dist/sdk/query.js +1 -35
  627. package/dist/sdk/read-output/continuation.js +1 -194
  628. package/dist/sdk/read-output-budget.js +1 -135
  629. package/dist/sdk/read-output-contracts.d.ts +1 -1
  630. package/dist/sdk/read-output-contracts.js +1 -1225
  631. package/dist/sdk/read-output-rows.js +1 -186
  632. package/dist/sdk/read-output-session.js +1 -208
  633. package/dist/sdk/relationship-analytics.js +1 -410
  634. package/dist/sdk/relationship-context.js +1 -284
  635. package/dist/sdk/relationship-history.js +4 -519
  636. package/dist/sdk/relationship-kinds/contract.js +1 -22
  637. package/dist/sdk/relationship-migration.js +1 -77
  638. package/dist/sdk/relationships.js +1 -579
  639. package/dist/sdk/reproducibility/process.js +1 -87
  640. package/dist/sdk/runtime-action-aliases.js +1 -59
  641. package/dist/sdk/runtime-extended-actions.js +1 -177
  642. package/dist/sdk/runtime-input.js +1 -614
  643. package/dist/sdk/runtime-primitives.js +1 -84
  644. package/dist/sdk/runtime-public-contracts.d.ts +2 -1
  645. package/dist/sdk/runtime-public-contracts.js +1 -4
  646. package/dist/sdk/runtime-stats-options.js +1 -38
  647. package/dist/sdk/runtime.d.ts +4 -0
  648. package/dist/sdk/runtime.js +1 -1928
  649. package/dist/sdk/scheduling-shortcuts.js +1 -63
  650. package/dist/sdk/schema-migration.js +3 -856
  651. package/dist/sdk/schema.d.ts +2 -1
  652. package/dist/sdk/schema.js +1 -1376
  653. package/dist/sdk/search-refresh-worker.js +1 -18
  654. package/dist/sdk/similarity-scoring.js +1 -53
  655. package/dist/sdk/similarity.js +1 -326
  656. package/dist/sdk/start-task-status.js +1 -14
  657. package/dist/sdk/stats.js +1 -270
  658. package/dist/sdk/structured-mutations.js +1 -580
  659. package/dist/sdk/telemetry-flush.js +1 -13
  660. package/dist/sdk/telemetry.js +1 -405
  661. package/dist/sdk/templates.js +2 -292
  662. package/dist/sdk/test/batch.js +2 -509
  663. package/dist/sdk/test/entry.js +1 -70
  664. package/dist/sdk/test/execution.js +6 -2211
  665. package/dist/sdk/test/linked-command-detection.js +1 -546
  666. package/dist/sdk/test/measurements.js +1 -91
  667. package/dist/sdk/test/parsers.js +1 -545
  668. package/dist/sdk/test/runs.js +1 -193
  669. package/dist/sdk/test/trust.js +2 -206
  670. package/dist/sdk/testing.js +4 -1391
  671. package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
  672. package/dist/sdk/traceability/source-traceability.js +1 -292
  673. package/dist/sdk/tracker-root-discovery.js +1 -9
  674. package/dist/sdk/workspace-contracts-cache.js +1 -28
  675. package/dist/sdk/workspace-contracts.js +1 -33
  676. package/dist/sdk/workspace-memory.js +2 -318
  677. package/dist/sdk/workspace-recipe.js +1 -71
  678. package/dist/sdk/workspace-snapshot.js +4 -613
  679. package/dist/sdk/workspace-transaction-gc.js +1 -149
  680. package/dist/sdk/workspace-transaction.js +2 -363
  681. package/dist/sdk/workspace.js +3 -127
  682. package/dist/types/index.js +1 -9
  683. package/dist/types.d.ts +4 -0
  684. package/dist/types.js +1 -245
  685. package/docs/AGENT_GUIDE.md +1 -1
  686. package/docs/COMMANDS.md +10 -0
  687. package/docs/CONFIGURATION.md +12 -1
  688. package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
  689. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
  690. package/docs/EXTENSIONS.md +1 -0
  691. package/docs/HISTORY_MAINTENANCE.md +125 -0
  692. package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
  693. package/docs/PACKAGE_EVIDENCE.md +92 -0
  694. package/docs/PLANNING_MEASUREMENTS.md +183 -0
  695. package/docs/README.md +4 -0
  696. package/docs/READ_OUTPUT_CONTRACTS.md +5 -0
  697. package/docs/SCRIPTING.md +21 -0
  698. package/docs/TESTING.md +33 -0
  699. package/docs/WORKFLOW_POLICIES.md +129 -0
  700. package/docs/generated/FLAG_LEXICON_BUDGETS.md +7 -7
  701. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -5
  702. package/marketplace.json +2 -2
  703. package/package.json +5 -5
  704. package/packages/pm-beads/package.json +1 -1
  705. package/packages/pm-calendar/package.json +1 -1
  706. package/packages/pm-command-kit/package.json +1 -1
  707. package/packages/pm-digital-twin/package.json +1 -1
  708. package/packages/pm-governance-audit/package.json +1 -1
  709. package/packages/pm-guide-shell/package.json +1 -1
  710. package/packages/pm-kanban/package.json +1 -1
  711. package/packages/pm-lifecycle-hooks/package.json +1 -1
  712. package/packages/pm-linked-test-adapters/package.json +1 -1
  713. package/packages/pm-search-advanced/package.json +1 -1
  714. package/packages/pm-templates/package.json +1 -1
  715. package/packages/pm-todos/package.json +1 -1
  716. package/packages/pm-vcs/package.json +1 -1
  717. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  718. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  719. package/scripts/finalize-build.mjs +45 -3
  720. package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
  721. package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
  722. package/dist/cli-bundle/chunks/chunk-JX4DH4WC.js +0 -3
  723. package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
  724. package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
  725. package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
  726. package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
  727. package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
  728. package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
  729. package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
  730. package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
  731. package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +0 -2
  732. package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
  733. package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
  734. package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
  735. package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
  736. package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
  737. package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
  738. package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
  739. package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
  740. package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
  741. package/dist/cli-bundle/focused-chunks/chunk-PEFABF7E.js +0 -26
  742. package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
  743. package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
  744. package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
  745. package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
  746. package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
@@ -1,2137 +1,2 @@
1
- /**
2
- * @module sdk/lifecycle/update
3
- *
4
- * Implements the pm update command surface and its agent-facing runtime behavior.
5
- */
6
-
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5a6614ac-62fd-5680-9eed-447bfb7a167f")}catch(e){}}();
8
- import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
- import { resolveMutationStdinTokenFields } from "../../core/item/parse.js";
10
- import { COMMON_MUTATION_COMMAND_OPTION_KEYS, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, normalizeItemId, toItemRecord, buildInvalidTypeError, assertParentReferenceIsNotSelf, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, applyAcceptanceCriteriaMutations, applyTagRemovals, assertNoUnknownCsvKeys, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, shouldResolveMutationStdinTokens, transferMutationStdinTokenPolicy, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, isTerminalStatus, collectRuntimeUpdateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, describeAllowedTransitions, evaluateTransition, resolveTypeWorkflows, EXIT_CODE, PmCliError, stableValueEquals, resolveIsoOrRelative, getActiveExtensionRegistrations, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, buildItemNotFoundError, listAllItemMetadataLight, locateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
11
- import { mutateItemWithHistoryContextResolver } from "../../core/store/item-store.js";
12
- import { runClose } from "./close.js";
13
- import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
14
- import { applyLegacyNoneCollectionNormalizers, createLegacyNoneCollectionNormalizers, assertNoLegacyNoneToken, assertNoLegacyNoneTokens, isLegacyNoneToken, } from "./legacy-none-tokens.js";
15
- import { ensureEnumValue as ensureEnum } from "./recurrence-parsers.js";
16
- import { parseEventEntries, parseReminderEntries, parseTypeOptionEntries, } from "./repeatable-metadata-parsers.js";
17
- import { assertDependencyEdgesAllowed, assertDependencyTargetsResolvable, assertValidBareDependencyFlagValue, } from "../dependency-flag-validation.js";
18
- import { normalizeDependencySeedId, normalizeItemReference, isExternalDependencyReference, normalizeDependencySourceKind, } from "../dependency-provenance.js";
19
- import { resolveCanonicalRelationshipKind } from "../relationships.js";
20
- import { collectNewOrderingCycleWarnings } from "../graph/mutation-advisory.js";
21
- import { assertHierarchyMutationAllowed } from "../graph/hierarchy-integrity.js";
22
- import { resolveWorkspaceRelationshipKindRegistry } from "../graph/assembly.js";
23
- import { acquireHierarchyMutationLock } from "./hierarchy-mutation-lock.js";
24
- import { DEPENDENCY_KIND_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES, } from "../../types/index.js";
25
- import { parseDocs, parseFiles, parseLogSeed, parseTests, requireStringOption, } from "./create.js";
26
- import { attachLinkedTestMutationProvenance } from "../test/trust.js";
27
- import { COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR, COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR, COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON, parseCommandUnsetTargets, resolveRuntimeUnsetFieldDefinition, } from "./shared-unset-fields.js";
28
- const UPDATE_UNSET_FIELD_DEFINITIONS = [
29
- ...COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON,
30
- {
31
- canonical: "close-reason",
32
- aliases: ["close_reason", "close-reason"],
33
- optionKey: "closeReason",
34
- metadataKey: "close_reason",
35
- },
36
- ...COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR,
37
- ...COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR,
38
- ];
39
- const UPDATE_UNSET_ALIAS_MAP = (() => {
40
- const map = new Map();
41
- for (const definition of UPDATE_UNSET_FIELD_DEFINITIONS) {
42
- for (const alias of definition.aliases) {
43
- map.set(alias, {
44
- optionKey: definition.optionKey,
45
- metadataKey: definition.metadataKey,
46
- });
47
- }
48
- }
49
- return map;
50
- })();
51
- const UPDATE_OPTION_KEY_TO_UNSET_CANONICAL = new Map(UPDATE_UNSET_FIELD_DEFINITIONS.map((definition) => [
52
- definition.optionKey,
53
- definition.canonical,
54
- ]));
55
- const UPDATE_UNSET_SUPPORTED_CANONICAL_FIELDS = UPDATE_UNSET_FIELD_DEFINITIONS.map((definition) => definition.canonical)
56
- .sort((left, right) => left.localeCompare(right))
57
- .join(", ");
58
- const OWNERSHIP_BYPASS_DISALLOWED_UNSET_ITEM_METADATA_KEYS = new Set([
59
- "close_reason",
60
- "assignee",
61
- "parent",
62
- "blocked_by",
63
- "blocked_reason",
64
- "unblock_note",
65
- "dependencies",
66
- "comments",
67
- "notes",
68
- "learnings",
69
- "files",
70
- "tests",
71
- "docs",
72
- "reminders",
73
- "events",
74
- ]);
75
- const UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS = createLegacyNoneCollectionNormalizers({
76
- depDisableFlagKey: "replaceDeps",
77
- fileDisableFlagKey: "replaceFiles",
78
- testDisableFlagKey: "replaceTests",
79
- docDisableFlagKey: "replaceDocs",
80
- });
81
- function normalizeLegacyNoneUpdateOptions(options) {
82
- const normalized = {
83
- ...options,
84
- unset: options.unset ? [...options.unset] : undefined,
85
- };
86
- /* c8 ignore start -- unset dedupe helper branch permutations are covered by legacy option compatibility suites. */
87
- const appendUnsetTarget = (value) => {
88
- const current = normalized.unset ? [...normalized.unset] : [];
89
- if (!current.includes(value)) {
90
- current.push(value);
91
- }
92
- normalized.unset = current;
93
- };
94
- /* c8 ignore stop */
95
- const scalarOptionKeys = new Set([
96
- ...UPDATE_OPTION_KEY_TO_UNSET_CANONICAL.keys(),
97
- "rank",
98
- ]);
99
- for (const optionKey of scalarOptionKeys) {
100
- const candidate = normalized[optionKey];
101
- if (typeof candidate !== "string" || !isLegacyNoneToken(candidate)) {
102
- continue;
103
- }
104
- /* c8 ignore start -- rank alias canonicalization is exercised in legacy-option compatibility tests. */
105
- const canonicalUnset = optionKey === "rank"
106
- ? "order"
107
- : (UPDATE_OPTION_KEY_TO_UNSET_CANONICAL.get(optionKey) ?? optionKey);
108
- appendUnsetTarget(canonicalUnset);
109
- normalized[optionKey] = undefined;
110
- /* c8 ignore stop */
111
- }
112
- return transferMutationStdinTokenPolicy(options, applyLegacyNoneCollectionNormalizers(normalized, UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS));
113
- }
114
- function parseUpdateUnsetTargets(raw, runtimeFieldRegistry, extensionFieldNames = []) {
115
- return parseCommandUnsetTargets({
116
- raw,
117
- supportedFields: UPDATE_UNSET_SUPPORTED_CANONICAL_FIELDS,
118
- resolveDefinition: (trimmed) => {
119
- const extensionFieldName = extensionFieldNames.find((fieldName) => {
120
- const normalizedFieldName = fieldName.toLowerCase();
121
- return (normalizedFieldName === trimmed ||
122
- normalizedFieldName.replaceAll("_", "-") === trimmed ||
123
- normalizedFieldName.replaceAll("-", "_") === trimmed);
124
- });
125
- const definition = UPDATE_UNSET_ALIAS_MAP.get(trimmed) ??
126
- resolveRuntimeUnsetFieldDefinition(trimmed, "update", runtimeFieldRegistry) ??
127
- (extensionFieldName
128
- ? { optionKey: "field", metadataKey: extensionFieldName }
129
- : undefined);
130
- return definition;
131
- },
132
- });
133
- }
134
- // Restricted append-style flags have dedicated commands with their own
135
- // ownership semantics; map each one to its exact replacement invocation so
136
- // scope errors tell the agent how to retry instead of dead-ending. The
137
- // evidence append flags are allowed by the metadata ownership bypass, but still used by
138
- // narrower scopes such as the dependency ownership bypass.
139
- const OWNERSHIP_BYPASS_RESTRICTED_FLAG_REPLACEMENTS = new Map([
140
- ["--comment", (id) => `pm comments ${id} --add "<text>" --force`],
141
- [
142
- "--file",
143
- (id) => `pm files ${id} --add "path=<path>,scope=<scope>,note=<note>" --force`,
144
- ],
145
- [
146
- "--doc",
147
- (id) => `pm docs ${id} --add "path=<path>,scope=<scope>,note=<note>" --force`,
148
- ],
149
- ]);
150
- function buildOwnershipBypassRestrictedOptionsError(params) {
151
- // Only surface replacement commands for restricted flags the caller actually
152
- // passed, so the guidance is an exact retry path.
153
- const replacementCommands = params.disallowedFlags.flatMap((flag) => {
154
- const replacement = OWNERSHIP_BYPASS_RESTRICTED_FLAG_REPLACEMENTS.get(flag);
155
- return replacement ? [replacement(params.id)] : [];
156
- });
157
- const replacementSteps = params.disallowedFlags.flatMap((flag) => {
158
- const replacement = OWNERSHIP_BYPASS_RESTRICTED_FLAG_REPLACEMENTS.get(flag);
159
- return replacement
160
- ? [`Replace ${flag} with: ${replacement(params.id)}`]
161
- : [];
162
- });
163
- return new PmCliError(params.message, EXIT_CODE.USAGE, {
164
- code: params.code,
165
- required: params.required,
166
- why: params.why,
167
- ...(replacementCommands.length > 0
168
- ? { examples: replacementCommands }
169
- : {}),
170
- nextSteps: [
171
- `Re-run without: ${params.disallowedFlags.join(", ")}`,
172
- ...replacementSteps,
173
- ],
174
- });
175
- }
176
- function enforceOwnershipBypassScope(id, options, clearItemMetadataKeys) {
177
- const ownershipMetadataBypass = options.ownershipMetadataBypass === true;
178
- const ownershipDependencyBypass = options.ownershipDependencyBypass === true;
179
- if (!ownershipMetadataBypass && !ownershipDependencyBypass) {
180
- return;
181
- }
182
- if (ownershipMetadataBypass && ownershipDependencyBypass) {
183
- throw new PmCliError("Choose only one package-provided ownership bypass mode.", EXIT_CODE.USAGE);
184
- }
185
- const pushIf = (condition, flag, list) => {
186
- if (condition) {
187
- list.push(flag);
188
- }
189
- };
190
- if (ownershipDependencyBypass) {
191
- const disallowedFlags = [];
192
- pushIf(options.title !== undefined, "--title", disallowedFlags);
193
- pushIf(options.description !== undefined, "--description", disallowedFlags);
194
- pushIf(options.body !== undefined, "--body", disallowedFlags);
195
- pushIf(options.status !== undefined, "--status", disallowedFlags);
196
- pushIf(options.closeReason !== undefined, "--close-reason", disallowedFlags);
197
- pushIf(options.priority !== undefined, "--priority", disallowedFlags);
198
- pushIf(options.type !== undefined, "--type", disallowedFlags);
199
- pushIf(options.tags !== undefined, "--tags", disallowedFlags);
200
- pushIf(Array.isArray(options.addTags) && options.addTags.length > 0, "--add-tags", disallowedFlags);
201
- pushIf(Array.isArray(options.removeTags) && options.removeTags.length > 0, "--remove-tags", disallowedFlags);
202
- pushIf(options.deadline !== undefined, "--deadline", disallowedFlags);
203
- pushIf(options.estimatedMinutes !== undefined, "--estimate", disallowedFlags);
204
- pushIf(options.acceptanceCriteria !== undefined, "--acceptance-criteria", disallowedFlags);
205
- pushIf(Array.isArray(options.addAc) && options.addAc.length > 0, "--add-ac", disallowedFlags);
206
- pushIf(Array.isArray(options.removeAc) && options.removeAc.length > 0, "--remove-ac", disallowedFlags);
207
- pushIf(options.definitionOfReady !== undefined, "--definition-of-ready", disallowedFlags);
208
- pushIf(options.order !== undefined || options.rank !== undefined, "--order/--rank", disallowedFlags);
209
- pushIf(options.goal !== undefined, "--goal", disallowedFlags);
210
- pushIf(options.objective !== undefined, "--objective", disallowedFlags);
211
- pushIf(options.value !== undefined, "--value", disallowedFlags);
212
- pushIf(options.impact !== undefined, "--impact", disallowedFlags);
213
- pushIf(options.outcome !== undefined, "--outcome", disallowedFlags);
214
- pushIf(options.whyNow !== undefined, "--why-now", disallowedFlags);
215
- pushIf(options.assignee !== undefined, "--assignee", disallowedFlags);
216
- pushIf(options.parent !== undefined, "--parent", disallowedFlags);
217
- pushIf(options.reviewer !== undefined, "--reviewer", disallowedFlags);
218
- pushIf(options.risk !== undefined, "--risk", disallowedFlags);
219
- pushIf(options.confidence !== undefined, "--confidence", disallowedFlags);
220
- pushIf(options.sprint !== undefined, "--sprint", disallowedFlags);
221
- pushIf(options.release !== undefined, "--release", disallowedFlags);
222
- pushIf(options.blockedBy !== undefined, "--blocked-by", disallowedFlags);
223
- pushIf(options.blockedReason !== undefined, "--blocked-reason", disallowedFlags);
224
- pushIf(options.unblockNote !== undefined, "--unblock-note", disallowedFlags);
225
- pushIf(options.reporter !== undefined, "--reporter", disallowedFlags);
226
- pushIf(options.severity !== undefined, "--severity", disallowedFlags);
227
- pushIf(options.environment !== undefined, "--environment", disallowedFlags);
228
- pushIf(options.reproSteps !== undefined, "--repro-steps", disallowedFlags);
229
- pushIf(options.resolution !== undefined, "--resolution", disallowedFlags);
230
- pushIf(options.expectedResult !== undefined, "--expected-result", disallowedFlags);
231
- pushIf(options.actualResult !== undefined, "--actual-result", disallowedFlags);
232
- pushIf(options.affectedVersion !== undefined, "--affected-version", disallowedFlags);
233
- pushIf(options.fixedVersion !== undefined, "--fixed-version", disallowedFlags);
234
- pushIf(options.component !== undefined, "--component", disallowedFlags);
235
- pushIf(options.regression !== undefined, "--regression", disallowedFlags);
236
- pushIf(options.customerImpact !== undefined, "--customer-impact", disallowedFlags);
237
- pushIf(options.depRemove !== undefined, "--dep-remove", disallowedFlags);
238
- pushIf(options.replaceDeps === true, "--replace-deps", disallowedFlags);
239
- pushIf(options.replaceTests === true, "--replace-tests", disallowedFlags);
240
- pushIf(options.replaceFiles === true, "--replace-files", disallowedFlags);
241
- pushIf(options.replaceDocs === true, "--replace-docs", disallowedFlags);
242
- pushIf(options.comment !== undefined, "--comment", disallowedFlags);
243
- pushIf(options.note !== undefined, "--note", disallowedFlags);
244
- pushIf(options.learning !== undefined, "--learning", disallowedFlags);
245
- pushIf(options.file !== undefined, "--file", disallowedFlags);
246
- pushIf(options.test !== undefined, "--test", disallowedFlags);
247
- pushIf(options.doc !== undefined, "--doc", disallowedFlags);
248
- pushIf(options.reminder !== undefined, "--reminder", disallowedFlags);
249
- pushIf(options.event !== undefined, "--event", disallowedFlags);
250
- pushIf(options.typeOption !== undefined, "--type-option", disallowedFlags);
251
- pushIf(options.clearDeps === true, "--clear-deps", disallowedFlags);
252
- pushIf(options.clearComments === true, "--clear-comments", disallowedFlags);
253
- pushIf(options.clearNotes === true, "--clear-notes", disallowedFlags);
254
- pushIf(options.clearLearnings === true, "--clear-learnings", disallowedFlags);
255
- pushIf(options.clearFiles === true, "--clear-files", disallowedFlags);
256
- pushIf(options.clearTests === true, "--clear-tests", disallowedFlags);
257
- pushIf(options.clearDocs === true, "--clear-docs", disallowedFlags);
258
- pushIf(options.clearReminders === true, "--clear-reminders", disallowedFlags);
259
- pushIf(options.clearEvents === true, "--clear-events", disallowedFlags);
260
- pushIf(options.clearTypeOptions === true, "--clear-type-options", disallowedFlags);
261
- pushIf(options.force === true, "--force", disallowedFlags);
262
- pushIf(clearItemMetadataKeys.size > 0, "--unset", disallowedFlags);
263
- if (options.dep === undefined || options.dep.length === 0) {
264
- throw new PmCliError("The dependency ownership bypass requires at least one --dep value", EXIT_CODE.USAGE);
265
- }
266
- if (disallowedFlags.length > 0) {
267
- throw buildOwnershipBypassRestrictedOptionsError({
268
- id,
269
- code: "ownership_dependency_bypass_restricted_options",
270
- message: `The dependency ownership bypass supports append-only dependency additions via --dep. Remove restricted options: ${disallowedFlags.join(", ")}`,
271
- required: "Pass only --dep additions (plus --message/--author) with the dependency ownership bypass.",
272
- why: "the dependency ownership bypass is a narrow non-owner override scoped to append-only dependency additions; every other mutation keeps its normal ownership rules.",
273
- disallowedFlags,
274
- });
275
- }
276
- return;
277
- }
278
- const disallowedFlags = [];
279
- pushIf(options.status !== undefined, "--status", disallowedFlags);
280
- pushIf(options.closeReason !== undefined, "--close-reason", disallowedFlags);
281
- pushIf(options.assignee !== undefined, "--assignee", disallowedFlags);
282
- pushIf(options.parent !== undefined, "--parent", disallowedFlags);
283
- pushIf(options.blockedBy !== undefined, "--blocked-by", disallowedFlags);
284
- pushIf(options.blockedReason !== undefined, "--blocked-reason", disallowedFlags);
285
- pushIf(options.unblockNote !== undefined, "--unblock-note", disallowedFlags);
286
- pushIf(options.dep !== undefined, "--dep", disallowedFlags);
287
- pushIf(options.depRemove !== undefined, "--dep-remove", disallowedFlags);
288
- pushIf(options.replaceDeps === true, "--replace-deps", disallowedFlags);
289
- pushIf(options.replaceTests === true, "--replace-tests", disallowedFlags);
290
- pushIf(options.replaceFiles === true, "--replace-files", disallowedFlags);
291
- pushIf(options.replaceDocs === true, "--replace-docs", disallowedFlags);
292
- pushIf(options.note !== undefined, "--note", disallowedFlags);
293
- pushIf(options.learning !== undefined, "--learning", disallowedFlags);
294
- pushIf(options.test !== undefined, "--test", disallowedFlags);
295
- pushIf(options.reminder !== undefined, "--reminder", disallowedFlags);
296
- pushIf(options.event !== undefined, "--event", disallowedFlags);
297
- pushIf(options.clearDeps === true, "--clear-deps", disallowedFlags);
298
- pushIf(options.clearComments === true, "--clear-comments", disallowedFlags);
299
- pushIf(options.clearNotes === true, "--clear-notes", disallowedFlags);
300
- pushIf(options.clearLearnings === true, "--clear-learnings", disallowedFlags);
301
- pushIf(options.clearFiles === true, "--clear-files", disallowedFlags);
302
- pushIf(options.clearTests === true, "--clear-tests", disallowedFlags);
303
- pushIf(options.clearDocs === true, "--clear-docs", disallowedFlags);
304
- pushIf(options.clearReminders === true, "--clear-reminders", disallowedFlags);
305
- pushIf(options.clearEvents === true, "--clear-events", disallowedFlags);
306
- /* c8 ignore start -- unset ordering fallback is validated by package-governance integration coverage. */
307
- const disallowedUnset = [...clearItemMetadataKeys]
308
- .filter((field) => OWNERSHIP_BYPASS_DISALLOWED_UNSET_ITEM_METADATA_KEYS.has(field))
309
- .sort((left, right) => left.localeCompare(right))
310
- .map((field) => `--unset ${field.replaceAll("_", "-")}`);
311
- /* c8 ignore stop */
312
- disallowedFlags.push(...disallowedUnset);
313
- if (disallowedFlags.length > 0) {
314
- throw buildOwnershipBypassRestrictedOptionsError({
315
- id,
316
- code: "ownership_metadata_bypass_restricted_options",
317
- message: `The metadata ownership bypass only supports non-lifecycle metadata fields and evidence appends. Remove restricted options: ${disallowedFlags.join(", ")}`,
318
- required: "Limit the metadata ownership bypass to non-lifecycle metadata fields plus append-only --comment/--file/--doc evidence; route restricted appends and lifecycle changes through their dedicated commands.",
319
- why: "the metadata ownership bypass is a non-owner override scoped to metadata maintenance and append-only evidence; lifecycle, ownership, dependency mutations, restricted append fields, and clear/replace operations keep their normal ownership rules.",
320
- disallowedFlags,
321
- });
322
- }
323
- }
324
- /* c8 ignore start -- lifecycle/dependency edge branches are exercised by dedicated update workflow integration tests. */
325
- function parseStatus(value, statusRegistry) {
326
- const normalized = normalizeStatusInput(value, statusRegistry);
327
- if (!normalized) {
328
- const allowedStatuses = statusRegistry.definitions.map((definition) => definition.id);
329
- throw new PmCliError(`Invalid --status value "${value}". Allowed: ${allowedStatuses.join(", ")}`, EXIT_CODE.USAGE);
330
- }
331
- return normalized;
332
- }
333
- /** Enforce per-type allowed-transition rules (governance.workflow_enforcement). `off` (default) or an unrestricted type is a no-op. `strict` throws on a disallowed transition; `warn` returns a warning string surfaced on the update result. The target status is the raw `--status` value (resolved case-insensitively through the registry inside evaluateTransition). */
334
- function enforceTypeWorkflowTransition(params) {
335
- if (params.enforcement === "off" || params.typeWorkflows.length === 0) {
336
- return undefined;
337
- }
338
- const result = evaluateTransition({
339
- typeName: params.typeName,
340
- fromStatus: params.fromStatus,
341
- toStatus: params.toStatus,
342
- typeWorkflows: params.typeWorkflows,
343
- statusRegistry: params.statusRegistry,
344
- });
345
- if (!result.hasRule || result.allowed) {
346
- return undefined;
347
- }
348
- const normalizedFrom = normalizeStatusInput(params.fromStatus, params.statusRegistry) ??
349
- params.fromStatus;
350
- const normalizedTo = normalizeStatusInput(params.toStatus, params.statusRegistry) ??
351
- params.toStatus;
352
- const message = `Disallowed transition for type "${params.typeName}": ${normalizedFrom} -> ${normalizedTo}. ` +
353
- `Allowed transitions: ${describeAllowedTransitions(result.allowedTransitions)}.`;
354
- if (params.enforcement === "strict") {
355
- throw new PmCliError(message, EXIT_CODE.USAGE);
356
- }
357
- return `workflow_transition_not_allowed: ${message}`;
358
- }
359
- function parseDependencyCreatedAt(value, currentIso) {
360
- if (!value || value.trim() === "" || value.trim().toLowerCase() === "now") {
361
- return currentIso;
362
- }
363
- return normalizeDependencyTimestamp(value);
364
- }
365
- function normalizeDependencyTimestamp(value) {
366
- const parsed = Date.parse(value);
367
- if (!Number.isFinite(parsed)) {
368
- throw new PmCliError(`Invalid dependency created_at timestamp "${value}"`, EXIT_CODE.USAGE);
369
- }
370
- return new Date(parsed).toISOString();
371
- }
372
- function parseOptionalDependencyString(value) {
373
- if (value === undefined)
374
- return undefined;
375
- const trimmed = value.trim();
376
- return trimmed.length > 0 ? trimmed : undefined;
377
- }
378
- /** Allowed CSV/markdown keys for the update `--dep` addition seed (GH-258). */
379
- const DEP_ADDITION_KEYS = [
380
- "id",
381
- "kind",
382
- "type",
383
- "author",
384
- "created_at",
385
- "source_kind",
386
- ];
387
- /** Allowed CSV/markdown keys for the `--dep-remove` selector (GH-258). */
388
- const DEP_REMOVE_KEYS = [
389
- "id",
390
- "kind",
391
- "type",
392
- "author",
393
- "created_at",
394
- "source_kind",
395
- ];
396
- function looksLikeStructuredDependencyEntry(raw) {
397
- if (raw.startsWith("```") || raw.includes("\n")) {
398
- return true;
399
- }
400
- if (/^(?:[-*+]\s+)?(?:id|kind|type|author|created_at|source_kind)\s*[:=]/i.test(raw)) {
401
- return true;
402
- }
403
- // A first-key typo (e.g. `bogus=v,id=pm-2`) must still be parsed so the unknown
404
- // key is rejected rather than swallowed as a bare item id (GH-258).
405
- return looksLikeGenericKeyValueEntry(raw);
406
- }
407
- function normalizeDependencyKindInput(raw) {
408
- return typeof raw === "string"
409
- ? (resolveCanonicalRelationshipKind(raw) ?? raw.trim())
410
- : raw;
411
- }
412
- /** Parse dependency additions into their canonical storage representation. */
413
- export function parseDependencyAdditions(raw, prefix, nowIso, fallbackAuthor) {
414
- if (!raw) {
415
- return { additions: [] };
416
- }
417
- assertNoLegacyNoneTokens(raw, "--dep", "Use --clear-deps to clear dependencies.");
418
- const additions = raw.map((entry) => {
419
- const trimmedEntry = entry.trim();
420
- const isStructured = looksLikeStructuredDependencyEntry(trimmedEntry);
421
- assertValidBareDependencyFlagValue(trimmedEntry, isStructured);
422
- const kv = isStructured
423
- ? parseCsvKv(entry, "--dep")
424
- : { id: trimmedEntry, kind: "related" };
425
- if (isStructured) {
426
- assertNoUnknownCsvKeys(kv, "--dep", DEP_ADDITION_KEYS);
427
- }
428
- const id = kv.id?.trim();
429
- const kind = normalizeDependencyKindInput((kv.kind ?? kv.type)?.trim());
430
- if (!id || !kind) {
431
- throw new PmCliError("--dep requires id and kind, or a bare item id to add a related dependency", EXIT_CODE.USAGE);
432
- }
433
- if (id.toLowerCase() === "undefined") {
434
- throw new PmCliError(`--dep id must not use placeholder token "${id}". Use --clear-deps to clear dependencies.`, EXIT_CODE.USAGE);
435
- }
436
- const sourceKind = normalizeDependencySourceKind(parseOptionalDependencyString(kv.source_kind));
437
- const explicitAuthor = parseOptionalDependencyString(kv.author);
438
- return {
439
- id: normalizeDependencySeedId(id, prefix, sourceKind),
440
- kind: ensureEnum(kind, DEPENDENCY_KIND_VALUES, "dependency kind"),
441
- created_at: parseDependencyCreatedAt(kv.created_at, nowIso),
442
- author: explicitAuthor ?? fallbackAuthor,
443
- source_kind: sourceKind ?? "cli:update:dep",
444
- author_source: explicitAuthor ? "asserted" : "detected",
445
- };
446
- });
447
- return { additions };
448
- }
449
- function parseDependencyRemovals(raw, prefix) {
450
- if (!raw) {
451
- return [];
452
- }
453
- assertNoLegacyNoneTokens(raw, "--dep-remove");
454
- return raw.map((entry) => {
455
- const trimmed = entry.trim();
456
- if (!trimmed) {
457
- throw new PmCliError("--dep-remove requires id or key/value selectors", EXIT_CODE.USAGE);
458
- }
459
- const isStructured = looksLikeStructuredDependencyEntry(trimmed);
460
- assertValidBareDependencyFlagValue(trimmed, isStructured, "--dep-remove");
461
- if (isStructured) {
462
- const kv = parseCsvKv(trimmed, "--dep-remove");
463
- assertNoUnknownCsvKeys(kv, "--dep-remove", DEP_REMOVE_KEYS);
464
- const idRaw = kv.id?.trim();
465
- if (!idRaw) {
466
- throw new PmCliError("--dep-remove key/value form requires id=<value>", EXIT_CODE.USAGE);
467
- }
468
- if (idRaw.toLowerCase() === "undefined") {
469
- throw new PmCliError(`--dep-remove id must not use placeholder token "${idRaw}"`, EXIT_CODE.USAGE);
470
- }
471
- const kindRaw = normalizeDependencyKindInput(parseOptionalDependencyString(kv.kind ?? kv.type));
472
- const sourceKind = normalizeDependencySourceKind(parseOptionalDependencyString(kv.source_kind));
473
- const author = parseOptionalDependencyString(kv.author);
474
- const createdAt = parseOptionalDependencyString(kv.created_at);
475
- return {
476
- id: normalizeDependencySeedId(idRaw, prefix, sourceKind),
477
- kind: kindRaw
478
- ? ensureEnum(kindRaw, DEPENDENCY_KIND_VALUES, "dependency kind")
479
- : undefined,
480
- source_kind: sourceKind,
481
- author,
482
- created_at: createdAt
483
- ? normalizeDependencyTimestamp(createdAt)
484
- : undefined,
485
- };
486
- }
487
- if (trimmed.toLowerCase() === "undefined") {
488
- throw new PmCliError(`--dep-remove id must not use placeholder token "${trimmed}"`, EXIT_CODE.USAGE);
489
- }
490
- return {
491
- id: normalizeItemId(trimmed, prefix),
492
- };
493
- });
494
- }
495
- function dependencyKey(value) {
496
- const sourceKind = value.source_kind?.trim().toLowerCase() ?? "";
497
- return [value.id.trim().toLowerCase(), value.kind, sourceKind].join("\u0000");
498
- }
499
- /** Return the complete normalized identity of one stored dependency row. */
500
- function storedDependencyIdentityKey(value) {
501
- const sourceKind = value.source_kind?.trim().toLowerCase() ?? "";
502
- const author = value.author?.trim().toLowerCase() ?? "";
503
- const rawCreatedAt = value.created_at?.trim() ?? "";
504
- const parsedCreatedAt = Date.parse(rawCreatedAt);
505
- const createdAt = Number.isFinite(parsedCreatedAt)
506
- ? new Date(parsedCreatedAt).toISOString()
507
- : rawCreatedAt;
508
- return [
509
- value.id.trim().toLowerCase(),
510
- value.kind,
511
- sourceKind,
512
- author,
513
- createdAt,
514
- ].join("\u0000");
515
- }
516
- // pm-kyd6: `--blocked-by` writes the `blocked_by` scalar, but the dependency
517
- // graph (`pm deps`) is built only from the `dependencies` array. Mirror the
518
- // behaviour create.ts already has so the metadata and the graph agree: a
519
- // resolvable blocker also gets a `blocked_by` dependency edge. Repeated
520
- // `--blocked-by` updates preserve prior blocker edges because the graph is the
521
- // full dependency record; the scalar remains the latest primary blocker for
522
- // backward compatibility. Clearing the scalar removes all derived blocker edges.
523
- function reconcileBlockedByDependency(current, nextBlockedById, nowIsoValue, author) {
524
- let next = [...(current ?? [])];
525
- let changed = false;
526
- if (nextBlockedById === undefined) {
527
- const filtered = next.filter((dep) => dep.kind !== "blocked_by");
528
- if (filtered.length !== next.length) {
529
- next = filtered;
530
- changed = true;
531
- }
532
- if (!changed) {
533
- return { dependencies: current, changed: false };
534
- }
535
- return { dependencies: next.length > 0 ? next : undefined, changed: true };
536
- }
537
- if (!next.some((dep) => dep.kind === "blocked_by" && dep.id === nextBlockedById)) {
538
- next.push({
539
- id: nextBlockedById,
540
- kind: "blocked_by",
541
- created_at: nowIsoValue,
542
- author,
543
- source_kind: "cli:update:blocked_by",
544
- author_source: "detected",
545
- });
546
- changed = true;
547
- }
548
- if (!changed) {
549
- return { dependencies: current, changed: false };
550
- }
551
- return { dependencies: next.length > 0 ? next : undefined, changed: true };
552
- }
553
- // pm-kyd6: resolve the --blocked-by target before the synchronous mutate
554
- // callback so a real blocker can also become a `blocked_by` dependency edge.
555
- // `id` is set when the target resolves; `unresolved` carries the raw value when
556
- // --blocked-by points at an item that does not exist (the scalar is still set,
557
- // mirroring create.ts and the never-block missing-parent behaviour, but the
558
- // caller surfaces a warning so the metadata/graph mismatch is visible).
559
- async function resolveBlockedByDependencyTarget(blockedByOption, blockedByCleared, pmRoot, idPrefix, itemFormat, typeToFolder) {
560
- if (blockedByOption === undefined || blockedByCleared) {
561
- return {};
562
- }
563
- const blockedByValue = blockedByOption.trim();
564
- if (blockedByValue.length === 0) {
565
- return {};
566
- }
567
- const located = await locateItem(pmRoot, normalizeItemId(blockedByValue, idPrefix), idPrefix, itemFormat, typeToFolder);
568
- return located ? { id: located.id } : { unresolved: blockedByValue };
569
- }
570
- // pm-kyd6: apply the reconciled blocked_by dependency edge to the item metadata
571
- // and record the `dependencies` change. Kept out of the mutate callback so the
572
- // large runUpdate function stays under the static-quality complexity budget.
573
- function applyBlockedByDependencyEdge(metadata, resolvedBlockedById, nowIsoValue, author, changedFields) {
574
- const reconciled = reconcileBlockedByDependency(metadata.dependencies, resolvedBlockedById, nowIsoValue, author);
575
- if (!reconciled.changed) {
576
- return;
577
- }
578
- if (reconciled.dependencies === undefined) {
579
- delete metadata.dependencies;
580
- }
581
- else {
582
- metadata.dependencies = reconciled.dependencies;
583
- }
584
- if (!changedFields.includes("dependencies")) {
585
- changedFields.push("dependencies");
586
- }
587
- }
588
- function fileKey(value) {
589
- return `${value.path}::${value.scope}`;
590
- }
591
- function docKey(value) {
592
- return `${value.path}::${value.scope}`;
593
- }
594
- function testKey(value) {
595
- return `${value.command}::${value.path ?? ""}::${value.scope}::${value.pm_context_mode ?? ""}::${value.workspace_context_mode ?? ""}`;
596
- }
597
- function matchesDependencySelector(value, selector) {
598
- if (value.id.trim().toLowerCase() !== selector.id.trim().toLowerCase()) {
599
- return false;
600
- }
601
- if (selector.kind && value.kind !== selector.kind) {
602
- return false;
603
- }
604
- if (selector.source_kind !== undefined &&
605
- value.source_kind?.trim().toLowerCase() !==
606
- selector.source_kind.trim().toLowerCase()) {
607
- return false;
608
- }
609
- if (selector.author !== undefined &&
610
- value.author?.trim().toLowerCase() !== selector.author.trim().toLowerCase()) {
611
- return false;
612
- }
613
- if (selector.created_at !== undefined &&
614
- (value.created_at === undefined ||
615
- !Number.isFinite(Date.parse(value.created_at)) ||
616
- new Date(Date.parse(value.created_at)).toISOString() !==
617
- selector.created_at)) {
618
- return false;
619
- }
620
- return true;
621
- }
622
- function normalizeUpdatePolicyOptionKey(raw, typeName) {
623
- const canonical = canonicalizeCommandOptionKey("update", raw);
624
- if (!canonical) {
625
- throw new PmCliError(`Unsupported command_option_policies option "${raw}" for update command on type "${typeName}"`, EXIT_CODE.CONFLICT);
626
- }
627
- return canonical;
628
- }
629
- function collectProvidedUpdatePolicyOptions(options, runtimeFieldRegistry, extensionFieldNames) {
630
- const provided = new Set();
631
- const mark = (optionKey, isProvided) => {
632
- if (isProvided) {
633
- provided.add(optionKey);
634
- }
635
- };
636
- mark("title", options.title !== undefined);
637
- mark("description", options.description !== undefined);
638
- mark("body", options.body !== undefined);
639
- mark("status", options.status !== undefined);
640
- mark("closeReason", options.closeReason !== undefined);
641
- mark("priority", options.priority !== undefined);
642
- mark("type", options.type !== undefined);
643
- // `--add-tags` / `--remove-tags` mutate the same `tags` field as `--tags`, so
644
- // they count toward the `tags` command_option_policy (disabled + required).
645
- mark("tags", options.tags !== undefined ||
646
- (Array.isArray(options.addTags) && options.addTags.length > 0) ||
647
- (Array.isArray(options.removeTags) && options.removeTags.length > 0));
648
- mark("deadline", options.deadline !== undefined);
649
- mark("estimatedMinutes", options.estimatedMinutes !== undefined);
650
- // `--add-ac` / `--remove-ac` mutate the same `acceptance_criteria` field as
651
- // `--acceptance-criteria`, so they count toward its command_option_policy.
652
- mark("acceptanceCriteria", options.acceptanceCriteria !== undefined ||
653
- (Array.isArray(options.addAc) && options.addAc.length > 0) ||
654
- (Array.isArray(options.removeAc) && options.removeAc.length > 0));
655
- mark("definitionOfReady", options.definitionOfReady !== undefined);
656
- mark("order", options.order !== undefined || options.rank !== undefined);
657
- mark("goal", options.goal !== undefined);
658
- mark("objective", options.objective !== undefined);
659
- mark("value", options.value !== undefined);
660
- mark("impact", options.impact !== undefined);
661
- mark("outcome", options.outcome !== undefined);
662
- mark("whyNow", options.whyNow !== undefined);
663
- mark("author", options.author !== undefined);
664
- mark("message", options.message !== undefined);
665
- mark("assignee", options.assignee !== undefined);
666
- mark("parent", options.parent !== undefined);
667
- mark("reviewer", options.reviewer !== undefined);
668
- mark("risk", options.risk !== undefined);
669
- mark("confidence", options.confidence !== undefined);
670
- mark("sprint", options.sprint !== undefined);
671
- mark("release", options.release !== undefined);
672
- mark("blockedBy", options.blockedBy !== undefined);
673
- mark("blockedReason", options.blockedReason !== undefined);
674
- mark("unblockNote", options.unblockNote !== undefined);
675
- mark("reporter", options.reporter !== undefined);
676
- mark("severity", options.severity !== undefined);
677
- mark("environment", options.environment !== undefined);
678
- mark("reproSteps", options.reproSteps !== undefined);
679
- mark("resolution", options.resolution !== undefined);
680
- mark("expectedResult", options.expectedResult !== undefined);
681
- mark("actualResult", options.actualResult !== undefined);
682
- mark("affectedVersion", options.affectedVersion !== undefined);
683
- mark("fixedVersion", options.fixedVersion !== undefined);
684
- mark("component", options.component !== undefined);
685
- mark("regression", options.regression !== undefined);
686
- mark("customerImpact", options.customerImpact !== undefined);
687
- mark("dep", options.dep !== undefined);
688
- mark("depRemove", options.depRemove !== undefined);
689
- mark("dep", options.replaceDeps === true);
690
- mark("comment", options.comment !== undefined);
691
- mark("note", options.note !== undefined);
692
- mark("learning", options.learning !== undefined);
693
- mark("file", options.file !== undefined);
694
- mark("test", options.test !== undefined);
695
- mark("test", options.replaceTests === true);
696
- mark("file", options.replaceFiles === true);
697
- mark("doc", options.replaceDocs === true);
698
- mark("doc", options.doc !== undefined);
699
- mark("reminder", options.reminder !== undefined);
700
- mark("event", options.event !== undefined);
701
- mark("typeOption", options.typeOption !== undefined);
702
- mark("field", options.field !== undefined);
703
- mark("force", options.force === true);
704
- mark("ownershipMetadataBypass", options.ownershipMetadataBypass === true);
705
- mark("ownershipDependencyBypass", options.ownershipDependencyBypass === true);
706
- mark("dep", options.clearDeps === true);
707
- mark("comment", options.clearComments === true);
708
- mark("note", options.clearNotes === true);
709
- mark("learning", options.clearLearnings === true);
710
- mark("file", options.clearFiles === true);
711
- mark("test", options.clearTests === true);
712
- mark("doc", options.clearDocs === true);
713
- mark("reminder", options.clearReminders === true);
714
- mark("event", options.clearEvents === true);
715
- mark("typeOption", options.clearTypeOptions === true);
716
- if (options.unset && options.unset.length > 0) {
717
- const unsetTargets = parseUpdateUnsetTargets(options.unset, runtimeFieldRegistry, extensionFieldNames);
718
- for (const optionKey of unsetTargets.optionKeys) {
719
- mark(optionKey, true);
720
- }
721
- }
722
- return provided;
723
- }
724
- function enforceUpdateOptionsByType(typeName, options, typeRegistry, runtimeFieldRegistry, extensionFieldNames) {
725
- const typeDefinition = resolveTypeDefinition(typeName, typeRegistry);
726
- if (!typeDefinition) {
727
- throw new PmCliError(`Invalid type value "${typeName}"`, EXIT_CODE.USAGE);
728
- }
729
- const policyState = resolveCommandOptionPolicyState(typeDefinition, "update", []);
730
- if (policyState.errors.length > 0) {
731
- throw new PmCliError(policyState.errors.join("; "), EXIT_CODE.CONFLICT);
732
- }
733
- const provided = collectProvidedUpdatePolicyOptions(options, runtimeFieldRegistry, extensionFieldNames);
734
- for (const disabled of policyState.disabled) {
735
- if (provided.has(normalizeUpdatePolicyOptionKey(disabled, typeName))) {
736
- throw new PmCliError(`Option ${commandOptionFlagLabel("update", disabled)} is disabled for type "${typeName}" by command_option_policies`, EXIT_CODE.USAGE);
737
- }
738
- }
739
- for (const required of policyState.required) {
740
- if (!provided.has(normalizeUpdatePolicyOptionKey(required, typeName))) {
741
- throw new PmCliError(`Missing required option ${commandOptionFlagLabel("update", required)} for type "${typeName}"`, EXIT_CODE.USAGE);
742
- }
743
- }
744
- }
745
- // `rank` is a legacy alias for `order`; keep it out of the scalar loop if the
746
- // shared mutation key list ever grows to include that alias.
747
- const UPDATE_LEGACY_COMMON_SCALAR_OPTION_EXCLUSIONS = new Set([
748
- "order",
749
- "rank",
750
- ]);
751
- const UPDATE_LEGACY_COMMON_SCALAR_OPTION_KEYS = COMMON_MUTATION_COMMAND_OPTION_KEYS.filter((key) => !UPDATE_LEGACY_COMMON_SCALAR_OPTION_EXCLUSIONS.has(key));
752
- const UPDATE_LEGACY_SCALAR_OPTION_KEYS = ["tags", "closeReason", ...UPDATE_LEGACY_COMMON_SCALAR_OPTION_KEYS];
753
- const UPDATE_SIMPLE_FIELD_FLAG_KEYS = [
754
- "title",
755
- "description",
756
- "body",
757
- "status",
758
- "closeReason",
759
- "completedAt",
760
- "priority",
761
- "type",
762
- ...COMMON_MUTATION_COMMAND_OPTION_KEYS,
763
- "dep",
764
- "depRemove",
765
- "comment",
766
- "note",
767
- "learning",
768
- "file",
769
- "test",
770
- "doc",
771
- "reminder",
772
- "event",
773
- "typeOption",
774
- "field",
775
- ];
776
- const UPDATE_POST_TAG_SCALAR_MUTATIONS = [
777
- {
778
- optionKey: "deadline",
779
- metadataKey: "deadline",
780
- transform: (value, context) => resolveIsoOrRelative(value, context.nowValue, "deadline"),
781
- },
782
- {
783
- optionKey: "estimatedMinutes",
784
- metadataKey: "estimated_minutes",
785
- transform: (value) => parseOptionalNonNegativeInteger(value, "estimated-minutes"),
786
- },
787
- {
788
- optionKey: "acceptanceCriteria",
789
- metadataKey: "acceptance_criteria",
790
- transform: (value) => value,
791
- },
792
- { optionKey: "definitionOfReady", metadataKey: "definition_of_ready" },
793
- { optionKey: "goal", metadataKey: "goal" },
794
- { optionKey: "objective", metadataKey: "objective" },
795
- { optionKey: "value", metadataKey: "value" },
796
- { optionKey: "impact", metadataKey: "impact" },
797
- { optionKey: "outcome", metadataKey: "outcome" },
798
- { optionKey: "whyNow", metadataKey: "why_now" },
799
- ];
800
- const UPDATE_STAKEHOLDER_SCALAR_MUTATIONS = [
801
- { optionKey: "reviewer", metadataKey: "reviewer" },
802
- {
803
- optionKey: "risk",
804
- metadataKey: "risk",
805
- transform: (value) => ensureEnum(normalizeRiskInput(value), RISK_VALUES, "risk"),
806
- },
807
- {
808
- optionKey: "confidence",
809
- metadataKey: "confidence",
810
- transform: (value) => parseConfidenceInput(value),
811
- },
812
- ];
813
- const UPDATE_ISSUE_SCALAR_MUTATIONS = [
814
- { optionKey: "blockedReason", metadataKey: "blocked_reason" },
815
- { optionKey: "unblockNote", metadataKey: "unblock_note" },
816
- { optionKey: "reporter", metadataKey: "reporter" },
817
- {
818
- optionKey: "severity",
819
- metadataKey: "severity",
820
- transform: (value) => ensureEnum(normalizeSeverityInput(value), ISSUE_SEVERITY_VALUES, "severity"),
821
- },
822
- { optionKey: "environment", metadataKey: "environment" },
823
- { optionKey: "reproSteps", metadataKey: "repro_steps" },
824
- { optionKey: "resolution", metadataKey: "resolution" },
825
- { optionKey: "expectedResult", metadataKey: "expected_result" },
826
- { optionKey: "actualResult", metadataKey: "actual_result" },
827
- { optionKey: "affectedVersion", metadataKey: "affected_version" },
828
- { optionKey: "fixedVersion", metadataKey: "fixed_version" },
829
- { optionKey: "component", metadataKey: "component" },
830
- {
831
- optionKey: "regression",
832
- metadataKey: "regression",
833
- transform: (value) => parseRegressionInput(value),
834
- },
835
- { optionKey: "customerImpact", metadataKey: "customer_impact" },
836
- ];
837
- function applyUpdateScalarMutations(definitions, options, context) {
838
- for (const definition of definitions) {
839
- const optionValue = options[definition.optionKey];
840
- const shouldClear = context.clearItemMetadataKeys.has(definition.metadataKey);
841
- if (optionValue === undefined && !shouldClear) {
842
- continue;
843
- }
844
- if (shouldClear) {
845
- delete context.metadataRecord[definition.metadataKey];
846
- context.changedFields.push(definition.metadataKey);
847
- continue;
848
- }
849
- if (typeof optionValue !== "string") {
850
- throw new PmCliError(`${commandOptionFlagLabel("update", String(definition.optionKey))} must be a string value`, EXIT_CODE.USAGE);
851
- }
852
- context.metadataRecord[definition.metadataKey] = definition.transform
853
- ? definition.transform(optionValue, context)
854
- : optionValue.trim();
855
- context.changedFields.push(definition.metadataKey);
856
- }
857
- }
858
- async function resolveStdinUpdateOptions(options) {
859
- const scalarFields = [
860
- ["body", "--body"],
861
- ["description", "--description"],
862
- ];
863
- const listFields = [
864
- ["dep", "--dep"],
865
- ["depRemove", "--dep-remove"],
866
- ["comment", "--comment"],
867
- ["note", "--note"],
868
- ["learning", "--learning"],
869
- ["file", "--file"],
870
- ["test", "--test"],
871
- ["doc", "--doc"],
872
- ["reminder", "--reminder"],
873
- ["event", "--event"],
874
- ["typeOption", "--type-option"],
875
- ["field", "--field"],
876
- ];
877
- return normalizeLegacyNoneUpdateOptions(await resolveMutationStdinTokenFields(options, scalarFields, listFields));
878
- }
879
- /** Resolve update stdin tokens once while preserving transport-marked literals. */
880
- export async function resolveUpdateTransportOptions(options) {
881
- return shouldResolveMutationStdinTokens(options)
882
- ? await resolveStdinUpdateOptions(options)
883
- : normalizeLegacyNoneUpdateOptions(options);
884
- }
885
- function buildClearCollectionDefinitions(options) {
886
- return [
887
- {
888
- enabled: options.clearDeps || options.replaceDeps,
889
- optionKey: "dep",
890
- clearFlag: "--clear-deps",
891
- valueFlag: "--dep",
892
- values: options.dep,
893
- metadataKey: "dependencies",
894
- },
895
- {
896
- enabled: options.clearComments,
897
- optionKey: "comment",
898
- clearFlag: "--clear-comments",
899
- valueFlag: "--comment",
900
- values: options.comment,
901
- metadataKey: "comments",
902
- },
903
- {
904
- enabled: options.clearNotes,
905
- optionKey: "note",
906
- clearFlag: "--clear-notes",
907
- valueFlag: "--note",
908
- values: options.note,
909
- metadataKey: "notes",
910
- },
911
- {
912
- enabled: options.clearLearnings,
913
- optionKey: "learning",
914
- clearFlag: "--clear-learnings",
915
- valueFlag: "--learning",
916
- values: options.learning,
917
- metadataKey: "learnings",
918
- },
919
- {
920
- enabled: options.clearFiles || options.replaceFiles,
921
- optionKey: "file",
922
- clearFlag: "--clear-files",
923
- valueFlag: "--file",
924
- values: options.file,
925
- metadataKey: "files",
926
- },
927
- {
928
- enabled: options.clearTests || options.replaceTests,
929
- optionKey: "test",
930
- clearFlag: "--clear-tests",
931
- valueFlag: "--test",
932
- values: options.test,
933
- metadataKey: "tests",
934
- },
935
- {
936
- enabled: options.clearDocs || options.replaceDocs,
937
- optionKey: "doc",
938
- clearFlag: "--clear-docs",
939
- valueFlag: "--doc",
940
- values: options.doc,
941
- metadataKey: "docs",
942
- },
943
- {
944
- enabled: options.clearReminders,
945
- optionKey: "reminder",
946
- clearFlag: "--clear-reminders",
947
- valueFlag: "--reminder",
948
- values: options.reminder,
949
- metadataKey: "reminders",
950
- },
951
- {
952
- enabled: options.clearEvents,
953
- optionKey: "event",
954
- clearFlag: "--clear-events",
955
- valueFlag: "--event",
956
- values: options.event,
957
- metadataKey: "events",
958
- },
959
- {
960
- enabled: options.clearTypeOptions,
961
- optionKey: "typeOption",
962
- clearFlag: "--clear-type-options",
963
- valueFlag: "--type-option",
964
- values: options.typeOption,
965
- metadataKey: "type_options",
966
- },
967
- ];
968
- }
969
- function validateLinkedArtifactReplacement(params) {
970
- if (params.enabled && (!params.values || params.values.length === 0)) {
971
- throw new PmCliError(`${params.replaceFlag} requires at least one ${params.valueFlag} entry`, EXIT_CODE.USAGE);
972
- }
973
- if (params.enabled && params.clearEnabled) {
974
- throw new PmCliError(`${params.replaceFlag} cannot be combined with ${params.clearFlag}`, EXIT_CODE.USAGE);
975
- }
976
- }
977
- /** Validate mutually exclusive and required update mutation option combinations. */
978
- export function assertUpdateMutationOptionCombinations(options) {
979
- const hasAdditiveAcceptanceCriteriaMutation = (options.addAc?.length ?? 0) > 0 || (options.removeAc?.length ?? 0) > 0;
980
- if (options.acceptanceCriteria !== undefined &&
981
- hasAdditiveAcceptanceCriteriaMutation) {
982
- throw new PmCliError("Cannot combine --acceptance-criteria replacement with --add-ac or --remove-ac. Use --remove-ac and --add-ac together for an atomic one-entry repair.", EXIT_CODE.USAGE, {
983
- code: "acceptance_criteria_mutation_conflict",
984
- reason: "replacement_and_additive_mutation_combined",
985
- nextSteps: [
986
- "Use --acceptance-criteria alone to replace the complete list.",
987
- "Use --remove-ac <old> --add-ac <new> to repair one criterion without replacing unrelated entries.",
988
- ],
989
- });
990
- }
991
- if (options.replaceDeps === true &&
992
- (options.dep === undefined || options.dep.length === 0)) {
993
- throw new PmCliError("--replace-deps requires at least one --dep entry", EXIT_CODE.USAGE);
994
- }
995
- if (options.replaceDeps === true &&
996
- options.depRemove !== undefined &&
997
- options.depRemove.length > 0) {
998
- throw new PmCliError("--replace-deps cannot be combined with --dep-remove", EXIT_CODE.USAGE);
999
- }
1000
- validateLinkedArtifactReplacement({
1001
- enabled: options.replaceTests === true,
1002
- values: options.test,
1003
- replaceFlag: "--replace-tests",
1004
- clearEnabled: options.clearTests === true,
1005
- clearFlag: "--clear-tests",
1006
- valueFlag: "--test",
1007
- });
1008
- validateLinkedArtifactReplacement({
1009
- enabled: options.replaceFiles === true,
1010
- values: options.file,
1011
- replaceFlag: "--replace-files",
1012
- clearEnabled: options.clearFiles === true,
1013
- clearFlag: "--clear-files",
1014
- valueFlag: "--file",
1015
- });
1016
- validateLinkedArtifactReplacement({
1017
- enabled: options.replaceDocs === true,
1018
- values: options.doc,
1019
- replaceFlag: "--replace-docs",
1020
- clearEnabled: options.clearDocs === true,
1021
- clearFlag: "--clear-docs",
1022
- valueFlag: "--doc",
1023
- });
1024
- }
1025
- function applyClearCollectionDefinitions(params) {
1026
- for (const definition of params.definitions) {
1027
- if (!definition.enabled) {
1028
- continue;
1029
- }
1030
- const isReplacement = (definition.optionKey === "dep" && params.options.replaceDeps === true) ||
1031
- (definition.optionKey === "test" &&
1032
- params.options.replaceTests === true) ||
1033
- (definition.optionKey === "file" &&
1034
- params.options.replaceFiles === true) ||
1035
- (definition.optionKey === "doc" && params.options.replaceDocs === true);
1036
- if (definition.values && definition.values.length > 0 && !isReplacement) {
1037
- throw new PmCliError(`Cannot combine ${definition.clearFlag} with ${definition.valueFlag}`, EXIT_CODE.USAGE);
1038
- }
1039
- params.clearOptionKeys.add(definition.optionKey);
1040
- params.clearItemMetadataKeys.add(definition.metadataKey);
1041
- }
1042
- }
1043
- function buildScalarOptionPresence(options) {
1044
- const presence = {};
1045
- for (const key of UPDATE_LEGACY_SCALAR_OPTION_KEYS) {
1046
- presence[String(key)] = options[key] !== undefined;
1047
- }
1048
- presence.order = options.order !== undefined || options.rank !== undefined;
1049
- return presence;
1050
- }
1051
- function rejectUnsetScalarConflicts(options, unsetTargets) {
1052
- const scalarOptionPresence = buildScalarOptionPresence(options);
1053
- for (const [optionKey, hasValue] of Object.entries(scalarOptionPresence)) {
1054
- if (!hasValue || !unsetTargets.optionKeys.has(optionKey)) {
1055
- continue;
1056
- }
1057
- const unsetField = UPDATE_OPTION_KEY_TO_UNSET_CANONICAL.get(optionKey) ?? optionKey;
1058
- throw new PmCliError(`Cannot combine --unset ${unsetField} with ${commandOptionFlagLabel("update", optionKey)}`, EXIT_CODE.USAGE);
1059
- }
1060
- if (unsetTargets.metadataKeys.has("acceptance_criteria")) {
1061
- if (Array.isArray(options.addAc) && options.addAc.length > 0) {
1062
- throw new PmCliError("Cannot combine --unset acceptance-criteria with --add-ac", EXIT_CODE.USAGE);
1063
- }
1064
- if (Array.isArray(options.removeAc) && options.removeAc.length > 0) {
1065
- throw new PmCliError("Cannot combine --unset acceptance-criteria with --remove-ac", EXIT_CODE.USAGE);
1066
- }
1067
- }
1068
- if (!unsetTargets.metadataKeys.has("tags")) {
1069
- return;
1070
- }
1071
- if (Array.isArray(options.addTags) && options.addTags.length > 0) {
1072
- throw new PmCliError("Cannot combine --unset tags with --add-tags", EXIT_CODE.USAGE);
1073
- }
1074
- if (Array.isArray(options.removeTags) && options.removeTags.length > 0) {
1075
- throw new PmCliError("Cannot combine --unset tags with --remove-tags", EXIT_CODE.USAGE);
1076
- }
1077
- }
1078
- function rejectLegacyScalarTokens(options) {
1079
- const assertNoLegacyScalarToken = (value, optionKey) => {
1080
- const unsetField = UPDATE_OPTION_KEY_TO_UNSET_CANONICAL.get(optionKey);
1081
- const hint = unsetField
1082
- ? `Use --unset ${unsetField} to clear this field.`
1083
- : undefined;
1084
- assertNoLegacyNoneToken(value, commandOptionFlagLabel("update", optionKey), hint);
1085
- };
1086
- for (const key of UPDATE_LEGACY_SCALAR_OPTION_KEYS) {
1087
- assertNoLegacyScalarToken(options[key], String(key));
1088
- }
1089
- assertNoLegacyScalarToken(options.order ?? options.rank, "order");
1090
- assertNoLegacyNoneTokens(options.reminder, "--reminder", "Use --clear-reminders to clear reminders.");
1091
- assertNoLegacyNoneTokens(options.event, "--event", "Use --clear-events to clear linked events.");
1092
- }
1093
- function buildUpdateFieldFlags(options, runtimeFieldUpdates) {
1094
- const flags = {};
1095
- for (const key of UPDATE_SIMPLE_FIELD_FLAG_KEYS) {
1096
- flags[String(key)] = options[key] !== undefined;
1097
- }
1098
- flags.tags = options.tags !== undefined;
1099
- flags.addTags = Array.isArray(options.addTags) && options.addTags.length > 0;
1100
- flags.removeTags =
1101
- Array.isArray(options.removeTags) && options.removeTags.length > 0;
1102
- flags.addAc = Array.isArray(options.addAc) && options.addAc.length > 0;
1103
- flags.removeAc =
1104
- Array.isArray(options.removeAc) && options.removeAc.length > 0;
1105
- flags.order = options.order !== undefined;
1106
- flags.rank = options.rank !== undefined;
1107
- flags.replaceDeps = options.replaceDeps === true;
1108
- flags.replaceTests = options.replaceTests === true;
1109
- flags.replaceFiles = options.replaceFiles === true;
1110
- flags.replaceDocs = options.replaceDocs === true;
1111
- flags.unset = options.unset !== undefined && options.unset.length > 0;
1112
- flags.clearDeps = options.clearDeps === true;
1113
- flags.clearComments = options.clearComments === true;
1114
- flags.clearNotes = options.clearNotes === true;
1115
- flags.clearLearnings = options.clearLearnings === true;
1116
- flags.clearFiles = options.clearFiles === true;
1117
- flags.clearTests = options.clearTests === true;
1118
- flags.clearDocs = options.clearDocs === true;
1119
- flags.clearReminders = options.clearReminders === true;
1120
- flags.clearEvents = options.clearEvents === true;
1121
- flags.clearTypeOptions = options.clearTypeOptions === true;
1122
- flags.runtimeFields = Object.keys(runtimeFieldUpdates).length > 0;
1123
- return flags;
1124
- }
1125
- async function buildNoopUpdateResult(params) {
1126
- const located = await locateItem(params.pmRoot, params.id, params.settings.id_prefix, params.settings.item_format, params.typeRegistry.type_to_folder);
1127
- if (!located) {
1128
- throw await buildItemNotFoundError(params.pmRoot, params.id, params.settings.id_prefix, params.typeRegistry.type_to_folder);
1129
- }
1130
- const { document } = await readLocatedItem(located, {
1131
- schema: params.settings.schema,
1132
- });
1133
- return {
1134
- item: toItemRecord(document.metadata),
1135
- changed_fields: [],
1136
- warnings: ["noop_no_update_fields"],
1137
- };
1138
- }
1139
- async function loadUpdateRelationshipGraph(params) {
1140
- if (!params.fieldFlags.dep &&
1141
- !params.fieldFlags.blockedBy &&
1142
- !params.fieldFlags.parent &&
1143
- !params.clearedMetadataKeys.has("parent"))
1144
- return undefined;
1145
- return listAllItemMetadataLight(params.pmRoot, params.settings.item_format, params.typeToFolder, undefined, params.settings.schema);
1146
- }
1147
- function assertUpdateHierarchyIntegrity(params) {
1148
- if (!params.before)
1149
- return;
1150
- assertHierarchyMutationAllowed(params.before, params.before.map((item) => item.id === params.document.metadata.id ? params.document.metadata : item), params.document.metadata.id, (status) => isTerminalStatus(status, params.statusRegistry), resolveWorkspaceRelationshipKindRegistry());
1151
- }
1152
- function assertMatchingOrderRank(options) {
1153
- if (options.order !== undefined &&
1154
- options.rank !== undefined &&
1155
- options.order !== options.rank) {
1156
- throw new PmCliError("--order and --rank must match when both are provided", EXIT_CODE.USAGE);
1157
- }
1158
- }
1159
- /** Canonicalize local parent input before self/existence checks; preserve explicit remote locators and explicit unsets. */
1160
- async function resolveParentReferenceForUpdate(params) {
1161
- if (params.options.parent === undefined ||
1162
- params.unsetTargets.metadataKeys.has("parent")) {
1163
- return { resolvedParentValue: undefined, warnings: [] };
1164
- }
1165
- const resolvedParentValue = normalizeItemReference(normalizeParentReferenceValue(params.options.parent), params.settings.id_prefix);
1166
- if (isExternalDependencyReference(resolvedParentValue)) {
1167
- return { resolvedParentValue, warnings: [] };
1168
- }
1169
- assertParentReferenceIsNotSelf(params.id, resolvedParentValue, params.settings.id_prefix);
1170
- const parentLocated = await locateItem(params.pmRoot, resolvedParentValue, params.settings.id_prefix, params.settings.item_format, params.typeRegistry.type_to_folder);
1171
- if (parentLocated) {
1172
- return { resolvedParentValue, warnings: [] };
1173
- }
1174
- const normalizedParentId = normalizeItemId(resolvedParentValue, params.settings.id_prefix);
1175
- return {
1176
- resolvedParentValue,
1177
- warnings: validateMissingParentReference(normalizedParentId, params.parentReferencePolicy).warnings,
1178
- };
1179
- }
1180
- function blockedByResolutionWarnings(resolution) {
1181
- return resolution.unresolved === undefined
1182
- ? []
1183
- : [`blocked_by_unresolved:${resolution.unresolved}`];
1184
- }
1185
- async function collectWorkflowTransitionWarnings(params) {
1186
- if (params.workflowEnforcement === "off" ||
1187
- params.typeWorkflows.length === 0 ||
1188
- !params.fieldFlags.status ||
1189
- params.options.status === undefined) {
1190
- return [];
1191
- }
1192
- const located = await locateItem(params.pmRoot, params.id, params.settings.id_prefix, params.settings.item_format, params.typeRegistry.type_to_folder);
1193
- if (!located) {
1194
- throw await buildItemNotFoundError(params.pmRoot, params.id, params.settings.id_prefix, params.typeRegistry.type_to_folder);
1195
- }
1196
- const { document } = await readLocatedItem(located, {
1197
- schema: params.settings.schema,
1198
- });
1199
- const effectiveType = params.options.type !== undefined
1200
- ? (resolveTypeName(params.options.type, params.typeRegistry) ??
1201
- params.options.type)
1202
- : (document.metadata?.type ?? "");
1203
- const warning = enforceTypeWorkflowTransition({
1204
- enforcement: params.workflowEnforcement,
1205
- typeWorkflows: params.typeWorkflows,
1206
- statusRegistry: params.statusRegistry,
1207
- typeName: effectiveType,
1208
- fromStatus: document.metadata?.status ?? "",
1209
- toStatus: params.options.status,
1210
- });
1211
- return warning ? [warning] : [];
1212
- }
1213
- /** Delegate the configured close transition to the closure writer, applying other requested fields first and retaining its evidence. */
1214
- async function routeCloseStatusUpdate(context) {
1215
- if (!context.fieldFlags.status) {
1216
- return undefined;
1217
- }
1218
- const targetStatus = normalizeStatusInput(context.options.status, context.statusRegistry);
1219
- if (targetStatus !== context.statusRegistry.close_status) {
1220
- return undefined;
1221
- }
1222
- const otherFieldKeys = Object.entries(context.fieldFlags)
1223
- .filter(([key, value]) => value &&
1224
- key !== "status" &&
1225
- key !== "closeReason" &&
1226
- key !== "completedAt")
1227
- .map(([key]) => key);
1228
- const routeWarnings = [];
1229
- let preChangedFields = [];
1230
- if (otherFieldKeys.length > 0) {
1231
- const preUpdateOptions = transferMutationStdinTokenPolicy(context.options, {
1232
- ...context.options,
1233
- status: undefined,
1234
- closeReason: undefined,
1235
- message: undefined,
1236
- });
1237
- const preUpdate = await runUpdate(context.id, preUpdateOptions, context.global);
1238
- preChangedFields = preUpdate.changed_fields;
1239
- routeWarnings.push(...preUpdate.warnings);
1240
- }
1241
- const closeResult = await runClose(context.id, context.options.closeReason, {
1242
- author: context.options.author,
1243
- message: context.options.message,
1244
- force: context.options.force,
1245
- completedAt: context.options.completedAt,
1246
- }, context.global);
1247
- const warnings = [
1248
- ...context.workflowTransitionWarnings,
1249
- ...routeWarnings,
1250
- ...closeResult.warnings,
1251
- "auto_routed_from_update_to_close",
1252
- ];
1253
- return {
1254
- item: closeResult.item,
1255
- changed_fields: [...preChangedFields, ...closeResult.changed_fields],
1256
- warnings,
1257
- };
1258
- }
1259
- function applySimpleItemMutations(document, options, statusRegistry, changedFields) {
1260
- if (options.title !== undefined) {
1261
- document.metadata.title = requireStringOption(options.title, "--title");
1262
- changedFields.push("title");
1263
- }
1264
- if (options.description !== undefined) {
1265
- document.metadata.description = options.description;
1266
- changedFields.push("description");
1267
- }
1268
- if (options.body !== undefined) {
1269
- document.body = options.body;
1270
- changedFields.push("body");
1271
- }
1272
- return (normalizeStatusInput(document.metadata.status, statusRegistry) ??
1273
- document.metadata.status);
1274
- }
1275
- const TERMINAL_EVIDENCE_METADATA_KEYS = [
1276
- "closed_at",
1277
- "completed_at",
1278
- "close_reason",
1279
- "resolution",
1280
- "expected_result",
1281
- "actual_result",
1282
- "fixed_version",
1283
- ];
1284
- /** Remove stale terminal evidence when work returns to an active lifecycle. */
1285
- function clearTerminalEvidence(metadata, changedFields) {
1286
- for (const key of TERMINAL_EVIDENCE_METADATA_KEYS) {
1287
- if (metadata[key] === undefined) {
1288
- continue;
1289
- }
1290
- delete metadata[key];
1291
- changedFields.push(key);
1292
- }
1293
- }
1294
- function applyStatusMutation(document, context, statusInput, previousStatusNormalized, changedFields) {
1295
- const status = parseStatus(statusInput, context.statusRegistry);
1296
- document.metadata.status = status;
1297
- changedFields.push("status");
1298
- if (status === context.statusRegistry.close_status &&
1299
- (document.metadata.closed_at === undefined ||
1300
- document.metadata.closed_at === null)) {
1301
- document.metadata.closed_at = context.nowIso;
1302
- document.metadata.completed_at = context.nowIso;
1303
- changedFields.push("closed_at", "completed_at");
1304
- return;
1305
- }
1306
- if (!isTerminalStatus(status, context.statusRegistry) &&
1307
- isTerminalStatus(previousStatusNormalized, context.statusRegistry)) {
1308
- clearTerminalEvidence(document.metadata, changedFields);
1309
- }
1310
- }
1311
- function applyStatusAndCompletionMutations(document, context, previousStatusNormalized, changedFields) {
1312
- if (context.options.status !== undefined) {
1313
- applyStatusMutation(document, context, context.options.status, previousStatusNormalized, changedFields);
1314
- }
1315
- if (context.options.completedAt !== undefined) {
1316
- if (!isTerminalStatus(document.metadata.status, context.statusRegistry)) {
1317
- throw new PmCliError("--completed-at can only be set on a terminal item", EXIT_CODE.USAGE);
1318
- }
1319
- document.metadata.completed_at = resolveIsoOrRelative(context.options.completedAt, new Date(context.nowIso), "completed-at");
1320
- changedFields.push("completed_at");
1321
- }
1322
- }
1323
- function applyCloseReasonMutations(document, context, previousStatusNormalized, changedFields) {
1324
- if (context.options.closeReason !== undefined ||
1325
- context.clearItemMetadataKeys.has("close_reason")) {
1326
- if (context.clearItemMetadataKeys.has("close_reason")) {
1327
- delete document.metadata.close_reason;
1328
- }
1329
- else {
1330
- const closeReason = context.options.closeReason?.trim() ?? "";
1331
- if (closeReason.length === 0) {
1332
- throw new PmCliError("--close-reason must not be empty", EXIT_CODE.USAGE);
1333
- }
1334
- document.metadata.close_reason = closeReason;
1335
- }
1336
- changedFields.push("close_reason");
1337
- return;
1338
- }
1339
- if (context.options.status !== undefined &&
1340
- isTerminalStatus(previousStatusNormalized, context.statusRegistry) &&
1341
- !isTerminalStatus(document.metadata.status, context.statusRegistry) &&
1342
- document.metadata.close_reason !== undefined) {
1343
- delete document.metadata.close_reason;
1344
- changedFields.push("close_reason");
1345
- }
1346
- }
1347
- function applyStatusAndCloseReasonMutations(document, context, previousStatusNormalized, changedFields) {
1348
- applyStatusAndCompletionMutations(document, context, previousStatusNormalized, changedFields);
1349
- applyCloseReasonMutations(document, context, previousStatusNormalized, changedFields);
1350
- }
1351
- /** Resolve priority and type changes against runtime registries before enforcing type-specific options and recording changed fields. */
1352
- function applyPriorityTypeAndOptions(document, context, changedFields) {
1353
- let activeTypeName = resolveTypeName(document.metadata.type, context.typeRegistry) ??
1354
- document.metadata.type;
1355
- if (context.options.priority !== undefined) {
1356
- document.metadata.priority = resolvePriority(context.options.priority);
1357
- changedFields.push("priority");
1358
- }
1359
- if (context.options.type !== undefined) {
1360
- const resolvedTypeName = resolveTypeName(context.options.type, context.typeRegistry);
1361
- if (!resolvedTypeName) {
1362
- throw new PmCliError(buildInvalidTypeError(context.options.type, context.typeRegistry.types, resolveItemTypesFilePath(context.pmRoot, context.settings.schema)), EXIT_CODE.USAGE);
1363
- }
1364
- document.metadata.type = resolvedTypeName;
1365
- activeTypeName = resolvedTypeName;
1366
- changedFields.push("type");
1367
- }
1368
- enforceUpdateOptionsByType(activeTypeName, context.options, context.typeRegistry, context.runtimeFieldRegistry, context.extensionFieldNames);
1369
- applyTypeOptionMutation(document, context, activeTypeName, changedFields);
1370
- return activeTypeName;
1371
- }
1372
- function applyTypeOptionMutation(document, context, activeTypeName, changedFields) {
1373
- if (context.options.typeOption !== undefined ||
1374
- context.clearItemMetadataKeys.has("type_options")) {
1375
- if (context.clearItemMetadataKeys.has("type_options")) {
1376
- delete document.metadata.type_options;
1377
- }
1378
- else {
1379
- const parsedTypeOptions = parseTypeOptionEntries(context.options.typeOption ?? []);
1380
- const validation = validateTypeOptions(activeTypeName, parsedTypeOptions, context.typeRegistry);
1381
- if (validation.errors.length > 0) {
1382
- throw new PmCliError(validation.errors.join("; "), EXIT_CODE.USAGE);
1383
- }
1384
- document.metadata.type_options = validation.normalized;
1385
- }
1386
- changedFields.push("type_options");
1387
- return;
1388
- }
1389
- if (context.options.type === undefined ||
1390
- document.metadata.type_options === undefined) {
1391
- return;
1392
- }
1393
- const validation = validateTypeOptions(activeTypeName, document.metadata.type_options, context.typeRegistry);
1394
- if (validation.errors.length > 0) {
1395
- throw new PmCliError(`Current type options are incompatible with type "${activeTypeName}". ${validation.errors.join("; ")}. Use --clear-type-options to clear them.`, EXIT_CODE.USAGE);
1396
- }
1397
- document.metadata.type_options = validation.normalized;
1398
- }
1399
- /** Collapse duplicate rows only for identities explicitly touched by this mutation. */
1400
- function normalizeTouchedDependencyIdentities(current, additions) {
1401
- const touchedKeys = new Set(additions.map((entry) => dependencyKey(entry)));
1402
- const retainedStoredIdentities = new Set();
1403
- return current.filter((entry) => {
1404
- if (!touchedKeys.has(dependencyKey(entry))) {
1405
- return true;
1406
- }
1407
- const storedIdentity = storedDependencyIdentityKey(entry);
1408
- if (retainedStoredIdentities.has(storedIdentity)) {
1409
- return false;
1410
- }
1411
- retainedStoredIdentities.add(storedIdentity);
1412
- return true;
1413
- });
1414
- }
1415
- /** Refuse lossless removals unless every selector resolves against stored edges. */
1416
- function assertDependencyRemovalSelectorsMatch(current, selectors, itemId) {
1417
- const unmatchedSelectors = selectors.filter((selector) => !current.some((entry) => matchesDependencySelector(entry, selector)));
1418
- if (unmatchedSelectors.length === 0) {
1419
- return;
1420
- }
1421
- throw new PmCliError(`Dependency removal did not match ${unmatchedSelectors.length === 1 ? "a stored edge" : "stored edges"}.`, EXIT_CODE.NOT_FOUND, {
1422
- code: "dependency_remove_no_match",
1423
- reason: "selector_not_found",
1424
- unmatched_selectors: unmatchedSelectors,
1425
- available_dependencies: current.map((entry) => ({
1426
- id: entry.id,
1427
- kind: entry.kind,
1428
- source_kind: entry.source_kind,
1429
- author: entry.author,
1430
- created_at: entry.created_at,
1431
- })),
1432
- why: "Failing on a zero-match selector prevents a mistyped dependency removal from being reported as successful.",
1433
- nextSteps: [
1434
- `Inspect the current item with: pm get ${itemId} --full`,
1435
- "Retry --dep-remove with the exact id plus any kind, source_kind, author, or created_at selectors needed to identify one stored row.",
1436
- ],
1437
- });
1438
- }
1439
- function applyDependencyMutations(document, context, changedFields) {
1440
- if (context.options.dep === undefined &&
1441
- context.options.depRemove === undefined &&
1442
- !context.clearItemMetadataKeys.has("dependencies")) {
1443
- return;
1444
- }
1445
- let nextDependencies = context.clearItemMetadataKeys.has("dependencies")
1446
- ? []
1447
- : [...(document.metadata.dependencies ?? [])];
1448
- if (context.dependencyUpdates.additions.length > 0) {
1449
- nextDependencies = normalizeTouchedDependencyIdentities(nextDependencies, context.dependencyUpdates.additions);
1450
- const seen = new Set(nextDependencies.map((entry) => dependencyKey(entry)));
1451
- for (const addition of context.dependencyUpdates.additions) {
1452
- const key = dependencyKey(addition);
1453
- if (!seen.has(key)) {
1454
- nextDependencies.push(addition);
1455
- seen.add(key);
1456
- }
1457
- }
1458
- }
1459
- if (context.dependencyRemovals.length > 0) {
1460
- assertDependencyRemovalSelectorsMatch(nextDependencies, context.dependencyRemovals, document.metadata.id);
1461
- nextDependencies = nextDependencies.filter((entry) => !context.dependencyRemovals.some((selector) => matchesDependencySelector(entry, selector)));
1462
- }
1463
- if (nextDependencies.length === 0) {
1464
- delete document.metadata.dependencies;
1465
- }
1466
- else {
1467
- document.metadata.dependencies = nextDependencies;
1468
- }
1469
- changedFields.push("dependencies");
1470
- }
1471
- function applyLogCollectionMutations(document, context, changedFields) {
1472
- applyLogCollectionMutation(document, "comments", context.options.comment, context.commentUpdates.values, context.clearItemMetadataKeys, changedFields);
1473
- applyLogCollectionMutation(document, "notes", context.options.note, context.noteUpdates.values, context.clearItemMetadataKeys, changedFields);
1474
- applyLogCollectionMutation(document, "learnings", context.options.learning, context.learningUpdates.values, context.clearItemMetadataKeys, changedFields);
1475
- }
1476
- function applyLogCollectionMutation(document, key, optionValue, values, clearItemMetadataKeys, changedFields) {
1477
- if (optionValue === undefined && !clearItemMetadataKeys.has(key)) {
1478
- return;
1479
- }
1480
- if (clearItemMetadataKeys.has(key) || !values || values.length === 0) {
1481
- delete document.metadata[key];
1482
- }
1483
- else {
1484
- document.metadata[key] = [
1485
- ...(document.metadata[key] ?? []),
1486
- ...values,
1487
- ];
1488
- }
1489
- changedFields.push(key);
1490
- }
1491
- function applyEvidenceCollectionMutations(document, context, changedFields) {
1492
- applyUniqueLinkedCollectionMutation(document, "files", context.options.file, context.fileUpdates.values, fileKey, context.options.replaceFiles === true, context.clearItemMetadataKeys, changedFields);
1493
- applyTestCollectionMutation(document, context, changedFields);
1494
- applyUniqueLinkedCollectionMutation(document, "docs", context.options.doc, context.docUpdates.values, docKey, context.options.replaceDocs === true, context.clearItemMetadataKeys, changedFields);
1495
- }
1496
- function applyUniqueLinkedCollectionMutation(document, key, optionValue, values, keyOf, replace, clearItemMetadataKeys, changedFields) {
1497
- if (optionValue === undefined && !clearItemMetadataKeys.has(key)) {
1498
- return;
1499
- }
1500
- if (replace) {
1501
- document.metadata[key] = values;
1502
- }
1503
- else if (clearItemMetadataKeys.has(key) || !values || values.length === 0) {
1504
- delete document.metadata[key];
1505
- }
1506
- else {
1507
- const next = [...(document.metadata[key] ?? [])];
1508
- const seen = new Set(next.map((entry) => keyOf(entry)));
1509
- for (const entry of values) {
1510
- const keyValue = keyOf(entry);
1511
- if (!seen.has(keyValue)) {
1512
- next.push(entry);
1513
- seen.add(keyValue);
1514
- }
1515
- }
1516
- document.metadata[key] = next;
1517
- }
1518
- changedFields.push(key);
1519
- }
1520
- function applyTestCollectionMutation(document, context, changedFields) {
1521
- if (context.options.test === undefined &&
1522
- !context.clearItemMetadataKeys.has("tests")) {
1523
- return;
1524
- }
1525
- if (context.clearItemMetadataKeys.has("tests") &&
1526
- context.options.replaceTests === true) {
1527
- document.metadata.tests =
1528
- dedupeLinkedTests(context.testUpdates.values) ?? [];
1529
- }
1530
- else if (context.clearItemMetadataKeys.has("tests") ||
1531
- !context.testUpdates.values ||
1532
- context.testUpdates.values.length === 0) {
1533
- delete document.metadata.tests;
1534
- }
1535
- else {
1536
- document.metadata.tests = dedupeLinkedTests([
1537
- ...(document.metadata.tests ?? []),
1538
- ...context.testUpdates.values,
1539
- ]);
1540
- }
1541
- if (document.metadata.tests !== undefined &&
1542
- document.metadata.tests.length === 0) {
1543
- delete document.metadata.tests;
1544
- }
1545
- changedFields.push("tests");
1546
- }
1547
- function dedupeLinkedTests(values) {
1548
- if (!values || values.length === 0) {
1549
- return undefined;
1550
- }
1551
- const next = [];
1552
- const seen = new Set();
1553
- for (const entry of values) {
1554
- const key = testKey(entry);
1555
- if (!seen.has(key)) {
1556
- next.push(entry);
1557
- seen.add(key);
1558
- }
1559
- }
1560
- return next;
1561
- }
1562
- function applyTagsAndPlanningMutations(document, context, scalarMutationContext) {
1563
- const addTagsValues = context.options.addTags;
1564
- const removeTagsValues = context.options.removeTags;
1565
- const hasAdditiveTagMutation = (Array.isArray(addTagsValues) && addTagsValues.length > 0) ||
1566
- (Array.isArray(removeTagsValues) && removeTagsValues.length > 0);
1567
- if (context.options.tags !== undefined ||
1568
- context.clearItemMetadataKeys.has("tags") ||
1569
- hasAdditiveTagMutation) {
1570
- const baseTags = context.clearItemMetadataKeys.has("tags")
1571
- ? []
1572
- : context.options.tags !== undefined
1573
- ? parseTags(context.options.tags)
1574
- : Array.isArray(document.metadata.tags)
1575
- ? [...document.metadata.tags]
1576
- : [];
1577
- document.metadata.tags = applyTagRemovals(mergeAdditiveTags(baseTags, addTagsValues), removeTagsValues);
1578
- scalarMutationContext.changedFields.push("tags");
1579
- }
1580
- applyUpdateScalarMutations(UPDATE_POST_TAG_SCALAR_MUTATIONS, context.options, scalarMutationContext);
1581
- applyOrderMutation(document, context, scalarMutationContext.changedFields);
1582
- }
1583
- // GH-612: `--add-ac` / `--remove-ac` edit individual "; "-separated criteria so
1584
- // concurrent branch edits with disjoint additions merge instead of clobbering
1585
- // the whole acceptance_criteria value (tag-API parity). Runs after the scalar
1586
- // mutations so composition with a `--ac` replace uses the replaced base.
1587
- function applyAcceptanceCriteriaAdditiveMutation(document, context, scalarMutationContext) {
1588
- const addValues = context.options.addAc;
1589
- const removeValues = context.options.removeAc;
1590
- if (!(Array.isArray(addValues) && addValues.length > 0) &&
1591
- !(Array.isArray(removeValues) && removeValues.length > 0)) {
1592
- return;
1593
- }
1594
- const mutation = applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(document.metadata.acceptance_criteria), addValues, removeValues);
1595
- if (mutation.unmatchedRemovals.length > 0) {
1596
- throw new PmCliError(`Acceptance criteria removal did not match: ${mutation.unmatchedRemovals.join(", ")}`, EXIT_CODE.NOT_FOUND, {
1597
- code: "acceptance_criteria_remove_unmatched",
1598
- reason: "exact_match_not_found",
1599
- field: "acceptance_criteria",
1600
- unmatched: mutation.unmatchedRemovals,
1601
- why: "Lossless removal fails instead of silently applying the remaining mutations when an exact selector is wrong.",
1602
- nextSteps: [
1603
- "Read the current acceptance_criteria value and retry with the exact criterion text.",
1604
- "Use --acceptance-criteria alone only when replacing the complete list is intentional.",
1605
- ],
1606
- });
1607
- }
1608
- const nextValue = mutation.criteria.join("; ");
1609
- if (document.metadata.acceptance_criteria === nextValue) {
1610
- return;
1611
- }
1612
- if (nextValue === "" && document.metadata.acceptance_criteria === undefined) {
1613
- return;
1614
- }
1615
- document.metadata.acceptance_criteria = nextValue;
1616
- if (!scalarMutationContext.changedFields.includes("acceptance_criteria")) {
1617
- scalarMutationContext.changedFields.push("acceptance_criteria");
1618
- }
1619
- }
1620
- function applyOrderMutation(document, context, changedFields) {
1621
- const orderRaw = context.options.order ?? context.options.rank;
1622
- if (orderRaw === undefined && !context.clearItemMetadataKeys.has("order")) {
1623
- return;
1624
- }
1625
- if (context.clearItemMetadataKeys.has("order")) {
1626
- delete document.metadata.order;
1627
- }
1628
- else {
1629
- const parsedOrder = parseOptionalNumber(orderRaw ?? "", "order");
1630
- if (!Number.isInteger(parsedOrder)) {
1631
- throw new PmCliError("Order must be an integer", EXIT_CODE.USAGE);
1632
- }
1633
- document.metadata.order = parsedOrder;
1634
- }
1635
- changedFields.push("order");
1636
- }
1637
- function applyOwnershipAndIssueMutations(document, context, scalarMutationContext, warnings) {
1638
- applyAssigneeMutation(document, context, scalarMutationContext.changedFields);
1639
- applyParentMutation(document, context, scalarMutationContext.changedFields);
1640
- applyUpdateScalarMutations(UPDATE_STAKEHOLDER_SCALAR_MUTATIONS, context.options, scalarMutationContext);
1641
- applySprintReleaseMutation(document, context, "sprint", warnings, scalarMutationContext.changedFields);
1642
- applySprintReleaseMutation(document, context, "release", warnings, scalarMutationContext.changedFields);
1643
- applyBlockedByMutation(document, context, scalarMutationContext.changedFields);
1644
- applyUpdateScalarMutations(UPDATE_ISSUE_SCALAR_MUTATIONS, context.options, scalarMutationContext);
1645
- }
1646
- function applyAssigneeMutation(document, context, changedFields) {
1647
- if (context.options.assignee === undefined &&
1648
- !context.clearItemMetadataKeys.has("assignee")) {
1649
- return;
1650
- }
1651
- if (context.clearItemMetadataKeys.has("assignee")) {
1652
- delete document.metadata.assignee;
1653
- }
1654
- else {
1655
- const assignee = context.options.assignee?.trim() ?? "";
1656
- if (assignee === "") {
1657
- throw new PmCliError("--assignee must not be empty. Use --unset assignee to clear it.", EXIT_CODE.USAGE);
1658
- }
1659
- document.metadata.assignee = assignee;
1660
- }
1661
- changedFields.push("assignee");
1662
- }
1663
- function applyParentMutation(document, context, changedFields) {
1664
- if (context.options.parent === undefined &&
1665
- !context.clearItemMetadataKeys.has("parent")) {
1666
- return;
1667
- }
1668
- if (context.clearItemMetadataKeys.has("parent")) {
1669
- delete document.metadata.parent;
1670
- }
1671
- else {
1672
- document.metadata.parent = context.resolvedParentValue ?? "";
1673
- }
1674
- changedFields.push("parent");
1675
- }
1676
- function applySprintReleaseMutation(document, context, key, warnings, changedFields) {
1677
- if (context.options[key] === undefined &&
1678
- !context.clearItemMetadataKeys.has(key)) {
1679
- return;
1680
- }
1681
- if (context.clearItemMetadataKeys.has(key)) {
1682
- delete document.metadata[key];
1683
- }
1684
- else {
1685
- const validation = validateSprintOrReleaseValue(key, context.options[key] ?? "", context.settings.validation.sprint_release_format);
1686
- document.metadata[key] = validation.value;
1687
- warnings.push(...validation.warnings);
1688
- }
1689
- changedFields.push(key);
1690
- }
1691
- function applyBlockedByMutation(document, context, changedFields) {
1692
- if (context.options.blockedBy === undefined &&
1693
- !context.clearItemMetadataKeys.has("blocked_by")) {
1694
- return;
1695
- }
1696
- if (context.clearItemMetadataKeys.has("blocked_by")) {
1697
- delete document.metadata.blocked_by;
1698
- }
1699
- else {
1700
- document.metadata.blocked_by = context.options.blockedBy?.trim() ?? "";
1701
- }
1702
- changedFields.push("blocked_by");
1703
- if (context.clearItemMetadataKeys.has("blocked_by") ||
1704
- context.resolvedBlockedByDependencyId !== undefined) {
1705
- applyBlockedByDependencyEdge(document.metadata, context.resolvedBlockedByDependencyId, context.nowIso, context.author, changedFields);
1706
- }
1707
- }
1708
- function applyScheduleMutations(document, context, changedFields) {
1709
- if (context.options.reminder !== undefined ||
1710
- context.clearItemMetadataKeys.has("reminders")) {
1711
- if (context.clearItemMetadataKeys.has("reminders")) {
1712
- delete document.metadata.reminders;
1713
- }
1714
- else {
1715
- document.metadata.reminders = parseReminderEntries(context.options.reminder ?? [], context.nowValue, { valueMode: "trimmed" });
1716
- }
1717
- changedFields.push("reminders");
1718
- }
1719
- if (context.options.event !== undefined ||
1720
- context.clearItemMetadataKeys.has("events")) {
1721
- if (context.clearItemMetadataKeys.has("events")) {
1722
- delete document.metadata.events;
1723
- }
1724
- else {
1725
- document.metadata.events = parseEventEntries(context.options.event ?? [], context.nowValue, {
1726
- allDayEmptyGuard: "truthy",
1727
- recurrenceEmptyNumericGuard: "truthy",
1728
- });
1729
- }
1730
- changedFields.push("events");
1731
- }
1732
- }
1733
- function applyRuntimeAndRegisteredFieldMutations(metadataRecord, context, changedFields) {
1734
- clearDynamicFields(metadataRecord, context.runtimeFieldRegistry.definitions.map((definition) => definition.metadata_key), context.clearItemMetadataKeys, changedFields);
1735
- clearDynamicFields(metadataRecord, context.extensionFieldNames, context.clearItemMetadataKeys, changedFields);
1736
- for (const [fieldKey, fieldValue] of Object.entries(context.runtimeFieldUpdates)) {
1737
- if (context.clearItemMetadataKeys.has(fieldKey)) {
1738
- const fieldFlag = fieldKey.replaceAll("_", "-");
1739
- const definition = context.runtimeFieldRegistry.definitions.find((candidate) => candidate.metadata_key === fieldKey);
1740
- const updateFlag = definition?.cli_flag ?? fieldFlag;
1741
- throw new PmCliError(`Cannot combine --unset ${fieldFlag} with --${updateFlag}`, EXIT_CODE.USAGE);
1742
- }
1743
- if (stableValueEquals(metadataRecord[fieldKey], fieldValue)) {
1744
- continue;
1745
- }
1746
- metadataRecord[fieldKey] = fieldValue;
1747
- changedFields.push(fieldKey);
1748
- }
1749
- const registeredItemFieldUpdates = parseRegisteredItemFieldAssignments(context.options.field, context.extensionRegistrations);
1750
- for (const fieldKey of Object.keys(registeredItemFieldUpdates)) {
1751
- if (context.clearItemMetadataKeys.has(fieldKey)) {
1752
- throw new PmCliError(`Cannot combine --unset ${fieldKey.replaceAll("_", "-")} with --field ${fieldKey}=...`, EXIT_CODE.USAGE);
1753
- }
1754
- }
1755
- for (const [fieldKey, fieldValue] of Object.entries(registeredItemFieldUpdates)) {
1756
- if (!stableValueEquals(metadataRecord[fieldKey], fieldValue)) {
1757
- metadataRecord[fieldKey] = fieldValue;
1758
- changedFields.push(fieldKey);
1759
- }
1760
- }
1761
- }
1762
- function clearDynamicFields(metadataRecord, fieldKeys, clearItemMetadataKeys, changedFields) {
1763
- for (const fieldKey of fieldKeys) {
1764
- if (!clearItemMetadataKeys.has(fieldKey) ||
1765
- metadataRecord[fieldKey] === undefined) {
1766
- continue;
1767
- }
1768
- delete metadataRecord[fieldKey];
1769
- changedFields.push(fieldKey);
1770
- }
1771
- }
1772
- function mutateUpdateDocument(document, context) {
1773
- const beforeMetadata = structuredClone(toItemRecord(document.metadata));
1774
- const beforeBody = document.body;
1775
- const changedFields = [];
1776
- const warnings = [];
1777
- const previousStatusNormalized = applySimpleItemMutations(document, context.options, context.statusRegistry, changedFields);
1778
- const metadataRecord = toItemRecord(document.metadata);
1779
- const scalarMutationContext = {
1780
- metadataRecord,
1781
- clearItemMetadataKeys: context.clearItemMetadataKeys,
1782
- changedFields,
1783
- nowValue: context.nowValue,
1784
- };
1785
- applyStatusAndCloseReasonMutations(document, context, previousStatusNormalized, changedFields);
1786
- applyPriorityTypeAndOptions(document, context, changedFields);
1787
- applyDependencyMutations(document, context, changedFields);
1788
- applyLogCollectionMutations(document, context, changedFields);
1789
- applyEvidenceCollectionMutations(document, context, changedFields);
1790
- applyTagsAndPlanningMutations(document, context, scalarMutationContext);
1791
- applyAcceptanceCriteriaAdditiveMutation(document, context, scalarMutationContext);
1792
- applyOwnershipAndIssueMutations(document, context, scalarMutationContext, warnings);
1793
- if (context.options.dep !== undefined ||
1794
- context.options.depRemove !== undefined ||
1795
- context.options.blockedBy !== undefined ||
1796
- context.clearItemMetadataKeys.has("dependencies") ||
1797
- context.clearItemMetadataKeys.has("blocked_by")) {
1798
- assertDependencyEdgesAllowed(document.metadata.id, document.metadata.dependencies);
1799
- }
1800
- if (normalizeStatusInput(document.metadata.status, context.statusRegistry) ===
1801
- context.statusRegistry.canceled_status &&
1802
- document.metadata.assignee !== undefined) {
1803
- delete document.metadata.assignee;
1804
- if (!changedFields.includes("assignee")) {
1805
- changedFields.push("assignee");
1806
- }
1807
- }
1808
- applyScheduleMutations(document, context, changedFields);
1809
- applyRuntimeAndRegisteredFieldMutations(metadataRecord, context, changedFields);
1810
- try {
1811
- applyRegisteredItemFieldDefaultsAndValidation(metadataRecord, context.extensionRegistrations, { skipDefaultFields: context.clearItemMetadataKeys });
1812
- }
1813
- catch (error) {
1814
- throw new PmCliError(error instanceof Error
1815
- ? error.message
1816
- : "Invalid extension item field values", EXIT_CODE.USAGE);
1817
- }
1818
- const afterMetadata = toItemRecord(document.metadata);
1819
- const actualChangedFields = [...new Set(changedFields)].filter((field) => field === "body"
1820
- ? document.body !== beforeBody
1821
- : !stableValueEquals(beforeMetadata[field], afterMetadata[field]));
1822
- if (context.options.acceptanceCriteria !== undefined &&
1823
- actualChangedFields.includes("acceptance_criteria")) {
1824
- warnings.push(`acceptance_criteria_replaced:${splitAcceptanceCriteria(beforeMetadata.acceptance_criteria).length}:${splitAcceptanceCriteria(afterMetadata.acceptance_criteria).length}`);
1825
- }
1826
- return { changedFields: actualChangedFields, warnings };
1827
- }
1828
- /** Implements run update for the public runtime surface of this module. */
1829
- async function runUpdateWithContext(id, options, global, execution = {}) {
1830
- options = await resolveUpdateTransportOptions(options);
1831
- const pmRoot = resolvePmRoot(process.cwd(), global.path);
1832
- await assertInitializedTracker(pmRoot);
1833
- const settings = await readSettings(pmRoot);
1834
- const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
1835
- const runtimeFieldRegistry = resolveRuntimeFieldRegistry(settings.schema);
1836
- const extensionRegistrations = getActiveExtensionRegistrations();
1837
- const extensionFieldNames = collectRegisteredItemFieldNames(extensionRegistrations);
1838
- const typeRegistry = resolveItemTypeRegistry(settings, extensionRegistrations);
1839
- // Per-type allowed-transition enforcement is read RAW (not preset-derived) so
1840
- // existing projects are unaffected when unset; defaults to "off".
1841
- const workflowEnforcement = settings.governance.workflow_enforcement ?? "off";
1842
- const typeWorkflows = workflowEnforcement === "off" ? [] : resolveTypeWorkflows(settings.schema);
1843
- const parentReferencePolicy = [
1844
- {
1845
- strict_error: "strict_error",
1846
- warn: "warn",
1847
- off: "off",
1848
- },
1849
- {
1850
- strict_error: "warn",
1851
- warn: "warn",
1852
- off: "off",
1853
- },
1854
- ][Number(options.allowMissingParent === true)][settings.validation.parent_reference];
1855
- const unsetTargets = parseUpdateUnsetTargets(options.unset, runtimeFieldRegistry, extensionFieldNames);
1856
- const clearOptionKeys = new Set(unsetTargets.optionKeys);
1857
- const clearItemMetadataKeys = new Set(unsetTargets.metadataKeys);
1858
- assertUpdateMutationOptionCombinations(options);
1859
- applyClearCollectionDefinitions({
1860
- definitions: buildClearCollectionDefinitions(options),
1861
- options,
1862
- clearOptionKeys,
1863
- clearItemMetadataKeys,
1864
- });
1865
- enforceOwnershipBypassScope(id, options, clearItemMetadataKeys);
1866
- rejectUnsetScalarConflicts(options, unsetTargets);
1867
- rejectLegacyScalarTokens(options);
1868
- const author = resolveAuthor(options.author, settings.author_default);
1869
- const nowValue = new Date();
1870
- const nowIso = nowValue.toISOString();
1871
- const dependencyUpdates = parseDependencyAdditions(options.dep, settings.id_prefix, nowIso, author);
1872
- assertDependencyEdgesAllowed(id, dependencyUpdates.additions);
1873
- const dependencyTargetWarnings = await assertDependencyTargetsResolvable({
1874
- pmRoot,
1875
- dependencies: dependencyUpdates.additions,
1876
- idPrefix: settings.id_prefix,
1877
- itemFormat: settings.item_format,
1878
- typeToFolder: typeRegistry.type_to_folder,
1879
- allowUnresolved: options.allowUnresolvedDeps,
1880
- holders: [{ id }],
1881
- schema: settings.schema,
1882
- });
1883
- const dependencyRemovals = parseDependencyRemovals(options.depRemove, settings.id_prefix);
1884
- const parsedCommentUpdates = parseLogSeed("--comment", options.comment, nowIso, author);
1885
- const commentUpdates = options.ownershipMetadataBypass === true && parsedCommentUpdates.values
1886
- ? {
1887
- ...parsedCommentUpdates,
1888
- values: parsedCommentUpdates.values.map((entry) => ({
1889
- ...entry,
1890
- author,
1891
- })),
1892
- }
1893
- : parsedCommentUpdates;
1894
- const noteUpdates = parseLogSeed("--note", options.note, nowIso, author);
1895
- const learningUpdates = parseLogSeed("--learning", options.learning, nowIso, author);
1896
- const fileUpdates = parseFiles(options.file);
1897
- const testUpdates = parseTests(options.test);
1898
- testUpdates.values = await attachLinkedTestMutationProvenance(testUpdates.values, author, nowIso);
1899
- const docUpdates = parseDocs(options.doc);
1900
- const workflowTransitionWarnings = [];
1901
- const parentReference = await resolveParentReferenceForUpdate({
1902
- id,
1903
- options,
1904
- unsetTargets,
1905
- pmRoot,
1906
- settings,
1907
- typeRegistry,
1908
- parentReferencePolicy,
1909
- });
1910
- // pm-kyd6: resolve the --blocked-by target up front (async) so the sync
1911
- // mutate callback can mirror create.ts and add a `blocked_by` dependency edge.
1912
- const blockedByResolution = await resolveBlockedByDependencyTarget(options.blockedBy, clearItemMetadataKeys.has("blocked_by"), pmRoot, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);
1913
- const resolvedBlockedByDependencyId = blockedByResolution.id;
1914
- const parentReferenceWarnings = [
1915
- ...parentReference.warnings,
1916
- ...blockedByResolutionWarnings(blockedByResolution),
1917
- ];
1918
- const runtimeFieldUpdates = collectRuntimeUpdateFieldValues(options, runtimeFieldRegistry, options.runtimeFieldCommands);
1919
- const fieldFlags = buildUpdateFieldFlags(options, runtimeFieldUpdates);
1920
- const changedFlags = Object.values(fieldFlags).some(Boolean);
1921
- if (!changedFlags) {
1922
- return buildNoopUpdateResult({ pmRoot, id, settings, typeRegistry });
1923
- }
1924
- workflowTransitionWarnings.push(...(await collectWorkflowTransitionWarnings({
1925
- options,
1926
- fieldFlags,
1927
- workflowEnforcement,
1928
- typeWorkflows,
1929
- statusRegistry,
1930
- typeRegistry,
1931
- pmRoot,
1932
- id,
1933
- settings,
1934
- })));
1935
- const routedClose = await routeCloseStatusUpdate({
1936
- options,
1937
- fieldFlags,
1938
- statusRegistry,
1939
- workflowTransitionWarnings,
1940
- global,
1941
- id,
1942
- });
1943
- if (routedClose) {
1944
- return routedClose;
1945
- }
1946
- assertMatchingOrderRank(options);
1947
- const relationshipRegistry = resolveWorkspaceRelationshipKindRegistry();
1948
- const hierarchyMutationRequired = (fieldFlags.parent && !clearItemMetadataKeys.has("parent")) ||
1949
- dependencyUpdates.additions.some((dependency) => relationshipRegistry.resolve(dependency.kind)?.hierarchy);
1950
- const releaseHierarchyMutationLock = await acquireHierarchyMutationLock({
1951
- pmRoot,
1952
- author,
1953
- ttlSeconds: settings.locks.ttl_seconds,
1954
- waitMs: settings.locks.wait_ms,
1955
- required: hierarchyMutationRequired,
1956
- });
1957
- try {
1958
- let graphBeforeUpdate = await loadUpdateRelationshipGraph({
1959
- fieldFlags,
1960
- clearedMetadataKeys: clearItemMetadataKeys,
1961
- pmRoot,
1962
- settings,
1963
- typeToFolder: typeRegistry.type_to_folder,
1964
- });
1965
- let lifecycleTransition;
1966
- let recurrenceHistoryContext;
1967
- const result = await mutateItemWithHistoryContextResolver({
1968
- pmRoot,
1969
- settings,
1970
- typeToFolder: typeRegistry.type_to_folder,
1971
- id,
1972
- op: resolveUpdateHistoryOperation(options, execution),
1973
- author,
1974
- message: options.message,
1975
- resolveHistoryContext: () => recurrenceHistoryContext,
1976
- force: options.force,
1977
- bypassAssigneeConflict: options.ownershipMetadataBypass === true ||
1978
- options.ownershipDependencyBypass === true,
1979
- extensionFieldNames,
1980
- skipNoop: true,
1981
- mutate(document) {
1982
- lifecycleTransition = prepareRecurrenceTransition({
1983
- document,
1984
- recurrenceReason: execution.recurrenceReason,
1985
- requestedStatus: options.status,
1986
- statusRegistry,
1987
- });
1988
- recurrenceHistoryContext = lifecycleTransition
1989
- ? { recurrence: lifecycleTransition }
1990
- : undefined;
1991
- graphBeforeUpdate = graphBeforeUpdate?.map((item) => item.id === document.metadata.id
1992
- ? structuredClone(document.metadata)
1993
- : item);
1994
- const mutation = mutateUpdateDocument(document, {
1995
- options,
1996
- settings,
1997
- typeRegistry,
1998
- statusRegistry,
1999
- runtimeFieldRegistry,
2000
- extensionRegistrations,
2001
- extensionFieldNames,
2002
- clearItemMetadataKeys,
2003
- dependencyUpdates,
2004
- dependencyRemovals,
2005
- commentUpdates,
2006
- noteUpdates,
2007
- learningUpdates,
2008
- fileUpdates,
2009
- testUpdates,
2010
- docUpdates,
2011
- resolvedParentValue: parentReference.resolvedParentValue,
2012
- resolvedBlockedByDependencyId,
2013
- runtimeFieldUpdates,
2014
- nowValue,
2015
- nowIso,
2016
- author,
2017
- pmRoot,
2018
- });
2019
- assertUpdateHierarchyIntegrity({
2020
- before: graphBeforeUpdate,
2021
- document,
2022
- statusRegistry,
2023
- });
2024
- return mutation;
2025
- },
2026
- });
2027
- await releaseHierarchyMutationLock();
2028
- const orderingCycleWarnings = graphBeforeUpdate
2029
- ? collectNewOrderingCycleWarnings(graphBeforeUpdate, graphBeforeUpdate.map((item) => item.id === result.item.id ? result.item : item), result.item.id)
2030
- : [];
2031
- return {
2032
- item: toItemRecord(result.item),
2033
- changed_fields: result.changedFields,
2034
- warnings: [
2035
- ...workflowTransitionWarnings,
2036
- ...parentReferenceWarnings,
2037
- ...dependencyTargetWarnings,
2038
- ...orderingCycleWarnings,
2039
- ...result.warnings,
2040
- ],
2041
- ...(lifecycleTransition === undefined
2042
- ? {}
2043
- : { lifecycle_transition: lifecycleTransition }),
2044
- };
2045
- }
2046
- finally {
2047
- await releaseHierarchyMutationLock();
2048
- }
2049
- }
2050
- /** Resolve the immutable operation name for ordinary, bypass, and recurrence updates. */
2051
- function resolveUpdateHistoryOperation(options, execution) {
2052
- if (options.ownershipMetadataBypass === true ||
2053
- options.ownershipDependencyBypass === true) {
2054
- return "update_ownership_bypass";
2055
- }
2056
- return execution.recurrenceReason === undefined ? "update" : "reopen";
2057
- }
2058
- /** Validate and capture a terminal-to-active recurrence while the item lock is held. */
2059
- function prepareRecurrenceTransition(params) {
2060
- if (params.recurrenceReason === undefined) {
2061
- return undefined;
2062
- }
2063
- const fromStatus = normalizeStatusInput(params.document.metadata.status, params.statusRegistry) ?? params.document.metadata.status;
2064
- if (!isTerminalStatus(fromStatus, params.statusRegistry)) {
2065
- throw new PmCliError(`Item ${params.document.metadata.id} is already active with status ${fromStatus}; recurrence transitions require a terminal item.`, EXIT_CODE.CONFLICT, {
2066
- code: "item_already_active",
2067
- reason: "recurrence_requires_terminal_item",
2068
- required: "Use item reopen only for a terminal item whose work has recurred.",
2069
- why: "Appending a recurrence event to active work would corrupt lifecycle history.",
2070
- recovery: {
2071
- suggested_retry: `pm get ${params.document.metadata.id} --full`,
2072
- suggested_retry_args: ["get", params.document.metadata.id, "--full"],
2073
- },
2074
- nextSteps: [
2075
- `Inspect the active item with: pm get ${params.document.metadata.id} --full`,
2076
- `Continue the existing work with: pm update ${params.document.metadata.id} ...`,
2077
- ],
2078
- });
2079
- }
2080
- const requestedStatus = params.requestedStatus ?? params.statusRegistry.open_status;
2081
- const toStatus = normalizeStatusInput(requestedStatus, params.statusRegistry) ??
2082
- requestedStatus;
2083
- const metadata = toItemRecord(params.document.metadata);
2084
- const previousTerminal = Object.fromEntries([
2085
- "close_reason",
2086
- "resolution",
2087
- "expected_result",
2088
- "actual_result",
2089
- "fixed_version",
2090
- ].flatMap((key) => {
2091
- const value = metadata[key];
2092
- return typeof value === "string" ? [[key, value]] : [];
2093
- }));
2094
- return {
2095
- reason: params.recurrenceReason,
2096
- from_status: fromStatus,
2097
- to_status: toStatus,
2098
- previous_terminal: previousTerminal,
2099
- };
2100
- }
2101
- /** Implements run update for the public runtime surface of this module. */
2102
- export async function runUpdate(id, options, global) {
2103
- return runUpdateWithContext(id, options, global);
2104
- }
2105
- /** Execute a recurrence transition through the exact atomic update pipeline. */
2106
- export async function runReopenUpdate(id, options, global, recurrenceReason) {
2107
- const result = await runUpdateWithContext(id, options, global, {
2108
- recurrenceReason,
2109
- });
2110
- if (result.lifecycle_transition === undefined) {
2111
- throw new PmCliError(`Item ${id} did not produce the required recurrence receipt.`, EXIT_CODE.GENERIC_FAILURE, {
2112
- code: "reopen_receipt_missing",
2113
- reason: "recurrence_transition_not_recorded",
2114
- required: "A successful reopen must return the terminal-to-active lifecycle transition recorded in immutable history.",
2115
- });
2116
- }
2117
- return { ...result, lifecycle_transition: result.lifecycle_transition };
2118
- }
2119
- /* c8 ignore stop */
2120
- /** Public contract for test only update command, shared by SDK and presentation-layer consumers. */
2121
- export const _testOnlyUpdateCommand = {
2122
- applyStatusAndCloseReasonMutations,
2123
- collectProvidedUpdatePolicyOptions,
2124
- buildOwnershipBypassRestrictedOptionsError,
2125
- enforceOwnershipBypassScope,
2126
- enforceTypeWorkflowTransition,
2127
- matchesDependencySelector,
2128
- normalizeLegacyNoneUpdateOptions,
2129
- normalizeUpdatePolicyOptionKey,
2130
- parseDependencyAdditions,
2131
- parseDependencyRemovals,
2132
- parseUpdateUnsetTargets,
2133
- reconcileBlockedByDependency,
2134
- resolveRuntimeUnsetDefinition: (token, registry) => resolveRuntimeUnsetFieldDefinition(token, "update", registry),
2135
- };
1
+ !(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="80ec599f-7198-5b07-bca2-253f85c137b7")}catch(e2){}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{resolveMutationStdinTokenFields}from"../../core/item/parse.js";import{COMMON_MUTATION_COMMAND_OPTION_KEYS,canonicalizeCommandOptionKey,commandOptionFlagLabel,resolveItemTypeRegistry,resolveCommandOptionPolicyState,resolveTypeDefinition,resolveTypeName,validateTypeOptions,normalizeItemId,toItemRecord,buildInvalidTypeError,assertParentReferenceIsNotSelf,normalizeParentReferenceValue,validateMissingParentReference,validateSprintOrReleaseValue,applyAcceptanceCriteriaMutations,applyTagRemovals,assertNoUnknownCsvKeys,looksLikeGenericKeyValueEntry,mergeAdditiveTags,parseCsvKv,parseOptionalNonNegativeInteger,parseOptionalNumber,parseTags,shouldResolveMutationStdinTokens,transferMutationStdinTokenPolicy,splitAcceptanceCriteria,resolvePriority,normalizeStatusInput,isTerminalStatus,collectRuntimeUpdateFieldValues,resolveItemTypesFilePath,resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry,describeAllowedTransitions,evaluateTransition,resolveTypeWorkflows,EXIT_CODE,PmCliError,stableValueEquals,resolveIsoOrRelative,getActiveExtensionRegistrations,collectRegisteredItemFieldNames,applyRegisteredItemFieldDefaultsAndValidation,parseRegisteredItemFieldAssignments,buildItemNotFoundError,listAllItemMetadataLight,locateItem,readLocatedItem,resolvePmRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{mutateItemWithHistoryContextResolver}from"../../core/store/item-store.js";import{runClose}from"./close.js";import{normalizeRiskInput,normalizeSeverityInput,parseConfidenceInput,parseRegressionInput}from"./metadata-normalizers.js";import{applyLegacyNoneCollectionNormalizers,createLegacyNoneCollectionNormalizers,assertNoLegacyNoneToken,assertNoLegacyNoneTokens,isLegacyNoneToken}from"./legacy-none-tokens.js";import{ensureEnumValue as ensureEnum}from"./recurrence-parsers.js";import{parseEventEntries,parseReminderEntries,parseTypeOptionEntries}from"./repeatable-metadata-parsers.js";import{assertDependencyEdgesAllowed,assertDependencyTargetsResolvable,assertValidBareDependencyFlagValue}from"../dependency-flag-validation.js";import{normalizeDependencySeedId,normalizeItemReference,isExternalDependencyReference,normalizeDependencySourceKind}from"../dependency-provenance.js";import{resolveCanonicalRelationshipKind}from"../relationships.js";import{collectNewOrderingCycleWarnings}from"../graph/mutation-advisory.js";import{assertHierarchyMutationAllowed}from"../graph/hierarchy-integrity.js";import{resolveWorkspaceRelationshipKindRegistry}from"../graph/assembly.js";import{acquireHierarchyMutationLock}from"./hierarchy-mutation-lock.js";import{DEPENDENCY_KIND_VALUES,ISSUE_SEVERITY_VALUES,RISK_VALUES}from"../../types/index.js";import{parseDocs,parseFiles,parseLogSeed,parseTests,requireStringOption}from"./create.js";import{attachLinkedTestMutationProvenance}from"../test/trust.js";import{COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR,COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR,COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON,parseCommandUnsetTargets,resolveRuntimeUnsetFieldDefinition}from"./shared-unset-fields.js";const UPDATE_UNSET_FIELD_DEFINITIONS=[...COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON,{canonical:"close-reason",aliases:["close_reason","close-reason"],optionKey:"closeReason",metadataKey:"close_reason"},...COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR,...COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR];const UPDATE_UNSET_ALIAS_MAP=(()=>{const map=new Map;for(const definition of UPDATE_UNSET_FIELD_DEFINITIONS){for(const alias of definition.aliases){map.set(alias,{optionKey:definition.optionKey,metadataKey:definition.metadataKey})}}return map})();const UPDATE_OPTION_KEY_TO_UNSET_CANONICAL=new Map(UPDATE_UNSET_FIELD_DEFINITIONS.map(definition=>[definition.optionKey,definition.canonical]));const UPDATE_UNSET_SUPPORTED_CANONICAL_FIELDS=UPDATE_UNSET_FIELD_DEFINITIONS.map(definition=>definition.canonical).sort((left,right)=>left.localeCompare(right)).join(", ");const OWNERSHIP_BYPASS_DISALLOWED_UNSET_ITEM_METADATA_KEYS=new Set(["close_reason","assignee","parent","blocked_by","blocked_reason","unblock_note","dependencies","comments","notes","learnings","files","tests","docs","reminders","events"]);const UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS=createLegacyNoneCollectionNormalizers({depDisableFlagKey:"replaceDeps",fileDisableFlagKey:"replaceFiles",testDisableFlagKey:"replaceTests",docDisableFlagKey:"replaceDocs"});function normalizeLegacyNoneUpdateOptions(options){const normalized={...options,unset:options.unset?[...options.unset]:void 0};const appendUnsetTarget=value=>{const current=normalized.unset?[...normalized.unset]:[];if(!current.includes(value)){current.push(value)}normalized.unset=current};const scalarOptionKeys=new Set([...UPDATE_OPTION_KEY_TO_UNSET_CANONICAL.keys(),"rank"]);for(const optionKey of scalarOptionKeys){const candidate=normalized[optionKey];if(typeof candidate!=="string"||!isLegacyNoneToken(candidate)){continue}const canonicalUnset=optionKey==="rank"?"order":UPDATE_OPTION_KEY_TO_UNSET_CANONICAL.get(optionKey)??optionKey;appendUnsetTarget(canonicalUnset);normalized[optionKey]=void 0}return transferMutationStdinTokenPolicy(options,applyLegacyNoneCollectionNormalizers(normalized,UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS))}function parseUpdateUnsetTargets(raw,runtimeFieldRegistry,extensionFieldNames=[]){return parseCommandUnsetTargets({raw,supportedFields:UPDATE_UNSET_SUPPORTED_CANONICAL_FIELDS,resolveDefinition:trimmed=>{const extensionFieldName=extensionFieldNames.find(fieldName=>{const normalizedFieldName=fieldName.toLowerCase();return normalizedFieldName===trimmed||normalizedFieldName.replaceAll("_","-")===trimmed||normalizedFieldName.replaceAll("-","_")===trimmed});const definition=UPDATE_UNSET_ALIAS_MAP.get(trimmed)??resolveRuntimeUnsetFieldDefinition(trimmed,"update",runtimeFieldRegistry)??(extensionFieldName?{optionKey:"field",metadataKey:extensionFieldName}:void 0);return definition}})}const OWNERSHIP_BYPASS_RESTRICTED_FLAG_REPLACEMENTS=new Map([["--comment",id=>`pm comments ${id} --add "<text>" --force`],["--file",id=>`pm files ${id} --add "path=<path>,scope=<scope>,note=<note>" --force`],["--doc",id=>`pm docs ${id} --add "path=<path>,scope=<scope>,note=<note>" --force`]]);function buildOwnershipBypassRestrictedOptionsError(params){const replacementCommands=params.disallowedFlags.flatMap(flag=>{const replacement=OWNERSHIP_BYPASS_RESTRICTED_FLAG_REPLACEMENTS.get(flag);return replacement?[replacement(params.id)]:[]});const replacementSteps=params.disallowedFlags.flatMap(flag=>{const replacement=OWNERSHIP_BYPASS_RESTRICTED_FLAG_REPLACEMENTS.get(flag);return replacement?[`Replace ${flag} with: ${replacement(params.id)}`]:[]});return new PmCliError(params.message,EXIT_CODE.USAGE,{code:params.code,required:params.required,why:params.why,...replacementCommands.length>0?{examples:replacementCommands}:{},nextSteps:[`Re-run without: ${params.disallowedFlags.join(", ")}`,...replacementSteps]})}function enforceOwnershipBypassScope(id,options,clearItemMetadataKeys){const ownershipMetadataBypass=options.ownershipMetadataBypass===true;const ownershipDependencyBypass=options.ownershipDependencyBypass===true;if(!ownershipMetadataBypass&&!ownershipDependencyBypass){return}if(ownershipMetadataBypass&&ownershipDependencyBypass){throw new PmCliError("Choose only one package-provided ownership bypass mode.",EXIT_CODE.USAGE)}const pushIf=(condition,flag,list)=>{if(condition){list.push(flag)}};if(ownershipDependencyBypass){const disallowedFlags2=[];pushIf(options.title!==void 0,"--title",disallowedFlags2);pushIf(options.description!==void 0,"--description",disallowedFlags2);pushIf(options.body!==void 0,"--body",disallowedFlags2);pushIf(options.status!==void 0,"--status",disallowedFlags2);pushIf(options.closeReason!==void 0,"--close-reason",disallowedFlags2);pushIf(options.priority!==void 0,"--priority",disallowedFlags2);pushIf(options.type!==void 0,"--type",disallowedFlags2);pushIf(options.tags!==void 0,"--tags",disallowedFlags2);pushIf(Array.isArray(options.addTags)&&options.addTags.length>0,"--add-tags",disallowedFlags2);pushIf(Array.isArray(options.removeTags)&&options.removeTags.length>0,"--remove-tags",disallowedFlags2);pushIf(options.deadline!==void 0,"--deadline",disallowedFlags2);pushIf(options.estimatedMinutes!==void 0,"--estimate",disallowedFlags2);pushIf(options.acceptanceCriteria!==void 0,"--acceptance-criteria",disallowedFlags2);pushIf(Array.isArray(options.addAc)&&options.addAc.length>0,"--add-ac",disallowedFlags2);pushIf(Array.isArray(options.removeAc)&&options.removeAc.length>0,"--remove-ac",disallowedFlags2);pushIf(options.definitionOfReady!==void 0,"--definition-of-ready",disallowedFlags2);pushIf(options.order!==void 0||options.rank!==void 0,"--order/--rank",disallowedFlags2);pushIf(options.goal!==void 0,"--goal",disallowedFlags2);pushIf(options.objective!==void 0,"--objective",disallowedFlags2);pushIf(options.value!==void 0,"--value",disallowedFlags2);pushIf(options.impact!==void 0,"--impact",disallowedFlags2);pushIf(options.outcome!==void 0,"--outcome",disallowedFlags2);pushIf(options.whyNow!==void 0,"--why-now",disallowedFlags2);pushIf(options.assignee!==void 0,"--assignee",disallowedFlags2);pushIf(options.parent!==void 0,"--parent",disallowedFlags2);pushIf(options.reviewer!==void 0,"--reviewer",disallowedFlags2);pushIf(options.risk!==void 0,"--risk",disallowedFlags2);pushIf(options.confidence!==void 0,"--confidence",disallowedFlags2);pushIf(options.sprint!==void 0,"--sprint",disallowedFlags2);pushIf(options.release!==void 0,"--release",disallowedFlags2);pushIf(options.blockedBy!==void 0,"--blocked-by",disallowedFlags2);pushIf(options.blockedReason!==void 0,"--blocked-reason",disallowedFlags2);pushIf(options.unblockNote!==void 0,"--unblock-note",disallowedFlags2);pushIf(options.reporter!==void 0,"--reporter",disallowedFlags2);pushIf(options.severity!==void 0,"--severity",disallowedFlags2);pushIf(options.environment!==void 0,"--environment",disallowedFlags2);pushIf(options.reproSteps!==void 0,"--repro-steps",disallowedFlags2);pushIf(options.resolution!==void 0,"--resolution",disallowedFlags2);pushIf(options.expectedResult!==void 0,"--expected-result",disallowedFlags2);pushIf(options.actualResult!==void 0,"--actual-result",disallowedFlags2);pushIf(options.affectedVersion!==void 0,"--affected-version",disallowedFlags2);pushIf(options.fixedVersion!==void 0,"--fixed-version",disallowedFlags2);pushIf(options.component!==void 0,"--component",disallowedFlags2);pushIf(options.regression!==void 0,"--regression",disallowedFlags2);pushIf(options.customerImpact!==void 0,"--customer-impact",disallowedFlags2);pushIf(options.depRemove!==void 0,"--dep-remove",disallowedFlags2);pushIf(options.replaceDeps===true,"--replace-deps",disallowedFlags2);pushIf(options.replaceTests===true,"--replace-tests",disallowedFlags2);pushIf(options.replaceFiles===true,"--replace-files",disallowedFlags2);pushIf(options.replaceDocs===true,"--replace-docs",disallowedFlags2);pushIf(options.comment!==void 0,"--comment",disallowedFlags2);pushIf(options.note!==void 0,"--note",disallowedFlags2);pushIf(options.learning!==void 0,"--learning",disallowedFlags2);pushIf(options.file!==void 0,"--file",disallowedFlags2);pushIf(options.test!==void 0,"--test",disallowedFlags2);pushIf(options.doc!==void 0,"--doc",disallowedFlags2);pushIf(options.reminder!==void 0,"--reminder",disallowedFlags2);pushIf(options.event!==void 0,"--event",disallowedFlags2);pushIf(options.typeOption!==void 0,"--type-option",disallowedFlags2);pushIf(options.clearDeps===true,"--clear-deps",disallowedFlags2);pushIf(options.clearComments===true,"--clear-comments",disallowedFlags2);pushIf(options.clearNotes===true,"--clear-notes",disallowedFlags2);pushIf(options.clearLearnings===true,"--clear-learnings",disallowedFlags2);pushIf(options.clearFiles===true,"--clear-files",disallowedFlags2);pushIf(options.clearTests===true,"--clear-tests",disallowedFlags2);pushIf(options.clearDocs===true,"--clear-docs",disallowedFlags2);pushIf(options.clearReminders===true,"--clear-reminders",disallowedFlags2);pushIf(options.clearEvents===true,"--clear-events",disallowedFlags2);pushIf(options.clearTypeOptions===true,"--clear-type-options",disallowedFlags2);pushIf(options.force===true,"--force",disallowedFlags2);pushIf(clearItemMetadataKeys.size>0,"--unset",disallowedFlags2);if(options.dep===void 0||options.dep.length===0){throw new PmCliError("The dependency ownership bypass requires at least one --dep value",EXIT_CODE.USAGE)}if(disallowedFlags2.length>0){throw buildOwnershipBypassRestrictedOptionsError({id,code:"ownership_dependency_bypass_restricted_options",message:`The dependency ownership bypass supports append-only dependency additions via --dep. Remove restricted options: ${disallowedFlags2.join(", ")}`,required:"Pass only --dep additions (plus --message/--author) with the dependency ownership bypass.",why:"the dependency ownership bypass is a narrow non-owner override scoped to append-only dependency additions; every other mutation keeps its normal ownership rules.",disallowedFlags:disallowedFlags2})}return}const disallowedFlags=[];pushIf(options.status!==void 0,"--status",disallowedFlags);pushIf(options.closeReason!==void 0,"--close-reason",disallowedFlags);pushIf(options.assignee!==void 0,"--assignee",disallowedFlags);pushIf(options.parent!==void 0,"--parent",disallowedFlags);pushIf(options.blockedBy!==void 0,"--blocked-by",disallowedFlags);pushIf(options.blockedReason!==void 0,"--blocked-reason",disallowedFlags);pushIf(options.unblockNote!==void 0,"--unblock-note",disallowedFlags);pushIf(options.dep!==void 0,"--dep",disallowedFlags);pushIf(options.depRemove!==void 0,"--dep-remove",disallowedFlags);pushIf(options.replaceDeps===true,"--replace-deps",disallowedFlags);pushIf(options.replaceTests===true,"--replace-tests",disallowedFlags);pushIf(options.replaceFiles===true,"--replace-files",disallowedFlags);pushIf(options.replaceDocs===true,"--replace-docs",disallowedFlags);pushIf(options.note!==void 0,"--note",disallowedFlags);pushIf(options.learning!==void 0,"--learning",disallowedFlags);pushIf(options.test!==void 0,"--test",disallowedFlags);pushIf(options.reminder!==void 0,"--reminder",disallowedFlags);pushIf(options.event!==void 0,"--event",disallowedFlags);pushIf(options.clearDeps===true,"--clear-deps",disallowedFlags);pushIf(options.clearComments===true,"--clear-comments",disallowedFlags);pushIf(options.clearNotes===true,"--clear-notes",disallowedFlags);pushIf(options.clearLearnings===true,"--clear-learnings",disallowedFlags);pushIf(options.clearFiles===true,"--clear-files",disallowedFlags);pushIf(options.clearTests===true,"--clear-tests",disallowedFlags);pushIf(options.clearDocs===true,"--clear-docs",disallowedFlags);pushIf(options.clearReminders===true,"--clear-reminders",disallowedFlags);pushIf(options.clearEvents===true,"--clear-events",disallowedFlags);const disallowedUnset=[...clearItemMetadataKeys].filter(field=>OWNERSHIP_BYPASS_DISALLOWED_UNSET_ITEM_METADATA_KEYS.has(field)).sort((left,right)=>left.localeCompare(right)).map(field=>`--unset ${field.replaceAll("_","-")}`);disallowedFlags.push(...disallowedUnset);if(disallowedFlags.length>0){throw buildOwnershipBypassRestrictedOptionsError({id,code:"ownership_metadata_bypass_restricted_options",message:`The metadata ownership bypass only supports non-lifecycle metadata fields and evidence appends. Remove restricted options: ${disallowedFlags.join(", ")}`,required:"Limit the metadata ownership bypass to non-lifecycle metadata fields plus append-only --comment/--file/--doc evidence; route restricted appends and lifecycle changes through their dedicated commands.",why:"the metadata ownership bypass is a non-owner override scoped to metadata maintenance and append-only evidence; lifecycle, ownership, dependency mutations, restricted append fields, and clear/replace operations keep their normal ownership rules.",disallowedFlags})}}function parseStatus(value,statusRegistry){const normalized=normalizeStatusInput(value,statusRegistry);if(!normalized){const allowedStatuses=statusRegistry.definitions.map(definition=>definition.id);throw new PmCliError(`Invalid --status value "${value}". Allowed: ${allowedStatuses.join(", ")}`,EXIT_CODE.USAGE)}return normalized}function enforceTypeWorkflowTransition(params){if(params.enforcement==="off"||params.typeWorkflows.length===0){return void 0}const result=evaluateTransition({typeName:params.typeName,fromStatus:params.fromStatus,toStatus:params.toStatus,typeWorkflows:params.typeWorkflows,statusRegistry:params.statusRegistry});if(!result.hasRule||result.allowed){return void 0}const normalizedFrom=normalizeStatusInput(params.fromStatus,params.statusRegistry)??params.fromStatus;const normalizedTo=normalizeStatusInput(params.toStatus,params.statusRegistry)??params.toStatus;const message=`Disallowed transition for type "${params.typeName}": ${normalizedFrom} -> ${normalizedTo}. Allowed transitions: ${describeAllowedTransitions(result.allowedTransitions)}.`;if(params.enforcement==="strict"){throw new PmCliError(message,EXIT_CODE.USAGE)}return`workflow_transition_not_allowed: ${message}`}function parseDependencyCreatedAt(value,currentIso){if(!value||value.trim()===""||value.trim().toLowerCase()==="now"){return currentIso}return normalizeDependencyTimestamp(value)}function normalizeDependencyTimestamp(value){const parsed=Date.parse(value);if(!Number.isFinite(parsed)){throw new PmCliError(`Invalid dependency created_at timestamp "${value}"`,EXIT_CODE.USAGE)}return new Date(parsed).toISOString()}function parseOptionalDependencyString(value){if(value===void 0)return void 0;const trimmed=value.trim();return trimmed.length>0?trimmed:void 0}const DEP_ADDITION_KEYS=["id","kind","type","author","created_at","source_kind"];const DEP_REMOVE_KEYS=["id","kind","type","author","created_at","source_kind"];function looksLikeStructuredDependencyEntry(raw){if(raw.startsWith("```")||raw.includes("\n")){return true}if(/^(?:[-*+]\s+)?(?:id|kind|type|author|created_at|source_kind)\s*[:=]/i.test(raw)){return true}return looksLikeGenericKeyValueEntry(raw)}function normalizeDependencyKindInput(raw){return typeof raw==="string"?resolveCanonicalRelationshipKind(raw)??raw.trim():raw}function parseDependencyAdditions(raw,prefix,nowIso,fallbackAuthor){if(!raw){return{additions:[]}}assertNoLegacyNoneTokens(raw,"--dep","Use --clear-deps to clear dependencies.");const additions=raw.map(entry=>{const trimmedEntry=entry.trim();const isStructured=looksLikeStructuredDependencyEntry(trimmedEntry);assertValidBareDependencyFlagValue(trimmedEntry,isStructured);const kv=isStructured?parseCsvKv(entry,"--dep"):{id:trimmedEntry,kind:"related"};if(isStructured){assertNoUnknownCsvKeys(kv,"--dep",DEP_ADDITION_KEYS)}const id=kv.id?.trim();const kind=normalizeDependencyKindInput((kv.kind??kv.type)?.trim());if(!id||!kind){throw new PmCliError("--dep requires id and kind, or a bare item id to add a related dependency",EXIT_CODE.USAGE)}if(id.toLowerCase()==="undefined"){throw new PmCliError(`--dep id must not use placeholder token "${id}". Use --clear-deps to clear dependencies.`,EXIT_CODE.USAGE)}const sourceKind=normalizeDependencySourceKind(parseOptionalDependencyString(kv.source_kind));const explicitAuthor=parseOptionalDependencyString(kv.author);return{id:normalizeDependencySeedId(id,prefix,sourceKind),kind:ensureEnum(kind,DEPENDENCY_KIND_VALUES,"dependency kind","kind"),created_at:parseDependencyCreatedAt(kv.created_at,nowIso),author:explicitAuthor??fallbackAuthor,source_kind:sourceKind??"cli:update:dep",author_source:explicitAuthor?"asserted":"detected"}});return{additions}}function parseDependencyRemovals(raw,prefix){if(!raw){return[]}assertNoLegacyNoneTokens(raw,"--dep-remove");return raw.map(entry=>{const trimmed=entry.trim();if(!trimmed){throw new PmCliError("--dep-remove requires id or key/value selectors",EXIT_CODE.USAGE)}const isStructured=looksLikeStructuredDependencyEntry(trimmed);assertValidBareDependencyFlagValue(trimmed,isStructured,"--dep-remove");if(isStructured){const kv=parseCsvKv(trimmed,"--dep-remove");assertNoUnknownCsvKeys(kv,"--dep-remove",DEP_REMOVE_KEYS);const idRaw=kv.id?.trim();if(!idRaw){throw new PmCliError("--dep-remove key/value form requires id=<value>",EXIT_CODE.USAGE)}if(idRaw.toLowerCase()==="undefined"){throw new PmCliError(`--dep-remove id must not use placeholder token "${idRaw}"`,EXIT_CODE.USAGE)}const kindRaw=normalizeDependencyKindInput(parseOptionalDependencyString(kv.kind??kv.type));const sourceKind=normalizeDependencySourceKind(parseOptionalDependencyString(kv.source_kind));const author=parseOptionalDependencyString(kv.author);const createdAt=parseOptionalDependencyString(kv.created_at);return{id:normalizeDependencySeedId(idRaw,prefix,sourceKind),kind:kindRaw?ensureEnum(kindRaw,DEPENDENCY_KIND_VALUES,"dependency kind","kind"):void 0,source_kind:sourceKind,author,created_at:createdAt?normalizeDependencyTimestamp(createdAt):void 0}}if(trimmed.toLowerCase()==="undefined"){throw new PmCliError(`--dep-remove id must not use placeholder token "${trimmed}"`,EXIT_CODE.USAGE)}return{id:normalizeItemId(trimmed,prefix)}})}function dependencyKey(value){const sourceKind=value.source_kind?.trim().toLowerCase()??"";return[value.id.trim().toLowerCase(),value.kind,sourceKind].join("\0")}function storedDependencyIdentityKey(value){const sourceKind=value.source_kind?.trim().toLowerCase()??"";const author=value.author?.trim().toLowerCase()??"";const rawCreatedAt=value.created_at?.trim()??"";const parsedCreatedAt=Date.parse(rawCreatedAt);const createdAt=Number.isFinite(parsedCreatedAt)?new Date(parsedCreatedAt).toISOString():rawCreatedAt;return[value.id.trim().toLowerCase(),value.kind,sourceKind,author,createdAt].join("\0")}function reconcileBlockedByDependency(current,nextBlockedById,nowIsoValue,author){let next=[...current??[]];let changed=false;if(nextBlockedById===void 0){const filtered=next.filter(dep=>dep.kind!=="blocked_by");if(filtered.length!==next.length){next=filtered;changed=true}if(!changed){return{dependencies:current,changed:false}}return{dependencies:next.length>0?next:void 0,changed:true}}if(!next.some(dep=>dep.kind==="blocked_by"&&dep.id===nextBlockedById)){next.push({id:nextBlockedById,kind:"blocked_by",created_at:nowIsoValue,author,source_kind:"cli:update:blocked_by",author_source:"detected"});changed=true}if(!changed){return{dependencies:current,changed:false}}return{dependencies:next.length>0?next:void 0,changed:true}}async function resolveBlockedByDependencyTarget(blockedByOption,blockedByCleared,pmRoot,idPrefix,itemFormat,typeToFolder){if(blockedByOption===void 0||blockedByCleared){return{}}const blockedByValue=blockedByOption.trim();if(blockedByValue.length===0){return{}}const located=await locateItem(pmRoot,normalizeItemId(blockedByValue,idPrefix),idPrefix,itemFormat,typeToFolder);return located?{id:located.id}:{unresolved:blockedByValue}}function applyBlockedByDependencyEdge(metadata,resolvedBlockedById,nowIsoValue,author,changedFields){const reconciled=reconcileBlockedByDependency(metadata.dependencies,resolvedBlockedById,nowIsoValue,author);if(!reconciled.changed){return}if(reconciled.dependencies===void 0){delete metadata.dependencies}else{metadata.dependencies=reconciled.dependencies}if(!changedFields.includes("dependencies")){changedFields.push("dependencies")}}function fileKey(value){return`${value.path}::${value.scope}`}function docKey(value){return`${value.path}::${value.scope}`}function testKey(value){return`${value.command}::${value.path??""}::${value.scope}::${value.pm_context_mode??""}::${value.workspace_context_mode??""}`}function matchesDependencySelector(value,selector){if(value.id.trim().toLowerCase()!==selector.id.trim().toLowerCase()){return false}if(selector.kind&&value.kind!==selector.kind){return false}if(selector.source_kind!==void 0&&value.source_kind?.trim().toLowerCase()!==selector.source_kind.trim().toLowerCase()){return false}if(selector.author!==void 0&&value.author?.trim().toLowerCase()!==selector.author.trim().toLowerCase()){return false}if(selector.created_at!==void 0&&(value.created_at===void 0||!Number.isFinite(Date.parse(value.created_at))||new Date(Date.parse(value.created_at)).toISOString()!==selector.created_at)){return false}return true}function normalizeUpdatePolicyOptionKey(raw,typeName){const canonical=canonicalizeCommandOptionKey("update",raw);if(!canonical){throw new PmCliError(`Unsupported command_option_policies option "${raw}" for update command on type "${typeName}"`,EXIT_CODE.CONFLICT)}return canonical}function collectProvidedUpdatePolicyOptions(options,runtimeFieldRegistry,extensionFieldNames){const provided=new Set;const mark=(optionKey,isProvided)=>{if(isProvided){provided.add(optionKey)}};mark("title",options.title!==void 0);mark("description",options.description!==void 0);mark("body",options.body!==void 0);mark("status",options.status!==void 0);mark("closeReason",options.closeReason!==void 0);mark("priority",options.priority!==void 0);mark("type",options.type!==void 0);mark("tags",options.tags!==void 0||Array.isArray(options.addTags)&&options.addTags.length>0||Array.isArray(options.removeTags)&&options.removeTags.length>0);mark("deadline",options.deadline!==void 0);mark("estimatedMinutes",options.estimatedMinutes!==void 0);mark("acceptanceCriteria",options.acceptanceCriteria!==void 0||Array.isArray(options.addAc)&&options.addAc.length>0||Array.isArray(options.removeAc)&&options.removeAc.length>0);mark("definitionOfReady",options.definitionOfReady!==void 0);mark("order",options.order!==void 0||options.rank!==void 0);mark("goal",options.goal!==void 0);mark("objective",options.objective!==void 0);mark("value",options.value!==void 0);mark("impact",options.impact!==void 0);mark("outcome",options.outcome!==void 0);mark("whyNow",options.whyNow!==void 0);mark("author",options.author!==void 0);mark("message",options.message!==void 0);mark("assignee",options.assignee!==void 0);mark("parent",options.parent!==void 0);mark("reviewer",options.reviewer!==void 0);mark("risk",options.risk!==void 0);mark("confidence",options.confidence!==void 0);mark("sprint",options.sprint!==void 0);mark("release",options.release!==void 0);mark("blockedBy",options.blockedBy!==void 0);mark("blockedReason",options.blockedReason!==void 0);mark("unblockNote",options.unblockNote!==void 0);mark("reporter",options.reporter!==void 0);mark("severity",options.severity!==void 0);mark("environment",options.environment!==void 0);mark("reproSteps",options.reproSteps!==void 0);mark("resolution",options.resolution!==void 0);mark("expectedResult",options.expectedResult!==void 0);mark("actualResult",options.actualResult!==void 0);mark("affectedVersion",options.affectedVersion!==void 0);mark("fixedVersion",options.fixedVersion!==void 0);mark("component",options.component!==void 0);mark("regression",options.regression!==void 0);mark("customerImpact",options.customerImpact!==void 0);mark("dep",options.dep!==void 0);mark("depRemove",options.depRemove!==void 0);mark("dep",options.replaceDeps===true);mark("comment",options.comment!==void 0);mark("note",options.note!==void 0);mark("learning",options.learning!==void 0);mark("file",options.file!==void 0);mark("test",options.test!==void 0);mark("test",options.replaceTests===true);mark("file",options.replaceFiles===true);mark("doc",options.replaceDocs===true);mark("doc",options.doc!==void 0);mark("reminder",options.reminder!==void 0);mark("event",options.event!==void 0);mark("typeOption",options.typeOption!==void 0);mark("field",options.field!==void 0);mark("force",options.force===true);mark("ownershipMetadataBypass",options.ownershipMetadataBypass===true);mark("ownershipDependencyBypass",options.ownershipDependencyBypass===true);mark("dep",options.clearDeps===true);mark("comment",options.clearComments===true);mark("note",options.clearNotes===true);mark("learning",options.clearLearnings===true);mark("file",options.clearFiles===true);mark("test",options.clearTests===true);mark("doc",options.clearDocs===true);mark("reminder",options.clearReminders===true);mark("event",options.clearEvents===true);mark("typeOption",options.clearTypeOptions===true);if(options.unset&&options.unset.length>0){const unsetTargets=parseUpdateUnsetTargets(options.unset,runtimeFieldRegistry,extensionFieldNames);for(const optionKey of unsetTargets.optionKeys){mark(optionKey,true)}}return provided}function enforceUpdateOptionsByType(typeName,options,typeRegistry,runtimeFieldRegistry,extensionFieldNames){const typeDefinition=resolveTypeDefinition(typeName,typeRegistry);if(!typeDefinition){throw new PmCliError(`Invalid type value "${typeName}"`,EXIT_CODE.USAGE)}const policyState=resolveCommandOptionPolicyState(typeDefinition,"update",[]);if(policyState.errors.length>0){throw new PmCliError(policyState.errors.join("; "),EXIT_CODE.CONFLICT)}const provided=collectProvidedUpdatePolicyOptions(options,runtimeFieldRegistry,extensionFieldNames);for(const disabled of policyState.disabled){if(provided.has(normalizeUpdatePolicyOptionKey(disabled,typeName))){throw new PmCliError(`Option ${commandOptionFlagLabel("update",disabled)} is disabled for type "${typeName}" by command_option_policies`,EXIT_CODE.USAGE)}}for(const required of policyState.required){if(!provided.has(normalizeUpdatePolicyOptionKey(required,typeName))){throw new PmCliError(`Missing required option ${commandOptionFlagLabel("update",required)} for type "${typeName}"`,EXIT_CODE.USAGE)}}}const UPDATE_LEGACY_COMMON_SCALAR_OPTION_EXCLUSIONS=new Set(["order","rank"]);const UPDATE_LEGACY_COMMON_SCALAR_OPTION_KEYS=COMMON_MUTATION_COMMAND_OPTION_KEYS.filter(key=>!UPDATE_LEGACY_COMMON_SCALAR_OPTION_EXCLUSIONS.has(key));const UPDATE_LEGACY_SCALAR_OPTION_KEYS=["tags","closeReason",...UPDATE_LEGACY_COMMON_SCALAR_OPTION_KEYS];const UPDATE_SIMPLE_FIELD_FLAG_KEYS=["title","description","body","status","closeReason","completedAt","priority","type",...COMMON_MUTATION_COMMAND_OPTION_KEYS,"dep","depRemove","comment","note","learning","file","test","doc","reminder","event","typeOption","field"];const UPDATE_POST_TAG_SCALAR_MUTATIONS=[{optionKey:"deadline",metadataKey:"deadline",transform:(value,context)=>resolveIsoOrRelative(value,context.nowValue,"deadline")},{optionKey:"estimatedMinutes",metadataKey:"estimated_minutes",transform:value=>parseOptionalNonNegativeInteger(value,"estimated-minutes")},{optionKey:"acceptanceCriteria",metadataKey:"acceptance_criteria",transform:value=>value},{optionKey:"definitionOfReady",metadataKey:"definition_of_ready"},{optionKey:"goal",metadataKey:"goal"},{optionKey:"objective",metadataKey:"objective"},{optionKey:"value",metadataKey:"value"},{optionKey:"impact",metadataKey:"impact"},{optionKey:"outcome",metadataKey:"outcome"},{optionKey:"whyNow",metadataKey:"why_now"}];const UPDATE_STAKEHOLDER_SCALAR_MUTATIONS=[{optionKey:"reviewer",metadataKey:"reviewer"},{optionKey:"risk",metadataKey:"risk",transform:value=>ensureEnum(normalizeRiskInput(value),RISK_VALUES,"risk")},{optionKey:"confidence",metadataKey:"confidence",transform:value=>parseConfidenceInput(value)}];const UPDATE_ISSUE_SCALAR_MUTATIONS=[{optionKey:"blockedReason",metadataKey:"blocked_reason"},{optionKey:"unblockNote",metadataKey:"unblock_note"},{optionKey:"reporter",metadataKey:"reporter"},{optionKey:"severity",metadataKey:"severity",transform:value=>ensureEnum(normalizeSeverityInput(value),ISSUE_SEVERITY_VALUES,"severity")},{optionKey:"environment",metadataKey:"environment"},{optionKey:"reproSteps",metadataKey:"repro_steps"},{optionKey:"resolution",metadataKey:"resolution"},{optionKey:"expectedResult",metadataKey:"expected_result"},{optionKey:"actualResult",metadataKey:"actual_result"},{optionKey:"affectedVersion",metadataKey:"affected_version"},{optionKey:"fixedVersion",metadataKey:"fixed_version"},{optionKey:"component",metadataKey:"component"},{optionKey:"regression",metadataKey:"regression",transform:value=>parseRegressionInput(value)},{optionKey:"customerImpact",metadataKey:"customer_impact"}];function applyUpdateScalarMutations(definitions,options,context){for(const definition of definitions){const optionValue=options[definition.optionKey];const shouldClear=context.clearItemMetadataKeys.has(definition.metadataKey);if(optionValue===void 0&&!shouldClear){continue}if(shouldClear){delete context.metadataRecord[definition.metadataKey];context.changedFields.push(definition.metadataKey);continue}if(typeof optionValue!=="string"){throw new PmCliError(`${commandOptionFlagLabel("update",String(definition.optionKey))} must be a string value`,EXIT_CODE.USAGE)}context.metadataRecord[definition.metadataKey]=definition.transform?definition.transform(optionValue,context):optionValue.trim();context.changedFields.push(definition.metadataKey)}}async function resolveStdinUpdateOptions(options){const scalarFields=[["body","--body"],["description","--description"]];const listFields=[["dep","--dep"],["depRemove","--dep-remove"],["comment","--comment"],["note","--note"],["learning","--learning"],["file","--file"],["test","--test"],["doc","--doc"],["reminder","--reminder"],["event","--event"],["typeOption","--type-option"],["field","--field"]];return normalizeLegacyNoneUpdateOptions(await resolveMutationStdinTokenFields(options,scalarFields,listFields))}async function resolveUpdateTransportOptions(options){return shouldResolveMutationStdinTokens(options)?await resolveStdinUpdateOptions(options):normalizeLegacyNoneUpdateOptions(options)}function buildClearCollectionDefinitions(options){return[{enabled:options.clearDeps||options.replaceDeps,optionKey:"dep",clearFlag:"--clear-deps",valueFlag:"--dep",values:options.dep,metadataKey:"dependencies"},{enabled:options.clearComments,optionKey:"comment",clearFlag:"--clear-comments",valueFlag:"--comment",values:options.comment,metadataKey:"comments"},{enabled:options.clearNotes,optionKey:"note",clearFlag:"--clear-notes",valueFlag:"--note",values:options.note,metadataKey:"notes"},{enabled:options.clearLearnings,optionKey:"learning",clearFlag:"--clear-learnings",valueFlag:"--learning",values:options.learning,metadataKey:"learnings"},{enabled:options.clearFiles||options.replaceFiles,optionKey:"file",clearFlag:"--clear-files",valueFlag:"--file",values:options.file,metadataKey:"files"},{enabled:options.clearTests||options.replaceTests,optionKey:"test",clearFlag:"--clear-tests",valueFlag:"--test",values:options.test,metadataKey:"tests"},{enabled:options.clearDocs||options.replaceDocs,optionKey:"doc",clearFlag:"--clear-docs",valueFlag:"--doc",values:options.doc,metadataKey:"docs"},{enabled:options.clearReminders,optionKey:"reminder",clearFlag:"--clear-reminders",valueFlag:"--reminder",values:options.reminder,metadataKey:"reminders"},{enabled:options.clearEvents,optionKey:"event",clearFlag:"--clear-events",valueFlag:"--event",values:options.event,metadataKey:"events"},{enabled:options.clearTypeOptions,optionKey:"typeOption",clearFlag:"--clear-type-options",valueFlag:"--type-option",values:options.typeOption,metadataKey:"type_options"}]}function validateLinkedArtifactReplacement(params){if(params.enabled&&(!params.values||params.values.length===0)){throw new PmCliError(`${params.replaceFlag} requires at least one ${params.valueFlag} entry`,EXIT_CODE.USAGE)}if(params.enabled&&params.clearEnabled){throw new PmCliError(`${params.replaceFlag} cannot be combined with ${params.clearFlag}`,EXIT_CODE.USAGE)}}function assertUpdateMutationOptionCombinations(options){const hasAdditiveAcceptanceCriteriaMutation=(options.addAc?.length??0)>0||(options.removeAc?.length??0)>0;if(options.acceptanceCriteria!==void 0&&hasAdditiveAcceptanceCriteriaMutation){throw new PmCliError("Cannot combine --acceptance-criteria replacement with --add-ac or --remove-ac. Use --remove-ac and --add-ac together for an atomic one-entry repair.",EXIT_CODE.USAGE,{code:"acceptance_criteria_mutation_conflict",reason:"replacement_and_additive_mutation_combined",nextSteps:["Use --acceptance-criteria alone to replace the complete list.","Use --remove-ac <old> --add-ac <new> to repair one criterion without replacing unrelated entries."]})}if(options.replaceDeps===true&&(options.dep===void 0||options.dep.length===0)){throw new PmCliError("--replace-deps requires at least one --dep entry",EXIT_CODE.USAGE)}if(options.replaceDeps===true&&options.depRemove!==void 0&&options.depRemove.length>0){throw new PmCliError("--replace-deps cannot be combined with --dep-remove",EXIT_CODE.USAGE)}validateLinkedArtifactReplacement({enabled:options.replaceTests===true,values:options.test,replaceFlag:"--replace-tests",clearEnabled:options.clearTests===true,clearFlag:"--clear-tests",valueFlag:"--test"});validateLinkedArtifactReplacement({enabled:options.replaceFiles===true,values:options.file,replaceFlag:"--replace-files",clearEnabled:options.clearFiles===true,clearFlag:"--clear-files",valueFlag:"--file"});validateLinkedArtifactReplacement({enabled:options.replaceDocs===true,values:options.doc,replaceFlag:"--replace-docs",clearEnabled:options.clearDocs===true,clearFlag:"--clear-docs",valueFlag:"--doc"})}function applyClearCollectionDefinitions(params){for(const definition of params.definitions){if(!definition.enabled){continue}const isReplacement=definition.optionKey==="dep"&&params.options.replaceDeps===true||definition.optionKey==="test"&&params.options.replaceTests===true||definition.optionKey==="file"&&params.options.replaceFiles===true||definition.optionKey==="doc"&&params.options.replaceDocs===true;if(definition.values&&definition.values.length>0&&!isReplacement){throw new PmCliError(`Cannot combine ${definition.clearFlag} with ${definition.valueFlag}`,EXIT_CODE.USAGE)}params.clearOptionKeys.add(definition.optionKey);params.clearItemMetadataKeys.add(definition.metadataKey)}}function buildScalarOptionPresence(options){const presence={};for(const key of UPDATE_LEGACY_SCALAR_OPTION_KEYS){presence[String(key)]=options[key]!==void 0}presence.order=options.order!==void 0||options.rank!==void 0;return presence}function rejectUnsetScalarConflicts(options,unsetTargets){const scalarOptionPresence=buildScalarOptionPresence(options);for(const[optionKey,hasValue]of Object.entries(scalarOptionPresence)){if(!hasValue||!unsetTargets.optionKeys.has(optionKey)){continue}const unsetField=UPDATE_OPTION_KEY_TO_UNSET_CANONICAL.get(optionKey)??optionKey;throw new PmCliError(`Cannot combine --unset ${unsetField} with ${commandOptionFlagLabel("update",optionKey)}`,EXIT_CODE.USAGE)}if(unsetTargets.metadataKeys.has("acceptance_criteria")){if(Array.isArray(options.addAc)&&options.addAc.length>0){throw new PmCliError("Cannot combine --unset acceptance-criteria with --add-ac",EXIT_CODE.USAGE)}if(Array.isArray(options.removeAc)&&options.removeAc.length>0){throw new PmCliError("Cannot combine --unset acceptance-criteria with --remove-ac",EXIT_CODE.USAGE)}}if(!unsetTargets.metadataKeys.has("tags")){return}if(Array.isArray(options.addTags)&&options.addTags.length>0){throw new PmCliError("Cannot combine --unset tags with --add-tags",EXIT_CODE.USAGE)}if(Array.isArray(options.removeTags)&&options.removeTags.length>0){throw new PmCliError("Cannot combine --unset tags with --remove-tags",EXIT_CODE.USAGE)}}function rejectLegacyScalarTokens(options){const assertNoLegacyScalarToken=(value,optionKey)=>{const unsetField=UPDATE_OPTION_KEY_TO_UNSET_CANONICAL.get(optionKey);const hint=unsetField?`Use --unset ${unsetField} to clear this field.`:void 0;assertNoLegacyNoneToken(value,commandOptionFlagLabel("update",optionKey),hint)};for(const key of UPDATE_LEGACY_SCALAR_OPTION_KEYS){assertNoLegacyScalarToken(options[key],String(key))}assertNoLegacyScalarToken(options.order??options.rank,"order");assertNoLegacyNoneTokens(options.reminder,"--reminder","Use --clear-reminders to clear reminders.");assertNoLegacyNoneTokens(options.event,"--event","Use --clear-events to clear linked events.")}function buildUpdateFieldFlags(options,runtimeFieldUpdates){const flags={};for(const key of UPDATE_SIMPLE_FIELD_FLAG_KEYS){flags[String(key)]=options[key]!==void 0}flags.tags=options.tags!==void 0;flags.addTags=Array.isArray(options.addTags)&&options.addTags.length>0;flags.removeTags=Array.isArray(options.removeTags)&&options.removeTags.length>0;flags.addAc=Array.isArray(options.addAc)&&options.addAc.length>0;flags.removeAc=Array.isArray(options.removeAc)&&options.removeAc.length>0;flags.order=options.order!==void 0;flags.rank=options.rank!==void 0;flags.replaceDeps=options.replaceDeps===true;flags.replaceTests=options.replaceTests===true;flags.replaceFiles=options.replaceFiles===true;flags.replaceDocs=options.replaceDocs===true;flags.unset=options.unset!==void 0&&options.unset.length>0;flags.clearDeps=options.clearDeps===true;flags.clearComments=options.clearComments===true;flags.clearNotes=options.clearNotes===true;flags.clearLearnings=options.clearLearnings===true;flags.clearFiles=options.clearFiles===true;flags.clearTests=options.clearTests===true;flags.clearDocs=options.clearDocs===true;flags.clearReminders=options.clearReminders===true;flags.clearEvents=options.clearEvents===true;flags.clearTypeOptions=options.clearTypeOptions===true;flags.runtimeFields=Object.keys(runtimeFieldUpdates).length>0;return flags}async function buildNoopUpdateResult(params){const located=await locateItem(params.pmRoot,params.id,params.settings.id_prefix,params.settings.item_format,params.typeRegistry.type_to_folder);if(!located){throw await buildItemNotFoundError(params.pmRoot,params.id,params.settings.id_prefix,params.typeRegistry.type_to_folder)}const{document}=await readLocatedItem(located,{schema:params.settings.schema});return{item:toItemRecord(document.metadata),changed_fields:[],warnings:["noop_no_update_fields"]}}async function loadUpdateRelationshipGraph(params){if(!params.fieldFlags.dep&&!params.fieldFlags.blockedBy&&!params.fieldFlags.parent&&!params.clearedMetadataKeys.has("parent"))return void 0;return listAllItemMetadataLight(params.pmRoot,params.settings.item_format,params.typeToFolder,void 0,params.settings.schema)}function assertUpdateHierarchyIntegrity(params){if(!params.before)return;assertHierarchyMutationAllowed(params.before,params.before.map(item=>item.id===params.document.metadata.id?params.document.metadata:item),params.document.metadata.id,status=>isTerminalStatus(status,params.statusRegistry),resolveWorkspaceRelationshipKindRegistry())}function assertMatchingOrderRank(options){if(options.order!==void 0&&options.rank!==void 0&&options.order!==options.rank){throw new PmCliError("--order and --rank must match when both are provided",EXIT_CODE.USAGE)}}async function resolveParentReferenceForUpdate(params){if(params.options.parent===void 0||params.unsetTargets.metadataKeys.has("parent")){return{resolvedParentValue:void 0,warnings:[]}}const resolvedParentValue=normalizeItemReference(normalizeParentReferenceValue(params.options.parent),params.settings.id_prefix);if(isExternalDependencyReference(resolvedParentValue)){return{resolvedParentValue,warnings:[]}}assertParentReferenceIsNotSelf(params.id,resolvedParentValue,params.settings.id_prefix);const parentLocated=await locateItem(params.pmRoot,resolvedParentValue,params.settings.id_prefix,params.settings.item_format,params.typeRegistry.type_to_folder);if(parentLocated){return{resolvedParentValue,warnings:[]}}const normalizedParentId=normalizeItemId(resolvedParentValue,params.settings.id_prefix);return{resolvedParentValue,warnings:validateMissingParentReference(normalizedParentId,params.parentReferencePolicy).warnings}}function blockedByResolutionWarnings(resolution){return resolution.unresolved===void 0?[]:[`blocked_by_unresolved:${resolution.unresolved}`]}async function collectWorkflowTransitionWarnings(params){if(params.workflowEnforcement==="off"||params.typeWorkflows.length===0||!params.fieldFlags.status||params.options.status===void 0){return[]}const located=await locateItem(params.pmRoot,params.id,params.settings.id_prefix,params.settings.item_format,params.typeRegistry.type_to_folder);if(!located){throw await buildItemNotFoundError(params.pmRoot,params.id,params.settings.id_prefix,params.typeRegistry.type_to_folder)}const{document}=await readLocatedItem(located,{schema:params.settings.schema});const effectiveType=params.options.type!==void 0?resolveTypeName(params.options.type,params.typeRegistry)??params.options.type:document.metadata?.type??"";const warning=enforceTypeWorkflowTransition({enforcement:params.workflowEnforcement,typeWorkflows:params.typeWorkflows,statusRegistry:params.statusRegistry,typeName:effectiveType,fromStatus:document.metadata?.status??"",toStatus:params.options.status});return warning?[warning]:[]}async function routeCloseStatusUpdate(context){if(!context.fieldFlags.status){return void 0}const targetStatus=normalizeStatusInput(context.options.status,context.statusRegistry);if(targetStatus!==context.statusRegistry.close_status){return void 0}const otherFieldKeys=Object.entries(context.fieldFlags).filter(([key,value])=>value&&key!=="status"&&key!=="closeReason"&&key!=="completedAt").map(([key])=>key);const routeWarnings=[];let preChangedFields=[];if(otherFieldKeys.length>0){const preUpdateOptions=transferMutationStdinTokenPolicy(context.options,{...context.options,status:void 0,closeReason:void 0,message:void 0});const preUpdate=await runUpdate(context.id,preUpdateOptions,context.global);preChangedFields=preUpdate.changed_fields;routeWarnings.push(...preUpdate.warnings)}const closeResult=await runClose(context.id,context.options.closeReason,{author:context.options.author,message:context.options.message,force:context.options.force,completedAt:context.options.completedAt},context.global);const warnings=[...context.workflowTransitionWarnings,...routeWarnings,...closeResult.warnings,"auto_routed_from_update_to_close"];return{item:closeResult.item,changed_fields:[...preChangedFields,...closeResult.changed_fields],warnings}}function applySimpleItemMutations(document,options,statusRegistry,changedFields){if(options.title!==void 0){document.metadata.title=requireStringOption(options.title,"--title");changedFields.push("title")}if(options.description!==void 0){document.metadata.description=options.description;changedFields.push("description")}if(options.body!==void 0){document.body=options.body;changedFields.push("body")}return normalizeStatusInput(document.metadata.status,statusRegistry)??document.metadata.status}const TERMINAL_EVIDENCE_METADATA_KEYS=["closed_at","completed_at","close_reason","resolution","expected_result","actual_result","fixed_version"];function clearTerminalEvidence(metadata,changedFields){for(const key of TERMINAL_EVIDENCE_METADATA_KEYS){if(metadata[key]===void 0){continue}delete metadata[key];changedFields.push(key)}}function applyStatusMutation(document,context,statusInput,previousStatusNormalized,changedFields){const status=parseStatus(statusInput,context.statusRegistry);document.metadata.status=status;changedFields.push("status");if(status===context.statusRegistry.close_status&&(document.metadata.closed_at===void 0||document.metadata.closed_at===null)){document.metadata.closed_at=context.nowIso;document.metadata.completed_at=context.nowIso;changedFields.push("closed_at","completed_at");return}if(!isTerminalStatus(status,context.statusRegistry)&&isTerminalStatus(previousStatusNormalized,context.statusRegistry)){clearTerminalEvidence(document.metadata,changedFields)}}function applyStatusAndCompletionMutations(document,context,previousStatusNormalized,changedFields){if(context.options.status!==void 0){applyStatusMutation(document,context,context.options.status,previousStatusNormalized,changedFields)}if(context.options.completedAt!==void 0){if(!isTerminalStatus(document.metadata.status,context.statusRegistry)){throw new PmCliError("--completed-at can only be set on a terminal item",EXIT_CODE.USAGE)}document.metadata.completed_at=resolveIsoOrRelative(context.options.completedAt,new Date(context.nowIso),"completed-at");changedFields.push("completed_at")}}function applyCloseReasonMutations(document,context,previousStatusNormalized,changedFields){if(context.options.closeReason!==void 0||context.clearItemMetadataKeys.has("close_reason")){if(context.clearItemMetadataKeys.has("close_reason")){delete document.metadata.close_reason}else{const closeReason=context.options.closeReason?.trim()??"";if(closeReason.length===0){throw new PmCliError("--close-reason must not be empty",EXIT_CODE.USAGE)}document.metadata.close_reason=closeReason}changedFields.push("close_reason");return}if(context.options.status!==void 0&&isTerminalStatus(previousStatusNormalized,context.statusRegistry)&&!isTerminalStatus(document.metadata.status,context.statusRegistry)&&document.metadata.close_reason!==void 0){delete document.metadata.close_reason;changedFields.push("close_reason")}}function applyStatusAndCloseReasonMutations(document,context,previousStatusNormalized,changedFields){applyStatusAndCompletionMutations(document,context,previousStatusNormalized,changedFields);applyCloseReasonMutations(document,context,previousStatusNormalized,changedFields)}function applyPriorityTypeAndOptions(document,context,changedFields){let activeTypeName=resolveTypeName(document.metadata.type,context.typeRegistry)??document.metadata.type;if(context.options.priority!==void 0){document.metadata.priority=resolvePriority(context.options.priority);changedFields.push("priority")}if(context.options.type!==void 0){const resolvedTypeName=resolveTypeName(context.options.type,context.typeRegistry);if(!resolvedTypeName){throw new PmCliError(buildInvalidTypeError(context.options.type,context.typeRegistry.types,resolveItemTypesFilePath(context.pmRoot,context.settings.schema)),EXIT_CODE.USAGE)}document.metadata.type=resolvedTypeName;activeTypeName=resolvedTypeName;changedFields.push("type")}enforceUpdateOptionsByType(activeTypeName,context.options,context.typeRegistry,context.runtimeFieldRegistry,context.extensionFieldNames);applyTypeOptionMutation(document,context,activeTypeName,changedFields);return activeTypeName}function applyTypeOptionMutation(document,context,activeTypeName,changedFields){if(context.options.typeOption!==void 0||context.clearItemMetadataKeys.has("type_options")){if(context.clearItemMetadataKeys.has("type_options")){delete document.metadata.type_options}else{const parsedTypeOptions=parseTypeOptionEntries(context.options.typeOption??[]);const validation2=validateTypeOptions(activeTypeName,parsedTypeOptions,context.typeRegistry);if(validation2.errors.length>0){throw new PmCliError(validation2.errors.join("; "),EXIT_CODE.USAGE)}document.metadata.type_options=validation2.normalized}changedFields.push("type_options");return}if(context.options.type===void 0||document.metadata.type_options===void 0){return}const validation=validateTypeOptions(activeTypeName,document.metadata.type_options,context.typeRegistry);if(validation.errors.length>0){throw new PmCliError(`Current type options are incompatible with type "${activeTypeName}". ${validation.errors.join("; ")}. Use --clear-type-options to clear them.`,EXIT_CODE.USAGE)}document.metadata.type_options=validation.normalized}function normalizeTouchedDependencyIdentities(current,additions){const touchedKeys=new Set(additions.map(entry=>dependencyKey(entry)));const retainedStoredIdentities=new Set;return current.filter(entry=>{if(!touchedKeys.has(dependencyKey(entry))){return true}const storedIdentity=storedDependencyIdentityKey(entry);if(retainedStoredIdentities.has(storedIdentity)){return false}retainedStoredIdentities.add(storedIdentity);return true})}function assertDependencyRemovalSelectorsMatch(current,selectors,itemId){const unmatchedSelectors=selectors.filter(selector=>!current.some(entry=>matchesDependencySelector(entry,selector)));if(unmatchedSelectors.length===0){return}throw new PmCliError(`Dependency removal did not match ${unmatchedSelectors.length===1?"a stored edge":"stored edges"}.`,EXIT_CODE.NOT_FOUND,{code:"dependency_remove_no_match",reason:"selector_not_found",unmatched_selectors:unmatchedSelectors,available_dependencies:current.map(entry=>({id:entry.id,kind:entry.kind,source_kind:entry.source_kind,author:entry.author,created_at:entry.created_at})),why:"Failing on a zero-match selector prevents a mistyped dependency removal from being reported as successful.",nextSteps:[`Inspect the current item with: pm get ${itemId} --full`,"Retry --dep-remove with the exact id plus any kind, source_kind, author, or created_at selectors needed to identify one stored row."]})}function applyDependencyMutations(document,context,changedFields){if(context.options.dep===void 0&&context.options.depRemove===void 0&&!context.clearItemMetadataKeys.has("dependencies")){return}let nextDependencies=context.clearItemMetadataKeys.has("dependencies")?[]:[...document.metadata.dependencies??[]];if(context.dependencyUpdates.additions.length>0){nextDependencies=normalizeTouchedDependencyIdentities(nextDependencies,context.dependencyUpdates.additions);const seen=new Set(nextDependencies.map(entry=>dependencyKey(entry)));for(const addition of context.dependencyUpdates.additions){const key=dependencyKey(addition);if(!seen.has(key)){nextDependencies.push(addition);seen.add(key)}}}if(context.dependencyRemovals.length>0){assertDependencyRemovalSelectorsMatch(nextDependencies,context.dependencyRemovals,document.metadata.id);nextDependencies=nextDependencies.filter(entry=>!context.dependencyRemovals.some(selector=>matchesDependencySelector(entry,selector)))}if(nextDependencies.length===0){delete document.metadata.dependencies}else{document.metadata.dependencies=nextDependencies}changedFields.push("dependencies")}function applyLogCollectionMutations(document,context,changedFields){applyLogCollectionMutation(document,"comments",context.options.comment,context.commentUpdates.values,context.clearItemMetadataKeys,changedFields);applyLogCollectionMutation(document,"notes",context.options.note,context.noteUpdates.values,context.clearItemMetadataKeys,changedFields);applyLogCollectionMutation(document,"learnings",context.options.learning,context.learningUpdates.values,context.clearItemMetadataKeys,changedFields)}function applyLogCollectionMutation(document,key,optionValue,values,clearItemMetadataKeys,changedFields){if(optionValue===void 0&&!clearItemMetadataKeys.has(key)){return}if(clearItemMetadataKeys.has(key)||!values||values.length===0){delete document.metadata[key]}else{document.metadata[key]=[...document.metadata[key]??[],...values]}changedFields.push(key)}function applyEvidenceCollectionMutations(document,context,changedFields){applyUniqueLinkedCollectionMutation(document,"files",context.options.file,context.fileUpdates.values,fileKey,context.options.replaceFiles===true,context.clearItemMetadataKeys,changedFields);applyTestCollectionMutation(document,context,changedFields);applyUniqueLinkedCollectionMutation(document,"docs",context.options.doc,context.docUpdates.values,docKey,context.options.replaceDocs===true,context.clearItemMetadataKeys,changedFields)}function applyUniqueLinkedCollectionMutation(document,key,optionValue,values,keyOf,replace,clearItemMetadataKeys,changedFields){if(optionValue===void 0&&!clearItemMetadataKeys.has(key)){return}if(replace){document.metadata[key]=values}else if(clearItemMetadataKeys.has(key)||!values||values.length===0){delete document.metadata[key]}else{const next=[...document.metadata[key]??[]];const seen=new Set(next.map(entry=>keyOf(entry)));for(const entry of values){const keyValue=keyOf(entry);if(!seen.has(keyValue)){next.push(entry);seen.add(keyValue)}}document.metadata[key]=next}changedFields.push(key)}function applyTestCollectionMutation(document,context,changedFields){if(context.options.test===void 0&&!context.clearItemMetadataKeys.has("tests")){return}if(context.clearItemMetadataKeys.has("tests")&&context.options.replaceTests===true){document.metadata.tests=dedupeLinkedTests(context.testUpdates.values)??[]}else if(context.clearItemMetadataKeys.has("tests")||!context.testUpdates.values||context.testUpdates.values.length===0){delete document.metadata.tests}else{document.metadata.tests=dedupeLinkedTests([...document.metadata.tests??[],...context.testUpdates.values])}if(document.metadata.tests!==void 0&&document.metadata.tests.length===0){delete document.metadata.tests}changedFields.push("tests")}function dedupeLinkedTests(values){if(!values||values.length===0){return void 0}const next=[];const seen=new Set;for(const entry of values){const key=testKey(entry);if(!seen.has(key)){next.push(entry);seen.add(key)}}return next}function applyTagsAndPlanningMutations(document,context,scalarMutationContext){const addTagsValues=context.options.addTags;const removeTagsValues=context.options.removeTags;const hasAdditiveTagMutation=Array.isArray(addTagsValues)&&addTagsValues.length>0||Array.isArray(removeTagsValues)&&removeTagsValues.length>0;if(context.options.tags!==void 0||context.clearItemMetadataKeys.has("tags")||hasAdditiveTagMutation){const baseTags=context.clearItemMetadataKeys.has("tags")?[]:context.options.tags!==void 0?parseTags(context.options.tags):Array.isArray(document.metadata.tags)?[...document.metadata.tags]:[];document.metadata.tags=applyTagRemovals(mergeAdditiveTags(baseTags,addTagsValues),removeTagsValues);scalarMutationContext.changedFields.push("tags")}applyUpdateScalarMutations(UPDATE_POST_TAG_SCALAR_MUTATIONS,context.options,scalarMutationContext);applyOrderMutation(document,context,scalarMutationContext.changedFields)}function applyAcceptanceCriteriaAdditiveMutation(document,context,scalarMutationContext){const addValues=context.options.addAc;const removeValues=context.options.removeAc;if(!(Array.isArray(addValues)&&addValues.length>0)&&!(Array.isArray(removeValues)&&removeValues.length>0)){return}const mutation=applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(document.metadata.acceptance_criteria),addValues,removeValues);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,why:"Lossless removal fails instead of silently applying the remaining mutations when an exact selector is wrong.",nextSteps:["Read the current acceptance_criteria value and retry with the exact criterion text.","Use --acceptance-criteria alone only when replacing the complete list is intentional."]})}const nextValue=mutation.criteria.join("; ");if(document.metadata.acceptance_criteria===nextValue){return}if(nextValue===""&&document.metadata.acceptance_criteria===void 0){return}document.metadata.acceptance_criteria=nextValue;if(!scalarMutationContext.changedFields.includes("acceptance_criteria")){scalarMutationContext.changedFields.push("acceptance_criteria")}}function applyOrderMutation(document,context,changedFields){const orderRaw=context.options.order??context.options.rank;if(orderRaw===void 0&&!context.clearItemMetadataKeys.has("order")){return}if(context.clearItemMetadataKeys.has("order")){delete document.metadata.order}else{const parsedOrder=parseOptionalNumber(orderRaw??"","order");if(!Number.isInteger(parsedOrder)){throw new PmCliError("Order must be an integer",EXIT_CODE.USAGE)}document.metadata.order=parsedOrder}changedFields.push("order")}function applyOwnershipAndIssueMutations(document,context,scalarMutationContext,warnings){applyAssigneeMutation(document,context,scalarMutationContext.changedFields);applyParentMutation(document,context,scalarMutationContext.changedFields);applyUpdateScalarMutations(UPDATE_STAKEHOLDER_SCALAR_MUTATIONS,context.options,scalarMutationContext);applySprintReleaseMutation(document,context,"sprint",warnings,scalarMutationContext.changedFields);applySprintReleaseMutation(document,context,"release",warnings,scalarMutationContext.changedFields);applyBlockedByMutation(document,context,scalarMutationContext.changedFields);applyUpdateScalarMutations(UPDATE_ISSUE_SCALAR_MUTATIONS,context.options,scalarMutationContext)}function applyAssigneeMutation(document,context,changedFields){if(context.options.assignee===void 0&&!context.clearItemMetadataKeys.has("assignee")){return}if(context.clearItemMetadataKeys.has("assignee")){delete document.metadata.assignee}else{const assignee=context.options.assignee?.trim()??"";if(assignee===""){throw new PmCliError("--assignee must not be empty. Use --unset assignee to clear it.",EXIT_CODE.USAGE)}document.metadata.assignee=assignee}changedFields.push("assignee")}function applyParentMutation(document,context,changedFields){if(context.options.parent===void 0&&!context.clearItemMetadataKeys.has("parent")){return}if(context.clearItemMetadataKeys.has("parent")){delete document.metadata.parent}else{document.metadata.parent=context.resolvedParentValue??""}changedFields.push("parent")}function applySprintReleaseMutation(document,context,key,warnings,changedFields){if(context.options[key]===void 0&&!context.clearItemMetadataKeys.has(key)){return}if(context.clearItemMetadataKeys.has(key)){delete document.metadata[key]}else{const validation=validateSprintOrReleaseValue(key,context.options[key]??"",context.settings.validation.sprint_release_format);document.metadata[key]=validation.value;warnings.push(...validation.warnings)}changedFields.push(key)}function applyBlockedByMutation(document,context,changedFields){if(context.options.blockedBy===void 0&&!context.clearItemMetadataKeys.has("blocked_by")){return}if(context.clearItemMetadataKeys.has("blocked_by")){delete document.metadata.blocked_by}else{document.metadata.blocked_by=context.options.blockedBy?.trim()??""}changedFields.push("blocked_by");if(context.clearItemMetadataKeys.has("blocked_by")||context.resolvedBlockedByDependencyId!==void 0){applyBlockedByDependencyEdge(document.metadata,context.resolvedBlockedByDependencyId,context.nowIso,context.author,changedFields)}}function applyScheduleMutations(document,context,changedFields){if(context.options.reminder!==void 0||context.clearItemMetadataKeys.has("reminders")){if(context.clearItemMetadataKeys.has("reminders")){delete document.metadata.reminders}else{document.metadata.reminders=parseReminderEntries(context.options.reminder??[],context.nowValue,{valueMode:"trimmed"})}changedFields.push("reminders")}if(context.options.event!==void 0||context.clearItemMetadataKeys.has("events")){if(context.clearItemMetadataKeys.has("events")){delete document.metadata.events}else{document.metadata.events=parseEventEntries(context.options.event??[],context.nowValue,{allDayEmptyGuard:"truthy",recurrenceEmptyNumericGuard:"truthy"})}changedFields.push("events")}}function applyRuntimeAndRegisteredFieldMutations(metadataRecord,context,changedFields){clearDynamicFields(metadataRecord,context.runtimeFieldRegistry.definitions.map(definition=>definition.metadata_key),context.clearItemMetadataKeys,changedFields);clearDynamicFields(metadataRecord,context.extensionFieldNames,context.clearItemMetadataKeys,changedFields);for(const[fieldKey,fieldValue]of Object.entries(context.runtimeFieldUpdates)){if(context.clearItemMetadataKeys.has(fieldKey)){const fieldFlag=fieldKey.replaceAll("_","-");const definition=context.runtimeFieldRegistry.definitions.find(candidate=>candidate.metadata_key===fieldKey);const updateFlag=definition?.cli_flag??fieldFlag;throw new PmCliError(`Cannot combine --unset ${fieldFlag} with --${updateFlag}`,EXIT_CODE.USAGE)}if(stableValueEquals(metadataRecord[fieldKey],fieldValue)){continue}metadataRecord[fieldKey]=fieldValue;changedFields.push(fieldKey)}const registeredItemFieldUpdates=parseRegisteredItemFieldAssignments(context.options.field,context.extensionRegistrations);for(const fieldKey of Object.keys(registeredItemFieldUpdates)){if(context.clearItemMetadataKeys.has(fieldKey)){throw new PmCliError(`Cannot combine --unset ${fieldKey.replaceAll("_","-")} with --field ${fieldKey}=...`,EXIT_CODE.USAGE)}}for(const[fieldKey,fieldValue]of Object.entries(registeredItemFieldUpdates)){if(!stableValueEquals(metadataRecord[fieldKey],fieldValue)){metadataRecord[fieldKey]=fieldValue;changedFields.push(fieldKey)}}}function clearDynamicFields(metadataRecord,fieldKeys,clearItemMetadataKeys,changedFields){for(const fieldKey of fieldKeys){if(!clearItemMetadataKeys.has(fieldKey)||metadataRecord[fieldKey]===void 0){continue}delete metadataRecord[fieldKey];changedFields.push(fieldKey)}}function mutateUpdateDocument(document,context){const beforeMetadata=structuredClone(toItemRecord(document.metadata));const beforeBody=document.body;const changedFields=[];const warnings=[];const previousStatusNormalized=applySimpleItemMutations(document,context.options,context.statusRegistry,changedFields);const metadataRecord=toItemRecord(document.metadata);const scalarMutationContext={metadataRecord,clearItemMetadataKeys:context.clearItemMetadataKeys,changedFields,nowValue:context.nowValue};applyStatusAndCloseReasonMutations(document,context,previousStatusNormalized,changedFields);applyPriorityTypeAndOptions(document,context,changedFields);applyDependencyMutations(document,context,changedFields);applyLogCollectionMutations(document,context,changedFields);applyEvidenceCollectionMutations(document,context,changedFields);applyTagsAndPlanningMutations(document,context,scalarMutationContext);applyAcceptanceCriteriaAdditiveMutation(document,context,scalarMutationContext);applyOwnershipAndIssueMutations(document,context,scalarMutationContext,warnings);if(context.options.dep!==void 0||context.options.depRemove!==void 0||context.options.blockedBy!==void 0||context.clearItemMetadataKeys.has("dependencies")||context.clearItemMetadataKeys.has("blocked_by")){assertDependencyEdgesAllowed(document.metadata.id,document.metadata.dependencies)}if(normalizeStatusInput(document.metadata.status,context.statusRegistry)===context.statusRegistry.canceled_status&&document.metadata.assignee!==void 0){delete document.metadata.assignee;if(!changedFields.includes("assignee")){changedFields.push("assignee")}}applyScheduleMutations(document,context,changedFields);applyRuntimeAndRegisteredFieldMutations(metadataRecord,context,changedFields);try{applyRegisteredItemFieldDefaultsAndValidation(metadataRecord,context.extensionRegistrations,{skipDefaultFields:context.clearItemMetadataKeys})}catch(error){throw new PmCliError(error instanceof Error?error.message:"Invalid extension item field values",EXIT_CODE.USAGE)}const afterMetadata=toItemRecord(document.metadata);const actualChangedFields=[...new Set(changedFields)].filter(field=>field==="body"?document.body!==beforeBody:!stableValueEquals(beforeMetadata[field],afterMetadata[field]));if(context.options.acceptanceCriteria!==void 0&&actualChangedFields.includes("acceptance_criteria")){warnings.push(`acceptance_criteria_replaced:${splitAcceptanceCriteria(beforeMetadata.acceptance_criteria).length}:${splitAcceptanceCriteria(afterMetadata.acceptance_criteria).length}`)}return{changedFields:actualChangedFields,warnings}}async function runUpdateWithContext(id,options,global2,execution={}){options=await resolveUpdateTransportOptions(options);const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);const statusRegistry=resolveRuntimeStatusRegistry(settings.schema);const runtimeFieldRegistry=resolveRuntimeFieldRegistry(settings.schema);const extensionRegistrations=getActiveExtensionRegistrations();const extensionFieldNames=collectRegisteredItemFieldNames(extensionRegistrations);const typeRegistry=resolveItemTypeRegistry(settings,extensionRegistrations);const workflowEnforcement=settings.governance.workflow_enforcement??"off";const typeWorkflows=workflowEnforcement==="off"?[]:resolveTypeWorkflows(settings.schema);const parentReferencePolicy=[{strict_error:"strict_error",warn:"warn",off:"off"},{strict_error:"warn",warn:"warn",off:"off"}][Number(options.allowMissingParent===true)][settings.validation.parent_reference];const unsetTargets=parseUpdateUnsetTargets(options.unset,runtimeFieldRegistry,extensionFieldNames);const clearOptionKeys=new Set(unsetTargets.optionKeys);const clearItemMetadataKeys=new Set(unsetTargets.metadataKeys);assertUpdateMutationOptionCombinations(options);applyClearCollectionDefinitions({definitions:buildClearCollectionDefinitions(options),options,clearOptionKeys,clearItemMetadataKeys});enforceOwnershipBypassScope(id,options,clearItemMetadataKeys);rejectUnsetScalarConflicts(options,unsetTargets);rejectLegacyScalarTokens(options);const author=resolveAuthor(options.author,settings.author_default);const nowValue=new Date;const nowIso=nowValue.toISOString();const dependencyUpdates=parseDependencyAdditions(options.dep,settings.id_prefix,nowIso,author);assertDependencyEdgesAllowed(id,dependencyUpdates.additions);const dependencyTargetWarnings=await assertDependencyTargetsResolvable({pmRoot,dependencies:dependencyUpdates.additions,idPrefix:settings.id_prefix,itemFormat:settings.item_format,typeToFolder:typeRegistry.type_to_folder,allowUnresolved:options.allowUnresolvedDeps,holders:[{id}],schema:settings.schema});const dependencyRemovals=parseDependencyRemovals(options.depRemove,settings.id_prefix);const parsedCommentUpdates=parseLogSeed("--comment",options.comment,nowIso,author);const commentUpdates=options.ownershipMetadataBypass===true&&parsedCommentUpdates.values?{...parsedCommentUpdates,values:parsedCommentUpdates.values.map(entry=>({...entry,author}))}:parsedCommentUpdates;const noteUpdates=parseLogSeed("--note",options.note,nowIso,author);const learningUpdates=parseLogSeed("--learning",options.learning,nowIso,author);const fileUpdates=parseFiles(options.file);const testUpdates=parseTests(options.test);testUpdates.values=await attachLinkedTestMutationProvenance(testUpdates.values,author,nowIso);const docUpdates=parseDocs(options.doc);const workflowTransitionWarnings=[];const parentReference=await resolveParentReferenceForUpdate({id,options,unsetTargets,pmRoot,settings,typeRegistry,parentReferencePolicy});const blockedByResolution=await resolveBlockedByDependencyTarget(options.blockedBy,clearItemMetadataKeys.has("blocked_by"),pmRoot,settings.id_prefix,settings.item_format,typeRegistry.type_to_folder);const resolvedBlockedByDependencyId=blockedByResolution.id;const parentReferenceWarnings=[...parentReference.warnings,...blockedByResolutionWarnings(blockedByResolution)];const runtimeFieldUpdates=collectRuntimeUpdateFieldValues(options,runtimeFieldRegistry,options.runtimeFieldCommands);const fieldFlags=buildUpdateFieldFlags(options,runtimeFieldUpdates);const changedFlags=Object.values(fieldFlags).some(Boolean);if(!changedFlags){return buildNoopUpdateResult({pmRoot,id,settings,typeRegistry})}workflowTransitionWarnings.push(...await collectWorkflowTransitionWarnings({options,fieldFlags,workflowEnforcement,typeWorkflows,statusRegistry,typeRegistry,pmRoot,id,settings}));const routedClose=await routeCloseStatusUpdate({options,fieldFlags,statusRegistry,workflowTransitionWarnings,global:global2,id});if(routedClose){return routedClose}assertMatchingOrderRank(options);const relationshipRegistry=resolveWorkspaceRelationshipKindRegistry();const hierarchyMutationRequired=fieldFlags.parent&&!clearItemMetadataKeys.has("parent")||dependencyUpdates.additions.some(dependency=>relationshipRegistry.resolve(dependency.kind)?.hierarchy);const releaseHierarchyMutationLock=await acquireHierarchyMutationLock({pmRoot,author,ttlSeconds:settings.locks.ttl_seconds,waitMs:settings.locks.wait_ms,required:hierarchyMutationRequired});try{let graphBeforeUpdate=await loadUpdateRelationshipGraph({fieldFlags,clearedMetadataKeys:clearItemMetadataKeys,pmRoot,settings,typeToFolder:typeRegistry.type_to_folder});let lifecycleTransition;let recurrenceHistoryContext;const result=await mutateItemWithHistoryContextResolver({pmRoot,settings,typeToFolder:typeRegistry.type_to_folder,id,op:resolveUpdateHistoryOperation(options,execution),author,message:options.message,resolveHistoryContext:()=>recurrenceHistoryContext,force:options.force,bypassAssigneeConflict:options.ownershipMetadataBypass===true||options.ownershipDependencyBypass===true,extensionFieldNames,skipNoop:true,mutate(document){lifecycleTransition=prepareRecurrenceTransition({document,recurrenceReason:execution.recurrenceReason,requestedStatus:options.status,statusRegistry});recurrenceHistoryContext=lifecycleTransition?{recurrence:lifecycleTransition}:void 0;graphBeforeUpdate=graphBeforeUpdate?.map(item=>item.id===document.metadata.id?structuredClone(document.metadata):item);const mutation=mutateUpdateDocument(document,{options,settings,typeRegistry,statusRegistry,runtimeFieldRegistry,extensionRegistrations,extensionFieldNames,clearItemMetadataKeys,dependencyUpdates,dependencyRemovals,commentUpdates,noteUpdates,learningUpdates,fileUpdates,testUpdates,docUpdates,resolvedParentValue:parentReference.resolvedParentValue,resolvedBlockedByDependencyId,runtimeFieldUpdates,nowValue,nowIso,author,pmRoot});assertUpdateHierarchyIntegrity({before:graphBeforeUpdate,document,statusRegistry});return mutation}});await releaseHierarchyMutationLock();const orderingCycleWarnings=graphBeforeUpdate?collectNewOrderingCycleWarnings(graphBeforeUpdate,graphBeforeUpdate.map(item=>item.id===result.item.id?result.item:item),result.item.id):[];return{item:toItemRecord(result.item),changed_fields:result.changedFields,warnings:[...workflowTransitionWarnings,...parentReferenceWarnings,...dependencyTargetWarnings,...orderingCycleWarnings,...result.warnings],...lifecycleTransition===void 0?{}:{lifecycle_transition:lifecycleTransition}}}finally{await releaseHierarchyMutationLock()}}function resolveUpdateHistoryOperation(options,execution){if(options.ownershipMetadataBypass===true||options.ownershipDependencyBypass===true){return"update_ownership_bypass"}return execution.recurrenceReason===void 0?"update":"reopen"}function prepareRecurrenceTransition(params){if(params.recurrenceReason===void 0){return void 0}const fromStatus=normalizeStatusInput(params.document.metadata.status,params.statusRegistry)??params.document.metadata.status;if(!isTerminalStatus(fromStatus,params.statusRegistry)){throw new PmCliError(`Item ${params.document.metadata.id} is already active with status ${fromStatus}; recurrence transitions require a terminal item.`,EXIT_CODE.CONFLICT,{code:"item_already_active",reason:"recurrence_requires_terminal_item",required:"Use item reopen only for a terminal item whose work has recurred.",why:"Appending a recurrence event to active work would corrupt lifecycle history.",recovery:{suggested_retry:`pm get ${params.document.metadata.id} --full`,suggested_retry_args:["get",params.document.metadata.id,"--full"]},nextSteps:[`Inspect the active item with: pm get ${params.document.metadata.id} --full`,`Continue the existing work with: pm update ${params.document.metadata.id} ...`]})}const requestedStatus=params.requestedStatus??params.statusRegistry.open_status;const toStatus=normalizeStatusInput(requestedStatus,params.statusRegistry)??requestedStatus;const metadata=toItemRecord(params.document.metadata);const previousTerminal=Object.fromEntries(["close_reason","resolution","expected_result","actual_result","fixed_version"].flatMap(key=>{const value=metadata[key];return typeof value==="string"?[[key,value]]:[]}));return{reason:params.recurrenceReason,from_status:fromStatus,to_status:toStatus,previous_terminal:previousTerminal}}async function runUpdate(id,options,global2){return runUpdateWithContext(id,options,global2)}async function runReopenUpdate(id,options,global2,recurrenceReason){const result=await runUpdateWithContext(id,options,global2,{recurrenceReason});if(result.lifecycle_transition===void 0){throw new PmCliError(`Item ${id} did not produce the required recurrence receipt.`,EXIT_CODE.GENERIC_FAILURE,{code:"reopen_receipt_missing",reason:"recurrence_transition_not_recorded",required:"A successful reopen must return the terminal-to-active lifecycle transition recorded in immutable history."})}return{...result,lifecycle_transition:result.lifecycle_transition}}const _testOnlyUpdateCommand={applyStatusAndCloseReasonMutations,collectProvidedUpdatePolicyOptions,buildOwnershipBypassRestrictedOptionsError,enforceOwnershipBypassScope,enforceTypeWorkflowTransition,matchesDependencySelector,normalizeLegacyNoneUpdateOptions,normalizeUpdatePolicyOptionKey,parseDependencyAdditions,parseDependencyRemovals,parseUpdateUnsetTargets,reconcileBlockedByDependency,resolveRuntimeUnsetDefinition:(token,registry)=>resolveRuntimeUnsetFieldDefinition(token,"update",registry)};export{_testOnlyUpdateCommand,assertUpdateMutationOptionCombinations,parseDependencyAdditions,resolveUpdateTransportOptions,runReopenUpdate,runUpdate};
2136
2
  //# sourceMappingURL=update.js.map
2137
- //# debugId=5a6614ac-62fd-5680-9eed-447bfb7a167f