@unbrained/pm-cli 2026.7.20 → 2026.7.21

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 (421) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +11 -0
  3. package/dist/cli/commander-usage.d.ts +1 -1
  4. package/dist/cli/commander-usage.js +5 -5
  5. package/dist/cli/commander-usage.js.map +1 -1
  6. package/dist/cli/commands/completion.js +13 -5
  7. package/dist/cli/commands/completion.js.map +1 -1
  8. package/dist/cli/commands/contracts.js +4 -3
  9. package/dist/cli/commands/contracts.js.map +1 -1
  10. package/dist/cli/error-guidance.d.ts +2 -0
  11. package/dist/cli/error-guidance.js +7 -2
  12. package/dist/cli/error-guidance.js.map +1 -1
  13. package/dist/cli/main.d.ts +1 -5
  14. package/dist/cli/main.js +12 -50
  15. package/dist/cli/main.js.map +1 -1
  16. package/dist/cli/register-list-query.js +13 -3
  17. package/dist/cli/register-list-query.js.map +1 -1
  18. package/dist/cli/register-mutation.js +45 -3
  19. package/dist/cli/register-mutation.js.map +1 -1
  20. package/dist/cli/register-structured-mutation.d.ts +14 -0
  21. package/dist/cli/register-structured-mutation.js +62 -0
  22. package/dist/cli/register-structured-mutation.js.map +1 -0
  23. package/dist/cli/registration-helpers.js +5 -3
  24. package/dist/cli/registration-helpers.js.map +1 -1
  25. package/dist/cli-bundle/bundle-manifest.json +280 -296
  26. package/dist/cli-bundle/chunks/{append-E6V54WOQ.js → append-7OVFYR3C.js} +3 -3
  27. package/dist/cli-bundle/chunks/{append-NNJ3EFIT.js → append-DFETHAZL.js} +3 -3
  28. package/dist/cli-bundle/chunks/{chunk-C3KD7U3T.js → chunk-2L6ZP22J.js} +241 -10
  29. package/dist/cli-bundle/chunks/chunk-2L6ZP22J.js.map +7 -0
  30. package/dist/cli-bundle/chunks/{chunk-KZEANWJS.js → chunk-4PUUNQDV.js} +98 -30
  31. package/dist/cli-bundle/chunks/chunk-4PUUNQDV.js.map +7 -0
  32. package/dist/cli-bundle/chunks/{chunk-RDV4ZFYS.js → chunk-4QOB7L7I.js} +7 -9
  33. package/dist/cli-bundle/chunks/{chunk-RDV4ZFYS.js.map → chunk-4QOB7L7I.js.map} +1 -1
  34. package/dist/cli-bundle/chunks/{chunk-3LPFHE3P.js → chunk-4QSQ6XDK.js} +62 -20
  35. package/dist/cli-bundle/chunks/chunk-4QSQ6XDK.js.map +1 -0
  36. package/dist/cli-bundle/chunks/{chunk-QJKL5PHS.js → chunk-7656MAUL.js} +2 -2
  37. package/dist/cli-bundle/chunks/{chunk-3AO5VSDR.js → chunk-7RW4JCU2.js} +328 -6
  38. package/dist/cli-bundle/chunks/chunk-7RW4JCU2.js.map +7 -0
  39. package/dist/cli-bundle/chunks/{chunk-X6K5XTTN.js → chunk-7W2UAXXT.js} +5 -5
  40. package/dist/cli-bundle/chunks/{chunk-SSKOQNMS.js → chunk-ABWCF646.js} +9 -11
  41. package/dist/cli-bundle/chunks/{chunk-SSKOQNMS.js.map → chunk-ABWCF646.js.map} +1 -1
  42. package/dist/cli-bundle/chunks/{chunk-WVA4DVNV.js → chunk-ADBTSVGK.js} +71 -33
  43. package/dist/cli-bundle/chunks/chunk-ADBTSVGK.js.map +7 -0
  44. package/dist/cli-bundle/chunks/{chunk-J4FBIFU6.js → chunk-AELMUANP.js} +12 -6
  45. package/dist/cli-bundle/chunks/chunk-AELMUANP.js.map +1 -0
  46. package/dist/cli-bundle/chunks/{chunk-4F6BWJ4J.js → chunk-AMJPSANK.js} +57 -36
  47. package/dist/cli-bundle/chunks/chunk-AMJPSANK.js.map +7 -0
  48. package/dist/cli-bundle/chunks/{chunk-6VIJ7UA5.js → chunk-AS4SAZ5R.js} +850 -819
  49. package/dist/cli-bundle/chunks/chunk-AS4SAZ5R.js.map +7 -0
  50. package/dist/cli-bundle/chunks/{chunk-SG74J6MV.js → chunk-ATBCUC7Y.js} +574 -5
  51. package/dist/cli-bundle/chunks/chunk-ATBCUC7Y.js.map +1 -0
  52. package/dist/cli-bundle/chunks/{chunk-5OK4UGFV.js → chunk-BXNDKOR2.js} +3 -3
  53. package/dist/cli-bundle/chunks/{chunk-KSPWRNVP.js → chunk-CPX275C6.js} +2 -2
  54. package/dist/cli-bundle/chunks/{chunk-JH2ZSLO3.js → chunk-DZRV2OPA.js} +2 -2
  55. package/dist/cli-bundle/chunks/{chunk-L7BH7IWU.js → chunk-E5XMKOSB.js} +2 -2
  56. package/dist/cli-bundle/chunks/{chunk-CQTQKUUV.js → chunk-EWJWSNRU.js} +3 -3
  57. package/dist/cli-bundle/chunks/{chunk-DAQ45GCS.js → chunk-F2LBF7XJ.js} +22 -15
  58. package/dist/cli-bundle/chunks/chunk-F2LBF7XJ.js.map +7 -0
  59. package/dist/cli-bundle/chunks/{chunk-6XMUURSS.js → chunk-FJIFFBJX.js} +64 -33
  60. package/dist/cli-bundle/chunks/chunk-FJIFFBJX.js.map +1 -0
  61. package/dist/cli-bundle/chunks/{chunk-E7ICD63T.js → chunk-FO6OSVEN.js} +4 -6
  62. package/dist/cli-bundle/chunks/{chunk-E7ICD63T.js.map → chunk-FO6OSVEN.js.map} +1 -1
  63. package/dist/cli-bundle/chunks/{chunk-3MCTMJXI.js → chunk-FPBMLYPI.js} +2 -2
  64. package/dist/cli-bundle/chunks/{chunk-UZDQXNUB.js → chunk-FSE2IKJQ.js} +46 -5
  65. package/dist/cli-bundle/chunks/chunk-FSE2IKJQ.js.map +1 -0
  66. package/dist/cli-bundle/chunks/{chunk-IX677TRO.js → chunk-GKX4NJ7U.js} +8 -10
  67. package/dist/cli-bundle/chunks/{chunk-IX677TRO.js.map → chunk-GKX4NJ7U.js.map} +1 -1
  68. package/dist/cli-bundle/chunks/{chunk-DVDBQA3B.js → chunk-GTK4DTEW.js} +5 -5
  69. package/dist/cli-bundle/chunks/chunk-H7EAER5L.js +974 -0
  70. package/dist/cli-bundle/chunks/chunk-H7EAER5L.js.map +1 -0
  71. package/dist/cli-bundle/chunks/{chunk-5UX66S6U.js → chunk-ICDAQ4TD.js} +316 -8
  72. package/dist/cli-bundle/chunks/chunk-ICDAQ4TD.js.map +1 -0
  73. package/dist/cli-bundle/chunks/{chunk-YQQNAKW3.js → chunk-JFD5LPMI.js} +6 -8
  74. package/dist/cli-bundle/chunks/{chunk-YQQNAKW3.js.map → chunk-JFD5LPMI.js.map} +1 -1
  75. package/dist/cli-bundle/chunks/{chunk-QANSTTC7.js → chunk-JXCW2TI2.js} +6 -8
  76. package/dist/cli-bundle/chunks/{chunk-QANSTTC7.js.map → chunk-JXCW2TI2.js.map} +1 -1
  77. package/dist/cli-bundle/chunks/{chunk-GSJSM5BJ.js → chunk-K36WV5J6.js} +76 -13
  78. package/dist/cli-bundle/chunks/chunk-K36WV5J6.js.map +1 -0
  79. package/dist/cli-bundle/chunks/{chunk-GVI6FAFG.js → chunk-K55VMLSS.js} +7 -5
  80. package/dist/cli-bundle/chunks/chunk-K55VMLSS.js.map +7 -0
  81. package/dist/cli-bundle/chunks/{chunk-GIQSU6S2.js → chunk-KBLZ3AA5.js} +2 -2
  82. package/dist/cli-bundle/chunks/{chunk-XJF7CDNH.js → chunk-KH44WBAT.js} +2 -2
  83. package/dist/cli-bundle/chunks/{chunk-GV2262OF.js → chunk-LAV26CQG.js} +2 -2
  84. package/dist/cli-bundle/chunks/{chunk-VDO2JMD4.js → chunk-LVC72YRD.js} +2 -2
  85. package/dist/cli-bundle/chunks/{chunk-3VY6MIEO.js → chunk-LZYP423P.js} +35 -6
  86. package/dist/cli-bundle/chunks/chunk-LZYP423P.js.map +7 -0
  87. package/dist/cli-bundle/chunks/{chunk-ZYPFOO3L.js → chunk-MATHDCGG.js} +3 -3
  88. package/dist/cli-bundle/chunks/{chunk-OV7MSW3I.js → chunk-MWQ2HC2A.js} +99 -31
  89. package/dist/cli-bundle/chunks/chunk-MWQ2HC2A.js.map +1 -0
  90. package/dist/cli-bundle/chunks/{chunk-NHT3F4WZ.js → chunk-NUF7ROFH.js} +840 -816
  91. package/dist/cli-bundle/chunks/chunk-NUF7ROFH.js.map +1 -0
  92. package/dist/cli-bundle/chunks/{chunk-AOEOYL3S.js → chunk-O4BCOJTZ.js} +3 -3
  93. package/dist/cli-bundle/chunks/{chunk-RJO3YAFM.js → chunk-OCUBRA6D.js} +2 -2
  94. package/dist/cli-bundle/chunks/{chunk-5IZJWSDB.js → chunk-OG5DVFMA.js} +22 -15
  95. package/dist/cli-bundle/chunks/chunk-OG5DVFMA.js.map +1 -0
  96. package/dist/cli-bundle/chunks/{chunk-I577UHC7.js → chunk-OR42SO64.js} +2 -2
  97. package/dist/cli-bundle/chunks/{chunk-ZOJ3LR7O.js → chunk-OY7DMU5P.js} +2 -2
  98. package/dist/cli-bundle/chunks/{chunk-HEWM6CEN.js → chunk-P7MTHPJQ.js} +50 -9
  99. package/dist/cli-bundle/chunks/chunk-P7MTHPJQ.js.map +7 -0
  100. package/dist/cli-bundle/chunks/{chunk-2BO4CA46.js → chunk-PFNHX655.js} +236 -12
  101. package/dist/cli-bundle/chunks/{chunk-2BO4CA46.js.map → chunk-PFNHX655.js.map} +1 -1
  102. package/dist/cli-bundle/chunks/{chunk-ZV2NTVMJ.js → chunk-PONKZPCJ.js} +2 -2
  103. package/dist/cli-bundle/chunks/{chunk-THAOZG4U.js → chunk-PQSEQD6E.js} +8 -6
  104. package/dist/cli-bundle/chunks/chunk-PQSEQD6E.js.map +1 -0
  105. package/dist/cli-bundle/chunks/chunk-PWDEHT3L.js +991 -0
  106. package/dist/cli-bundle/chunks/chunk-PWDEHT3L.js.map +7 -0
  107. package/dist/cli-bundle/chunks/{chunk-UX6SSO2I.js → chunk-PZC2FUOQ.js} +2 -2
  108. package/dist/cli-bundle/chunks/{chunk-WUVEBQW6.js → chunk-QG4GFLQ6.js} +3 -5
  109. package/dist/cli-bundle/chunks/{chunk-WUVEBQW6.js.map → chunk-QG4GFLQ6.js.map} +1 -1
  110. package/dist/cli-bundle/chunks/{chunk-VQIHNHMJ.js → chunk-QIH77CAG.js} +2 -2
  111. package/dist/cli-bundle/chunks/{chunk-R3EWPG4A.js → chunk-QJIKE24M.js} +2 -2
  112. package/dist/cli-bundle/chunks/{chunk-QLZ643FM.js → chunk-QOOTOD3W.js} +10 -12
  113. package/dist/cli-bundle/chunks/{chunk-QLZ643FM.js.map → chunk-QOOTOD3W.js.map} +1 -1
  114. package/dist/cli-bundle/chunks/{chunk-MYSS5H2A.js → chunk-R3P6FZJW.js} +5 -7
  115. package/dist/cli-bundle/chunks/{chunk-MYSS5H2A.js.map → chunk-R3P6FZJW.js.map} +1 -1
  116. package/dist/cli-bundle/chunks/{chunk-G3COA6GS.js → chunk-RNPZYNHS.js} +56 -35
  117. package/dist/cli-bundle/chunks/chunk-RNPZYNHS.js.map +1 -0
  118. package/dist/cli-bundle/chunks/{chunk-T44FMVRL.js → chunk-RPESLSO5.js} +62 -20
  119. package/dist/cli-bundle/chunks/chunk-RPESLSO5.js.map +7 -0
  120. package/dist/cli-bundle/chunks/{chunk-INSTSQNZ.js → chunk-SY4SFZSD.js} +595 -3
  121. package/dist/cli-bundle/chunks/chunk-SY4SFZSD.js.map +7 -0
  122. package/dist/cli-bundle/chunks/{chunk-HB3P4M52.js → chunk-TRSHFPRZ.js} +2 -2
  123. package/dist/cli-bundle/chunks/{chunk-HRW7GF6T.js → chunk-UCBDQI5E.js} +2 -2
  124. package/dist/cli-bundle/chunks/{chunk-4U4Z6AHI.js → chunk-V22ZPOKN.js} +2 -2
  125. package/dist/cli-bundle/chunks/{chunk-JM6YAXTR.js → chunk-VHXHVTUU.js} +2 -2
  126. package/dist/cli-bundle/chunks/{chunk-LPEYZRUR.js → chunk-VJQG4BIM.js} +35 -6
  127. package/dist/cli-bundle/chunks/chunk-VJQG4BIM.js.map +1 -0
  128. package/dist/cli-bundle/chunks/{chunk-D6NXDNP3.js → chunk-VLRGDBLY.js} +2 -2
  129. package/dist/cli-bundle/chunks/{chunk-JAPE62Y5.js → chunk-VNTCM3VW.js} +3 -3
  130. package/dist/cli-bundle/chunks/{chunk-FDHPAVVB.js → chunk-VXOOB6YX.js} +2 -2
  131. package/dist/cli-bundle/chunks/{chunk-GFQP7HAZ.js → chunk-VZIZB6QH.js} +3 -5
  132. package/dist/cli-bundle/chunks/{chunk-GFQP7HAZ.js.map → chunk-VZIZB6QH.js.map} +1 -1
  133. package/dist/cli-bundle/chunks/{chunk-HQ3SB4CN.js → chunk-X3W65QK3.js} +2 -2
  134. package/dist/cli-bundle/chunks/{chunk-RZJLNXFG.js → chunk-XJTABV3X.js} +3 -3
  135. package/dist/cli-bundle/chunks/{chunk-GVT754PX.js → chunk-YCIUJJOD.js} +11 -5
  136. package/dist/cli-bundle/chunks/chunk-YCIUJJOD.js.map +7 -0
  137. package/dist/cli-bundle/chunks/{chunk-IJNK6WW2.js → chunk-Z75ONV25.js} +75 -12
  138. package/dist/cli-bundle/chunks/chunk-Z75ONV25.js.map +7 -0
  139. package/dist/cli-bundle/chunks/{chunk-4L23AGQ7.js → chunk-Z7VWXXJM.js} +5 -7
  140. package/dist/cli-bundle/chunks/{chunk-4L23AGQ7.js.map → chunk-Z7VWXXJM.js.map} +1 -1
  141. package/dist/cli-bundle/chunks/{chunk-YBT7O4KT.js → chunk-ZTVA4KLN.js} +4 -6
  142. package/dist/cli-bundle/chunks/{chunk-YBT7O4KT.js.map → chunk-ZTVA4KLN.js.map} +1 -1
  143. package/dist/cli-bundle/chunks/{chunk-TYHJDFYW.js → chunk-ZVZGXPQ5.js} +2 -2
  144. package/dist/cli-bundle/chunks/{close-many-SDA426VT.js → close-many-5RZXVN4J.js} +5 -6
  145. package/dist/cli-bundle/chunks/{close-many-UTZANOCQ.js → close-many-RZVTUGBG.js} +5 -6
  146. package/dist/cli-bundle/chunks/{comments-LZN6FXXC.js → comments-TPU7QRBL.js} +4 -4
  147. package/dist/cli-bundle/chunks/{comments-VBQ345ND.js → comments-Z4KV6FU3.js} +4 -4
  148. package/dist/cli-bundle/chunks/{create-GG4RBCGC.js → create-EIFBIVNQ.js} +6 -6
  149. package/dist/cli-bundle/chunks/{create-JBC5KUW6.js → create-RGSPN5GD.js} +6 -6
  150. package/dist/cli-bundle/chunks/{deps-FI4O6NQS.js → deps-UH5EQQUY.js} +3 -3
  151. package/dist/cli-bundle/chunks/{deps-DELOO4TL.js → deps-YG7UF3VR.js} +3 -3
  152. package/dist/cli-bundle/chunks/{docs-6Z2MP526.js → docs-G32TK6XS.js} +4 -4
  153. package/dist/cli-bundle/chunks/{docs-2UYBP5D6.js → docs-JWWNRC27.js} +4 -4
  154. package/dist/cli-bundle/chunks/{files-HKEAN5MA.js → files-3H32UQ4K.js} +4 -4
  155. package/dist/cli-bundle/chunks/{files-HEUGSJZL.js → files-4ALMCSKB.js} +4 -4
  156. package/dist/cli-bundle/chunks/{history-compact-7NDVP3PT.js → history-compact-77BT2LUB.js} +3 -4
  157. package/dist/cli-bundle/chunks/{history-compact-65YVN5DB.js → history-compact-VCKGTX64.js} +3 -4
  158. package/dist/cli-bundle/chunks/{history-redact-7YBL4XSG.js → history-redact-LJPZPNFA.js} +2 -3
  159. package/dist/cli-bundle/chunks/{history-redact-IZGNJBU4.js → history-redact-PWTTJ3XS.js} +2 -3
  160. package/dist/cli-bundle/chunks/{history-repair-7M4PYQUH.js → history-repair-I7CBNCV3.js} +5 -6
  161. package/dist/cli-bundle/chunks/{history-repair-GNGETJLI.js → history-repair-YTDZRK5E.js} +5 -6
  162. package/dist/cli-bundle/chunks/{learnings-3YXDRWFT.js → learnings-CYNOICKR.js} +4 -4
  163. package/dist/cli-bundle/chunks/{learnings-ALC6IMNL.js → learnings-KTYW3AL7.js} +4 -4
  164. package/dist/cli-bundle/chunks/{notes-7JMLQ447.js → notes-FGO63FXL.js} +4 -4
  165. package/dist/cli-bundle/chunks/{notes-JFCLTC5C.js → notes-ZERD3KB2.js} +4 -4
  166. package/dist/cli-bundle/chunks/{plan-T3XB3WTK.js → plan-OFJUBIM5.js} +7 -7
  167. package/dist/cli-bundle/chunks/{plan-KOIPWVOZ.js → plan-SGCDDTYR.js} +7 -7
  168. package/dist/cli-bundle/chunks/{profile-OILJHKUW.js → profile-3THJPIQY.js} +4 -5
  169. package/dist/cli-bundle/chunks/{profile-RJXA7PGS.js → profile-XEZAMMBW.js} +4 -5
  170. package/dist/cli-bundle/chunks/{register-list-query-CFVG75P3.js → register-list-query-BR435Q2H.js} +19 -16
  171. package/dist/cli-bundle/chunks/register-list-query-BR435Q2H.js.map +1 -0
  172. package/dist/cli-bundle/chunks/{register-list-query-E7UVY4TN.js → register-list-query-RWTWLOBE.js} +18 -15
  173. package/dist/cli-bundle/chunks/register-list-query-RWTWLOBE.js.map +7 -0
  174. package/dist/cli-bundle/chunks/{register-mutation-IQ55E25C.js → register-mutation-HLWC2WNP.js} +167 -31
  175. package/dist/cli-bundle/chunks/register-mutation-HLWC2WNP.js.map +1 -0
  176. package/dist/cli-bundle/chunks/{register-mutation-4VJTXBZW.js → register-mutation-ZJX5AZM5.js} +173 -30
  177. package/dist/cli-bundle/chunks/register-mutation-ZJX5AZM5.js.map +7 -0
  178. package/dist/cli-bundle/chunks/{register-operations-AR7RMX4W.js → register-operations-744YBJMV.js} +23 -25
  179. package/dist/cli-bundle/chunks/{register-operations-AR7RMX4W.js.map → register-operations-744YBJMV.js.map} +1 -1
  180. package/dist/cli-bundle/chunks/{register-operations-NOLZGORC.js → register-operations-UEBJH6AN.js} +21 -23
  181. package/dist/cli-bundle/chunks/{register-operations-NOLZGORC.js.map → register-operations-UEBJH6AN.js.map} +1 -1
  182. package/dist/cli-bundle/chunks/{register-setup-EYZ7VTPZ.js → register-setup-5DA4UZXI.js} +7 -8
  183. package/dist/cli-bundle/chunks/{register-setup-EYZ7VTPZ.js.map → register-setup-5DA4UZXI.js.map} +1 -1
  184. package/dist/cli-bundle/chunks/{register-setup-BB77VUEE.js → register-setup-6H25M3BH.js} +9 -10
  185. package/dist/cli-bundle/chunks/{register-setup-BB77VUEE.js.map → register-setup-6H25M3BH.js.map} +1 -1
  186. package/dist/cli-bundle/chunks/{restore-ZH65GZFB.js → restore-6TDVSATY.js} +4 -5
  187. package/dist/cli-bundle/chunks/{restore-L6IAGOD7.js → restore-RSL7C7LO.js} +4 -5
  188. package/dist/cli-bundle/chunks/{schema-4ERWM5QJ.js → schema-HFXFSGPG.js} +2 -3
  189. package/dist/cli-bundle/chunks/{schema-55DL3Q52.js → schema-TPVTIJPO.js} +2 -3
  190. package/dist/cli-bundle/chunks/{update-FW6FKDOP.js → update-LJZCL5SI.js} +7 -7
  191. package/dist/cli-bundle/chunks/{update-TJHSPRPT.js → update-SIA7LH5Y.js} +7 -7
  192. package/dist/cli-bundle/chunks/{update-many-PWXX5WHO.js → update-many-BDBZVGQL.js} +11 -12
  193. package/dist/cli-bundle/chunks/{update-many-NNALYQCN.js → update-many-MOY3A5B3.js} +11 -12
  194. package/dist/cli-bundle/main.js +60 -85
  195. package/dist/cli-bundle/main.js.map +2 -2
  196. package/dist/cli-bundle/sdk-runtime.js +37 -37
  197. package/dist/cli-bundle/sdk.js +126 -291
  198. package/dist/cli-bundle/sdk.js.map +4 -4
  199. package/dist/core/item/parse.d.ts +1 -1
  200. package/dist/core/item/parse.js +13 -7
  201. package/dist/core/item/parse.js.map +1 -1
  202. package/dist/core/output/mutation-projection.d.ts +2 -0
  203. package/dist/core/output/mutation-projection.js +33 -2
  204. package/dist/core/output/mutation-projection.js.map +1 -1
  205. package/dist/core/output/output.d.ts +4 -0
  206. package/dist/core/output/output.js +18 -13
  207. package/dist/core/output/output.js.map +1 -1
  208. package/dist/core/shared/command-types.d.ts +4 -0
  209. package/dist/core/shared/command-types.js +2 -2
  210. package/dist/core/shared/command-types.js.map +1 -1
  211. package/dist/mcp/server.js +39 -4
  212. package/dist/mcp/server.js.map +1 -1
  213. package/dist/mcp/tool-definitions.js +45 -4
  214. package/dist/mcp/tool-definitions.js.map +1 -1
  215. package/dist/sdk/cli-bootstrap.d.ts +2 -0
  216. package/dist/sdk/cli-bootstrap.js +20 -27
  217. package/dist/sdk/cli-bootstrap.js.map +1 -1
  218. package/dist/sdk/cli-contracts/enum-contracts.d.ts +2 -2
  219. package/dist/sdk/cli-contracts/enum-contracts.js +7 -2
  220. package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -1
  221. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  222. package/dist/sdk/cli-contracts/flag-contracts.js +21 -2
  223. package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
  224. package/dist/sdk/cli-contracts/tool-option-contracts.js +10 -2
  225. package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -1
  226. package/dist/sdk/cli-contracts/tool-parameter-tables.js +16 -3
  227. package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
  228. package/dist/sdk/cli-contracts/tool-schema.js +6 -2
  229. package/dist/sdk/cli-contracts/tool-schema.js.map +1 -1
  230. package/dist/sdk/cli-contracts.d.ts +1 -1
  231. package/dist/sdk/cli-contracts.js +3 -3
  232. package/dist/sdk/cli-contracts.js.map +1 -1
  233. package/dist/sdk/cli-program.js +4 -2
  234. package/dist/sdk/cli-program.js.map +1 -1
  235. package/dist/sdk/dependencies.d.ts +3 -2
  236. package/dist/sdk/dependencies.js +13 -12
  237. package/dist/sdk/dependencies.js.map +1 -1
  238. package/dist/sdk/error-runtime.d.ts +10 -0
  239. package/dist/sdk/error-runtime.js +59 -0
  240. package/dist/sdk/error-runtime.js.map +1 -0
  241. package/dist/sdk/graph/analytics.d.ts +9 -0
  242. package/dist/sdk/graph/analytics.js +24 -13
  243. package/dist/sdk/graph/analytics.js.map +1 -1
  244. package/dist/sdk/graph/assembly.d.ts +39 -0
  245. package/dist/sdk/graph/assembly.js +92 -12
  246. package/dist/sdk/graph/assembly.js.map +1 -1
  247. package/dist/sdk/graph/cache.d.ts +4 -1
  248. package/dist/sdk/graph/cache.js +17 -4
  249. package/dist/sdk/graph/cache.js.map +1 -1
  250. package/dist/sdk/graph/centrality.d.ts +82 -0
  251. package/dist/sdk/graph/centrality.js +259 -0
  252. package/dist/sdk/graph/centrality.js.map +1 -0
  253. package/dist/sdk/graph/durable-cache.d.ts +71 -0
  254. package/dist/sdk/graph/durable-cache.js +205 -0
  255. package/dist/sdk/graph/durable-cache.js.map +1 -0
  256. package/dist/sdk/graph/governance.d.ts +69 -1
  257. package/dist/sdk/graph/governance.js +143 -35
  258. package/dist/sdk/graph/governance.js.map +1 -1
  259. package/dist/sdk/graph/index.d.ts +7 -4
  260. package/dist/sdk/graph/index.js +8 -5
  261. package/dist/sdk/graph/index.js.map +1 -1
  262. package/dist/sdk/graph/mutation-advisory.d.ts +35 -4
  263. package/dist/sdk/graph/mutation-advisory.js +124 -35
  264. package/dist/sdk/graph/mutation-advisory.js.map +1 -1
  265. package/dist/sdk/graph/remediation.js +12 -2
  266. package/dist/sdk/graph/remediation.js.map +1 -1
  267. package/dist/sdk/graph/run.d.ts +133 -2
  268. package/dist/sdk/graph/run.js +217 -8
  269. package/dist/sdk/graph/run.js.map +1 -1
  270. package/dist/sdk/graph/scheduling.d.ts +59 -0
  271. package/dist/sdk/graph/scheduling.js +125 -0
  272. package/dist/sdk/graph/scheduling.js.map +1 -0
  273. package/dist/sdk/graph/traversal.d.ts +11 -0
  274. package/dist/sdk/graph/traversal.js +16 -2
  275. package/dist/sdk/graph/traversal.js.map +1 -1
  276. package/dist/sdk/index.d.ts +4 -0
  277. package/dist/sdk/index.js +6 -2
  278. package/dist/sdk/index.js.map +1 -1
  279. package/dist/sdk/runtime-input.js +7 -2
  280. package/dist/sdk/runtime-input.js.map +1 -1
  281. package/dist/sdk/runtime-primitives.d.ts +10 -0
  282. package/dist/sdk/runtime-primitives.js +14 -0
  283. package/dist/sdk/runtime-primitives.js.map +1 -0
  284. package/dist/sdk/runtime.d.ts +15 -0
  285. package/dist/sdk/runtime.js +16 -3
  286. package/dist/sdk/runtime.js.map +1 -1
  287. package/dist/sdk/structured-mutations.d.ts +21 -0
  288. package/dist/sdk/structured-mutations.js +375 -0
  289. package/dist/sdk/structured-mutations.js.map +1 -0
  290. package/docs/COMMANDS.md +85 -5
  291. package/docs/RELATIONSHIP_GRAPH.md +48 -7
  292. package/docs/SDK.md +78 -3
  293. package/marketplace.json +2 -2
  294. package/package.json +1 -1
  295. package/packages/pm-beads/package.json +1 -1
  296. package/packages/pm-calendar/package.json +1 -1
  297. package/packages/pm-command-kit/package.json +1 -1
  298. package/packages/pm-governance-audit/package.json +1 -1
  299. package/packages/pm-guide-shell/package.json +1 -1
  300. package/packages/pm-kanban/package.json +1 -1
  301. package/packages/pm-lifecycle-hooks/package.json +1 -1
  302. package/packages/pm-linked-test-adapters/package.json +1 -1
  303. package/packages/pm-search-advanced/package.json +1 -1
  304. package/packages/pm-templates/package.json +1 -1
  305. package/packages/pm-todos/package.json +1 -1
  306. package/packages/pm-vcs/package.json +1 -1
  307. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  308. package/plugins/pm-claude/README.md +5 -3
  309. package/plugins/pm-claude/commands/pm-init.md +1 -1
  310. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  311. package/dist/cli-bundle/chunks/chunk-3AO5VSDR.js.map +0 -7
  312. package/dist/cli-bundle/chunks/chunk-3LPFHE3P.js.map +0 -1
  313. package/dist/cli-bundle/chunks/chunk-3VY6MIEO.js.map +0 -7
  314. package/dist/cli-bundle/chunks/chunk-4F6BWJ4J.js.map +0 -7
  315. package/dist/cli-bundle/chunks/chunk-5IZJWSDB.js.map +0 -1
  316. package/dist/cli-bundle/chunks/chunk-5UX66S6U.js.map +0 -1
  317. package/dist/cli-bundle/chunks/chunk-6C2ZZX5Z.js +0 -286
  318. package/dist/cli-bundle/chunks/chunk-6C2ZZX5Z.js.map +0 -1
  319. package/dist/cli-bundle/chunks/chunk-6VIJ7UA5.js.map +0 -7
  320. package/dist/cli-bundle/chunks/chunk-6XMUURSS.js.map +0 -1
  321. package/dist/cli-bundle/chunks/chunk-C3KD7U3T.js.map +0 -7
  322. package/dist/cli-bundle/chunks/chunk-CFHAODHQ.js +0 -334
  323. package/dist/cli-bundle/chunks/chunk-CFHAODHQ.js.map +0 -1
  324. package/dist/cli-bundle/chunks/chunk-DAQ45GCS.js.map +0 -7
  325. package/dist/cli-bundle/chunks/chunk-E6LEMURX.js +0 -249
  326. package/dist/cli-bundle/chunks/chunk-E6LEMURX.js.map +0 -7
  327. package/dist/cli-bundle/chunks/chunk-G3COA6GS.js.map +0 -1
  328. package/dist/cli-bundle/chunks/chunk-GSJSM5BJ.js.map +0 -1
  329. package/dist/cli-bundle/chunks/chunk-GVI6FAFG.js.map +0 -7
  330. package/dist/cli-bundle/chunks/chunk-GVT754PX.js.map +0 -7
  331. package/dist/cli-bundle/chunks/chunk-HEWM6CEN.js.map +0 -7
  332. package/dist/cli-bundle/chunks/chunk-IJNK6WW2.js.map +0 -7
  333. package/dist/cli-bundle/chunks/chunk-INSTSQNZ.js.map +0 -7
  334. package/dist/cli-bundle/chunks/chunk-J4FBIFU6.js.map +0 -1
  335. package/dist/cli-bundle/chunks/chunk-KZEANWJS.js.map +0 -7
  336. package/dist/cli-bundle/chunks/chunk-LPEYZRUR.js.map +0 -1
  337. package/dist/cli-bundle/chunks/chunk-NHT3F4WZ.js.map +0 -1
  338. package/dist/cli-bundle/chunks/chunk-OV7MSW3I.js.map +0 -1
  339. package/dist/cli-bundle/chunks/chunk-P7JTWYLH.js +0 -246
  340. package/dist/cli-bundle/chunks/chunk-P7JTWYLH.js.map +0 -1
  341. package/dist/cli-bundle/chunks/chunk-R5U2VZ3K.js +0 -344
  342. package/dist/cli-bundle/chunks/chunk-R5U2VZ3K.js.map +0 -7
  343. package/dist/cli-bundle/chunks/chunk-SG74J6MV.js.map +0 -1
  344. package/dist/cli-bundle/chunks/chunk-T44FMVRL.js.map +0 -7
  345. package/dist/cli-bundle/chunks/chunk-THAOZG4U.js.map +0 -1
  346. package/dist/cli-bundle/chunks/chunk-UQLXSG72.js +0 -289
  347. package/dist/cli-bundle/chunks/chunk-UQLXSG72.js.map +0 -7
  348. package/dist/cli-bundle/chunks/chunk-UZDQXNUB.js.map +0 -1
  349. package/dist/cli-bundle/chunks/chunk-WVA4DVNV.js.map +0 -7
  350. package/dist/cli-bundle/chunks/register-list-query-CFVG75P3.js.map +0 -1
  351. package/dist/cli-bundle/chunks/register-list-query-E7UVY4TN.js.map +0 -7
  352. package/dist/cli-bundle/chunks/register-mutation-4VJTXBZW.js.map +0 -7
  353. package/dist/cli-bundle/chunks/register-mutation-IQ55E25C.js.map +0 -1
  354. /package/dist/cli-bundle/chunks/{append-E6V54WOQ.js.map → append-7OVFYR3C.js.map} +0 -0
  355. /package/dist/cli-bundle/chunks/{append-NNJ3EFIT.js.map → append-DFETHAZL.js.map} +0 -0
  356. /package/dist/cli-bundle/chunks/{chunk-QJKL5PHS.js.map → chunk-7656MAUL.js.map} +0 -0
  357. /package/dist/cli-bundle/chunks/{chunk-X6K5XTTN.js.map → chunk-7W2UAXXT.js.map} +0 -0
  358. /package/dist/cli-bundle/chunks/{chunk-5OK4UGFV.js.map → chunk-BXNDKOR2.js.map} +0 -0
  359. /package/dist/cli-bundle/chunks/{chunk-KSPWRNVP.js.map → chunk-CPX275C6.js.map} +0 -0
  360. /package/dist/cli-bundle/chunks/{chunk-JH2ZSLO3.js.map → chunk-DZRV2OPA.js.map} +0 -0
  361. /package/dist/cli-bundle/chunks/{chunk-L7BH7IWU.js.map → chunk-E5XMKOSB.js.map} +0 -0
  362. /package/dist/cli-bundle/chunks/{chunk-CQTQKUUV.js.map → chunk-EWJWSNRU.js.map} +0 -0
  363. /package/dist/cli-bundle/chunks/{chunk-3MCTMJXI.js.map → chunk-FPBMLYPI.js.map} +0 -0
  364. /package/dist/cli-bundle/chunks/{chunk-DVDBQA3B.js.map → chunk-GTK4DTEW.js.map} +0 -0
  365. /package/dist/cli-bundle/chunks/{chunk-GIQSU6S2.js.map → chunk-KBLZ3AA5.js.map} +0 -0
  366. /package/dist/cli-bundle/chunks/{chunk-XJF7CDNH.js.map → chunk-KH44WBAT.js.map} +0 -0
  367. /package/dist/cli-bundle/chunks/{chunk-GV2262OF.js.map → chunk-LAV26CQG.js.map} +0 -0
  368. /package/dist/cli-bundle/chunks/{chunk-VDO2JMD4.js.map → chunk-LVC72YRD.js.map} +0 -0
  369. /package/dist/cli-bundle/chunks/{chunk-ZYPFOO3L.js.map → chunk-MATHDCGG.js.map} +0 -0
  370. /package/dist/cli-bundle/chunks/{chunk-AOEOYL3S.js.map → chunk-O4BCOJTZ.js.map} +0 -0
  371. /package/dist/cli-bundle/chunks/{chunk-RJO3YAFM.js.map → chunk-OCUBRA6D.js.map} +0 -0
  372. /package/dist/cli-bundle/chunks/{chunk-I577UHC7.js.map → chunk-OR42SO64.js.map} +0 -0
  373. /package/dist/cli-bundle/chunks/{chunk-ZOJ3LR7O.js.map → chunk-OY7DMU5P.js.map} +0 -0
  374. /package/dist/cli-bundle/chunks/{chunk-ZV2NTVMJ.js.map → chunk-PONKZPCJ.js.map} +0 -0
  375. /package/dist/cli-bundle/chunks/{chunk-UX6SSO2I.js.map → chunk-PZC2FUOQ.js.map} +0 -0
  376. /package/dist/cli-bundle/chunks/{chunk-VQIHNHMJ.js.map → chunk-QIH77CAG.js.map} +0 -0
  377. /package/dist/cli-bundle/chunks/{chunk-R3EWPG4A.js.map → chunk-QJIKE24M.js.map} +0 -0
  378. /package/dist/cli-bundle/chunks/{chunk-HB3P4M52.js.map → chunk-TRSHFPRZ.js.map} +0 -0
  379. /package/dist/cli-bundle/chunks/{chunk-HRW7GF6T.js.map → chunk-UCBDQI5E.js.map} +0 -0
  380. /package/dist/cli-bundle/chunks/{chunk-4U4Z6AHI.js.map → chunk-V22ZPOKN.js.map} +0 -0
  381. /package/dist/cli-bundle/chunks/{chunk-JM6YAXTR.js.map → chunk-VHXHVTUU.js.map} +0 -0
  382. /package/dist/cli-bundle/chunks/{chunk-D6NXDNP3.js.map → chunk-VLRGDBLY.js.map} +0 -0
  383. /package/dist/cli-bundle/chunks/{chunk-JAPE62Y5.js.map → chunk-VNTCM3VW.js.map} +0 -0
  384. /package/dist/cli-bundle/chunks/{chunk-FDHPAVVB.js.map → chunk-VXOOB6YX.js.map} +0 -0
  385. /package/dist/cli-bundle/chunks/{chunk-HQ3SB4CN.js.map → chunk-X3W65QK3.js.map} +0 -0
  386. /package/dist/cli-bundle/chunks/{chunk-RZJLNXFG.js.map → chunk-XJTABV3X.js.map} +0 -0
  387. /package/dist/cli-bundle/chunks/{chunk-TYHJDFYW.js.map → chunk-ZVZGXPQ5.js.map} +0 -0
  388. /package/dist/cli-bundle/chunks/{close-many-SDA426VT.js.map → close-many-5RZXVN4J.js.map} +0 -0
  389. /package/dist/cli-bundle/chunks/{close-many-UTZANOCQ.js.map → close-many-RZVTUGBG.js.map} +0 -0
  390. /package/dist/cli-bundle/chunks/{comments-LZN6FXXC.js.map → comments-TPU7QRBL.js.map} +0 -0
  391. /package/dist/cli-bundle/chunks/{comments-VBQ345ND.js.map → comments-Z4KV6FU3.js.map} +0 -0
  392. /package/dist/cli-bundle/chunks/{create-GG4RBCGC.js.map → create-EIFBIVNQ.js.map} +0 -0
  393. /package/dist/cli-bundle/chunks/{create-JBC5KUW6.js.map → create-RGSPN5GD.js.map} +0 -0
  394. /package/dist/cli-bundle/chunks/{deps-FI4O6NQS.js.map → deps-UH5EQQUY.js.map} +0 -0
  395. /package/dist/cli-bundle/chunks/{deps-DELOO4TL.js.map → deps-YG7UF3VR.js.map} +0 -0
  396. /package/dist/cli-bundle/chunks/{docs-6Z2MP526.js.map → docs-G32TK6XS.js.map} +0 -0
  397. /package/dist/cli-bundle/chunks/{docs-2UYBP5D6.js.map → docs-JWWNRC27.js.map} +0 -0
  398. /package/dist/cli-bundle/chunks/{files-HKEAN5MA.js.map → files-3H32UQ4K.js.map} +0 -0
  399. /package/dist/cli-bundle/chunks/{files-HEUGSJZL.js.map → files-4ALMCSKB.js.map} +0 -0
  400. /package/dist/cli-bundle/chunks/{history-compact-7NDVP3PT.js.map → history-compact-77BT2LUB.js.map} +0 -0
  401. /package/dist/cli-bundle/chunks/{history-compact-65YVN5DB.js.map → history-compact-VCKGTX64.js.map} +0 -0
  402. /package/dist/cli-bundle/chunks/{history-redact-7YBL4XSG.js.map → history-redact-LJPZPNFA.js.map} +0 -0
  403. /package/dist/cli-bundle/chunks/{history-redact-IZGNJBU4.js.map → history-redact-PWTTJ3XS.js.map} +0 -0
  404. /package/dist/cli-bundle/chunks/{history-repair-7M4PYQUH.js.map → history-repair-I7CBNCV3.js.map} +0 -0
  405. /package/dist/cli-bundle/chunks/{history-repair-GNGETJLI.js.map → history-repair-YTDZRK5E.js.map} +0 -0
  406. /package/dist/cli-bundle/chunks/{learnings-3YXDRWFT.js.map → learnings-CYNOICKR.js.map} +0 -0
  407. /package/dist/cli-bundle/chunks/{learnings-ALC6IMNL.js.map → learnings-KTYW3AL7.js.map} +0 -0
  408. /package/dist/cli-bundle/chunks/{notes-7JMLQ447.js.map → notes-FGO63FXL.js.map} +0 -0
  409. /package/dist/cli-bundle/chunks/{notes-JFCLTC5C.js.map → notes-ZERD3KB2.js.map} +0 -0
  410. /package/dist/cli-bundle/chunks/{plan-T3XB3WTK.js.map → plan-OFJUBIM5.js.map} +0 -0
  411. /package/dist/cli-bundle/chunks/{plan-KOIPWVOZ.js.map → plan-SGCDDTYR.js.map} +0 -0
  412. /package/dist/cli-bundle/chunks/{profile-OILJHKUW.js.map → profile-3THJPIQY.js.map} +0 -0
  413. /package/dist/cli-bundle/chunks/{profile-RJXA7PGS.js.map → profile-XEZAMMBW.js.map} +0 -0
  414. /package/dist/cli-bundle/chunks/{restore-ZH65GZFB.js.map → restore-6TDVSATY.js.map} +0 -0
  415. /package/dist/cli-bundle/chunks/{restore-L6IAGOD7.js.map → restore-RSL7C7LO.js.map} +0 -0
  416. /package/dist/cli-bundle/chunks/{schema-4ERWM5QJ.js.map → schema-HFXFSGPG.js.map} +0 -0
  417. /package/dist/cli-bundle/chunks/{schema-55DL3Q52.js.map → schema-TPVTIJPO.js.map} +0 -0
  418. /package/dist/cli-bundle/chunks/{update-FW6FKDOP.js.map → update-LJZCL5SI.js.map} +0 -0
  419. /package/dist/cli-bundle/chunks/{update-TJHSPRPT.js.map → update-SIA7LH5Y.js.map} +0 -0
  420. /package/dist/cli-bundle/chunks/{update-many-PWXX5WHO.js.map → update-many-BDBZVGQL.js.map} +0 -0
  421. /package/dist/cli-bundle/chunks/{update-many-NNALYQCN.js.map → update-many-MOY3A5B3.js.map} +0 -0
@@ -0,0 +1,21 @@
1
+ import type { BulkItemMutation } from "./item-transaction.js";
2
+ /** Validated transaction controls shared by atomic CLI and MCP adapters. */
3
+ export interface AtomicMutationControls {
4
+ /** Compensation policy applied to created items when a later step fails. */
5
+ createCompensation?: "close" | "delete";
6
+ /** Workspace transaction lock lifetime in seconds. */
7
+ lockTtlSeconds?: number;
8
+ /** Maximum time to wait for the workspace transaction lock. */
9
+ lockWaitMs?: number;
10
+ }
11
+ /** Validate and normalize atomic transaction controls at every transport boundary. */
12
+ export declare function parseAtomicMutationControls(value: Record<string, unknown>): AtomicMutationControls;
13
+ /** Parse a JSON array, or an object containing `mutations`, into an atomic mutation batch. */
14
+ export declare function parseItemMutationBatch(input: string): BulkItemMutation[];
15
+ /**
16
+ * Convert a direct item JSON document or `pm get --json` envelope into the
17
+ * create/update option shape. Explicit CLI flags override document values.
18
+ */
19
+ export declare function itemDocumentToMutationOptions(input: string, mode: "create" | "update", explicitOptions?: Record<string, unknown>): Record<string, unknown>;
20
+ /** Validate an already-decoded MCP mutation array through the same strict parser as CLI stdin. */
21
+ export declare function validateItemMutationRows(value: unknown): BulkItemMutation[];
@@ -0,0 +1,375 @@
1
+ /**
2
+ * @module sdk/structured-mutations
3
+ *
4
+ * Parses agent-authored JSON mutation payloads into the public atomic item
5
+ * transaction contract and normalizes full item documents for CLI round trips.
6
+ */
7
+
8
+ !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]="916a227a-1ec9-5af6-9b71-e871af2d7f0c")}catch(e){}}();
9
+ import { EXIT_CODE } from "../core/shared/constants.js";
10
+ import { PmCliError } from "../core/shared/errors.js";
11
+ import { levenshteinDistanceWithinLimit } from "../core/shared/levenshtein.js";
12
+ import { CLOSE_FLAG_CONTRACTS } from "./cli-contracts/flag-contracts.js";
13
+ import { CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS, UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS, } from "./cli-contracts/commander-mutation-options.js";
14
+ const MUTATION_ROW_KEYS = ["op", "id", "reason", "options"];
15
+ const ITEM_ENVELOPE_KEYS = [
16
+ "item",
17
+ "linked",
18
+ "schedule",
19
+ "claim_state",
20
+ "children",
21
+ ];
22
+ const READ_ONLY_ITEM_KEYS = new Set([
23
+ "created_at",
24
+ "updated_at",
25
+ "closed_at",
26
+ "version",
27
+ "format_version",
28
+ "path",
29
+ "author",
30
+ ]);
31
+ const UPDATE_READ_ONLY_ITEM_KEYS = new Set([...READ_ONLY_ITEM_KEYS, "id"]);
32
+ const ITEM_FIELD_KEYS = new Set([
33
+ "id",
34
+ "title",
35
+ "description",
36
+ "type",
37
+ "status",
38
+ "priority",
39
+ "tags",
40
+ "body",
41
+ "deadline",
42
+ "estimated_minutes",
43
+ "acceptance_criteria",
44
+ "definition_of_ready",
45
+ "order",
46
+ "rank",
47
+ "goal",
48
+ "objective",
49
+ "value",
50
+ "impact",
51
+ "outcome",
52
+ "why_now",
53
+ "assignee",
54
+ "parent",
55
+ "reviewer",
56
+ "risk",
57
+ "confidence",
58
+ "sprint",
59
+ "release",
60
+ "blocked_by",
61
+ "blocked_reason",
62
+ "unblock_note",
63
+ "reporter",
64
+ "severity",
65
+ "environment",
66
+ "repro_steps",
67
+ "resolution",
68
+ "expected_result",
69
+ "actual_result",
70
+ "affected_version",
71
+ "fixed_version",
72
+ "component",
73
+ "regression",
74
+ "customer_impact",
75
+ "close_reason",
76
+ "dependencies",
77
+ "comments",
78
+ "notes",
79
+ "learnings",
80
+ "files",
81
+ "tests",
82
+ "docs",
83
+ "reminders",
84
+ "events",
85
+ "type_options",
86
+ ]);
87
+ const MUTATION_OPTION_KEYS = {
88
+ create: CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS.map((contract) => contract.target),
89
+ update: UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS.map((contract) => contract.target),
90
+ close: CLOSE_FLAG_CONTRACTS.map((contract) => contract.flag
91
+ .slice(2)
92
+ .replaceAll(/-([a-z])/gu, (_match, letter) => letter.toUpperCase())).filter((key) => key !== "reason"),
93
+ };
94
+ /** Validate and normalize atomic transaction controls at every transport boundary. */
95
+ export function parseAtomicMutationControls(value) {
96
+ const controls = {};
97
+ const compensation = value.createCompensation;
98
+ if (compensation !== undefined) {
99
+ if (compensation !== "close" && compensation !== "delete") {
100
+ throw new PmCliError("createCompensation must be close or delete.", EXIT_CODE.USAGE);
101
+ }
102
+ controls.createCompensation = compensation;
103
+ }
104
+ for (const key of ["lockTtlSeconds", "lockWaitMs"]) {
105
+ const raw = value[key];
106
+ if (raw === undefined)
107
+ continue;
108
+ const parsed = typeof raw === "number" ||
109
+ (typeof raw === "string" && raw.trim().length > 0)
110
+ ? Number(raw)
111
+ : Number.NaN;
112
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
113
+ throw new PmCliError(`${key} must be a positive safe integer.`, EXIT_CODE.USAGE);
114
+ }
115
+ controls[key] = parsed;
116
+ }
117
+ return controls;
118
+ }
119
+ function isPlainObject(value) {
120
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
121
+ return false;
122
+ }
123
+ const prototype = Object.getPrototypeOf(value);
124
+ return prototype === Object.prototype || prototype === null;
125
+ }
126
+ function nearestKey(key, candidates) {
127
+ const limit = Math.max(1, Math.min(3, Math.floor(key.length / 4) + 1));
128
+ let best;
129
+ for (const candidate of candidates) {
130
+ const distance = levenshteinDistanceWithinLimit(key, candidate, limit);
131
+ if (distance !== null && (best === undefined || distance < best.distance)) {
132
+ best = { key: candidate, distance };
133
+ }
134
+ }
135
+ return best?.key;
136
+ }
137
+ function unknownKeyError(scope, key, candidates) {
138
+ const suggestion = nearestKey(key, candidates);
139
+ return new PmCliError(suggestion === undefined
140
+ ? `${scope} does not recognize key "${key}". Allowed keys: ${candidates.join(", ")}.`
141
+ : `${scope} does not recognize key "${key}". Did you mean "${suggestion}"?`, EXIT_CODE.USAGE, {
142
+ code: "stdin_json_unknown_key",
143
+ required: `Use documented ${scope} keys only.`,
144
+ why: "Strict structured input prevents silent typos from creating incomplete or unintended mutations.",
145
+ nextSteps: [
146
+ suggestion === undefined
147
+ ? `Remove or correct "${key}".`
148
+ : `Replace "${key}" with "${suggestion}".`,
149
+ ],
150
+ });
151
+ }
152
+ function parseJsonValue(input, label) {
153
+ try {
154
+ return JSON.parse(input);
155
+ }
156
+ catch (error) {
157
+ const detail = error instanceof Error ? error.message : String(error);
158
+ throw new PmCliError(`${label} must be valid JSON: ${detail}`, EXIT_CODE.USAGE, {
159
+ code: "stdin_json_invalid",
160
+ required: `Pipe one valid JSON ${label.toLowerCase()} into stdin.`,
161
+ why: "Structured mutation input must parse deterministically before any tracker write begins.",
162
+ });
163
+ }
164
+ }
165
+ function validateMutationObject(value, index) {
166
+ if (!isPlainObject(value)) {
167
+ throw new PmCliError(`Mutation ${index + 1} must be an object.`, EXIT_CODE.USAGE);
168
+ }
169
+ for (const key of Object.keys(value)) {
170
+ if (!MUTATION_ROW_KEYS.includes(key)) {
171
+ throw unknownKeyError(`mutation ${index + 1}`, key, MUTATION_ROW_KEYS);
172
+ }
173
+ }
174
+ return value;
175
+ }
176
+ function validateMutationOptions(options, op, index) {
177
+ if (options === undefined)
178
+ return undefined;
179
+ if (!isPlainObject(options)) {
180
+ throw new PmCliError(`Mutation ${index + 1} options must be an object.`, EXIT_CODE.USAGE);
181
+ }
182
+ for (const key of Object.keys(options)) {
183
+ if (!MUTATION_OPTION_KEYS[op].includes(key)) {
184
+ throw unknownKeyError(`mutation ${index + 1} ${op} options`, key, MUTATION_OPTION_KEYS[op]);
185
+ }
186
+ }
187
+ return options;
188
+ }
189
+ function validateMutationRow(value, index) {
190
+ const mutation = validateMutationObject(value, index);
191
+ const { op, id, reason } = mutation;
192
+ if (op !== "create" && op !== "update" && op !== "close") {
193
+ throw new PmCliError(`Mutation ${index + 1} op must be create, update, or close.`, EXIT_CODE.USAGE);
194
+ }
195
+ const options = validateMutationOptions(mutation.options, op, index);
196
+ if (typeof id !== "string" || id.trim().length === 0) {
197
+ throw new PmCliError(`Mutation ${index + 1} requires a non-empty id.`, EXIT_CODE.USAGE);
198
+ }
199
+ const normalizedId = id.trim();
200
+ if (op === "close") {
201
+ if (typeof reason !== "string" || reason.trim().length === 0) {
202
+ throw new PmCliError(`Mutation ${index + 1} close requires a non-empty reason.`, EXIT_CODE.USAGE);
203
+ }
204
+ return {
205
+ op,
206
+ id: normalizedId,
207
+ reason: reason.trim(),
208
+ ...(options === undefined
209
+ ? {}
210
+ : { options: options }),
211
+ };
212
+ }
213
+ if (!isPlainObject(options)) {
214
+ throw new PmCliError(`Mutation ${index + 1} ${op} requires an options object.`, EXIT_CODE.USAGE);
215
+ }
216
+ return {
217
+ op,
218
+ id: normalizedId,
219
+ options: options,
220
+ };
221
+ }
222
+ /** Parse a JSON array, or an object containing `mutations`, into an atomic mutation batch. */
223
+ export function parseItemMutationBatch(input) {
224
+ const parsed = parseJsonValue(input, "Mutation batch");
225
+ const rows = Array.isArray(parsed)
226
+ ? parsed
227
+ : isPlainObject(parsed) && Array.isArray(parsed.mutations)
228
+ ? parsed.mutations
229
+ : undefined;
230
+ if (rows === undefined || rows.length === 0) {
231
+ throw new PmCliError("Mutation batch must be a non-empty JSON array or an object with a non-empty mutations array.", EXIT_CODE.USAGE);
232
+ }
233
+ return rows.map((row, index) => validateMutationRow(row, index));
234
+ }
235
+ function serializePairs(value, keys) {
236
+ return keys
237
+ .filter((key) => value[key] !== undefined && value[key] !== null)
238
+ .map((key) => {
239
+ const rendered = String(value[key]);
240
+ return `${key}=${/[",\n\r\\]/u.test(rendered) ? JSON.stringify(rendered) : rendered}`;
241
+ })
242
+ .join(",");
243
+ }
244
+ function serializeObjectArray(value, keys, label) {
245
+ if (value === undefined)
246
+ return undefined;
247
+ if (!Array.isArray(value) || !value.every(isPlainObject)) {
248
+ throw new PmCliError(`${label} must be an array of objects.`, EXIT_CODE.USAGE);
249
+ }
250
+ return value.map((entry) => serializePairs(entry, keys));
251
+ }
252
+ function scalarItemOption(key, value) {
253
+ if (key === "tags" &&
254
+ Array.isArray(value) &&
255
+ value.every((entry) => typeof entry === "string")) {
256
+ return JSON.stringify(value);
257
+ }
258
+ if (typeof value === "number" || typeof value === "boolean") {
259
+ return String(value);
260
+ }
261
+ return value;
262
+ }
263
+ function appendFacetOptions(target, source, skipPersistedAnnotations = false) {
264
+ const mappings = [
265
+ ["dependencies", "dep", ["id", "kind", "created_at", "author"]],
266
+ ["comments", "comment", ["text", "created_at", "author"]],
267
+ ["notes", "note", ["text", "created_at", "author"]],
268
+ ["learnings", "learning", ["text", "created_at", "author"]],
269
+ ["files", "file", ["path", "scope", "note"]],
270
+ ["tests", "test", ["command", "scope", "timeout_seconds"]],
271
+ ["docs", "doc", ["path", "scope", "note"]],
272
+ ["reminders", "reminder", ["at", "text", "created_at"]],
273
+ ["events", "event", ["start_at", "end_at", "title", "location"]],
274
+ ["type_options", "typeOption", ["key", "value"]],
275
+ ];
276
+ for (const [sourceKey, targetKey, keys] of mappings) {
277
+ const sourceValue = source[sourceKey];
278
+ const serialized = serializeObjectArray(skipPersistedAnnotations &&
279
+ ["comments", "notes", "learnings"].includes(sourceKey) &&
280
+ Array.isArray(sourceValue)
281
+ ? sourceValue.filter((entry) => !isPlainObject(entry) || entry.created_at === undefined)
282
+ : sourceValue, keys, sourceKey);
283
+ if (serialized !== undefined && serialized.length > 0)
284
+ target[targetKey] = serialized;
285
+ }
286
+ }
287
+ function validateItemDocumentKeys(parsed, envelope) {
288
+ for (const key of Object.keys(parsed)) {
289
+ if (envelope) {
290
+ if (!ITEM_ENVELOPE_KEYS.includes(key))
291
+ throw unknownKeyError("item envelope", key, ITEM_ENVELOPE_KEYS);
292
+ continue;
293
+ }
294
+ if (!ITEM_FIELD_KEYS.has(key) &&
295
+ nearestKey(key, [...ITEM_FIELD_KEYS]) === undefined &&
296
+ nearestKey(key, ITEM_ENVELOPE_KEYS) === "item")
297
+ throw unknownKeyError("item envelope", key, ITEM_ENVELOPE_KEYS);
298
+ }
299
+ }
300
+ function resolveItemDocument(parsed) {
301
+ const envelope = Object.hasOwn(parsed, "item");
302
+ validateItemDocumentKeys(parsed, envelope);
303
+ const item = envelope ? parsed.item : parsed;
304
+ if (!isPlainObject(item)) {
305
+ throw new PmCliError("Item document item must be an object.", EXIT_CODE.USAGE);
306
+ }
307
+ return {
308
+ item,
309
+ ...(envelope && isPlainObject(parsed.linked)
310
+ ? { linked: parsed.linked }
311
+ : {}),
312
+ };
313
+ }
314
+ function appendItemDocumentEntry(documentOptions, key, value, mode) {
315
+ const readOnlyKeys = mode === "update" ? UPDATE_READ_ONLY_ITEM_KEYS : READ_ONLY_ITEM_KEYS;
316
+ if (readOnlyKeys.has(key))
317
+ return;
318
+ if (!ITEM_FIELD_KEYS.has(key)) {
319
+ const suggestion = nearestKey(key, [...ITEM_FIELD_KEYS]);
320
+ if (suggestion !== undefined)
321
+ throw unknownKeyError("item document", key, [...ITEM_FIELD_KEYS]);
322
+ const fields = Array.isArray(documentOptions.field)
323
+ ? documentOptions.field
324
+ : [];
325
+ fields.push(serializePairs({
326
+ key,
327
+ value: typeof value === "string" ? value : JSON.stringify(value),
328
+ }, ["key", "value"]));
329
+ documentOptions.field = fields;
330
+ return;
331
+ }
332
+ if ([
333
+ "dependencies",
334
+ "comments",
335
+ "notes",
336
+ "learnings",
337
+ "files",
338
+ "tests",
339
+ "docs",
340
+ "reminders",
341
+ "events",
342
+ "type_options",
343
+ ].includes(key))
344
+ return;
345
+ documentOptions[key.replaceAll(/_([a-z])/gu, (_match, letter) => letter.toUpperCase())] = scalarItemOption(key, value);
346
+ }
347
+ /**
348
+ * Convert a direct item JSON document or `pm get --json` envelope into the
349
+ * create/update option shape. Explicit CLI flags override document values.
350
+ */
351
+ export function itemDocumentToMutationOptions(input, mode, explicitOptions = {}) {
352
+ const parsed = parseJsonValue(input, "Item document");
353
+ if (!isPlainObject(parsed)) {
354
+ throw new PmCliError("Item document must be a JSON object.", EXIT_CODE.USAGE);
355
+ }
356
+ const { item, linked } = resolveItemDocument(parsed);
357
+ const documentOptions = {};
358
+ for (const [key, value] of Object.entries(item)) {
359
+ appendItemDocumentEntry(documentOptions, key, value, mode);
360
+ }
361
+ appendFacetOptions(documentOptions, item, mode === "update");
362
+ if (linked !== undefined)
363
+ appendFacetOptions(documentOptions, linked);
364
+ return {
365
+ ...documentOptions,
366
+ ...Object.fromEntries(Object.entries(explicitOptions).filter(([, value]) => value !== undefined)),
367
+ stdinJson: undefined,
368
+ };
369
+ }
370
+ /** Validate an already-decoded MCP mutation array through the same strict parser as CLI stdin. */
371
+ export function validateItemMutationRows(value) {
372
+ return parseItemMutationBatch(JSON.stringify(value));
373
+ }
374
+ //# sourceMappingURL=structured-mutations.js.map
375
+ //# debugId=916a227a-1ec9-5af6-9b71-e871af2d7f0c
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structured-mutations.js","sources":["sdk/structured-mutations.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module sdk/structured-mutations\n *\n * Parses agent-authored JSON mutation payloads into the public atomic item\n * transaction contract and normalizes full item documents for CLI round trips.\n */\nimport { EXIT_CODE } from \"../core/shared/constants.js\";\nimport { PmCliError } from \"../core/shared/errors.js\";\nimport { levenshteinDistanceWithinLimit } from \"../core/shared/levenshtein.js\";\nimport { CLOSE_FLAG_CONTRACTS } from \"./cli-contracts/flag-contracts.js\";\nimport {\n CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS,\n UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS,\n} from \"./cli-contracts/commander-mutation-options.js\";\nimport type { PmClientFullMutationOptions } from \"./runtime.js\";\nimport type { BulkItemMutation } from \"./item-transaction.js\";\n\nconst MUTATION_ROW_KEYS = [\"op\", \"id\", \"reason\", \"options\"] as const;\nconst ITEM_ENVELOPE_KEYS = [\n \"item\",\n \"linked\",\n \"schedule\",\n \"claim_state\",\n \"children\",\n] as const;\nconst READ_ONLY_ITEM_KEYS = new Set([\n \"created_at\",\n \"updated_at\",\n \"closed_at\",\n \"version\",\n \"format_version\",\n \"path\",\n \"author\",\n]);\nconst UPDATE_READ_ONLY_ITEM_KEYS = new Set([...READ_ONLY_ITEM_KEYS, \"id\"]);\nconst ITEM_FIELD_KEYS = new Set([\n \"id\",\n \"title\",\n \"description\",\n \"type\",\n \"status\",\n \"priority\",\n \"tags\",\n \"body\",\n \"deadline\",\n \"estimated_minutes\",\n \"acceptance_criteria\",\n \"definition_of_ready\",\n \"order\",\n \"rank\",\n \"goal\",\n \"objective\",\n \"value\",\n \"impact\",\n \"outcome\",\n \"why_now\",\n \"assignee\",\n \"parent\",\n \"reviewer\",\n \"risk\",\n \"confidence\",\n \"sprint\",\n \"release\",\n \"blocked_by\",\n \"blocked_reason\",\n \"unblock_note\",\n \"reporter\",\n \"severity\",\n \"environment\",\n \"repro_steps\",\n \"resolution\",\n \"expected_result\",\n \"actual_result\",\n \"affected_version\",\n \"fixed_version\",\n \"component\",\n \"regression\",\n \"customer_impact\",\n \"close_reason\",\n \"dependencies\",\n \"comments\",\n \"notes\",\n \"learnings\",\n \"files\",\n \"tests\",\n \"docs\",\n \"reminders\",\n \"events\",\n \"type_options\",\n]);\nconst MUTATION_OPTION_KEYS: Readonly<\n Record<BulkItemMutation[\"op\"], readonly string[]>\n> = {\n create: CREATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS.map(\n (contract) => contract.target,\n ),\n update: UPDATE_COMMANDER_OPTION_REGISTRATION_CONTRACTS.map(\n (contract) => contract.target,\n ),\n close: CLOSE_FLAG_CONTRACTS.map((contract) =>\n contract.flag\n .slice(2)\n .replaceAll(/-([a-z])/gu, (_match, letter: string) =>\n letter.toUpperCase(),\n ),\n ).filter((key) => key !== \"reason\"),\n};\n\n/** Validated transaction controls shared by atomic CLI and MCP adapters. */\nexport interface AtomicMutationControls {\n /** Compensation policy applied to created items when a later step fails. */\n createCompensation?: \"close\" | \"delete\";\n /** Workspace transaction lock lifetime in seconds. */\n lockTtlSeconds?: number;\n /** Maximum time to wait for the workspace transaction lock. */\n lockWaitMs?: number;\n}\n\n/** Validate and normalize atomic transaction controls at every transport boundary. */\nexport function parseAtomicMutationControls(\n value: Record<string, unknown>,\n): AtomicMutationControls {\n const controls: AtomicMutationControls = {};\n const compensation = value.createCompensation;\n if (compensation !== undefined) {\n if (compensation !== \"close\" && compensation !== \"delete\") {\n throw new PmCliError(\n \"createCompensation must be close or delete.\",\n EXIT_CODE.USAGE,\n );\n }\n controls.createCompensation = compensation;\n }\n for (const key of [\"lockTtlSeconds\", \"lockWaitMs\"] as const) {\n const raw = value[key];\n if (raw === undefined) continue;\n const parsed =\n typeof raw === \"number\" ||\n (typeof raw === \"string\" && raw.trim().length > 0)\n ? Number(raw)\n : Number.NaN;\n if (!Number.isSafeInteger(parsed) || parsed <= 0) {\n throw new PmCliError(\n `${key} must be a positive safe integer.`,\n EXIT_CODE.USAGE,\n );\n }\n controls[key] = parsed;\n }\n return controls;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction nearestKey(\n key: string,\n candidates: readonly string[],\n): string | undefined {\n const limit = Math.max(1, Math.min(3, Math.floor(key.length / 4) + 1));\n let best: { key: string; distance: number } | undefined;\n for (const candidate of candidates) {\n const distance = levenshteinDistanceWithinLimit(key, candidate, limit);\n if (distance !== null && (best === undefined || distance < best.distance)) {\n best = { key: candidate, distance };\n }\n }\n return best?.key;\n}\n\nfunction unknownKeyError(\n scope: string,\n key: string,\n candidates: readonly string[],\n): PmCliError {\n const suggestion = nearestKey(key, candidates);\n return new PmCliError(\n suggestion === undefined\n ? `${scope} does not recognize key \"${key}\". Allowed keys: ${candidates.join(\", \")}.`\n : `${scope} does not recognize key \"${key}\". Did you mean \"${suggestion}\"?`,\n EXIT_CODE.USAGE,\n {\n code: \"stdin_json_unknown_key\",\n required: `Use documented ${scope} keys only.`,\n why: \"Strict structured input prevents silent typos from creating incomplete or unintended mutations.\",\n nextSteps: [\n suggestion === undefined\n ? `Remove or correct \"${key}\".`\n : `Replace \"${key}\" with \"${suggestion}\".`,\n ],\n },\n );\n}\n\nfunction parseJsonValue(input: string, label: string): unknown {\n try {\n return JSON.parse(input) as unknown;\n } catch (error: unknown) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new PmCliError(\n `${label} must be valid JSON: ${detail}`,\n EXIT_CODE.USAGE,\n {\n code: \"stdin_json_invalid\",\n required: `Pipe one valid JSON ${label.toLowerCase()} into stdin.`,\n why: \"Structured mutation input must parse deterministically before any tracker write begins.\",\n },\n );\n }\n}\n\nfunction validateMutationObject(\n value: unknown,\n index: number,\n): Record<string, unknown> {\n if (!isPlainObject(value)) {\n throw new PmCliError(\n `Mutation ${index + 1} must be an object.`,\n EXIT_CODE.USAGE,\n );\n }\n for (const key of Object.keys(value)) {\n if (\n !MUTATION_ROW_KEYS.includes(key as (typeof MUTATION_ROW_KEYS)[number])\n ) {\n throw unknownKeyError(`mutation ${index + 1}`, key, MUTATION_ROW_KEYS);\n }\n }\n return value;\n}\n\nfunction validateMutationOptions(\n options: unknown,\n op: BulkItemMutation[\"op\"],\n index: number,\n): Record<string, unknown> | undefined {\n if (options === undefined) return undefined;\n if (!isPlainObject(options)) {\n throw new PmCliError(\n `Mutation ${index + 1} options must be an object.`,\n EXIT_CODE.USAGE,\n );\n }\n for (const key of Object.keys(options)) {\n if (!MUTATION_OPTION_KEYS[op].includes(key)) {\n throw unknownKeyError(\n `mutation ${index + 1} ${op} options`,\n key,\n MUTATION_OPTION_KEYS[op],\n );\n }\n }\n return options;\n}\n\nfunction validateMutationRow(value: unknown, index: number): BulkItemMutation {\n const mutation = validateMutationObject(value, index);\n const { op, id, reason } = mutation;\n if (op !== \"create\" && op !== \"update\" && op !== \"close\") {\n throw new PmCliError(\n `Mutation ${index + 1} op must be create, update, or close.`,\n EXIT_CODE.USAGE,\n );\n }\n const options = validateMutationOptions(mutation.options, op, index);\n if (typeof id !== \"string\" || id.trim().length === 0) {\n throw new PmCliError(\n `Mutation ${index + 1} requires a non-empty id.`,\n EXIT_CODE.USAGE,\n );\n }\n const normalizedId = id.trim();\n if (op === \"close\") {\n if (typeof reason !== \"string\" || reason.trim().length === 0) {\n throw new PmCliError(\n `Mutation ${index + 1} close requires a non-empty reason.`,\n EXIT_CODE.USAGE,\n );\n }\n return {\n op,\n id: normalizedId,\n reason: reason.trim(),\n ...(options === undefined\n ? {}\n : { options: options as PmClientFullMutationOptions }),\n };\n }\n if (!isPlainObject(options)) {\n throw new PmCliError(\n `Mutation ${index + 1} ${op} requires an options object.`,\n EXIT_CODE.USAGE,\n );\n }\n return {\n op,\n id: normalizedId,\n options: options as PmClientFullMutationOptions,\n };\n}\n\n/** Parse a JSON array, or an object containing `mutations`, into an atomic mutation batch. */\nexport function parseItemMutationBatch(input: string): BulkItemMutation[] {\n const parsed = parseJsonValue(input, \"Mutation batch\");\n const rows = Array.isArray(parsed)\n ? parsed\n : isPlainObject(parsed) && Array.isArray(parsed.mutations)\n ? parsed.mutations\n : undefined;\n if (rows === undefined || rows.length === 0) {\n throw new PmCliError(\n \"Mutation batch must be a non-empty JSON array or an object with a non-empty mutations array.\",\n EXIT_CODE.USAGE,\n );\n }\n return rows.map((row, index) => validateMutationRow(row, index));\n}\n\nfunction serializePairs(\n value: Record<string, unknown>,\n keys: readonly string[],\n): string {\n return keys\n .filter((key) => value[key] !== undefined && value[key] !== null)\n .map((key) => {\n const rendered = String(value[key]);\n return `${key}=${/[\",\\n\\r\\\\]/u.test(rendered) ? JSON.stringify(rendered) : rendered}`;\n })\n .join(\",\");\n}\n\nfunction serializeObjectArray(\n value: unknown,\n keys: readonly string[],\n label: string,\n): string[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value) || !value.every(isPlainObject)) {\n throw new PmCliError(\n `${label} must be an array of objects.`,\n EXIT_CODE.USAGE,\n );\n }\n return value.map((entry) => serializePairs(entry, keys));\n}\n\nfunction scalarItemOption(key: string, value: unknown): unknown {\n if (\n key === \"tags\" &&\n Array.isArray(value) &&\n value.every((entry) => typeof entry === \"string\")\n ) {\n return JSON.stringify(value);\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n return value;\n}\n\nfunction appendFacetOptions(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n skipPersistedAnnotations = false,\n): void {\n const mappings: ReadonlyArray<readonly [string, string, readonly string[]]> =\n [\n [\"dependencies\", \"dep\", [\"id\", \"kind\", \"created_at\", \"author\"]],\n [\"comments\", \"comment\", [\"text\", \"created_at\", \"author\"]],\n [\"notes\", \"note\", [\"text\", \"created_at\", \"author\"]],\n [\"learnings\", \"learning\", [\"text\", \"created_at\", \"author\"]],\n [\"files\", \"file\", [\"path\", \"scope\", \"note\"]],\n [\"tests\", \"test\", [\"command\", \"scope\", \"timeout_seconds\"]],\n [\"docs\", \"doc\", [\"path\", \"scope\", \"note\"]],\n [\"reminders\", \"reminder\", [\"at\", \"text\", \"created_at\"]],\n [\"events\", \"event\", [\"start_at\", \"end_at\", \"title\", \"location\"]],\n [\"type_options\", \"typeOption\", [\"key\", \"value\"]],\n ];\n for (const [sourceKey, targetKey, keys] of mappings) {\n const sourceValue = source[sourceKey];\n const serialized = serializeObjectArray(\n skipPersistedAnnotations &&\n [\"comments\", \"notes\", \"learnings\"].includes(sourceKey) &&\n Array.isArray(sourceValue)\n ? sourceValue.filter(\n (entry) =>\n !isPlainObject(entry) || entry.created_at === undefined,\n )\n : sourceValue,\n keys,\n sourceKey,\n );\n if (serialized !== undefined && serialized.length > 0)\n target[targetKey] = serialized;\n }\n}\n\nfunction validateItemDocumentKeys(\n parsed: Record<string, unknown>,\n envelope: boolean,\n): void {\n for (const key of Object.keys(parsed)) {\n if (envelope) {\n if (\n !ITEM_ENVELOPE_KEYS.includes(key as (typeof ITEM_ENVELOPE_KEYS)[number])\n )\n throw unknownKeyError(\"item envelope\", key, ITEM_ENVELOPE_KEYS);\n continue;\n }\n if (\n !ITEM_FIELD_KEYS.has(key) &&\n nearestKey(key, [...ITEM_FIELD_KEYS]) === undefined &&\n nearestKey(key, ITEM_ENVELOPE_KEYS) === \"item\"\n )\n throw unknownKeyError(\"item envelope\", key, ITEM_ENVELOPE_KEYS);\n }\n}\n\nfunction resolveItemDocument(parsed: Record<string, unknown>): {\n item: Record<string, unknown>;\n linked?: Record<string, unknown>;\n} {\n const envelope = Object.hasOwn(parsed, \"item\");\n validateItemDocumentKeys(parsed, envelope);\n const item = envelope ? parsed.item : parsed;\n if (!isPlainObject(item)) {\n throw new PmCliError(\n \"Item document item must be an object.\",\n EXIT_CODE.USAGE,\n );\n }\n return {\n item,\n ...(envelope && isPlainObject(parsed.linked)\n ? { linked: parsed.linked }\n : {}),\n };\n}\n\nfunction appendItemDocumentEntry(\n documentOptions: Record<string, unknown>,\n key: string,\n value: unknown,\n mode: \"create\" | \"update\",\n): void {\n const readOnlyKeys =\n mode === \"update\" ? UPDATE_READ_ONLY_ITEM_KEYS : READ_ONLY_ITEM_KEYS;\n if (readOnlyKeys.has(key)) return;\n if (!ITEM_FIELD_KEYS.has(key)) {\n const suggestion = nearestKey(key, [...ITEM_FIELD_KEYS]);\n if (suggestion !== undefined)\n throw unknownKeyError(\"item document\", key, [...ITEM_FIELD_KEYS]);\n const fields = Array.isArray(documentOptions.field)\n ? (documentOptions.field as string[])\n : [];\n fields.push(\n serializePairs(\n {\n key,\n value: typeof value === \"string\" ? value : JSON.stringify(value),\n },\n [\"key\", \"value\"],\n ),\n );\n documentOptions.field = fields;\n return;\n }\n if (\n [\n \"dependencies\",\n \"comments\",\n \"notes\",\n \"learnings\",\n \"files\",\n \"tests\",\n \"docs\",\n \"reminders\",\n \"events\",\n \"type_options\",\n ].includes(key)\n )\n return;\n documentOptions[\n key.replaceAll(/_([a-z])/gu, (_match, letter: string) =>\n letter.toUpperCase(),\n )\n ] = scalarItemOption(key, value);\n}\n\n/**\n * Convert a direct item JSON document or `pm get --json` envelope into the\n * create/update option shape. Explicit CLI flags override document values.\n */\nexport function itemDocumentToMutationOptions(\n input: string,\n mode: \"create\" | \"update\",\n explicitOptions: Record<string, unknown> = {},\n): Record<string, unknown> {\n const parsed = parseJsonValue(input, \"Item document\");\n if (!isPlainObject(parsed)) {\n throw new PmCliError(\n \"Item document must be a JSON object.\",\n EXIT_CODE.USAGE,\n );\n }\n const { item, linked } = resolveItemDocument(parsed);\n const documentOptions: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(item)) {\n appendItemDocumentEntry(documentOptions, key, value, mode);\n }\n appendFacetOptions(documentOptions, item, mode === \"update\");\n if (linked !== undefined) appendFacetOptions(documentOptions, linked);\n return {\n ...documentOptions,\n ...Object.fromEntries(\n Object.entries(explicitOptions).filter(\n ([, value]) => value !== undefined,\n ),\n ),\n stdinJson: undefined,\n };\n}\n\n/** Validate an already-decoded MCP mutation array through the same strict parser as CLI stdin. */\nexport function validateItemMutationRows(value: unknown): BulkItemMutation[] {\n return parseItemMutationBatch(JSON.stringify(value));\n}\n"],"names":[],"mappings":"AAAA;;;;;GAKG;;;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EACL,8CAA8C,EAC9C,8CAA8C,GAC/C,MAAM,+CAA+C,CAAC;AAIvD,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAU,CAAC;AACrE,MAAM,kBAAkB,GAAG;IACzB,MAAM;IACN,QAAQ;IACR,UAAU;IACV,aAAa;IACb,UAAU;CACF,CAAC;AACX,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,YAAY;IACZ,YAAY;IACZ,WAAW;IACX,SAAS;IACT,gBAAgB;IAChB,MAAM;IACN,QAAQ;CACT,CAAC,CAAC;AACH,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,mBAAmB,EAAE,IAAI,CAAC,CAAC,CAAC;AAC3E,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,IAAI;IACJ,OAAO;IACP,aAAa;IACb,MAAM;IACN,QAAQ;IACR,UAAU;IACV,MAAM;IACN,MAAM;IACN,UAAU;IACV,mBAAmB;IACnB,qBAAqB;IACrB,qBAAqB;IACrB,OAAO;IACP,MAAM;IACN,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,SAAS;IACT,SAAS;IACT,UAAU;IACV,QAAQ;IACR,UAAU;IACV,MAAM;IACN,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,YAAY;IACZ,gBAAgB;IAChB,cAAc;IACd,UAAU;IACV,UAAU;IACV,aAAa;IACb,aAAa;IACb,YAAY;IACZ,iBAAiB;IACjB,eAAe;IACf,kBAAkB;IAClB,eAAe;IACf,WAAW;IACX,YAAY;IACZ,iBAAiB;IACjB,cAAc;IACd,cAAc;IACd,UAAU;IACV,OAAO;IACP,WAAW;IACX,OAAO;IACP,OAAO;IACP,MAAM;IACN,WAAW;IACX,QAAQ;IACR,cAAc;CACf,CAAC,CAAC;AACH,MAAM,oBAAoB,GAEtB;IACF,MAAM,EAAE,8CAA8C,CAAC,GAAG,CACxD,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAC9B;IACD,MAAM,EAAE,8CAA8C,CAAC,GAAG,CACxD,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAC9B;IACD,KAAK,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC3C,QAAQ,CAAC,IAAI;SACV,KAAK,CAAC,CAAC,CAAC;SACR,UAAU,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAc,EAAE,EAAE,CACnD,MAAM,CAAC,WAAW,EAAE,CACrB,CACJ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,QAAQ,CAAC;CACpC,CAAC;AAYF,sFAAsF;AACtF,MAAM,UAAU,2BAA2B,CACzC,KAA8B;IAE9B,MAAM,QAAQ,GAA2B,EAAE,CAAC;IAC5C,MAAM,YAAY,GAAG,KAAK,CAAC,kBAAkB,CAAC;IAC9C,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,IAAI,YAAY,KAAK,OAAO,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;YAC1D,MAAM,IAAI,UAAU,CAClB,6CAA6C,EAC7C,SAAS,CAAC,KAAK,CAChB,CAAC;QACJ,CAAC;QACD,QAAQ,CAAC,kBAAkB,GAAG,YAAY,CAAC;IAC7C,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAU,EAAE,CAAC;QAC5D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,GAAG,KAAK,SAAS;YAAE,SAAS;QAChC,MAAM,MAAM,GACV,OAAO,GAAG,KAAK,QAAQ;YACvB,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;YAChD,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACb,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;QACjB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,UAAU,CAClB,GAAG,GAAG,mCAAmC,EACzC,SAAS,CAAC,KAAK,CAChB,CAAC;QACJ,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACzB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC;AAC9D,CAAC;AAED,SAAS,UAAU,CACjB,GAAW,EACX,UAA6B;IAE7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACvE,IAAI,IAAmD,CAAC;IACxD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,8BAA8B,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QACvE,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1E,IAAI,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,EAAE,GAAG,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CACtB,KAAa,EACb,GAAW,EACX,UAA6B;IAE7B,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC/C,OAAO,IAAI,UAAU,CACnB,UAAU,KAAK,SAAS;QACtB,CAAC,CAAC,GAAG,KAAK,4BAA4B,GAAG,oBAAoB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QACrF,CAAC,CAAC,GAAG,KAAK,4BAA4B,GAAG,oBAAoB,UAAU,IAAI,EAC7E,SAAS,CAAC,KAAK,EACf;QACE,IAAI,EAAE,wBAAwB;QAC9B,QAAQ,EAAE,kBAAkB,KAAK,aAAa;QAC9C,GAAG,EAAE,iGAAiG;QACtG,SAAS,EAAE;YACT,UAAU,KAAK,SAAS;gBACtB,CAAC,CAAC,sBAAsB,GAAG,IAAI;gBAC/B,CAAC,CAAC,YAAY,GAAG,WAAW,UAAU,IAAI;SAC7C;KACF,CACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAa,EAAE,KAAa;IAClD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAY,CAAC;IACtC,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,MAAM,IAAI,UAAU,CAClB,GAAG,KAAK,wBAAwB,MAAM,EAAE,EACxC,SAAS,CAAC,KAAK,EACf;YACE,IAAI,EAAE,oBAAoB;YAC1B,QAAQ,EAAE,uBAAuB,KAAK,CAAC,WAAW,EAAE,cAAc;YAClE,GAAG,EAAE,yFAAyF;SAC/F,CACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAC7B,KAAc,EACd,KAAa;IAEb,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAClB,YAAY,KAAK,GAAG,CAAC,qBAAqB,EAC1C,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,IACE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,GAAyC,CAAC,EACtE,CAAC;YACD,MAAM,eAAe,CAAC,YAAY,KAAK,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,iBAAiB,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,uBAAuB,CAC9B,OAAgB,EAChB,EAA0B,EAC1B,KAAa;IAEb,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAClB,YAAY,KAAK,GAAG,CAAC,6BAA6B,EAClD,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5C,MAAM,eAAe,CACnB,YAAY,KAAK,GAAG,CAAC,IAAI,EAAE,UAAU,EACrC,GAAG,EACH,oBAAoB,CAAC,EAAE,CAAC,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc,EAAE,KAAa;IACxD,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtD,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,KAAK,QAAQ,IAAI,EAAE,KAAK,QAAQ,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACzD,MAAM,IAAI,UAAU,CAClB,YAAY,KAAK,GAAG,CAAC,uCAAuC,EAC5D,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IACrE,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,UAAU,CAClB,YAAY,KAAK,GAAG,CAAC,2BAA2B,EAChD,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;QACnB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,UAAU,CAClB,YAAY,KAAK,GAAG,CAAC,qCAAqC,EAC1D,SAAS,CAAC,KAAK,CAChB,CAAC;QACJ,CAAC;QACD,OAAO;YACL,EAAE;YACF,EAAE,EAAE,YAAY;YAChB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACrB,GAAG,CAAC,OAAO,KAAK,SAAS;gBACvB,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,OAAO,EAAE,OAAsC,EAAE,CAAC;SACzD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAClB,YAAY,KAAK,GAAG,CAAC,IAAI,EAAE,8BAA8B,EACzD,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,OAAO;QACL,EAAE;QACF,EAAE,EAAE,YAAY;QAChB,OAAO,EAAE,OAAsC;KAChD,CAAC;AACJ,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAChC,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;YACxD,CAAC,CAAC,MAAM,CAAC,SAAS;YAClB,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,UAAU,CAClB,8FAA8F,EAC9F,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,cAAc,CACrB,KAA8B,EAC9B,IAAuB;IAEvB,OAAO,IAAI;SACR,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;SAChE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,OAAO,GAAG,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxF,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB,CAC3B,KAAc,EACd,IAAuB,EACvB,KAAa;IAEb,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,UAAU,CAClB,GAAG,KAAK,+BAA+B,EACvC,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW,EAAE,KAAc;IACnD,IACE,GAAG,KAAK,MAAM;QACd,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACpB,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EACjD,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC5D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CACzB,MAA+B,EAC/B,MAA+B,EAC/B,wBAAwB,GAAG,KAAK;IAEhC,MAAM,QAAQ,GACZ;QACE,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC/D,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;QACzD,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;QACnD,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;QAC3D,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;QAC1D,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QACvD,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAChE,CAAC,cAAc,EAAE,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;KACjD,CAAC;IACJ,KAAK,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QACpD,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,oBAAoB,CACrC,wBAAwB;YACtB,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;YACtD,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;YAC1B,CAAC,CAAC,WAAW,CAAC,MAAM,CAChB,CAAC,KAAK,EAAE,EAAE,CACR,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,CAC1D;YACH,CAAC,CAAC,WAAW,EACf,IAAI,EACJ,SAAS,CACV,CAAC;QACF,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YACnD,MAAM,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC;IACnC,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAC/B,MAA+B,EAC/B,QAAiB;IAEjB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAI,QAAQ,EAAE,CAAC;YACb,IACE,CAAC,kBAAkB,CAAC,QAAQ,CAAC,GAA0C,CAAC;gBAExE,MAAM,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;YAClE,SAAS;QACX,CAAC;QACD,IACE,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;YACzB,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,KAAK,SAAS;YACnD,UAAU,CAAC,GAAG,EAAE,kBAAkB,CAAC,KAAK,MAAM;YAE9C,MAAM,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,MAA+B;IAI1D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,wBAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7C,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,UAAU,CAClB,uCAAuC,EACvC,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI;QACJ,GAAG,CAAC,QAAQ,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC;YAC1C,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;YAC3B,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,eAAwC,EACxC,GAAW,EACX,KAAc,EACd,IAAyB;IAEzB,MAAM,YAAY,GAChB,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,mBAAmB,CAAC;IACvE,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO;IAClC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC;QACzD,IAAI,UAAU,KAAK,SAAS;YAC1B,MAAM,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC;YACjD,CAAC,CAAE,eAAe,CAAC,KAAkB;YACrC,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,CAAC,IAAI,CACT,cAAc,CACZ;YACE,GAAG;YACH,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;SACjE,EACD,CAAC,KAAK,EAAE,OAAO,CAAC,CACjB,CACF,CAAC;QACF,eAAe,CAAC,KAAK,GAAG,MAAM,CAAC;QAC/B,OAAO;IACT,CAAC;IACD,IACE;QACE,cAAc;QACd,UAAU;QACV,OAAO;QACP,WAAW;QACX,OAAO;QACP,OAAO;QACP,MAAM;QACN,WAAW;QACX,QAAQ;QACR,cAAc;KACf,CAAC,QAAQ,CAAC,GAAG,CAAC;QAEf,OAAO;IACT,eAAe,CACb,GAAG,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAc,EAAE,EAAE,CACtD,MAAM,CAAC,WAAW,EAAE,CACrB,CACF,GAAG,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,KAAa,EACb,IAAyB,EACzB,kBAA2C,EAAE;IAE7C,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IACtD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAClB,sCAAsC,EACtC,SAAS,CAAC,KAAK,CAChB,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,eAAe,GAA4B,EAAE,CAAC;IACpD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,uBAAuB,CAAC,eAAe,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAC7D,CAAC;IACD,kBAAkB,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC;IAC7D,IAAI,MAAM,KAAK,SAAS;QAAE,kBAAkB,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACtE,OAAO;QACL,GAAG,eAAe;QAClB,GAAG,MAAM,CAAC,WAAW,CACnB,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CACnC,CACF;QACD,SAAS,EAAE,SAAS;KACrB,CAAC;AACJ,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,wBAAwB,CAAC,KAAc;IACrD,OAAO,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACvD,CAAC","debugId":"916a227a-1ec9-5af6-9b71-e871af2d7f0c"}
package/docs/COMMANDS.md CHANGED
@@ -27,7 +27,7 @@ Tracked documentation work: [pm-u9d0](../.agents/pm/epics/pm-u9d0.toon).
27
27
  | ------------ | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
28
28
  | Bootstrap | `init`, `config`, `health`, `telemetry` | create and inspect tracker setup |
29
29
  | Lifecycle | `create`, `copy`, `focus`, `claim`, `update`, `append`, `close`, `release`, `delete`, `start-task`, `pause-task`, `close-task` | mutate item state |
30
- | Bulk | `update-many`, `close-many` | apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
30
+ | Bulk | `item mutate`, `update-many`, `close-many` | atomically commit heterogeneous SDK mutation batches, or apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
31
31
  | Scheduling | `meet`, `event`, `remind` | low-friction Meeting/Event/Reminder creation |
32
32
  | Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize` | agent-optimized living plans with ordered steps, evidence, decisions, validation, and materialization |
33
33
  | Links | `files`, `docs`, `test`, `deps` | connect items to artifacts, tests, and relationships |
@@ -327,6 +327,13 @@ When a flag is rejected with `Unknown option`, the error guidance now suggests t
327
327
 
328
328
  ## Create and Update
329
329
 
330
+ Tracked structured-input and compact-output work:
331
+ [pm-xm7c](../.agents/pm/features/pm-xm7c.toon),
332
+ [pm-kipd](../.agents/pm/features/pm-kipd.toon),
333
+ [pm-nilh](../.agents/pm/features/pm-nilh.toon),
334
+ [pm-cfed](../.agents/pm/features/pm-cfed.toon), and
335
+ [pm-g9xk](../.agents/pm/features/pm-g9xk.toon).
336
+
330
337
  Shortest agent-friendly create (positional title + defaults to `Task` type):
331
338
 
332
339
  ```bash
@@ -376,6 +383,25 @@ pm update pm-a1b2 --body-file ./specs/updated-spec.md
376
383
 
377
384
  `--body-file` is mutually exclusive with `--body` (passing both errors). Use `--body -` to read the body from piped stdin.
378
385
 
386
+ For whole-item automation, `--stdin-json` on create/update accepts either a
387
+ direct item object or the envelope emitted by `pm get <id> --json`. Read-only
388
+ fields are ignored, linked facets are normalized through their audited mutation
389
+ inputs, and explicit CLI flags override document values:
390
+
391
+ ```bash
392
+ # Create from a complete document.
393
+ printf '%s' '{"title":"Imported incident","type":"Issue","tags":["imported"]}' \
394
+ | pm create --stdin-json --json
395
+
396
+ # Lossless get -> edit -> update round trip.
397
+ pm get pm-a1b2 --json > item.json
398
+ # edit item.json with an ordinary JSON-aware tool
399
+ pm update pm-a1b2 --stdin-json < item.json
400
+ ```
401
+
402
+ Input is strict: a near-miss such as `acceptance_criterai` fails with a
403
+ did-you-mean diagnostic instead of becoming an accidental custom field.
404
+
379
405
  Repeated singular/plural list flags now accumulate, so `--tag a --tag b` is equivalent to `--tags a,b` (the same holds for `--status`, `--ids`, and `--fields` on read commands). Earlier versions silently kept only the last value. `list`/`search` also accept `--tags` as a never-block alias for the canonical read filter `--tag`.
380
406
 
381
407
  `--tags` REPLACES the whole tag list. To edit tags without restating the full set, use the additive/subtractive flags on `create`/`update`/`update-many`:
@@ -389,7 +415,7 @@ pm update pm-abc1 --remove-tags stale # drops "stale", keeps the rest
389
415
  pm create "New backend task" --add-tags backend,p1
390
416
  ```
391
417
 
392
- Acceptance criteria get the same additive treatment on `update`/`update-many`: `--acceptance-criteria`/`--ac` REPLACES the whole value, while `--add-ac <text>` appends one criterion (repeatable; deduped on exact text) and `--remove-ac <text>` removes one criterion by exact text match (repeatable; a non-matching selector adds a `remove_ac_unmatched:<text>` warning instead of silently no-oping). Criteria are stored joined by `` ; ``, so one criterion cannot contain a semicolon. Disjoint `--add-ac` edits from concurrent agents/branches merge cleanly instead of clobbering each other.
418
+ Acceptance criteria get the same additive treatment on `update`/`update-many`: `--acceptance-criteria`/`--ac` REPLACES the whole value, while `--add-ac <text>` appends one criterion (repeatable; deduped on exact text) and `--remove-ac <text>` removes one criterion by exact text match (repeatable; a non-matching selector adds a `remove_ac_unmatched:<text>` warning instead of silently no-oping). Criteria are stored with semicolon-space separators, so one criterion cannot contain a semicolon. Disjoint `--add-ac` edits from concurrent agents/branches merge cleanly instead of clobbering each other.
393
419
 
394
420
  ```bash
395
421
  pm update pm-abc1 --add-ac "error path covered by a regression test"
@@ -426,13 +452,29 @@ pm update <id> --expected "Retry succeeds after backoff" --actual "Retry threw o
426
452
 
427
453
  Repeat `--ac`/`--acceptance-criteria` to build multi-part criteria; values are stored in order joined by `; `. Dependency inputs accept either a bare existing item id or the explicit `id=<id>,kind=<kind>` form, and malformed shorthand such as `related:pm-abcd` fails before it can create a dangling graph edge.
428
454
 
429
- Mutation commands (`create`/`update`/`close`/`append`/...) echo a `changed_fields` array. In high-volume agent loops that array is mostly redundant with the item echo above it, so pass the global `--no-changed-fields` flag to replace it with a compact `changed_field_count`:
455
+ Mutation commands (`create`/`update`/`close`/`append`/...) default to an
456
+ agent-efficient `id`/`status`/`changed_field_count` envelope. Use
457
+ `--no-changed-fields` for the full item echo without the redundant delta array,
458
+ or `--full-changed-fields` to restore the legacy complete envelope:
430
459
 
431
460
  ```bash
432
- pm --no-changed-fields create "Probe item" # output keeps changed_field_count, drops the array
461
+ pm create "Probe item" # id + status + changed_field_count
462
+ pm --no-changed-fields create "Probe item" # item echo + changed_field_count
463
+ pm --full-changed-fields create "Probe item" # item echo + changed_fields array
433
464
  pm --id-only create "Probe item" # output is only id + status
434
465
  ```
435
466
 
467
+ For strict JSON consumers, the global `--lean` flag recursively omits null,
468
+ undefined, empty-array, and empty-object noise while preserving meaningful
469
+ false/zero/empty-string values. On usage failures it keeps only actionable
470
+ error fields (`type`, `code`, `detail`, `exit_code`, examples, next steps, and
471
+ recovery), reducing retry context without hiding the deterministic fix:
472
+
473
+ ```bash
474
+ pm --json --lean get pm-a1b2
475
+ pm --json --lean create --unknown-option
476
+ ```
477
+
436
478
  Use `pm create --allow-missing-parent --parent <id>` only for deliberate imports or staged backlog reconstruction. Normal `pm create --parent <id>` fails fast when the parent id cannot be resolved.
437
479
 
438
480
  Use `pm close <duplicate-id> --duplicate-of <canonical-id>` to close duplicates. The command validates the canonical target exists, records `duplicate_of`, auto-fills the close reason as `Duplicate of <canonical-id>` when no reason text was supplied, and fills the resolution/expected/actual closure fields when they were not provided explicitly.
@@ -447,6 +489,32 @@ When closing a blocker, `pm close` scans reverse `blocked_by` edges and auto-unb
447
489
 
448
490
  Over MCP the mutation tools (`pm_create`/`pm_update`/`pm_close`/`pm_run` append/update-many) are compact by default; pass `fullChangedFields=true` to restore the full `changed_fields` delta, or `idOnly=true` for single-item id/status output.
449
491
 
492
+ ### Atomic heterogeneous mutation batches
493
+
494
+ `pm item mutate` is the noun-first CLI adapter over the public SDK
495
+ `commitItemMutations` primitive. Pipe a non-empty JSON array (or an object with a
496
+ `mutations` array), provide one stable transaction id, and mix create/update/
497
+ close operations in order:
498
+
499
+ ```bash
500
+ pm item mutate \
501
+ --transaction-id sync-2026-07-20-001 \
502
+ --stdin-json <<'JSON'
503
+ [
504
+ {"op":"create","id":"ext-1042","options":{"title":"Imported issue","type":"Issue"}},
505
+ {"op":"update","id":"pm-a1b2","options":{"priority":"1","addTags":["synced"]}},
506
+ {"op":"close","id":"pm-c3d4","reason":"Resolved upstream"}
507
+ ]
508
+ JSON
509
+ ```
510
+
511
+ Use `--dry-run` to validate and preview without acquiring a writer lock. Reuse
512
+ the exact transaction id and deterministic batch after interruption: the SDK
513
+ journal resumes pending steps and never duplicates a successfully applied
514
+ step. `--create-compensation close|delete`, `--lock-ttl-seconds`, and
515
+ `--lock-wait-ms` expose the transaction safety controls. The equivalent MCP
516
+ surface is `pm_mutate`.
517
+
450
518
  ## Focus (session default parent)
451
519
 
452
520
  `pm focus` sets a session "focused" item so subsequent `pm create` calls default their `--parent` to it — project management is context management, and focus keeps new work attached to the active parent without restating `--parent` every time.
@@ -574,10 +642,22 @@ pm graph audit --sample 5 --exempt-isolate pm-root
574
642
  pm graph communities --kind blocked_by --limit 5
575
643
  pm graph redundancy --max-depth 6 --limit 20
576
644
  pm graph dominators <id> --direction outgoing --limit 10
645
+ pm graph slack --limit 20
646
+ pm graph centrality --kind blocked_by --limit 10
647
+ pm graph articulation --limit 20
577
648
  pm graph plan --sample 5 --limit 20
649
+ pm graph audit --save-baseline
650
+ pm graph audit --exempt-isolate-type Reminder,Event
651
+ pm graph index
652
+ pm graph index --rebuild
653
+ pm graph index --clear
578
654
  ```
579
655
 
580
- `graph` is read-only and answers workspace-wide relationship questions through the public SDK graph toolkit. `ancestors`/`descendants` walk registered hierarchy kinds, `predecessors`/`successors` walk order-bearing kinds, `paths` enumerates bounded simple paths between two items with per-edge kinds, and `impact` reports the bounded blast radius with an explaining path per affected item. `analyze` returns workspace execution analytics (topological layers, prerequisite frontier, critical path, genuine ordering cycles) plus knowledge-graph structure (components, orphans, hubs), and `audit` runs the policy-aware governance audit with counts-first findings, severities, and bounded evidence samples. Audit severity gates on lifecycle: ordering cycles and duplicated edge spellings confined to closed/canceled items downgrade to informational `legacy_ordering_cycle`/`legacy_duplicate_edge` findings (history debt, never repaired ad hoc), while `ordering_cycle` errors and `duplicate_edge` findings are reserved for subjects touching at least one active item; `duplicate_edge` reports parallel same-family spellings — including reciprocal inverse pairs such as `A blocked_by B` plus `B blocks A` — that transitive-reduction redundancy deliberately cannot see. `communities` clusters the undirected structure with deterministic label propagation (reporting `iterations` and `converged`), `redundancy` finds stored edges implied by a longer path of the same semantic family (`blocked_by`/`blocks` and hierarchy spellings witness each other, each row carrying its witness path), and `dominators` reports the structural bottlenecks of one item's reachable subgraph — nodes every path from the root must pass through, ranked by how much work they gate (`dominated_count`). `plan` derives a dry-run remediation plan from the audit plus the redundancy scan: exact `remove`/`retype`/`supersede`/`waive`/`investigate` proposals with per-step policy code, evidence, rationale, and confidence — nothing is ever applied automatically and no proposal invents an edge. Every envelope is counts-first with explicit `truncated`, `cost` (visited nodes, inspected edges), and `cache` (workspace fingerprint plus assembly/result hit-or-miss) metadata; repeated identical queries in long-lived hosts such as the MCP server are answered from a fingerprint-keyed snapshot cache that invalidates on any relationship-relevant item change. `--summary` suppresses row collections entirely. `--kind` accepts registered relationship kinds (repeatable or comma-separated) and fails fast on unknown values (`redundancy` additionally requires directed ordering or hierarchy kinds); `--after` resumes hierarchy/ordering walks after a previously returned node id (see [Relationship Graph](RELATIONSHIP_GRAPH.md)).
656
+ `graph` is read-only and answers workspace-wide relationship questions through the public SDK graph toolkit. `ancestors`/`descendants` walk registered hierarchy kinds, `predecessors`/`successors` walk order-bearing kinds, `paths` enumerates bounded simple paths between two items with per-edge kinds, and `impact` reports the bounded blast radius with an explaining path per affected item. `analyze` returns workspace execution analytics (topological layers, prerequisite frontier, critical path, genuine ordering cycles) plus knowledge-graph structure (components, orphans, hubs), and `audit` runs the policy-aware governance audit with counts-first findings, severities, and bounded evidence samples. Audit severity gates on lifecycle: ordering cycles and duplicated edge spellings confined to closed/canceled items downgrade to informational `legacy_ordering_cycle`/`legacy_duplicate_edge` findings (history debt, never repaired ad hoc), while `ordering_cycle` errors and `duplicate_edge` findings are reserved for subjects touching at least one active item; `duplicate_edge` reports parallel same-family spellings — including reciprocal inverse pairs such as `A blocked_by B` plus `B blocks A` — that transitive-reduction redundancy deliberately cannot see. `communities` clusters the undirected structure with deterministic label propagation (reporting `iterations` and `converged`), `redundancy` finds stored edges implied by a longer path of the same semantic family (`blocked_by`/`blocks` and hierarchy spellings witness each other, each row carrying its witness path), and `dominators` reports the structural bottlenecks of one item's reachable subgraph — nodes every path from the root must pass through, ranked by how much work they gate (`dominated_count`). Three planning and structural analytics complete the surface: `slack` runs the Critical Path Method over the order-bearing DAG and reports each task's earliest start, latest start, total float (`slack`), and whether it is `critical` (zero slack), plus the overall `makespan` and critical path — unit task durations keep it deterministic and metadata-independent, and genuine cycles are reported apart from the schedule; `centrality` ranks nodes by exact shortest-path `betweenness` (Brandes) with Wasserman–Faust `closeness`, undirected `degree`, and dependency fan-in/fan-out (`in_degree`/`out_degree`, ordering predecessors/successors oriented by precedence) over the simple undirected graph; and `articulation` reports the graph's articulation points and bridges — the cut vertices and cut edges whose removal fragments the knowledge graph into more components (single points of failure). `plan` derives a dry-run remediation plan from the audit plus the redundancy scan: exact `remove`/`retype`/`supersede`/`waive`/`investigate` proposals with per-step policy code, evidence, rationale, and confidence — nothing is ever applied automatically and no proposal invents an edge. Every envelope is counts-first with explicit `truncated`, `cost` (visited nodes, inspected edges), and `cache` (workspace fingerprint plus assembly/result hit-or-miss) metadata; repeated identical queries in long-lived hosts such as the MCP server are answered from a fingerprint-keyed snapshot cache that invalidates on any relationship-relevant item change. `--summary` suppresses row collections entirely. `--kind` accepts registered relationship kinds (repeatable or comma-separated) and fails fast on unknown values (`redundancy` additionally requires directed ordering or hierarchy kinds); `--after` resumes hierarchy/ordering walks after a previously returned node id (see [Relationship Graph](RELATIONSHIP_GRAPH.md)).
657
+
658
+ The audit also reports storage-layer integrity and per-type coverage. `duplicate_dependency_row` (warning on active holders, informational `legacy_duplicate_dependency_row` on terminal ones) catches raw dependency rows whose exact identity — holder, kind, and case-insensitive target — is stored more than once on one item; graph edge-identity dedup hides these from every assembled-graph projection, so the pre-assembly scan is the only surface that can see them. The audit `profile` gains `coverage_by_type`, a per-item-type breakdown of active, isolated, and degree-at-most-one nodes (untyped items bucket under `(untyped)`), and `--exempt-isolate-type <type>` (repeatable or comma-separated, case-insensitive) suppresses isolate/sparse coverage findings for types whose disconnection is policy-valid (reminders, calendar events) while keeping them counted in the profile. `--save-baseline` persists the audit census (`affected_subjects_by_code` plus the profile) as the machine-local comparison point under `.agents/pm/runtime/graph-audit-baseline.json`; every later audit automatically attaches a `baseline` block with the signed drift since that census (`same_snapshot`, per-code deltas, profile deltas including per-kind edge counts) — the temporal primitive for tracking relationship-graph health across sessions without storing full finding collections.
659
+
660
+ `index` maintains the durable cross-process graph index at `.agents/pm/runtime/graph-cache.json` (gitignored, machine-local): a fingerprint-keyed, atomically written, crash-safe envelope of deterministic query results that lets one-shot CLI invocations reuse analysis computed by earlier processes. Every non-index graph envelope reports `cache.durable` (`hit`, `miss`, or `off`). Persistence is automatic at ≥500 items and otherwise opt-in: `pm graph index` reports status (`fresh`/`stale`/`absent`, entry count, size, thresholds), `pm graph index --rebuild` clears, re-creates, and warms the envelope with the counts-first `analyze`/`audit` census queries (and enables persistence on small workspaces), and `pm graph index --clear` deletes it. The index is never authoritative — any relationship-relevant item change invalidates the fingerprint and queries transparently recompute from item storage.
581
661
 
582
662
  ## Linked Tests
583
663