@unbrained/pm-cli 2026.7.13 → 2026.7.14

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 (487) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +28 -0
  3. package/dist/cli/commands/aggregate.d.ts +1 -1
  4. package/dist/cli/commands/aggregate.js +18 -6
  5. package/dist/cli/commands/aggregate.js.map +1 -1
  6. package/dist/cli/commands/context.d.ts +16 -1
  7. package/dist/cli/commands/context.js +98 -16
  8. package/dist/cli/commands/context.js.map +1 -1
  9. package/dist/cli/commands/create.d.ts +1 -1
  10. package/dist/cli/commands/create.js +11 -7
  11. package/dist/cli/commands/create.js.map +1 -1
  12. package/dist/cli/commands/deps.d.ts +6 -96
  13. package/dist/cli/commands/deps.js +4 -214
  14. package/dist/cli/commands/deps.js.map +1 -1
  15. package/dist/cli/commands/docs.d.ts +2 -44
  16. package/dist/cli/commands/docs.js +8 -13
  17. package/dist/cli/commands/docs.js.map +1 -1
  18. package/dist/cli/commands/files.d.ts +6 -134
  19. package/dist/cli/commands/files.js +4 -294
  20. package/dist/cli/commands/files.js.map +1 -1
  21. package/dist/cli/commands/get.js +15 -2
  22. package/dist/cli/commands/get.js.map +1 -1
  23. package/dist/cli/commands/list.js +5 -6
  24. package/dist/cli/commands/list.js.map +1 -1
  25. package/dist/cli/commands/next.d.ts +3 -1
  26. package/dist/cli/commands/next.js +77 -20
  27. package/dist/cli/commands/next.js.map +1 -1
  28. package/dist/cli/commands/update-many.js +6 -3
  29. package/dist/cli/commands/update-many.js.map +1 -1
  30. package/dist/cli/commands/update.js +14 -7
  31. package/dist/cli/commands/update.js.map +1 -1
  32. package/dist/cli/commands/validate.d.ts +1 -1
  33. package/dist/cli/commands/validate.js +32 -35
  34. package/dist/cli/commands/validate.js.map +1 -1
  35. package/dist/cli/main.d.ts +2 -14
  36. package/dist/cli/main.js +27 -8
  37. package/dist/cli/main.js.map +1 -1
  38. package/dist/cli-bundle/chunks/append-DYQWQK2J.js +11 -0
  39. package/dist/cli-bundle/chunks/{append-2FS6MVG7.js → append-PVZJDM6J.js} +5 -5
  40. package/dist/cli-bundle/chunks/{chunk-J2WAWP4U.js → chunk-2FNWQXZ2.js} +4 -4
  41. package/dist/cli-bundle/chunks/{chunk-YFGYDZRP.js → chunk-2GA3NK35.js} +4 -4
  42. package/dist/cli-bundle/chunks/{chunk-XFEIASAC.js → chunk-2QIQGYPW.js} +2 -2
  43. package/dist/cli-bundle/chunks/{chunk-3WCGYH5Q.js → chunk-3CMRNVTO.js} +7 -7
  44. package/dist/cli-bundle/chunks/chunk-3HKUXVKV.js +9 -0
  45. package/dist/cli-bundle/chunks/{chunk-VDAZPPRU.js → chunk-3I3LRT2G.js} +2 -2
  46. package/dist/cli-bundle/chunks/{chunk-3P3RFJIQ.js → chunk-3TL7WOEF.js} +2 -2
  47. package/dist/cli-bundle/chunks/{chunk-4SHJ5JS3.js → chunk-44LNIULG.js} +4 -4
  48. package/dist/cli-bundle/chunks/{chunk-QFOAWBOB.js → chunk-4DY4KPQI.js} +11 -10
  49. package/dist/cli-bundle/chunks/{chunk-QFOAWBOB.js.map → chunk-4DY4KPQI.js.map} +2 -2
  50. package/dist/cli-bundle/chunks/{chunk-BVCF4ULV.js → chunk-4RXTMU57.js} +5 -5
  51. package/dist/cli-bundle/chunks/{chunk-XMI2TRY5.js → chunk-4WREH7RT.js} +4 -4
  52. package/dist/cli-bundle/chunks/{chunk-JYUGUXFW.js → chunk-5CT5BW6E.js} +5 -5
  53. package/dist/cli-bundle/chunks/{chunk-NA5SBIB4.js → chunk-5URI7TPJ.js} +44 -44
  54. package/dist/cli-bundle/chunks/chunk-5URI7TPJ.js.map +7 -0
  55. package/dist/cli-bundle/chunks/{chunk-QGH6WL6L.js → chunk-655STMGA.js} +2 -2
  56. package/dist/cli-bundle/chunks/{chunk-DGKBWCMA.js → chunk-6IIVBC56.js} +4 -4
  57. package/dist/cli-bundle/chunks/{chunk-SRQLQUO6.js → chunk-6MHSBDGD.js} +7 -7
  58. package/dist/cli-bundle/chunks/{chunk-SRQLQUO6.js.map → chunk-6MHSBDGD.js.map} +2 -2
  59. package/dist/cli-bundle/chunks/{chunk-D4GPNYYP.js → chunk-6OTZMORS.js} +6 -6
  60. package/dist/cli-bundle/chunks/{chunk-JVRVXO6M.js → chunk-6PKA3SJQ.js} +6 -6
  61. package/dist/cli-bundle/chunks/{chunk-2PR4ZTRO.js → chunk-6TTOHMTB.js} +8 -8
  62. package/dist/cli-bundle/chunks/{chunk-2PR4ZTRO.js.map → chunk-6TTOHMTB.js.map} +1 -1
  63. package/dist/cli-bundle/chunks/chunk-6X5MZ5R2.js +9 -0
  64. package/dist/cli-bundle/chunks/chunk-76UBY2EE.js +5 -0
  65. package/dist/cli-bundle/chunks/{chunk-ZS2KPCJN.js → chunk-7QDSYUMF.js} +7 -7
  66. package/dist/cli-bundle/chunks/{chunk-Z7TFPIJ6.js → chunk-7TQMR6LK.js} +7 -7
  67. package/dist/cli-bundle/chunks/{chunk-AHA4POA6.js → chunk-ABRCOSDC.js} +3 -3
  68. package/dist/cli-bundle/chunks/{chunk-XY3CC3EM.js → chunk-AFWZRL7M.js} +59 -53
  69. package/dist/cli-bundle/chunks/chunk-AFWZRL7M.js.map +7 -0
  70. package/dist/cli-bundle/chunks/{chunk-KQJVTQVK.js → chunk-ANSJHDOZ.js} +2 -2
  71. package/dist/cli-bundle/chunks/{chunk-OMT4NO7T.js → chunk-B5DZYTT3.js} +113 -24
  72. package/dist/cli-bundle/chunks/chunk-B5DZYTT3.js.map +7 -0
  73. package/dist/cli-bundle/chunks/chunk-B7SWOIP6.js +5 -0
  74. package/dist/cli-bundle/chunks/{chunk-D2LXG7WX.js → chunk-BN62TO2S.js} +5 -5
  75. package/dist/cli-bundle/chunks/chunk-BN62TO2S.js.map +1 -0
  76. package/dist/cli-bundle/chunks/{chunk-ZTSV7P2T.js → chunk-BPD26E3P.js} +357 -42
  77. package/dist/cli-bundle/chunks/chunk-BPD26E3P.js.map +1 -0
  78. package/dist/cli-bundle/chunks/{chunk-RKGFUC4O.js → chunk-CDJYP7OQ.js} +36 -14
  79. package/dist/cli-bundle/chunks/chunk-CDJYP7OQ.js.map +1 -0
  80. package/dist/cli-bundle/chunks/{chunk-VLFLRFJP.js → chunk-CIOZ376P.js} +20 -13
  81. package/dist/cli-bundle/chunks/chunk-CIOZ376P.js.map +1 -0
  82. package/dist/cli-bundle/chunks/{chunk-HXTCZSAI.js → chunk-DBZVUJTK.js} +3 -3
  83. package/dist/cli-bundle/chunks/{chunk-2QNOWOIB.js → chunk-DO5RGJXT.js} +3 -3
  84. package/dist/cli-bundle/chunks/{chunk-MKONZ4UO.js → chunk-DRNJPEPQ.js} +4 -4
  85. package/dist/cli-bundle/chunks/{chunk-XDT2PSXA.js → chunk-DVOLZJ3C.js} +12 -11
  86. package/dist/cli-bundle/chunks/{chunk-XDT2PSXA.js.map → chunk-DVOLZJ3C.js.map} +1 -1
  87. package/dist/cli-bundle/chunks/{chunk-H36FXA7B.js → chunk-DYEX6NFH.js} +4 -4
  88. package/dist/cli-bundle/chunks/{chunk-G3IB5GTD.js → chunk-E2WC6S4P.js} +15 -11
  89. package/dist/cli-bundle/chunks/chunk-E2WC6S4P.js.map +7 -0
  90. package/dist/cli-bundle/chunks/{chunk-GAJ7U7B4.js → chunk-ERL2YFJ2.js} +3 -3
  91. package/dist/cli-bundle/chunks/{chunk-FPEYOFEF.js → chunk-F7PSHRNO.js} +3 -3
  92. package/dist/cli-bundle/chunks/{chunk-UH7OLT6F.js → chunk-FDSBDNYE.js} +2 -2
  93. package/dist/cli-bundle/chunks/{chunk-DGJF32JF.js → chunk-FIGXOCEQ.js} +66 -21
  94. package/dist/cli-bundle/chunks/chunk-FIGXOCEQ.js.map +7 -0
  95. package/dist/cli-bundle/chunks/{chunk-RQAY7C5T.js → chunk-FJZDA6MS.js} +3 -3
  96. package/dist/cli-bundle/chunks/{chunk-B4TVNGRX.js → chunk-FO7GMJKG.js} +3 -3
  97. package/dist/cli-bundle/chunks/chunk-FRQ63VPB.js +5 -0
  98. package/dist/cli-bundle/chunks/{chunk-UTYNQ2WH.js → chunk-FS6UM5WH.js} +48 -27
  99. package/dist/cli-bundle/chunks/chunk-FS6UM5WH.js.map +7 -0
  100. package/dist/cli-bundle/chunks/{chunk-U252II47.js → chunk-FTQLW4JD.js} +4 -4
  101. package/dist/cli-bundle/chunks/{chunk-TNGLCRKS.js → chunk-GSEADLRH.js} +1821 -1809
  102. package/dist/cli-bundle/chunks/chunk-GSEADLRH.js.map +1 -0
  103. package/dist/cli-bundle/chunks/{chunk-TGG7YGMC.js → chunk-GXXC7QSK.js} +53 -47
  104. package/dist/cli-bundle/chunks/chunk-GXXC7QSK.js.map +1 -0
  105. package/dist/cli-bundle/chunks/{chunk-AGD4VZXH.js → chunk-H2QBAKLQ.js} +3 -3
  106. package/dist/cli-bundle/chunks/{chunk-CJVQ4XIG.js → chunk-HAMLIWAF.js} +4 -4
  107. package/dist/cli-bundle/chunks/{chunk-56DX6QYG.js → chunk-HL7V2PHX.js} +19 -13
  108. package/dist/cli-bundle/chunks/chunk-HL7V2PHX.js.map +1 -0
  109. package/dist/cli-bundle/chunks/{chunk-7QOIQTPB.js → chunk-HLHSQ5CA.js} +4 -4
  110. package/dist/cli-bundle/chunks/{chunk-AHC7J6XD.js → chunk-IA3YFTXT.js} +6 -6
  111. package/dist/cli-bundle/chunks/{chunk-5ZCVF4WF.js → chunk-IAPHYPRL.js} +2 -2
  112. package/dist/cli-bundle/chunks/{chunk-OCSQWIOW.js → chunk-IFZA4VB5.js} +4 -4
  113. package/dist/cli-bundle/chunks/{chunk-6O2HJENY.js → chunk-IGED7NH2.js} +61 -48
  114. package/dist/cli-bundle/chunks/chunk-IGED7NH2.js.map +7 -0
  115. package/dist/cli-bundle/chunks/{chunk-RPCCQDG2.js → chunk-ILLUE5DI.js} +36 -14
  116. package/dist/cli-bundle/chunks/chunk-ILLUE5DI.js.map +7 -0
  117. package/dist/cli-bundle/chunks/{chunk-4WMFM77X.js → chunk-J4NZOP3I.js} +5 -5
  118. package/dist/cli-bundle/chunks/{chunk-57JVERX3.js → chunk-JAF4TUQ7.js} +4 -4
  119. package/dist/cli-bundle/chunks/chunk-JAF4TUQ7.js.map +7 -0
  120. package/dist/cli-bundle/chunks/{chunk-MTNKSSSO.js → chunk-JL7WZ4O2.js} +3 -3
  121. package/dist/cli-bundle/chunks/{chunk-AZ52LTCY.js → chunk-K7WNZ7KD.js} +3 -3
  122. package/dist/cli-bundle/chunks/{chunk-2OLSXXIV.js → chunk-KADLSPIU.js} +4 -4
  123. package/dist/cli-bundle/chunks/{chunk-RQKORMM4.js → chunk-KB726FMH.js} +4 -4
  124. package/dist/cli-bundle/chunks/{chunk-WKSFBBZT.js → chunk-L24HCJFC.js} +114 -25
  125. package/dist/cli-bundle/chunks/chunk-L24HCJFC.js.map +1 -0
  126. package/dist/cli-bundle/chunks/{chunk-LDO24J5I.js → chunk-LWTIRS3Y.js} +365 -43
  127. package/dist/cli-bundle/chunks/chunk-LWTIRS3Y.js.map +7 -0
  128. package/dist/cli-bundle/chunks/{chunk-TZTQ4TVV.js → chunk-M6ASXYCU.js} +4 -4
  129. package/dist/cli-bundle/chunks/{chunk-WDDOAU7Z.js → chunk-M7EWN4TF.js} +3 -3
  130. package/dist/cli-bundle/chunks/{chunk-327DSGW2.js → chunk-MD6ULIPJ.js} +3 -3
  131. package/dist/cli-bundle/chunks/{chunk-OKDBHOON.js → chunk-MKL4CP2I.js} +61 -48
  132. package/dist/cli-bundle/chunks/chunk-MKL4CP2I.js.map +1 -0
  133. package/dist/cli-bundle/chunks/{chunk-M52DG2QJ.js → chunk-MQZ3PLCF.js} +2 -2
  134. package/dist/cli-bundle/chunks/{chunk-GQ2CQNGI.js → chunk-N3CMP4NI.js} +2 -2
  135. package/dist/cli-bundle/chunks/{chunk-J7SBFUZC.js → chunk-NAQYVWSQ.js} +4 -4
  136. package/dist/cli-bundle/chunks/{chunk-U2GMYP3L.js → chunk-NKW36AMT.js} +4 -4
  137. package/dist/cli-bundle/chunks/{chunk-5WEYOVZ7.js → chunk-OBDLEQG5.js} +19 -12
  138. package/dist/cli-bundle/chunks/chunk-OBDLEQG5.js.map +7 -0
  139. package/dist/cli-bundle/chunks/{chunk-VL4LYTJN.js → chunk-OI4S4KCI.js} +18 -12
  140. package/dist/cli-bundle/chunks/chunk-OI4S4KCI.js.map +7 -0
  141. package/dist/cli-bundle/chunks/{chunk-FCVVMAEX.js → chunk-P6MYFH6K.js} +60 -22
  142. package/dist/cli-bundle/chunks/chunk-P6MYFH6K.js.map +1 -0
  143. package/dist/cli-bundle/chunks/{chunk-FTQQAPRX.js → chunk-PHKP3AGR.js} +8 -8
  144. package/dist/cli-bundle/chunks/{chunk-WVUXNIYO.js → chunk-Q37E63AM.js} +4 -4
  145. package/dist/cli-bundle/chunks/{chunk-JVXV7ANV.js → chunk-Q7E6OYZK.js} +2 -2
  146. package/dist/cli-bundle/chunks/{chunk-WVUYATII.js → chunk-QABYZYLU.js} +4 -4
  147. package/dist/cli-bundle/chunks/{chunk-QRRUGIJN.js → chunk-QASRVKUQ.js} +45 -45
  148. package/dist/cli-bundle/chunks/chunk-QASRVKUQ.js.map +1 -0
  149. package/dist/cli-bundle/chunks/{chunk-L4262MFB.js → chunk-QK2ZN6UL.js} +14 -5
  150. package/dist/cli-bundle/chunks/{chunk-L4262MFB.js.map → chunk-QK2ZN6UL.js.map} +1 -1
  151. package/dist/cli-bundle/chunks/{chunk-7TQPV7HR.js → chunk-QSPARJWF.js} +2 -2
  152. package/dist/cli-bundle/chunks/{chunk-GTKILM6F.js → chunk-QZ7LT3XE.js} +3 -3
  153. package/dist/cli-bundle/chunks/{chunk-L3VKY6R6.js → chunk-RA5AIAMP.js} +3 -3
  154. package/dist/cli-bundle/chunks/{chunk-BJS27ALI.js → chunk-RGXD5JJR.js} +6 -6
  155. package/dist/cli-bundle/chunks/{chunk-TSEPW2P6.js → chunk-RMF3IOYQ.js} +7 -7
  156. package/dist/cli-bundle/chunks/{chunk-QXYKH56X.js → chunk-T4BRCB6Z.js} +1894 -1875
  157. package/dist/cli-bundle/chunks/chunk-T4BRCB6Z.js.map +7 -0
  158. package/dist/cli-bundle/chunks/{chunk-TGGTXC52.js → chunk-TH7U4KLY.js} +3 -3
  159. package/dist/cli-bundle/chunks/{chunk-LP4UATP6.js → chunk-TWLDBKQU.js} +3 -3
  160. package/dist/cli-bundle/chunks/{chunk-OTZ3C2NE.js → chunk-TZ2PSLLT.js} +49 -28
  161. package/dist/cli-bundle/chunks/chunk-TZ2PSLLT.js.map +1 -0
  162. package/dist/cli-bundle/chunks/{chunk-UK222BHQ.js → chunk-TZRTLMWM.js} +4 -4
  163. package/dist/cli-bundle/chunks/{chunk-6E6S2X6S.js → chunk-UB2QYSTO.js} +8 -8
  164. package/dist/cli-bundle/chunks/{chunk-S6CXUSYC.js → chunk-UGTVWL3E.js} +5 -5
  165. package/dist/cli-bundle/chunks/{chunk-BNS6QHTZ.js → chunk-UJ4HJYWL.js} +2 -2
  166. package/dist/cli-bundle/chunks/{chunk-BYVOEJPQ.js → chunk-UKUIIBDW.js} +4 -4
  167. package/dist/cli-bundle/chunks/{chunk-SGDBVR7X.js → chunk-UVBA6F5A.js} +2 -2
  168. package/dist/cli-bundle/chunks/{chunk-DZRZMBBF.js → chunk-VJTAEIPC.js} +5 -5
  169. package/dist/cli-bundle/chunks/{chunk-74PWVJON.js → chunk-W6HZ55JO.js} +2 -2
  170. package/dist/cli-bundle/chunks/{chunk-HR2MQAO5.js → chunk-WD6MSYMP.js} +13 -4
  171. package/dist/cli-bundle/chunks/{chunk-HR2MQAO5.js.map → chunk-WD6MSYMP.js.map} +2 -2
  172. package/dist/cli-bundle/chunks/{chunk-P7IFURWH.js → chunk-WPAWZW7S.js} +2 -2
  173. package/dist/cli-bundle/chunks/{chunk-36LEOWSX.js → chunk-WQUEHPZB.js} +2 -2
  174. package/dist/cli-bundle/chunks/{chunk-FCKJF7G2.js → chunk-WRKB56FC.js} +3 -3
  175. package/dist/cli-bundle/chunks/{chunk-KR5EHAN4.js → chunk-X3GYR4P2.js} +2 -2
  176. package/dist/cli-bundle/chunks/{chunk-J567OZJY.js → chunk-X6BVXQ52.js} +16 -12
  177. package/dist/cli-bundle/chunks/chunk-X6BVXQ52.js.map +1 -0
  178. package/dist/cli-bundle/chunks/chunk-Y72FV7RM.js +178 -0
  179. package/dist/cli-bundle/chunks/chunk-Y72FV7RM.js.map +7 -0
  180. package/dist/cli-bundle/chunks/{chunk-OWW2KXOV.js → chunk-YQYG2V23.js} +2 -2
  181. package/dist/cli-bundle/chunks/{chunk-G2SCT7BC.js → chunk-YVKE5ZDM.js} +4 -4
  182. package/dist/cli-bundle/chunks/{chunk-QHIN4UTF.js → chunk-ZAYYDNB3.js} +4 -4
  183. package/dist/cli-bundle/chunks/chunk-ZHBI2AP7.js +9 -0
  184. package/dist/cli-bundle/chunks/chunk-ZNP64HOW.js +175 -0
  185. package/dist/cli-bundle/chunks/chunk-ZNP64HOW.js.map +1 -0
  186. package/dist/cli-bundle/chunks/{chunk-GNVBUNJQ.js → chunk-ZTRBSABY.js} +3 -3
  187. package/dist/cli-bundle/chunks/{chunk-PY32KGQU.js → chunk-ZUKSZVBW.js} +5 -5
  188. package/dist/cli-bundle/chunks/{close-CU56F47E.js → close-LZECOMHO.js} +5 -5
  189. package/dist/cli-bundle/chunks/close-RI4JQQHU.js +12 -0
  190. package/dist/cli-bundle/chunks/close-many-LY2XJ52M.js +21 -0
  191. package/dist/cli-bundle/chunks/{close-many-ZQ2WP67J.js → close-many-ZHI6A5TN.js} +12 -12
  192. package/dist/cli-bundle/chunks/comments-35M273DN.js +13 -0
  193. package/dist/cli-bundle/chunks/{comments-UDUMKXL6.js → comments-AJWRTFZ5.js} +7 -7
  194. package/dist/cli-bundle/chunks/{copy-VFHECFBV.js → copy-GMXYKBXT.js} +4 -4
  195. package/dist/cli-bundle/chunks/copy-NPYM7M7U.js +9 -0
  196. package/dist/cli-bundle/chunks/create-F53OBTOU.js +27 -0
  197. package/dist/cli-bundle/chunks/{create-CE2X3SGF.js → create-HU4Q7RJX.js} +11 -9
  198. package/dist/cli-bundle/chunks/{delete-2JXQCHHT.js → delete-GSDZLTRC.js} +4 -4
  199. package/dist/cli-bundle/chunks/delete-ODRWJWAM.js +10 -0
  200. package/dist/cli-bundle/chunks/deps-U57I7EAK.js +16 -0
  201. package/dist/cli-bundle/chunks/{deps-FPXNLO6C.js → deps-WWB7P2GT.js} +7 -4
  202. package/dist/cli-bundle/chunks/docs-G7N4E2JO.js +14 -0
  203. package/dist/cli-bundle/chunks/{docs-AMAR4OHU.js → docs-MQIY2ZQS.js} +7 -7
  204. package/dist/cli-bundle/chunks/files-TBZD7V6H.js +18 -0
  205. package/dist/cli-bundle/chunks/{files-JFHN7DYM.js → files-TTY6N2AV.js} +7 -7
  206. package/dist/cli-bundle/chunks/focus-U5TRVCRS.js +10 -0
  207. package/dist/cli-bundle/chunks/{focus-QFN2RRZ7.js → focus-XT6YVFFX.js} +5 -5
  208. package/dist/cli-bundle/chunks/{history-compact-G34XMABV.js → history-compact-KKVUWB4V.js} +8 -8
  209. package/dist/cli-bundle/chunks/{history-compact-SAHT5D46.js → history-compact-M7GHYVFN.js} +8 -8
  210. package/dist/cli-bundle/chunks/{history-redact-IFJDNKLZ.js → history-redact-3DVZOILD.js} +6 -6
  211. package/dist/cli-bundle/chunks/history-redact-JIHZLHDP.js +16 -0
  212. package/dist/cli-bundle/chunks/{history-repair-NXLQTCVN.js → history-repair-ITDUMK4N.js} +8 -8
  213. package/dist/cli-bundle/chunks/history-repair-NAFCHLH7.js +18 -0
  214. package/dist/cli-bundle/chunks/{learnings-5CZKAMBS.js → learnings-FGO3NSFW.js} +7 -7
  215. package/dist/cli-bundle/chunks/learnings-SONGPSHI.js +13 -0
  216. package/dist/cli-bundle/chunks/notes-BSD53H2W.js +13 -0
  217. package/dist/cli-bundle/chunks/{notes-POMK37UI.js → notes-NQ6RXVW6.js} +7 -7
  218. package/dist/cli-bundle/chunks/{plan-YBNYNT3A.js → plan-2NNEO46V.js} +10 -10
  219. package/dist/cli-bundle/chunks/plan-AWLYGBNV.js +24 -0
  220. package/dist/cli-bundle/chunks/{profile-JNKSU6EQ.js → profile-AAQUU6T3.js} +9 -9
  221. package/dist/cli-bundle/chunks/{profile-A2WPVG6I.js → profile-U725ATWZ.js} +9 -9
  222. package/dist/cli-bundle/chunks/{register-list-query-UG4ZA5AU.js → register-list-query-BUWCYHBT.js} +14 -13
  223. package/dist/cli-bundle/chunks/{register-list-query-UG4ZA5AU.js.map → register-list-query-BUWCYHBT.js.map} +1 -1
  224. package/dist/cli-bundle/chunks/{register-list-query-KJULL4W3.js → register-list-query-KTZ6AGE7.js} +16 -15
  225. package/dist/cli-bundle/chunks/{register-list-query-KJULL4W3.js.map → register-list-query-KTZ6AGE7.js.map} +1 -1
  226. package/dist/cli-bundle/chunks/{register-mutation-3OXYXBKH.js → register-mutation-4FMGJJF7.js} +29 -29
  227. package/dist/cli-bundle/chunks/{register-mutation-WK265BM7.js → register-mutation-UELYYOR7.js} +29 -29
  228. package/dist/cli-bundle/chunks/{register-operations-C5SQH3FJ.js → register-operations-ISUX6LY5.js} +33 -29
  229. package/dist/cli-bundle/chunks/{register-operations-C5SQH3FJ.js.map → register-operations-ISUX6LY5.js.map} +1 -1
  230. package/dist/cli-bundle/chunks/{register-operations-FH3PBHYN.js → register-operations-JVW24J2Y.js} +35 -31
  231. package/dist/cli-bundle/chunks/{register-operations-FH3PBHYN.js.map → register-operations-JVW24J2Y.js.map} +1 -1
  232. package/dist/cli-bundle/chunks/{register-setup-CCK7CJVR.js → register-setup-5XNGKJ22.js} +15 -15
  233. package/dist/cli-bundle/chunks/{register-setup-CPZBGSOJ.js → register-setup-ZTNY6S7R.js} +15 -15
  234. package/dist/cli-bundle/chunks/restore-66GLMHIX.js +14 -0
  235. package/dist/cli-bundle/chunks/{restore-IVS5XGYR.js → restore-B3BAB6X2.js} +6 -6
  236. package/dist/cli-bundle/chunks/{schema-P2MF23JO.js → schema-LZNUYHDB.js} +6 -6
  237. package/dist/cli-bundle/chunks/schema-LZNUYHDB.js.map +7 -0
  238. package/dist/cli-bundle/chunks/{schema-R3U2REY4.js → schema-U7IM2DXV.js} +6 -6
  239. package/dist/cli-bundle/chunks/schema-U7IM2DXV.js.map +1 -0
  240. package/dist/cli-bundle/chunks/update-2XGHIVQ2.js +21 -0
  241. package/dist/cli-bundle/chunks/update-2XGHIVQ2.js.map +7 -0
  242. package/dist/cli-bundle/chunks/{update-YBIQESMH.js → update-Q3UCILNR.js} +12 -12
  243. package/dist/cli-bundle/chunks/update-Q3UCILNR.js.map +1 -0
  244. package/dist/cli-bundle/chunks/{update-many-F3CIV5SQ.js → update-many-75K57FS3.js} +19 -19
  245. package/dist/cli-bundle/chunks/update-many-75K57FS3.js.map +1 -0
  246. package/dist/cli-bundle/chunks/update-many-U42YA445.js +30 -0
  247. package/dist/cli-bundle/chunks/update-many-U42YA445.js.map +7 -0
  248. package/dist/cli-bundle/main.js +39 -16
  249. package/dist/cli-bundle/main.js.map +2 -2
  250. package/dist/cli-bundle/sdk-runtime.js +56 -53
  251. package/dist/cli-bundle/sdk-testing.js +6 -6
  252. package/dist/cli-bundle/sdk.js +115 -55
  253. package/dist/cli-bundle/sdk.js.map +2 -2
  254. package/dist/core/extensions/command-hook-context.d.ts +40 -0
  255. package/dist/core/extensions/command-hook-context.js +14 -0
  256. package/dist/core/extensions/command-hook-context.js.map +1 -0
  257. package/dist/core/extensions/index.d.ts +1 -0
  258. package/dist/core/extensions/index.js +4 -3
  259. package/dist/core/extensions/index.js.map +1 -1
  260. package/dist/core/item/parse.d.ts +2 -0
  261. package/dist/core/item/parse.js +11 -2
  262. package/dist/core/item/parse.js.map +1 -1
  263. package/dist/core/store/paths.d.ts +2 -0
  264. package/dist/core/store/paths.js +10 -2
  265. package/dist/core/store/paths.js.map +1 -1
  266. package/dist/mcp/tool-definitions.js +12 -2
  267. package/dist/mcp/tool-definitions.js.map +1 -1
  268. package/dist/sdk/context-packing.d.ts +114 -0
  269. package/dist/sdk/context-packing.js +219 -0
  270. package/dist/sdk/context-packing.js.map +1 -0
  271. package/dist/sdk/context-relevance.d.ts +1 -1
  272. package/dist/sdk/context-relevance.js +4 -2
  273. package/dist/sdk/context-relevance.js.map +1 -1
  274. package/dist/sdk/context-usage.d.ts +79 -0
  275. package/dist/sdk/context-usage.js +193 -0
  276. package/dist/sdk/context-usage.js.map +1 -0
  277. package/dist/sdk/dependencies.d.ts +145 -0
  278. package/dist/sdk/dependencies.js +327 -0
  279. package/dist/sdk/dependencies.js.map +1 -0
  280. package/dist/sdk/docs.d.ts +48 -0
  281. package/dist/sdk/docs.js +15 -0
  282. package/dist/sdk/docs.js.map +1 -0
  283. package/dist/sdk/files.d.ts +135 -0
  284. package/dist/sdk/files.js +320 -0
  285. package/dist/sdk/files.js.map +1 -0
  286. package/dist/sdk/index.d.ts +6 -0
  287. package/dist/sdk/index.js +8 -2
  288. package/dist/sdk/index.js.map +1 -1
  289. package/dist/{cli/commands → sdk}/linked-artifacts.d.ts +11 -5
  290. package/dist/{cli/commands → sdk}/linked-artifacts.js +49 -25
  291. package/dist/sdk/linked-artifacts.js.map +1 -0
  292. package/dist/sdk/runtime.d.ts +4 -4
  293. package/dist/sdk/runtime.js +7 -4
  294. package/dist/sdk/runtime.js.map +1 -1
  295. package/dist/sdk/workspace.js +3 -2
  296. package/dist/sdk/workspace.js.map +1 -1
  297. package/docs/AGENT_GUIDE.md +1 -1
  298. package/docs/CONFIGURATION.md +1 -0
  299. package/docs/PR_REVIEW_LOOP.md +21 -11
  300. package/docs/SDK.md +94 -0
  301. package/marketplace.json +2 -2
  302. package/package.json +1 -1
  303. package/packages/pm-beads/package.json +1 -1
  304. package/packages/pm-calendar/package.json +1 -1
  305. package/packages/pm-command-kit/package.json +1 -1
  306. package/packages/pm-governance-audit/package.json +1 -1
  307. package/packages/pm-guide-shell/package.json +1 -1
  308. package/packages/pm-kanban/package.json +1 -1
  309. package/packages/pm-lifecycle-hooks/package.json +1 -1
  310. package/packages/pm-linked-test-adapters/package.json +1 -1
  311. package/packages/pm-search-advanced/package.json +1 -1
  312. package/packages/pm-templates/package.json +1 -1
  313. package/packages/pm-todos/package.json +1 -1
  314. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  315. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  316. package/dist/cli/commands/linked-artifacts.js.map +0 -1
  317. package/dist/cli-bundle/chunks/append-CTKFDEAX.js +0 -11
  318. package/dist/cli-bundle/chunks/chunk-56DX6QYG.js.map +0 -1
  319. package/dist/cli-bundle/chunks/chunk-57JVERX3.js.map +0 -7
  320. package/dist/cli-bundle/chunks/chunk-5WEYOVZ7.js.map +0 -7
  321. package/dist/cli-bundle/chunks/chunk-6O2HJENY.js.map +0 -7
  322. package/dist/cli-bundle/chunks/chunk-CCAGZCZK.js +0 -17
  323. package/dist/cli-bundle/chunks/chunk-CCAGZCZK.js.map +0 -7
  324. package/dist/cli-bundle/chunks/chunk-D2LXG7WX.js.map +0 -1
  325. package/dist/cli-bundle/chunks/chunk-DGJF32JF.js.map +0 -7
  326. package/dist/cli-bundle/chunks/chunk-FCVVMAEX.js.map +0 -1
  327. package/dist/cli-bundle/chunks/chunk-FUOK7JZ6.js +0 -14
  328. package/dist/cli-bundle/chunks/chunk-FUOK7JZ6.js.map +0 -1
  329. package/dist/cli-bundle/chunks/chunk-G3IB5GTD.js.map +0 -7
  330. package/dist/cli-bundle/chunks/chunk-J567OZJY.js.map +0 -1
  331. package/dist/cli-bundle/chunks/chunk-LDO24J5I.js.map +0 -7
  332. package/dist/cli-bundle/chunks/chunk-NA5SBIB4.js.map +0 -7
  333. package/dist/cli-bundle/chunks/chunk-OKDBHOON.js.map +0 -1
  334. package/dist/cli-bundle/chunks/chunk-OMT4NO7T.js.map +0 -7
  335. package/dist/cli-bundle/chunks/chunk-OTZ3C2NE.js.map +0 -1
  336. package/dist/cli-bundle/chunks/chunk-QRRUGIJN.js.map +0 -1
  337. package/dist/cli-bundle/chunks/chunk-QXYKH56X.js.map +0 -7
  338. package/dist/cli-bundle/chunks/chunk-RKGFUC4O.js.map +0 -1
  339. package/dist/cli-bundle/chunks/chunk-RPCCQDG2.js.map +0 -7
  340. package/dist/cli-bundle/chunks/chunk-TGG7YGMC.js.map +0 -1
  341. package/dist/cli-bundle/chunks/chunk-TNGLCRKS.js.map +0 -1
  342. package/dist/cli-bundle/chunks/chunk-UTYNQ2WH.js.map +0 -7
  343. package/dist/cli-bundle/chunks/chunk-VL4LYTJN.js.map +0 -7
  344. package/dist/cli-bundle/chunks/chunk-VLFLRFJP.js.map +0 -1
  345. package/dist/cli-bundle/chunks/chunk-WKSFBBZT.js.map +0 -1
  346. package/dist/cli-bundle/chunks/chunk-XY3CC3EM.js.map +0 -7
  347. package/dist/cli-bundle/chunks/chunk-ZTSV7P2T.js.map +0 -1
  348. package/dist/cli-bundle/chunks/close-BWM7FTF4.js +0 -12
  349. package/dist/cli-bundle/chunks/close-many-AUHTVFUQ.js +0 -21
  350. package/dist/cli-bundle/chunks/comments-7D5VPBZI.js +0 -13
  351. package/dist/cli-bundle/chunks/copy-QJ6ZVWZV.js +0 -9
  352. package/dist/cli-bundle/chunks/create-FGMTTYOI.js +0 -25
  353. package/dist/cli-bundle/chunks/delete-L2GMMMPR.js +0 -10
  354. package/dist/cli-bundle/chunks/deps-KTFI4RWD.js +0 -13
  355. package/dist/cli-bundle/chunks/docs-VNURA275.js +0 -14
  356. package/dist/cli-bundle/chunks/files-UNFPZLTG.js +0 -18
  357. package/dist/cli-bundle/chunks/focus-MI2UHBP4.js +0 -10
  358. package/dist/cli-bundle/chunks/history-redact-VAHGBUHI.js +0 -16
  359. package/dist/cli-bundle/chunks/history-repair-DDYQXR43.js +0 -18
  360. package/dist/cli-bundle/chunks/learnings-VWJEKHEO.js +0 -13
  361. package/dist/cli-bundle/chunks/notes-NGVJJJQO.js +0 -13
  362. package/dist/cli-bundle/chunks/plan-U6SQJUFI.js +0 -24
  363. package/dist/cli-bundle/chunks/restore-AX6ZMGHZ.js +0 -14
  364. package/dist/cli-bundle/chunks/update-XYHF3YZF.js +0 -21
  365. package/dist/cli-bundle/chunks/update-many-5HKVHFUL.js +0 -30
  366. /package/dist/cli-bundle/chunks/{append-CTKFDEAX.js.map → append-DYQWQK2J.js.map} +0 -0
  367. /package/dist/cli-bundle/chunks/{append-2FS6MVG7.js.map → append-PVZJDM6J.js.map} +0 -0
  368. /package/dist/cli-bundle/chunks/{chunk-J2WAWP4U.js.map → chunk-2FNWQXZ2.js.map} +0 -0
  369. /package/dist/cli-bundle/chunks/{chunk-YFGYDZRP.js.map → chunk-2GA3NK35.js.map} +0 -0
  370. /package/dist/cli-bundle/chunks/{chunk-XFEIASAC.js.map → chunk-2QIQGYPW.js.map} +0 -0
  371. /package/dist/cli-bundle/chunks/{chunk-3WCGYH5Q.js.map → chunk-3CMRNVTO.js.map} +0 -0
  372. /package/dist/cli-bundle/chunks/{close-BWM7FTF4.js.map → chunk-3HKUXVKV.js.map} +0 -0
  373. /package/dist/cli-bundle/chunks/{chunk-VDAZPPRU.js.map → chunk-3I3LRT2G.js.map} +0 -0
  374. /package/dist/cli-bundle/chunks/{chunk-3P3RFJIQ.js.map → chunk-3TL7WOEF.js.map} +0 -0
  375. /package/dist/cli-bundle/chunks/{chunk-4SHJ5JS3.js.map → chunk-44LNIULG.js.map} +0 -0
  376. /package/dist/cli-bundle/chunks/{chunk-BVCF4ULV.js.map → chunk-4RXTMU57.js.map} +0 -0
  377. /package/dist/cli-bundle/chunks/{chunk-XMI2TRY5.js.map → chunk-4WREH7RT.js.map} +0 -0
  378. /package/dist/cli-bundle/chunks/{chunk-JYUGUXFW.js.map → chunk-5CT5BW6E.js.map} +0 -0
  379. /package/dist/cli-bundle/chunks/{chunk-QGH6WL6L.js.map → chunk-655STMGA.js.map} +0 -0
  380. /package/dist/cli-bundle/chunks/{chunk-DGKBWCMA.js.map → chunk-6IIVBC56.js.map} +0 -0
  381. /package/dist/cli-bundle/chunks/{chunk-D4GPNYYP.js.map → chunk-6OTZMORS.js.map} +0 -0
  382. /package/dist/cli-bundle/chunks/{chunk-JVRVXO6M.js.map → chunk-6PKA3SJQ.js.map} +0 -0
  383. /package/dist/cli-bundle/chunks/{close-many-AUHTVFUQ.js.map → chunk-6X5MZ5R2.js.map} +0 -0
  384. /package/dist/cli-bundle/chunks/{close-CU56F47E.js.map → chunk-76UBY2EE.js.map} +0 -0
  385. /package/dist/cli-bundle/chunks/{chunk-ZS2KPCJN.js.map → chunk-7QDSYUMF.js.map} +0 -0
  386. /package/dist/cli-bundle/chunks/{chunk-Z7TFPIJ6.js.map → chunk-7TQMR6LK.js.map} +0 -0
  387. /package/dist/cli-bundle/chunks/{chunk-AHA4POA6.js.map → chunk-ABRCOSDC.js.map} +0 -0
  388. /package/dist/cli-bundle/chunks/{chunk-KQJVTQVK.js.map → chunk-ANSJHDOZ.js.map} +0 -0
  389. /package/dist/cli-bundle/chunks/{close-many-ZQ2WP67J.js.map → chunk-B7SWOIP6.js.map} +0 -0
  390. /package/dist/cli-bundle/chunks/{chunk-HXTCZSAI.js.map → chunk-DBZVUJTK.js.map} +0 -0
  391. /package/dist/cli-bundle/chunks/{chunk-2QNOWOIB.js.map → chunk-DO5RGJXT.js.map} +0 -0
  392. /package/dist/cli-bundle/chunks/{chunk-MKONZ4UO.js.map → chunk-DRNJPEPQ.js.map} +0 -0
  393. /package/dist/cli-bundle/chunks/{chunk-H36FXA7B.js.map → chunk-DYEX6NFH.js.map} +0 -0
  394. /package/dist/cli-bundle/chunks/{chunk-GAJ7U7B4.js.map → chunk-ERL2YFJ2.js.map} +0 -0
  395. /package/dist/cli-bundle/chunks/{chunk-FPEYOFEF.js.map → chunk-F7PSHRNO.js.map} +0 -0
  396. /package/dist/cli-bundle/chunks/{chunk-UH7OLT6F.js.map → chunk-FDSBDNYE.js.map} +0 -0
  397. /package/dist/cli-bundle/chunks/{chunk-RQAY7C5T.js.map → chunk-FJZDA6MS.js.map} +0 -0
  398. /package/dist/cli-bundle/chunks/{chunk-B4TVNGRX.js.map → chunk-FO7GMJKG.js.map} +0 -0
  399. /package/dist/cli-bundle/chunks/{comments-UDUMKXL6.js.map → chunk-FRQ63VPB.js.map} +0 -0
  400. /package/dist/cli-bundle/chunks/{chunk-U252II47.js.map → chunk-FTQLW4JD.js.map} +0 -0
  401. /package/dist/cli-bundle/chunks/{chunk-AGD4VZXH.js.map → chunk-H2QBAKLQ.js.map} +0 -0
  402. /package/dist/cli-bundle/chunks/{chunk-CJVQ4XIG.js.map → chunk-HAMLIWAF.js.map} +0 -0
  403. /package/dist/cli-bundle/chunks/{chunk-7QOIQTPB.js.map → chunk-HLHSQ5CA.js.map} +0 -0
  404. /package/dist/cli-bundle/chunks/{chunk-AHC7J6XD.js.map → chunk-IA3YFTXT.js.map} +0 -0
  405. /package/dist/cli-bundle/chunks/{chunk-5ZCVF4WF.js.map → chunk-IAPHYPRL.js.map} +0 -0
  406. /package/dist/cli-bundle/chunks/{chunk-OCSQWIOW.js.map → chunk-IFZA4VB5.js.map} +0 -0
  407. /package/dist/cli-bundle/chunks/{chunk-4WMFM77X.js.map → chunk-J4NZOP3I.js.map} +0 -0
  408. /package/dist/cli-bundle/chunks/{chunk-MTNKSSSO.js.map → chunk-JL7WZ4O2.js.map} +0 -0
  409. /package/dist/cli-bundle/chunks/{chunk-AZ52LTCY.js.map → chunk-K7WNZ7KD.js.map} +0 -0
  410. /package/dist/cli-bundle/chunks/{chunk-2OLSXXIV.js.map → chunk-KADLSPIU.js.map} +0 -0
  411. /package/dist/cli-bundle/chunks/{chunk-RQKORMM4.js.map → chunk-KB726FMH.js.map} +0 -0
  412. /package/dist/cli-bundle/chunks/{chunk-TZTQ4TVV.js.map → chunk-M6ASXYCU.js.map} +0 -0
  413. /package/dist/cli-bundle/chunks/{chunk-WDDOAU7Z.js.map → chunk-M7EWN4TF.js.map} +0 -0
  414. /package/dist/cli-bundle/chunks/{chunk-327DSGW2.js.map → chunk-MD6ULIPJ.js.map} +0 -0
  415. /package/dist/cli-bundle/chunks/{chunk-M52DG2QJ.js.map → chunk-MQZ3PLCF.js.map} +0 -0
  416. /package/dist/cli-bundle/chunks/{chunk-GQ2CQNGI.js.map → chunk-N3CMP4NI.js.map} +0 -0
  417. /package/dist/cli-bundle/chunks/{chunk-J7SBFUZC.js.map → chunk-NAQYVWSQ.js.map} +0 -0
  418. /package/dist/cli-bundle/chunks/{chunk-U2GMYP3L.js.map → chunk-NKW36AMT.js.map} +0 -0
  419. /package/dist/cli-bundle/chunks/{chunk-FTQQAPRX.js.map → chunk-PHKP3AGR.js.map} +0 -0
  420. /package/dist/cli-bundle/chunks/{chunk-WVUXNIYO.js.map → chunk-Q37E63AM.js.map} +0 -0
  421. /package/dist/cli-bundle/chunks/{chunk-JVXV7ANV.js.map → chunk-Q7E6OYZK.js.map} +0 -0
  422. /package/dist/cli-bundle/chunks/{chunk-WVUYATII.js.map → chunk-QABYZYLU.js.map} +0 -0
  423. /package/dist/cli-bundle/chunks/{chunk-7TQPV7HR.js.map → chunk-QSPARJWF.js.map} +0 -0
  424. /package/dist/cli-bundle/chunks/{chunk-GTKILM6F.js.map → chunk-QZ7LT3XE.js.map} +0 -0
  425. /package/dist/cli-bundle/chunks/{chunk-L3VKY6R6.js.map → chunk-RA5AIAMP.js.map} +0 -0
  426. /package/dist/cli-bundle/chunks/{chunk-BJS27ALI.js.map → chunk-RGXD5JJR.js.map} +0 -0
  427. /package/dist/cli-bundle/chunks/{chunk-TSEPW2P6.js.map → chunk-RMF3IOYQ.js.map} +0 -0
  428. /package/dist/cli-bundle/chunks/{chunk-TGGTXC52.js.map → chunk-TH7U4KLY.js.map} +0 -0
  429. /package/dist/cli-bundle/chunks/{chunk-LP4UATP6.js.map → chunk-TWLDBKQU.js.map} +0 -0
  430. /package/dist/cli-bundle/chunks/{chunk-UK222BHQ.js.map → chunk-TZRTLMWM.js.map} +0 -0
  431. /package/dist/cli-bundle/chunks/{chunk-6E6S2X6S.js.map → chunk-UB2QYSTO.js.map} +0 -0
  432. /package/dist/cli-bundle/chunks/{chunk-S6CXUSYC.js.map → chunk-UGTVWL3E.js.map} +0 -0
  433. /package/dist/cli-bundle/chunks/{chunk-BNS6QHTZ.js.map → chunk-UJ4HJYWL.js.map} +0 -0
  434. /package/dist/cli-bundle/chunks/{chunk-BYVOEJPQ.js.map → chunk-UKUIIBDW.js.map} +0 -0
  435. /package/dist/cli-bundle/chunks/{chunk-SGDBVR7X.js.map → chunk-UVBA6F5A.js.map} +0 -0
  436. /package/dist/cli-bundle/chunks/{chunk-DZRZMBBF.js.map → chunk-VJTAEIPC.js.map} +0 -0
  437. /package/dist/cli-bundle/chunks/{chunk-74PWVJON.js.map → chunk-W6HZ55JO.js.map} +0 -0
  438. /package/dist/cli-bundle/chunks/{chunk-P7IFURWH.js.map → chunk-WPAWZW7S.js.map} +0 -0
  439. /package/dist/cli-bundle/chunks/{chunk-36LEOWSX.js.map → chunk-WQUEHPZB.js.map} +0 -0
  440. /package/dist/cli-bundle/chunks/{chunk-FCKJF7G2.js.map → chunk-WRKB56FC.js.map} +0 -0
  441. /package/dist/cli-bundle/chunks/{chunk-KR5EHAN4.js.map → chunk-X3GYR4P2.js.map} +0 -0
  442. /package/dist/cli-bundle/chunks/{chunk-OWW2KXOV.js.map → chunk-YQYG2V23.js.map} +0 -0
  443. /package/dist/cli-bundle/chunks/{chunk-G2SCT7BC.js.map → chunk-YVKE5ZDM.js.map} +0 -0
  444. /package/dist/cli-bundle/chunks/{chunk-QHIN4UTF.js.map → chunk-ZAYYDNB3.js.map} +0 -0
  445. /package/dist/cli-bundle/chunks/{comments-7D5VPBZI.js.map → chunk-ZHBI2AP7.js.map} +0 -0
  446. /package/dist/cli-bundle/chunks/{chunk-GNVBUNJQ.js.map → chunk-ZTRBSABY.js.map} +0 -0
  447. /package/dist/cli-bundle/chunks/{chunk-PY32KGQU.js.map → chunk-ZUKSZVBW.js.map} +0 -0
  448. /package/dist/cli-bundle/chunks/{copy-VFHECFBV.js.map → close-LZECOMHO.js.map} +0 -0
  449. /package/dist/cli-bundle/chunks/{copy-QJ6ZVWZV.js.map → close-RI4JQQHU.js.map} +0 -0
  450. /package/dist/cli-bundle/chunks/{create-FGMTTYOI.js.map → close-many-LY2XJ52M.js.map} +0 -0
  451. /package/dist/cli-bundle/chunks/{create-CE2X3SGF.js.map → close-many-ZHI6A5TN.js.map} +0 -0
  452. /package/dist/cli-bundle/chunks/{delete-L2GMMMPR.js.map → comments-35M273DN.js.map} +0 -0
  453. /package/dist/cli-bundle/chunks/{delete-2JXQCHHT.js.map → comments-AJWRTFZ5.js.map} +0 -0
  454. /package/dist/cli-bundle/chunks/{deps-FPXNLO6C.js.map → copy-GMXYKBXT.js.map} +0 -0
  455. /package/dist/cli-bundle/chunks/{deps-KTFI4RWD.js.map → copy-NPYM7M7U.js.map} +0 -0
  456. /package/dist/cli-bundle/chunks/{docs-VNURA275.js.map → create-F53OBTOU.js.map} +0 -0
  457. /package/dist/cli-bundle/chunks/{docs-AMAR4OHU.js.map → create-HU4Q7RJX.js.map} +0 -0
  458. /package/dist/cli-bundle/chunks/{files-JFHN7DYM.js.map → delete-GSDZLTRC.js.map} +0 -0
  459. /package/dist/cli-bundle/chunks/{files-UNFPZLTG.js.map → delete-ODRWJWAM.js.map} +0 -0
  460. /package/dist/cli-bundle/chunks/{focus-MI2UHBP4.js.map → deps-U57I7EAK.js.map} +0 -0
  461. /package/dist/cli-bundle/chunks/{focus-QFN2RRZ7.js.map → deps-WWB7P2GT.js.map} +0 -0
  462. /package/dist/cli-bundle/chunks/{history-compact-SAHT5D46.js.map → docs-G7N4E2JO.js.map} +0 -0
  463. /package/dist/cli-bundle/chunks/{history-compact-G34XMABV.js.map → docs-MQIY2ZQS.js.map} +0 -0
  464. /package/dist/cli-bundle/chunks/{history-redact-VAHGBUHI.js.map → files-TBZD7V6H.js.map} +0 -0
  465. /package/dist/cli-bundle/chunks/{history-redact-IFJDNKLZ.js.map → files-TTY6N2AV.js.map} +0 -0
  466. /package/dist/cli-bundle/chunks/{history-repair-DDYQXR43.js.map → focus-U5TRVCRS.js.map} +0 -0
  467. /package/dist/cli-bundle/chunks/{history-repair-NXLQTCVN.js.map → focus-XT6YVFFX.js.map} +0 -0
  468. /package/dist/cli-bundle/chunks/{learnings-5CZKAMBS.js.map → history-compact-KKVUWB4V.js.map} +0 -0
  469. /package/dist/cli-bundle/chunks/{learnings-VWJEKHEO.js.map → history-compact-M7GHYVFN.js.map} +0 -0
  470. /package/dist/cli-bundle/chunks/{notes-POMK37UI.js.map → history-redact-3DVZOILD.js.map} +0 -0
  471. /package/dist/cli-bundle/chunks/{notes-NGVJJJQO.js.map → history-redact-JIHZLHDP.js.map} +0 -0
  472. /package/dist/cli-bundle/chunks/{plan-YBNYNT3A.js.map → history-repair-ITDUMK4N.js.map} +0 -0
  473. /package/dist/cli-bundle/chunks/{plan-U6SQJUFI.js.map → history-repair-NAFCHLH7.js.map} +0 -0
  474. /package/dist/cli-bundle/chunks/{profile-JNKSU6EQ.js.map → learnings-FGO3NSFW.js.map} +0 -0
  475. /package/dist/cli-bundle/chunks/{profile-A2WPVG6I.js.map → learnings-SONGPSHI.js.map} +0 -0
  476. /package/dist/cli-bundle/chunks/{restore-AX6ZMGHZ.js.map → notes-BSD53H2W.js.map} +0 -0
  477. /package/dist/cli-bundle/chunks/{restore-IVS5XGYR.js.map → notes-NQ6RXVW6.js.map} +0 -0
  478. /package/dist/cli-bundle/chunks/{schema-R3U2REY4.js.map → plan-2NNEO46V.js.map} +0 -0
  479. /package/dist/cli-bundle/chunks/{schema-P2MF23JO.js.map → plan-AWLYGBNV.js.map} +0 -0
  480. /package/dist/cli-bundle/chunks/{update-YBIQESMH.js.map → profile-AAQUU6T3.js.map} +0 -0
  481. /package/dist/cli-bundle/chunks/{update-XYHF3YZF.js.map → profile-U725ATWZ.js.map} +0 -0
  482. /package/dist/cli-bundle/chunks/{register-mutation-3OXYXBKH.js.map → register-mutation-4FMGJJF7.js.map} +0 -0
  483. /package/dist/cli-bundle/chunks/{register-mutation-WK265BM7.js.map → register-mutation-UELYYOR7.js.map} +0 -0
  484. /package/dist/cli-bundle/chunks/{register-setup-CCK7CJVR.js.map → register-setup-5XNGKJ22.js.map} +0 -0
  485. /package/dist/cli-bundle/chunks/{register-setup-CPZBGSOJ.js.map → register-setup-ZTNY6S7R.js.map} +0 -0
  486. /package/dist/cli-bundle/chunks/{update-many-5HKVHFUL.js.map → restore-66GLMHIX.js.map} +0 -0
  487. /package/dist/cli-bundle/chunks/{update-many-F3CIV5SQ.js.map → restore-B3BAB6X2.js.map} +0 -0
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.",
9
- "version": "2026.7.13"
9
+ "version": "2026.7.14"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "pm-claude",
14
14
  "source": "./plugins/pm-claude",
15
15
  "description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.",
16
- "version": "2026.7.13",
16
+ "version": "2026.7.14",
17
17
  "author": {
18
18
  "name": "unbrained",
19
19
  "url": "https://github.com/unbraind/pm-cli"
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.7.14 - 2026-07-14
4
+
5
+ ### Added
6
+
7
+ - Context usage feedback signal: served-then-acted-on outcomes strengthen relevance scoring (retrieval-practice effect) ([pm-uwfs](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/features/pm-uwfs.toon))
8
+ - GH-544: linked-file path anchoring — files/docs add/glob/discover/validate-paths resolve at process.cwd() while validate --check-files anchors at the workspace root ([pm-chyh](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-chyh.toon))
9
+
10
+ ### Changed
11
+
12
+ - Replace obsolete front-matter vocabulary with item metadata terminology ([pm-hq28](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/tasks/pm-hq28.toon))
13
+
14
+ ### Fixed
15
+
16
+ - GH-533: create/update accept empty --title — required-title contract inconsistent between omitted and empty string ([pm-7je0](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-7je0.toon))
17
+ - GH-535: pm deps omits dangling parent references (missing_count:0, missing:false) contradicting validate's dangling_reference_count ([pm-p9sc](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-p9sc.toon))
18
+ - GH-542: MCP pm_copy nests title/message under options while sibling tools declare flat camelCase params — own suite triggers unexpected-arg warnings ([pm-hno5](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-hno5.toon))
19
+ - GH-532: --estimated-minutes accepts negative numbers and floats — missing non-negative-integer range validation ([pm-jh9t](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-jh9t.toon))
20
+ - GH-534: no-op update reports phantom changed_fields in --json while TOON reports empty, and changed_field_count is always null in JSON ([pm-45mb](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-45mb.toon))
21
+ - GH-526: aggregate --sum/--avg accept unknown field names and silently report 0 ([pm-96vo](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-96vo.toon))
22
+ - GH-530: list --status <invalid\> silently returns count 0 — validate against the status domain like --type and search status: ([pm-kj4k](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-kj4k.toon))
23
+ - Separate active dangling dependency warnings from terminal historical reference diagnostics ([pm-2ler](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/issues/pm-2ler.toon))
24
+
25
+ ### Other
26
+
27
+ - PR review helper: watch GitHub checks and enforce thread-scoped replies ([pm-0fxa](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/tasks/pm-0fxa.toon))
28
+ - Token-budget context packer: diversity-aware selection, projection degradation, and bounded output for pm context/next ([pm-55ra](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/tasks/pm-55ra.toon))
29
+ - Complete public linked-resource SDK primitives and actionable dependency governance ([pm-jcvg](https://github.com/unbraind/pm-cli/blob/main/.agents/pm/tasks/pm-jcvg.toon))
30
+
3
31
  ## 2026.7.13 - 2026-07-13
4
32
 
5
33
  ### Added
@@ -120,7 +120,7 @@ interface NumericAggregation {
120
120
  sum: boolean;
121
121
  avg: boolean;
122
122
  }
123
- declare function parseNumericAggregation(options: AggregateOptions): NumericAggregation | null;
123
+ declare function parseNumericAggregation(options: AggregateOptions, allowedFields?: readonly string[]): NumericAggregation | null;
124
124
  declare function parseGroupBy(raw: string | undefined): AggregateGroupField[];
125
125
  declare function normalizeTagGroupValue(tags: string[]): string | null;
126
126
  declare function resolveGroupValue(field: AggregateGroupField, item: AggregateListedItem): AggregateGroupValue;
@@ -4,14 +4,14 @@
4
4
  * Implements the pm aggregate command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="91c3695d-ea52-548f-967f-491f656c3ec3")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="fce074e9-e105-530a-a070-9a99c71b043d")}catch(e){}}();
8
8
  import { EXIT_CODE } from "../../core/shared/constants.js";
9
9
  import { PmCliError } from "../../core/shared/errors.js";
10
10
  import { splitCommaList } from "../../core/shared/split-comma-list.js";
11
11
  import { nowIso } from "../../core/shared/time.js";
12
12
  import { normalizeStatusInput } from "../../core/item/status.js";
13
13
  import { parseStatusFilterCsv } from "../../core/item/status-filter.js";
14
- import { resolveRuntimeStatusRegistry, } from "../../core/schema/runtime-schema.js";
14
+ import { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, } from "../../core/schema/runtime-schema.js";
15
15
  import { resolvePmRoot } from "../../core/store/paths.js";
16
16
  import { readSettings } from "../../core/store/settings.js";
17
17
  import { buildListQueryFilters } from "./list-filter-shared.js";
@@ -39,7 +39,7 @@ function parseStatus(raw, statusRegistry) {
39
39
  }
40
40
  return statuses[0];
41
41
  }
42
- function parseNumericAggregation(options) {
42
+ function parseNumericAggregation(options, allowedFields = ["estimate", "estimated_minutes", "priority"]) {
43
43
  const sumField = options.sum?.trim();
44
44
  const avgField = options.avg?.trim();
45
45
  const normalizedSum = sumField && sumField.length > 0 ? sumField : undefined;
@@ -50,8 +50,12 @@ function parseNumericAggregation(options) {
50
50
  if (normalizedSum && normalizedAvg && normalizedSum !== normalizedAvg) {
51
51
  throw new PmCliError("Aggregate --sum and --avg must target the same numeric field", EXIT_CODE.USAGE);
52
52
  }
53
+ const field = normalizedSum ?? normalizedAvg;
54
+ if (!allowedFields.includes(field)) {
55
+ throw new PmCliError(`Aggregate numeric field "${field}" is not registered. Allowed: ${allowedFields.join(", ")}`, EXIT_CODE.USAGE);
56
+ }
53
57
  return {
54
- field: normalizedSum ?? normalizedAvg,
58
+ field,
55
59
  sum: normalizedSum !== undefined,
56
60
  avg: normalizedAvg !== undefined,
57
61
  };
@@ -305,9 +309,17 @@ export async function runAggregate(options, global) {
305
309
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
306
310
  const settings = await readSettings(pmRoot);
307
311
  const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
312
+ const numericFields = [
313
+ "estimate",
314
+ "estimated_minutes",
315
+ "priority",
316
+ ...resolveRuntimeFieldRegistry(settings.schema).definitions
317
+ .filter((definition) => definition.type === "number")
318
+ .map((definition) => definition.metadata_key),
319
+ ];
308
320
  const groupBy = parseGroupBy(options.groupBy);
309
321
  const status = parseStatus(options.status, statusRegistry);
310
- const numericAggregation = parseNumericAggregation(options);
322
+ const numericAggregation = parseNumericAggregation(options, [...new Set(numericFields)].sort((left, right) => left.localeCompare(right)));
311
323
  const includeCompletion = options.completion === true;
312
324
  const includeUnparented = options.includeUnparented === true;
313
325
  const listed = await runList(status, buildListQueryFilters(options), global);
@@ -386,4 +398,4 @@ export const _testOnlyAggregateCommand = {
386
398
  updateCompletionCounts,
387
399
  };
388
400
  //# sourceMappingURL=aggregate.js.map
389
- //# debugId=91c3695d-ea52-548f-967f-491f656c3ec3
401
+ //# debugId=fce074e9-e105-530a-a070-9a99c71b043d
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate.js","sources":["cli/commands/aggregate.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module cli/commands/aggregate\n *\n * Implements the pm aggregate command surface and its agent-facing runtime behavior.\n */\nimport { EXIT_CODE } from \"../../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport { splitCommaList } from \"../../core/shared/split-comma-list.js\";\nimport { nowIso } from \"../../core/shared/time.js\";\nimport { normalizeStatusInput } from \"../../core/item/status.js\";\nimport { parseStatusFilterCsv } from \"../../core/item/status-filter.js\";\nimport {\n resolveRuntimeStatusRegistry,\n type RuntimeStatusRegistry,\n} from \"../../core/schema/runtime-schema.js\";\nimport { resolvePmRoot } from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport { type ItemStatus } from \"../../types/index.js\";\nimport { buildListQueryFilters } from \"./list-filter-shared.js\";\nimport { runList } from \"./list.js\";\n\ntype AggregateGroupField =\n | \"parent\"\n | \"type\"\n | \"priority\"\n | \"status\"\n | \"assignee\"\n | \"tags\"\n | \"sprint\"\n | \"release\";\ntype AggregateGroupValue = string | number | null;\ntype AggregateGroupRecord = Partial<\n Record<AggregateGroupField, AggregateGroupValue>\n>;\ntype AggregateListedItem = {\n type: string;\n status: ItemStatus;\n priority: number;\n parent?: string;\n assignee?: string;\n tags: string[];\n sprint?: string;\n release?: string;\n};\n\nconst AGGREGATE_GROUP_FIELDS: AggregateGroupField[] = [\n \"parent\",\n \"type\",\n \"priority\",\n \"status\",\n \"assignee\",\n \"tags\",\n \"sprint\",\n \"release\",\n];\n\n/** Documents the aggregate options payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateOptions {\n /** Value that configures or reports group by for this contract. */\n groupBy?: string;\n /** Value that configures or reports count for this contract. */\n count?: boolean;\n /** Value that configures or reports completion for this contract. */\n completion?: boolean;\n /** Value that configures or reports sum for this contract. */\n sum?: string;\n /** Value that configures or reports avg for this contract. */\n avg?: string;\n /** Value that configures or reports include unparented for this contract. */\n includeUnparented?: boolean;\n /** Lifecycle state reported for status. */\n status?: string;\n /** Schema type that determines the shape and validation rules for this value. */\n type?: string;\n /** Value that configures or reports tag for this contract. */\n tag?: string;\n /** Value that configures or reports priority for this contract. */\n priority?: string;\n /** Value that configures or reports deadline before for this contract. */\n deadlineBefore?: string;\n /** Value that configures or reports deadline after for this contract. */\n deadlineAfter?: string;\n /** Value that configures or reports assignee for this contract. */\n assignee?: string;\n /** Value that configures or reports assignee filter for this contract. */\n assigneeFilter?: string;\n /** Value that configures or reports parent for this contract. */\n parent?: string;\n /** Value that configures or reports sprint for this contract. */\n sprint?: string;\n /** Value that configures or reports release for this contract. */\n release?: string;\n}\n\n/** Documents the aggregate row payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateRow {\n /** Value that configures or reports group for this contract. */\n group: AggregateGroupRecord;\n /** Human-readable display label for this group. Blank/null group values render with an explicit \"(unassigned)\"-style label (per dimension) so terminal and grep-based consumers are never faced with an ambiguous empty key. The structured `group` record keeps the raw null for machine consumers. */\n group_label: string;\n /** Value that configures or reports count for this contract. */\n count: number;\n /** Value that configures or reports open for this contract. */\n open?: number;\n /** Value that configures or reports in progress for this contract. */\n in_progress?: number;\n /** Value that configures or reports closed for this contract. */\n closed?: number;\n /** Value that configures or reports other for this contract. */\n other?: number;\n /** Value that configures or reports completion pct for this contract. */\n completion_pct?: number;\n /** Number of null entries represented by this result. */\n null_count?: number;\n /** Value that configures or reports sum for this contract. */\n sum?: number | null;\n /** Value that configures or reports avg for this contract. */\n avg?: number | null;\n}\n\n/** Documents the aggregate result payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateResult {\n /** Value that configures or reports groups for this contract. */\n groups: AggregateRow[];\n /** Value that configures or reports count for this contract. */\n count: number;\n /** Value that configures or reports totals for this contract. */\n totals: {\n items_considered: number;\n items_grouped: number;\n items_skipped_unparented: number;\n };\n /** Value that configures or reports filters for this contract. */\n filters: {\n group_by: AggregateGroupField[];\n count: boolean;\n completion: boolean;\n sum?: string | null;\n avg?: string | null;\n numeric_field?: string | null;\n include_unparented: boolean;\n status: ItemStatus | null;\n type: string | null;\n tag: string | null;\n priority: string | null;\n deadline_before: string | null;\n deadline_after: string | null;\n assignee: string | null;\n assignee_filter: string | null;\n parent: string | null;\n sprint: string | null;\n release: string | null;\n };\n /** Value that configures or reports now for this contract. */\n now: string;\n /** Value that configures or reports warnings for this contract. */\n warnings?: string[];\n}\n\nfunction parseStatus(\n raw: string | undefined,\n statusRegistry: RuntimeStatusRegistry,\n): ItemStatus | undefined {\n const statuses = parseStatusFilterCsv(raw, statusRegistry, {\n strict: true,\n flagLabel: \"--status\",\n });\n if (!statuses || statuses.length === 0) {\n return undefined;\n }\n if (statuses.length > 1) {\n throw new PmCliError(\n 'Aggregate --status accepts one status, or the standalone \"all\" sentinel.',\n EXIT_CODE.USAGE,\n );\n }\n return statuses[0];\n}\n\ninterface NumericAggregation {\n field: string;\n sum: boolean;\n avg: boolean;\n}\n\nfunction parseNumericAggregation(\n options: AggregateOptions,\n): NumericAggregation | null {\n const sumField = options.sum?.trim();\n const avgField = options.avg?.trim();\n const normalizedSum = sumField && sumField.length > 0 ? sumField : undefined;\n const normalizedAvg = avgField && avgField.length > 0 ? avgField : undefined;\n if (!normalizedSum && !normalizedAvg) {\n return null;\n }\n if (normalizedSum && normalizedAvg && normalizedSum !== normalizedAvg) {\n throw new PmCliError(\n \"Aggregate --sum and --avg must target the same numeric field\",\n EXIT_CODE.USAGE,\n );\n }\n return {\n field: normalizedSum ?? normalizedAvg!,\n sum: normalizedSum !== undefined,\n avg: normalizedAvg !== undefined,\n };\n}\n\nfunction parseGroupBy(raw: string | undefined): AggregateGroupField[] {\n const value = raw?.trim() ?? \"status\";\n if (value.length === 0) {\n throw new PmCliError(\n \"--group-by requires at least one field name\",\n EXIT_CODE.USAGE,\n );\n }\n const requested = splitCommaList(value);\n if (requested.length === 0) {\n throw new PmCliError(\n \"--group-by requires a comma-separated list of fields\",\n EXIT_CODE.USAGE,\n );\n }\n for (const field of requested) {\n if (!AGGREGATE_GROUP_FIELDS.includes(field as AggregateGroupField)) {\n throw new PmCliError(\n `Aggregate group fields must be one of ${AGGREGATE_GROUP_FIELDS.join(\"|\")}; received \"${field}\"`,\n EXIT_CODE.USAGE,\n );\n }\n }\n return requested as AggregateGroupField[];\n}\n\nfunction normalizeTagGroupValue(tags: string[]): string | null {\n const normalized = [\n ...new Set(\n tags\n .map((tag) => tag.trim().toLowerCase())\n .filter((tag) => tag.length > 0),\n ),\n ].sort((left, right) => left.localeCompare(right));\n if (normalized.length === 0) {\n return null;\n }\n return normalized.join(\",\");\n}\n\nfunction resolveGroupValue(\n field: AggregateGroupField,\n item: AggregateListedItem,\n): AggregateGroupValue {\n switch (field) {\n case \"parent\":\n return item.parent ?? null;\n case \"type\":\n return item.type;\n case \"priority\":\n return item.priority;\n case \"status\":\n return item.status;\n case \"assignee\":\n return item.assignee ?? null;\n case \"tags\":\n return normalizeTagGroupValue(item.tags);\n case \"sprint\":\n return item.sprint ?? null;\n case \"release\":\n return item.release ?? null;\n default:\n return null;\n }\n}\n\nfunction compareNullableGroupValue(\n left: AggregateGroupValue | undefined,\n right: AggregateGroupValue | undefined,\n): number {\n const leftValue = left ?? null;\n const rightValue = right ?? null;\n if (leftValue === rightValue) {\n return 0;\n }\n if (leftValue === null) {\n return 1;\n }\n if (rightValue === null) {\n return -1;\n }\n if (typeof leftValue === \"number\" && typeof rightValue === \"number\") {\n return leftValue - rightValue;\n }\n return String(leftValue).localeCompare(String(rightValue));\n}\n\nfunction buildGroupKey(\n groupBy: AggregateGroupField[],\n group: AggregateGroupRecord,\n): string {\n return groupBy\n .map((field) => `${field}:${JSON.stringify(group[field] ?? null)}`)\n .join(\"|\");\n}\n\n/** Explicit display label for an empty/blank group value, keyed by dimension. */\nconst EMPTY_AGGREGATE_GROUP_LABELS: Record<AggregateGroupField, string> = {\n parent: \"(unparented)\",\n type: \"(untyped)\",\n priority: \"(no priority)\",\n status: \"(no status)\",\n assignee: \"(unassigned)\",\n tags: \"(untagged)\",\n sprint: \"(no sprint)\",\n release: \"(no release)\",\n};\n\n/** Render a single group field's value, substituting an explicit label for null. */\nfunction formatGroupFieldLabel(\n field: AggregateGroupField,\n value: AggregateGroupValue | undefined,\n): string {\n if (value === null || value === undefined || value === \"\") {\n return EMPTY_AGGREGATE_GROUP_LABELS[field];\n }\n return String(value);\n}\n\n/** Build the human-readable label for an aggregate row. Single-field grouping yields the bare (possibly substituted) value; multi-field grouping joins each \"field=value\" pair so composite groups stay unambiguous. */\nfunction buildGroupLabel(\n groupBy: AggregateGroupField[],\n group: AggregateGroupRecord,\n): string {\n if (groupBy.length === 1) {\n return formatGroupFieldLabel(groupBy[0], group[groupBy[0]]);\n }\n return groupBy\n .map((field) => `${field}=${formatGroupFieldLabel(field, group[field])}`)\n .join(\" | \");\n}\n\nfunction compareAggregateRows(\n left: AggregateRow,\n right: AggregateRow,\n groupBy: AggregateGroupField[],\n): number {\n for (const field of groupBy) {\n const byField = compareNullableGroupValue(\n left.group[field],\n right.group[field],\n );\n if (byField !== 0) {\n return byField;\n }\n }\n return 0;\n}\n\nfunction readNumericAggregateValue(\n item: AggregateListedItem,\n field: string,\n): number | null {\n const source = item as unknown as Record<string, unknown>;\n const raw = source[field];\n if (typeof raw === \"number\" && Number.isFinite(raw)) {\n return raw;\n }\n if (typeof raw === \"string\") {\n const trimmed = raw.trim();\n if (trimmed.length === 0) {\n return null;\n }\n const parsed = Number(trimmed);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n return null;\n}\n\ninterface AggregateAccumulator {\n /** group_label is derived once at finalization, so the accumulator omits it. */\n row: Omit<AggregateRow, \"group_label\">;\n numeric_count: number;\n numeric_sum: number;\n null_count: number;\n open_count: number;\n in_progress_count: number;\n closed_count: number;\n other_count: number;\n}\n\nfunction completionPct(closed: number, total: number): number {\n if (total <= 0) {\n return 0;\n }\n return Math.round((closed / total) * 10000) / 100;\n}\n\nfunction updateCompletionCounts(\n accumulator: AggregateAccumulator,\n status: ItemStatus,\n statusRegistry: RuntimeStatusRegistry,\n): void {\n const normalizedStatus =\n normalizeStatusInput(String(status), statusRegistry) ?? status;\n if (normalizedStatus === statusRegistry.open_status) {\n accumulator.open_count += 1;\n return;\n }\n if (\n normalizedStatus === \"in_progress\" ||\n (statusRegistry.active_statuses.has(normalizedStatus) &&\n normalizedStatus !== statusRegistry.open_status)\n ) {\n accumulator.in_progress_count += 1;\n return;\n }\n if (\n statusRegistry.terminal_done_statuses.has(normalizedStatus) ||\n normalizedStatus === statusRegistry.close_status\n ) {\n accumulator.closed_count += 1;\n return;\n }\n accumulator.other_count += 1;\n}\n\nfunction createAggregateAccumulator(\n group: AggregateGroupRecord,\n numericValue: number | null,\n): AggregateAccumulator {\n return {\n row: {\n group,\n count: 1,\n },\n numeric_count: numericValue === null ? 0 : 1,\n numeric_sum: numericValue ?? 0,\n null_count: numericValue === null ? 1 : 0,\n open_count: 0,\n in_progress_count: 0,\n closed_count: 0,\n other_count: 0,\n };\n}\n\nfunction updateNumericAggregation(\n accumulator: AggregateAccumulator,\n numericValue: number | null,\n): void {\n if (numericValue === null) {\n accumulator.null_count += 1;\n return;\n }\n accumulator.numeric_count += 1;\n accumulator.numeric_sum += numericValue;\n}\n\nfunction updateAggregateAccumulator(params: {\n accumulator: AggregateAccumulator;\n item: AggregateListedItem;\n statusRegistry: RuntimeStatusRegistry;\n includeCompletion: boolean;\n numericAggregation: NumericAggregation | null;\n numericValue: number | null;\n}): void {\n params.accumulator.row.count += 1;\n if (params.includeCompletion) {\n updateCompletionCounts(\n params.accumulator,\n params.item.status,\n params.statusRegistry,\n );\n }\n if (params.numericAggregation !== null) {\n updateNumericAggregation(params.accumulator, params.numericValue);\n }\n}\n\nfunction buildAggregateGroup(\n groupBy: AggregateGroupField[],\n item: AggregateListedItem,\n): AggregateGroupRecord {\n const group: AggregateGroupRecord = {};\n for (const field of groupBy) {\n group[field] = resolveGroupValue(field, item);\n }\n return group;\n}\n\nfunction finalizeAggregateRow(\n entry: AggregateAccumulator,\n groupBy: AggregateGroupField[],\n includeCompletion: boolean,\n numericAggregation: NumericAggregation | null,\n): AggregateRow {\n const row: AggregateRow = {\n ...entry.row,\n group_label: buildGroupLabel(groupBy, entry.row.group),\n };\n if (includeCompletion) {\n row.open = entry.open_count;\n row.in_progress = entry.in_progress_count;\n row.closed = entry.closed_count;\n row.other = entry.other_count;\n row.completion_pct = completionPct(entry.closed_count, entry.row.count);\n }\n if (numericAggregation !== null) {\n row.null_count = entry.null_count;\n if (numericAggregation.sum) {\n row.sum = entry.numeric_sum;\n }\n if (numericAggregation.avg) {\n row.avg =\n entry.numeric_count === 0\n ? null\n : entry.numeric_sum / entry.numeric_count;\n }\n }\n return row;\n}\n\nfunction buildAggregateFilters(params: {\n groupBy: AggregateGroupField[];\n includeCompletion: boolean;\n includeUnparented: boolean;\n status: ItemStatus | undefined;\n options: AggregateOptions;\n numericAggregation: NumericAggregation | null;\n}): AggregateResult[\"filters\"] {\n return {\n group_by: params.groupBy,\n count: true,\n completion: params.includeCompletion,\n include_unparented: params.includeUnparented,\n status: params.status ?? null,\n type: params.options.type ?? null,\n tag: params.options.tag ?? null,\n priority: params.options.priority ?? null,\n deadline_before: params.options.deadlineBefore ?? null,\n deadline_after: params.options.deadlineAfter ?? null,\n assignee: params.options.assignee ?? null,\n assignee_filter: params.options.assigneeFilter ?? null,\n parent: params.options.parent ?? null,\n sprint: params.options.sprint ?? null,\n release: params.options.release ?? null,\n ...(params.numericAggregation !== null\n ? {\n sum: params.options.sum ?? null,\n avg: params.options.avg ?? null,\n numeric_field: params.numericAggregation.field,\n }\n : {}),\n };\n}\n\n/** Implements run aggregate for the public runtime surface of this module. */\nexport async function runAggregate(\n options: AggregateOptions,\n global: GlobalOptions,\n): Promise<AggregateResult> {\n if (options.count === false) {\n throw new PmCliError(\n \"Aggregate grouped counts are always enabled; omit count=false.\",\n EXIT_CODE.USAGE,\n );\n }\n\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n const settings = await readSettings(pmRoot);\n const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);\n const groupBy = parseGroupBy(options.groupBy);\n const status = parseStatus(options.status, statusRegistry);\n const numericAggregation = parseNumericAggregation(options);\n const includeCompletion = options.completion === true;\n const includeUnparented = options.includeUnparented === true;\n\n const listed = await runList(status, buildListQueryFilters(options), global);\n\n const grouped = new Map<string, AggregateAccumulator>();\n let skippedUnparented = 0;\n let groupedItemCount = 0;\n\n for (const listedItem of listed.items) {\n const item = listedItem as AggregateListedItem;\n const group = buildAggregateGroup(groupBy, item);\n if (\n groupBy.includes(\"parent\") &&\n group.parent === null &&\n !includeUnparented\n ) {\n skippedUnparented += 1;\n continue;\n }\n const key = buildGroupKey(groupBy, group);\n const existing = grouped.get(key);\n const numericValue =\n numericAggregation === null\n ? null\n : readNumericAggregateValue(item, numericAggregation.field);\n if (existing) {\n updateAggregateAccumulator({\n accumulator: existing,\n item,\n statusRegistry,\n includeCompletion,\n numericAggregation,\n numericValue,\n });\n } else {\n const accumulator = createAggregateAccumulator(group, numericValue);\n if (includeCompletion) {\n updateCompletionCounts(accumulator, item.status, statusRegistry);\n }\n grouped.set(key, accumulator);\n }\n groupedItemCount += 1;\n }\n\n const groups = [...grouped.values()]\n .map((entry) =>\n finalizeAggregateRow(\n entry,\n groupBy,\n includeCompletion,\n numericAggregation,\n ),\n )\n .sort((left, right) => compareAggregateRows(left, right, groupBy));\n const warnings =\n listed.warnings && listed.warnings.length > 0 ? listed.warnings : undefined;\n\n return {\n groups,\n count: groups.length,\n totals: {\n items_considered: listed.items.length,\n items_grouped: groupedItemCount,\n items_skipped_unparented: skippedUnparented,\n },\n filters: buildAggregateFilters({\n groupBy,\n includeCompletion,\n includeUnparented,\n status,\n options,\n numericAggregation,\n }),\n now: nowIso(),\n ...(warnings ? { warnings } : {}),\n };\n}\n\n/** Public contract for test only aggregate command, shared by SDK and presentation-layer consumers. */\nexport const _testOnlyAggregateCommand = {\n buildGroupKey,\n compareAggregateRows,\n compareNullableGroupValue,\n completionPct,\n normalizeTagGroupValue,\n parseGroupBy,\n parseNumericAggregation,\n parseStatus,\n readNumericAggregateValue,\n resolveGroupValue,\n updateCompletionCounts,\n};\n"],"names":[],"mappings":"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","debugId":"91c3695d-ea52-548f-967f-491f656c3ec3"}
1
+ {"version":3,"file":"aggregate.js","sources":["cli/commands/aggregate.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module cli/commands/aggregate\n *\n * Implements the pm aggregate command surface and its agent-facing runtime behavior.\n */\nimport { EXIT_CODE } from \"../../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport { splitCommaList } from \"../../core/shared/split-comma-list.js\";\nimport { nowIso } from \"../../core/shared/time.js\";\nimport { normalizeStatusInput } from \"../../core/item/status.js\";\nimport { parseStatusFilterCsv } from \"../../core/item/status-filter.js\";\nimport {\n resolveRuntimeFieldRegistry,\n resolveRuntimeStatusRegistry,\n type RuntimeStatusRegistry,\n} from \"../../core/schema/runtime-schema.js\";\nimport { resolvePmRoot } from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport { type ItemStatus } from \"../../types/index.js\";\nimport { buildListQueryFilters } from \"./list-filter-shared.js\";\nimport { runList } from \"./list.js\";\n\ntype AggregateGroupField =\n | \"parent\"\n | \"type\"\n | \"priority\"\n | \"status\"\n | \"assignee\"\n | \"tags\"\n | \"sprint\"\n | \"release\";\ntype AggregateGroupValue = string | number | null;\ntype AggregateGroupRecord = Partial<\n Record<AggregateGroupField, AggregateGroupValue>\n>;\ntype AggregateListedItem = {\n type: string;\n status: ItemStatus;\n priority: number;\n parent?: string;\n assignee?: string;\n tags: string[];\n sprint?: string;\n release?: string;\n};\n\nconst AGGREGATE_GROUP_FIELDS: AggregateGroupField[] = [\n \"parent\",\n \"type\",\n \"priority\",\n \"status\",\n \"assignee\",\n \"tags\",\n \"sprint\",\n \"release\",\n];\n\n/** Documents the aggregate options payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateOptions {\n /** Value that configures or reports group by for this contract. */\n groupBy?: string;\n /** Value that configures or reports count for this contract. */\n count?: boolean;\n /** Value that configures or reports completion for this contract. */\n completion?: boolean;\n /** Value that configures or reports sum for this contract. */\n sum?: string;\n /** Value that configures or reports avg for this contract. */\n avg?: string;\n /** Value that configures or reports include unparented for this contract. */\n includeUnparented?: boolean;\n /** Lifecycle state reported for status. */\n status?: string;\n /** Schema type that determines the shape and validation rules for this value. */\n type?: string;\n /** Value that configures or reports tag for this contract. */\n tag?: string;\n /** Value that configures or reports priority for this contract. */\n priority?: string;\n /** Value that configures or reports deadline before for this contract. */\n deadlineBefore?: string;\n /** Value that configures or reports deadline after for this contract. */\n deadlineAfter?: string;\n /** Value that configures or reports assignee for this contract. */\n assignee?: string;\n /** Value that configures or reports assignee filter for this contract. */\n assigneeFilter?: string;\n /** Value that configures or reports parent for this contract. */\n parent?: string;\n /** Value that configures or reports sprint for this contract. */\n sprint?: string;\n /** Value that configures or reports release for this contract. */\n release?: string;\n}\n\n/** Documents the aggregate row payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateRow {\n /** Value that configures or reports group for this contract. */\n group: AggregateGroupRecord;\n /** Human-readable display label for this group. Blank/null group values render with an explicit \"(unassigned)\"-style label (per dimension) so terminal and grep-based consumers are never faced with an ambiguous empty key. The structured `group` record keeps the raw null for machine consumers. */\n group_label: string;\n /** Value that configures or reports count for this contract. */\n count: number;\n /** Value that configures or reports open for this contract. */\n open?: number;\n /** Value that configures or reports in progress for this contract. */\n in_progress?: number;\n /** Value that configures or reports closed for this contract. */\n closed?: number;\n /** Value that configures or reports other for this contract. */\n other?: number;\n /** Value that configures or reports completion pct for this contract. */\n completion_pct?: number;\n /** Number of null entries represented by this result. */\n null_count?: number;\n /** Value that configures or reports sum for this contract. */\n sum?: number | null;\n /** Value that configures or reports avg for this contract. */\n avg?: number | null;\n}\n\n/** Documents the aggregate result payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateResult {\n /** Value that configures or reports groups for this contract. */\n groups: AggregateRow[];\n /** Value that configures or reports count for this contract. */\n count: number;\n /** Value that configures or reports totals for this contract. */\n totals: {\n items_considered: number;\n items_grouped: number;\n items_skipped_unparented: number;\n };\n /** Value that configures or reports filters for this contract. */\n filters: {\n group_by: AggregateGroupField[];\n count: boolean;\n completion: boolean;\n sum?: string | null;\n avg?: string | null;\n numeric_field?: string | null;\n include_unparented: boolean;\n status: ItemStatus | null;\n type: string | null;\n tag: string | null;\n priority: string | null;\n deadline_before: string | null;\n deadline_after: string | null;\n assignee: string | null;\n assignee_filter: string | null;\n parent: string | null;\n sprint: string | null;\n release: string | null;\n };\n /** Value that configures or reports now for this contract. */\n now: string;\n /** Value that configures or reports warnings for this contract. */\n warnings?: string[];\n}\n\nfunction parseStatus(\n raw: string | undefined,\n statusRegistry: RuntimeStatusRegistry,\n): ItemStatus | undefined {\n const statuses = parseStatusFilterCsv(raw, statusRegistry, {\n strict: true,\n flagLabel: \"--status\",\n });\n if (!statuses || statuses.length === 0) {\n return undefined;\n }\n if (statuses.length > 1) {\n throw new PmCliError(\n 'Aggregate --status accepts one status, or the standalone \"all\" sentinel.',\n EXIT_CODE.USAGE,\n );\n }\n return statuses[0];\n}\n\ninterface NumericAggregation {\n field: string;\n sum: boolean;\n avg: boolean;\n}\n\nfunction parseNumericAggregation(\n options: AggregateOptions,\n allowedFields: readonly string[] = [\"estimate\", \"estimated_minutes\", \"priority\"],\n): NumericAggregation | null {\n const sumField = options.sum?.trim();\n const avgField = options.avg?.trim();\n const normalizedSum = sumField && sumField.length > 0 ? sumField : undefined;\n const normalizedAvg = avgField && avgField.length > 0 ? avgField : undefined;\n if (!normalizedSum && !normalizedAvg) {\n return null;\n }\n if (normalizedSum && normalizedAvg && normalizedSum !== normalizedAvg) {\n throw new PmCliError(\n \"Aggregate --sum and --avg must target the same numeric field\",\n EXIT_CODE.USAGE,\n );\n }\n const field = normalizedSum ?? normalizedAvg!;\n if (!allowedFields.includes(field)) {\n throw new PmCliError(\n `Aggregate numeric field \"${field}\" is not registered. Allowed: ${allowedFields.join(\", \")}`,\n EXIT_CODE.USAGE,\n );\n }\n return {\n field,\n sum: normalizedSum !== undefined,\n avg: normalizedAvg !== undefined,\n };\n}\n\nfunction parseGroupBy(raw: string | undefined): AggregateGroupField[] {\n const value = raw?.trim() ?? \"status\";\n if (value.length === 0) {\n throw new PmCliError(\n \"--group-by requires at least one field name\",\n EXIT_CODE.USAGE,\n );\n }\n const requested = splitCommaList(value);\n if (requested.length === 0) {\n throw new PmCliError(\n \"--group-by requires a comma-separated list of fields\",\n EXIT_CODE.USAGE,\n );\n }\n for (const field of requested) {\n if (!AGGREGATE_GROUP_FIELDS.includes(field as AggregateGroupField)) {\n throw new PmCliError(\n `Aggregate group fields must be one of ${AGGREGATE_GROUP_FIELDS.join(\"|\")}; received \"${field}\"`,\n EXIT_CODE.USAGE,\n );\n }\n }\n return requested as AggregateGroupField[];\n}\n\nfunction normalizeTagGroupValue(tags: string[]): string | null {\n const normalized = [\n ...new Set(\n tags\n .map((tag) => tag.trim().toLowerCase())\n .filter((tag) => tag.length > 0),\n ),\n ].sort((left, right) => left.localeCompare(right));\n if (normalized.length === 0) {\n return null;\n }\n return normalized.join(\",\");\n}\n\nfunction resolveGroupValue(\n field: AggregateGroupField,\n item: AggregateListedItem,\n): AggregateGroupValue {\n switch (field) {\n case \"parent\":\n return item.parent ?? null;\n case \"type\":\n return item.type;\n case \"priority\":\n return item.priority;\n case \"status\":\n return item.status;\n case \"assignee\":\n return item.assignee ?? null;\n case \"tags\":\n return normalizeTagGroupValue(item.tags);\n case \"sprint\":\n return item.sprint ?? null;\n case \"release\":\n return item.release ?? null;\n default:\n return null;\n }\n}\n\nfunction compareNullableGroupValue(\n left: AggregateGroupValue | undefined,\n right: AggregateGroupValue | undefined,\n): number {\n const leftValue = left ?? null;\n const rightValue = right ?? null;\n if (leftValue === rightValue) {\n return 0;\n }\n if (leftValue === null) {\n return 1;\n }\n if (rightValue === null) {\n return -1;\n }\n if (typeof leftValue === \"number\" && typeof rightValue === \"number\") {\n return leftValue - rightValue;\n }\n return String(leftValue).localeCompare(String(rightValue));\n}\n\nfunction buildGroupKey(\n groupBy: AggregateGroupField[],\n group: AggregateGroupRecord,\n): string {\n return groupBy\n .map((field) => `${field}:${JSON.stringify(group[field] ?? null)}`)\n .join(\"|\");\n}\n\n/** Explicit display label for an empty/blank group value, keyed by dimension. */\nconst EMPTY_AGGREGATE_GROUP_LABELS: Record<AggregateGroupField, string> = {\n parent: \"(unparented)\",\n type: \"(untyped)\",\n priority: \"(no priority)\",\n status: \"(no status)\",\n assignee: \"(unassigned)\",\n tags: \"(untagged)\",\n sprint: \"(no sprint)\",\n release: \"(no release)\",\n};\n\n/** Render a single group field's value, substituting an explicit label for null. */\nfunction formatGroupFieldLabel(\n field: AggregateGroupField,\n value: AggregateGroupValue | undefined,\n): string {\n if (value === null || value === undefined || value === \"\") {\n return EMPTY_AGGREGATE_GROUP_LABELS[field];\n }\n return String(value);\n}\n\n/** Build the human-readable label for an aggregate row. Single-field grouping yields the bare (possibly substituted) value; multi-field grouping joins each \"field=value\" pair so composite groups stay unambiguous. */\nfunction buildGroupLabel(\n groupBy: AggregateGroupField[],\n group: AggregateGroupRecord,\n): string {\n if (groupBy.length === 1) {\n return formatGroupFieldLabel(groupBy[0], group[groupBy[0]]);\n }\n return groupBy\n .map((field) => `${field}=${formatGroupFieldLabel(field, group[field])}`)\n .join(\" | \");\n}\n\nfunction compareAggregateRows(\n left: AggregateRow,\n right: AggregateRow,\n groupBy: AggregateGroupField[],\n): number {\n for (const field of groupBy) {\n const byField = compareNullableGroupValue(\n left.group[field],\n right.group[field],\n );\n if (byField !== 0) {\n return byField;\n }\n }\n return 0;\n}\n\nfunction readNumericAggregateValue(\n item: AggregateListedItem,\n field: string,\n): number | null {\n const source = item as unknown as Record<string, unknown>;\n const raw = source[field];\n if (typeof raw === \"number\" && Number.isFinite(raw)) {\n return raw;\n }\n if (typeof raw === \"string\") {\n const trimmed = raw.trim();\n if (trimmed.length === 0) {\n return null;\n }\n const parsed = Number(trimmed);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n return null;\n}\n\ninterface AggregateAccumulator {\n /** group_label is derived once at finalization, so the accumulator omits it. */\n row: Omit<AggregateRow, \"group_label\">;\n numeric_count: number;\n numeric_sum: number;\n null_count: number;\n open_count: number;\n in_progress_count: number;\n closed_count: number;\n other_count: number;\n}\n\nfunction completionPct(closed: number, total: number): number {\n if (total <= 0) {\n return 0;\n }\n return Math.round((closed / total) * 10000) / 100;\n}\n\nfunction updateCompletionCounts(\n accumulator: AggregateAccumulator,\n status: ItemStatus,\n statusRegistry: RuntimeStatusRegistry,\n): void {\n const normalizedStatus =\n normalizeStatusInput(String(status), statusRegistry) ?? status;\n if (normalizedStatus === statusRegistry.open_status) {\n accumulator.open_count += 1;\n return;\n }\n if (\n normalizedStatus === \"in_progress\" ||\n (statusRegistry.active_statuses.has(normalizedStatus) &&\n normalizedStatus !== statusRegistry.open_status)\n ) {\n accumulator.in_progress_count += 1;\n return;\n }\n if (\n statusRegistry.terminal_done_statuses.has(normalizedStatus) ||\n normalizedStatus === statusRegistry.close_status\n ) {\n accumulator.closed_count += 1;\n return;\n }\n accumulator.other_count += 1;\n}\n\nfunction createAggregateAccumulator(\n group: AggregateGroupRecord,\n numericValue: number | null,\n): AggregateAccumulator {\n return {\n row: {\n group,\n count: 1,\n },\n numeric_count: numericValue === null ? 0 : 1,\n numeric_sum: numericValue ?? 0,\n null_count: numericValue === null ? 1 : 0,\n open_count: 0,\n in_progress_count: 0,\n closed_count: 0,\n other_count: 0,\n };\n}\n\nfunction updateNumericAggregation(\n accumulator: AggregateAccumulator,\n numericValue: number | null,\n): void {\n if (numericValue === null) {\n accumulator.null_count += 1;\n return;\n }\n accumulator.numeric_count += 1;\n accumulator.numeric_sum += numericValue;\n}\n\nfunction updateAggregateAccumulator(params: {\n accumulator: AggregateAccumulator;\n item: AggregateListedItem;\n statusRegistry: RuntimeStatusRegistry;\n includeCompletion: boolean;\n numericAggregation: NumericAggregation | null;\n numericValue: number | null;\n}): void {\n params.accumulator.row.count += 1;\n if (params.includeCompletion) {\n updateCompletionCounts(\n params.accumulator,\n params.item.status,\n params.statusRegistry,\n );\n }\n if (params.numericAggregation !== null) {\n updateNumericAggregation(params.accumulator, params.numericValue);\n }\n}\n\nfunction buildAggregateGroup(\n groupBy: AggregateGroupField[],\n item: AggregateListedItem,\n): AggregateGroupRecord {\n const group: AggregateGroupRecord = {};\n for (const field of groupBy) {\n group[field] = resolveGroupValue(field, item);\n }\n return group;\n}\n\nfunction finalizeAggregateRow(\n entry: AggregateAccumulator,\n groupBy: AggregateGroupField[],\n includeCompletion: boolean,\n numericAggregation: NumericAggregation | null,\n): AggregateRow {\n const row: AggregateRow = {\n ...entry.row,\n group_label: buildGroupLabel(groupBy, entry.row.group),\n };\n if (includeCompletion) {\n row.open = entry.open_count;\n row.in_progress = entry.in_progress_count;\n row.closed = entry.closed_count;\n row.other = entry.other_count;\n row.completion_pct = completionPct(entry.closed_count, entry.row.count);\n }\n if (numericAggregation !== null) {\n row.null_count = entry.null_count;\n if (numericAggregation.sum) {\n row.sum = entry.numeric_sum;\n }\n if (numericAggregation.avg) {\n row.avg =\n entry.numeric_count === 0\n ? null\n : entry.numeric_sum / entry.numeric_count;\n }\n }\n return row;\n}\n\nfunction buildAggregateFilters(params: {\n groupBy: AggregateGroupField[];\n includeCompletion: boolean;\n includeUnparented: boolean;\n status: ItemStatus | undefined;\n options: AggregateOptions;\n numericAggregation: NumericAggregation | null;\n}): AggregateResult[\"filters\"] {\n return {\n group_by: params.groupBy,\n count: true,\n completion: params.includeCompletion,\n include_unparented: params.includeUnparented,\n status: params.status ?? null,\n type: params.options.type ?? null,\n tag: params.options.tag ?? null,\n priority: params.options.priority ?? null,\n deadline_before: params.options.deadlineBefore ?? null,\n deadline_after: params.options.deadlineAfter ?? null,\n assignee: params.options.assignee ?? null,\n assignee_filter: params.options.assigneeFilter ?? null,\n parent: params.options.parent ?? null,\n sprint: params.options.sprint ?? null,\n release: params.options.release ?? null,\n ...(params.numericAggregation !== null\n ? {\n sum: params.options.sum ?? null,\n avg: params.options.avg ?? null,\n numeric_field: params.numericAggregation.field,\n }\n : {}),\n };\n}\n\n/** Implements run aggregate for the public runtime surface of this module. */\nexport async function runAggregate(\n options: AggregateOptions,\n global: GlobalOptions,\n): Promise<AggregateResult> {\n if (options.count === false) {\n throw new PmCliError(\n \"Aggregate grouped counts are always enabled; omit count=false.\",\n EXIT_CODE.USAGE,\n );\n }\n\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n const settings = await readSettings(pmRoot);\n const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);\n const numericFields = [\n \"estimate\",\n \"estimated_minutes\",\n \"priority\",\n ...resolveRuntimeFieldRegistry(settings.schema).definitions\n .filter((definition) => definition.type === \"number\")\n .map((definition) => definition.metadata_key),\n ];\n const groupBy = parseGroupBy(options.groupBy);\n const status = parseStatus(options.status, statusRegistry);\n const numericAggregation = parseNumericAggregation(\n options,\n [...new Set(numericFields)].sort((left, right) => left.localeCompare(right)),\n );\n const includeCompletion = options.completion === true;\n const includeUnparented = options.includeUnparented === true;\n\n const listed = await runList(status, buildListQueryFilters(options), global);\n\n const grouped = new Map<string, AggregateAccumulator>();\n let skippedUnparented = 0;\n let groupedItemCount = 0;\n\n for (const listedItem of listed.items) {\n const item = listedItem as AggregateListedItem;\n const group = buildAggregateGroup(groupBy, item);\n if (\n groupBy.includes(\"parent\") &&\n group.parent === null &&\n !includeUnparented\n ) {\n skippedUnparented += 1;\n continue;\n }\n const key = buildGroupKey(groupBy, group);\n const existing = grouped.get(key);\n const numericValue =\n numericAggregation === null\n ? null\n : readNumericAggregateValue(item, numericAggregation.field);\n if (existing) {\n updateAggregateAccumulator({\n accumulator: existing,\n item,\n statusRegistry,\n includeCompletion,\n numericAggregation,\n numericValue,\n });\n } else {\n const accumulator = createAggregateAccumulator(group, numericValue);\n if (includeCompletion) {\n updateCompletionCounts(accumulator, item.status, statusRegistry);\n }\n grouped.set(key, accumulator);\n }\n groupedItemCount += 1;\n }\n\n const groups = [...grouped.values()]\n .map((entry) =>\n finalizeAggregateRow(\n entry,\n groupBy,\n includeCompletion,\n numericAggregation,\n ),\n )\n .sort((left, right) => compareAggregateRows(left, right, groupBy));\n const warnings =\n listed.warnings && listed.warnings.length > 0 ? listed.warnings : undefined;\n\n return {\n groups,\n count: groups.length,\n totals: {\n items_considered: listed.items.length,\n items_grouped: groupedItemCount,\n items_skipped_unparented: skippedUnparented,\n },\n filters: buildAggregateFilters({\n groupBy,\n includeCompletion,\n includeUnparented,\n status,\n options,\n numericAggregation,\n }),\n now: nowIso(),\n ...(warnings ? { warnings } : {}),\n };\n}\n\n/** Public contract for test only aggregate command, shared by SDK and presentation-layer consumers. */\nexport const _testOnlyAggregateCommand = {\n buildGroupKey,\n compareAggregateRows,\n compareNullableGroupValue,\n completionPct,\n normalizeTagGroupValue,\n parseGroupBy,\n parseNumericAggregation,\n parseStatus,\n readNumericAggregateValue,\n resolveGroupValue,\n updateCompletionCounts,\n};\n"],"names":[],"mappings":"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","debugId":"fce074e9-e105-530a-a070-9a99c71b043d"}
@@ -4,6 +4,7 @@ import type { ContextDepth, ContextSectionName, ContextSettings, ItemMetadata, I
4
4
  import { type CalendarRow } from "./calendar.js";
5
5
  import { type CompactActivityEntry } from "./activity.js";
6
6
  import { type ContextRelevanceCandidate, type ContextRelevanceContributions, type ContextRelevanceReport, type ContextRelevanceSignalName } from "../../sdk/context-relevance.js";
7
+ import { type ContextPackingReport } from "../../sdk/context-packing.js";
7
8
  /** Supported values accepted by the context output contract. */
8
9
  export declare const CONTEXT_OUTPUT_VALUES: readonly ["markdown", "toon", "json"];
9
10
  /** Restricts context output format values accepted by command, SDK, and storage contracts. */
@@ -309,6 +310,8 @@ export interface ContextResult {
309
310
  warnings?: string[];
310
311
  /** Value that configures or reports ranking for this contract. */
311
312
  ranking?: ContextRankingSummary;
313
+ /** Token-budget selection and projection accounting for ranked focus rows. */
314
+ packing?: ContextPackingSummary;
312
315
  /** Whether additional ranked focus rows remain after this page. */
313
316
  has_more?: boolean;
314
317
  /** Opaque continuation cursor for the next ranked focus page. */
@@ -318,6 +321,14 @@ export interface ContextResult {
318
321
  /** Explicit marker that focus rows were bounded. */
319
322
  truncated?: true;
320
323
  }
324
+ /** Compact token-budget accounting shared by context and next results. */
325
+ export type ContextPackingSummary = Omit<ContextPackingReport<unknown>, "included"> & {
326
+ included: Array<{
327
+ id: string;
328
+ projection: string;
329
+ tokens: number;
330
+ }>;
331
+ };
321
332
  /** Compact explainability envelope shared by context and next JSON results. */
322
333
  export interface ContextRankingSummary {
323
334
  /** Value that configures or reports model for this contract. */
@@ -382,7 +393,11 @@ declare function normalizedParentId(value: unknown): string | null;
382
393
  */
383
394
  export declare function compareCriticalItems(left: ItemMetadata, right: ItemMetadata, statusRegistry: RuntimeStatusRegistry): number;
384
395
  /** Derives the metadata signals currently available on compact item rows. More expensive history/index/semantic signals can be added by an extension scorer without changing the public candidate contract. */
385
- export declare function buildItemContextRelevanceCandidates(items: readonly ItemMetadata[], statusRegistry: RuntimeStatusRegistry, now: string, author: string | undefined): ContextRelevanceCandidate<ItemMetadata>[];
396
+ export declare function buildItemContextRelevanceCandidates(items: readonly ItemMetadata[], statusRegistry: RuntimeStatusRegistry, now: string, author: string | undefined, usageAffinity?: Readonly<Record<string, number>>): ContextRelevanceCandidate<ItemMetadata>[];
397
+ /** Packs a relevance report with monotone identity, summary, and full item projections. */
398
+ export declare function packRankedContextItems(report: ContextRelevanceReport<ItemMetadata>, tokenBudget: number, requiredIds?: ReadonlySet<string>, profile?: "context" | "next"): ContextPackingReport<ItemMetadata>;
399
+ /** Projects the SDK packer report onto the stable low-token command envelope. */
400
+ export declare function toContextPackingSummary(report: ContextPackingReport<ItemMetadata>): ContextPackingSummary;
386
401
  /** Project a full scorer report onto the low-token command explanation shape. */
387
402
  export declare function toContextRankingSummary<TItem>(report: ContextRelevanceReport<TItem>): ContextRankingSummary;
388
403
  declare function completionPct(closed: number, total: number): number;
@@ -4,7 +4,7 @@
4
4
  * Implements the pm context command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a1564ad2-3e32-5b66-9327-7ff92b7aee37")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7563a6df-9229-5af9-9849-85a058c01a46")}catch(e){}}();
8
8
  import { SETTINGS_DEFAULTS, EXIT_CODE } from "../../core/shared/constants.js";
9
9
  import { PmCliError } from "../../core/shared/errors.js";
10
10
  import { compareTimestampStrings, nowIso } from "../../core/shared/time.js";
@@ -19,6 +19,8 @@ import { runList } from "./list.js";
19
19
  import { runActivity } from "./activity.js";
20
20
  import { scoreContextCandidatesWithActiveExtensions, } from "../../sdk/context-relevance.js";
21
21
  import { createQueryFingerprint, encodeQueryCursor, resolveQueryCursorStart, } from "../../sdk/pagination.js";
22
+ import { packContextCandidates, } from "../../sdk/context-packing.js";
23
+ import { readContextUsageAffinity, recordContextUsageServing, } from "../../sdk/context-usage.js";
22
24
  // ---------------------------------------------------------------------------
23
25
  // Output format
24
26
  // ---------------------------------------------------------------------------
@@ -451,11 +453,12 @@ function buildItemContextRelevanceCandidate(item, params) {
451
453
  deadline_pressure: resolveDeadlinePressure(item.deadline, params.nowMs),
452
454
  knowledge_density: Math.min(knowledgeEntries / 5, 1),
453
455
  author_affinity: assignedToAuthor ? 1 : 0,
456
+ usage_affinity: params.usageAffinity?.[item.id],
454
457
  },
455
458
  };
456
459
  }
457
460
  /** Derives the metadata signals currently available on compact item rows. More expensive history/index/semantic signals can be added by an extension scorer without changing the public candidate contract. */
458
- export function buildItemContextRelevanceCandidates(items, statusRegistry, now, author) {
461
+ export function buildItemContextRelevanceCandidates(items, statusRegistry, now, author, usageAffinity) {
459
462
  const recencyOrder = [...items].sort((left, right) => compareTimestampStrings(sortableTimestamp(right.updated_at), sortableTimestamp(left.updated_at)) || left.id.localeCompare(right.id));
460
463
  const recencyRank = new Map(recencyOrder.map((item, index) => [item.id, index]));
461
464
  const recencyDenominator = Math.max(items.length - 1, 1);
@@ -468,8 +471,46 @@ export function buildItemContextRelevanceCandidates(items, statusRegistry, now,
468
471
  recencyRank,
469
472
  recencyDenominator,
470
473
  itemCount: items.length,
474
+ usageAffinity,
471
475
  }));
472
476
  }
477
+ function estimateJsonTokens(value) {
478
+ return Math.max(1, Math.ceil(Buffer.byteLength(JSON.stringify(value), "utf8") / 4));
479
+ }
480
+ /** Packs a relevance report with monotone identity, summary, and full item projections. */
481
+ export function packRankedContextItems(report, tokenBudget, requiredIds = new Set(), profile = "context") {
482
+ return packContextCandidates(report.ranked.map((entry) => ({
483
+ id: entry.id,
484
+ item: entry.item,
485
+ rank: entry.rank,
486
+ score: entry.score,
487
+ required: requiredIds.has(entry.id),
488
+ cluster: entry.item.parent?.trim() || entry.item.type,
489
+ token_costs: {
490
+ identity: estimateJsonTokens({ id: entry.id, title: entry.item.title }),
491
+ summary: estimateJsonTokens({
492
+ id: entry.id,
493
+ title: entry.item.title,
494
+ type: entry.item.type,
495
+ status: entry.item.status,
496
+ priority: entry.item.priority,
497
+ parent: entry.item.parent,
498
+ }),
499
+ full: estimateJsonTokens(entry.item),
500
+ },
501
+ })), { tokenBudget, profile, latencyBudgetMs: 25 });
502
+ }
503
+ /** Projects the SDK packer report onto the stable low-token command envelope. */
504
+ export function toContextPackingSummary(report) {
505
+ return {
506
+ ...report,
507
+ included: report.included.map((entry) => ({
508
+ id: entry.id,
509
+ projection: entry.projection,
510
+ tokens: entry.tokens,
511
+ })),
512
+ };
513
+ }
473
514
  /** Project a full scorer report onto the low-token command explanation shape. */
474
515
  export function toContextRankingSummary(report) {
475
516
  return {
@@ -1195,38 +1236,51 @@ function resolveContextSubtreeIds(parentScope, fullCorpus) {
1195
1236
  }
1196
1237
  return subtree.ids;
1197
1238
  }
1198
- async function resolveContextFocusGroups(listedItemMetadata, allItems, statusRegistry, sectionsIncluded, limit, now, author, cursor, cursorFingerprint, useBoundedPage) {
1239
+ async function resolveContextFocusGroups(listedItemMetadata, allItems, statusRegistry, sectionsIncluded, limit, now, author, cursor, cursorFingerprint, useBoundedPage, pmRoot) {
1199
1240
  const structural = [...listedItemMetadata].sort((left, right) => compareCriticalItems(left, right, statusRegistry));
1200
- const ranking = await scoreContextCandidatesWithActiveExtensions("context", buildItemContextRelevanceCandidates(structural, statusRegistry, now, author));
1241
+ const usage = await readContextUsageAffinity({
1242
+ pmRoot,
1243
+ author,
1244
+ enabled: process.env.PM_CONTEXT_USAGE_DISABLED !== "1",
1245
+ });
1246
+ const ranking = await scoreContextCandidatesWithActiveExtensions("context", buildItemContextRelevanceCandidates(structural, statusRegistry, now, author, usage.affinity));
1201
1247
  const ranked = ranking.ranked.map((entry) => entry.item);
1202
1248
  const activeStatuses = statusRegistry.active_statuses;
1203
- const activeItems = ranked.filter((item) => activeStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1249
+ const rankedActiveItems = ranked.filter((item) => activeStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1204
1250
  const pageStart = useBoundedPage
1205
- ? resolveQueryCursorStart(activeItems, cursor, cursorFingerprint, (item) => item.id)
1251
+ ? resolveQueryCursorStart(rankedActiveItems, cursor, cursorFingerprint, (item) => item.id)
1206
1252
  : 0;
1207
1253
  const focusPage = useBoundedPage
1208
- ? activeItems.slice(pageStart, pageStart + limit)
1209
- : activeItems;
1254
+ ? rankedActiveItems.slice(pageStart, pageStart + limit)
1255
+ : rankedActiveItems;
1210
1256
  const hasMore = useBoundedPage &&
1211
1257
  focusPage.length > 0 &&
1212
- pageStart + focusPage.length < activeItems.length;
1258
+ pageStart + focusPage.length < rankedActiveItems.length;
1213
1259
  const nextCursor = hasMore && focusPage.length > 0
1214
1260
  ? encodeQueryCursor(cursorFingerprint, focusPage[focusPage.length - 1].id, pageStart + focusPage.length - 1)
1215
1261
  : undefined;
1216
- const blockedItems = ranked.filter((item) => statusRegistry.blocked_statuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1262
+ const rankedBlockedItems = ranked.filter((item) => statusRegistry.blocked_statuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1263
+ const packingIds = new Set([
1264
+ ...focusPage.map((item) => item.id),
1265
+ ...rankedBlockedItems.slice(0, limit).map((item) => item.id),
1266
+ ]);
1267
+ const packing = packRankedContextItems({ ...ranking, ranked: ranking.ranked.filter((entry) => packingIds.has(entry.id)) }, Math.max(256, limit * 160));
1268
+ const packedItems = packing.included.map((entry) => entry.item);
1269
+ const activeItems = packedItems.filter((item) => activeStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1270
+ const blockedItems = packedItems.filter((item) => statusRegistry.blocked_statuses.has(normalizeStatusForRegistry(item.status, statusRegistry)));
1217
1271
  const childrenByParent = buildChildrenByParent(allItems);
1218
1272
  const focusChildrenByParent = contextNeedsAllItems(sectionsIncluded)
1219
1273
  ? childrenByParent
1220
1274
  : undefined;
1221
- const highLevel = focusPage
1275
+ const highLevel = activeItems
1222
1276
  .filter((item) => HIGH_LEVEL_TYPES.has(item.type))
1223
1277
  .slice(0, useBoundedPage ? focusPage.length : limit)
1224
1278
  .map((item) => toContextFocusItem(item, statusRegistry, focusChildrenByParent));
1225
- const lowLevel = focusPage
1279
+ const lowLevel = activeItems
1226
1280
  .filter((item) => !HIGH_LEVEL_TYPES.has(item.type))
1227
1281
  .slice(0, useBoundedPage ? focusPage.length : limit)
1228
1282
  .map((item) => toContextFocusItem(item, statusRegistry, focusChildrenByParent));
1229
- const blockedFallbackUsed = activeItems.length === 0;
1283
+ const blockedFallbackUsed = rankedActiveItems.length === 0;
1230
1284
  return {
1231
1285
  activeItems,
1232
1286
  blockedItems,
@@ -1239,6 +1293,7 @@ async function resolveContextFocusGroups(listedItemMetadata, allItems, statusReg
1239
1293
  : [],
1240
1294
  blockedFallbackUsed,
1241
1295
  ranking,
1296
+ packing,
1242
1297
  pageExtras: {
1243
1298
  ...(useBoundedPage ? { applied_limit: limit } : {}),
1244
1299
  ...(hasMore ? { has_more: true, truncated: true } : {}),
@@ -1382,15 +1437,39 @@ function maybeAttachEmptyContextSuggestions(result, activeItems, blockedItems) {
1382
1437
  "pm aggregate for a full project status overview",
1383
1438
  ];
1384
1439
  }
1440
+ async function attachContextUsageFeedback(result, focusGroups, pmRoot, author) {
1441
+ try {
1442
+ const included = new Set(focusGroups.packing.included.map((entry) => entry.id));
1443
+ await recordContextUsageServing({
1444
+ pmRoot,
1445
+ author,
1446
+ surface: "context",
1447
+ profile: focusGroups.packing.profile,
1448
+ rows: focusGroups.ranking.ranked.map((entry) => ({
1449
+ id: entry.id,
1450
+ rank: entry.rank,
1451
+ included: included.has(entry.id),
1452
+ })),
1453
+ enabled: process.env.PM_CONTEXT_USAGE_DISABLED !== "1",
1454
+ });
1455
+ }
1456
+ catch {
1457
+ result.warnings = mergeSortedWarnings(result.warnings, [
1458
+ "context_usage_feedback_write_failed",
1459
+ ]);
1460
+ }
1461
+ }
1385
1462
  /** Implements run context for the public runtime surface of this module. */
1386
1463
  export async function runContext(options, global) {
1464
+ const pmRoot = resolvePmRoot(process.cwd(), global.path);
1387
1465
  const resolvedRuntime = await resolveContextRuntime(options, global);
1388
1466
  const corpus = await loadContextCorpus(options, global, resolvedRuntime);
1389
1467
  const runtime = {
1390
1468
  ...resolvedRuntime,
1391
1469
  limit: resolveContextLimitAtScale(resolvedRuntime.limit, corpus.fullCorpus.length),
1392
1470
  };
1393
- const focusGroups = await resolveContextFocusGroups(corpus.listedItemMetadata, corpus.allItems, runtime.statusRegistry, runtime.sectionsIncluded, runtime.limit, nowIso(), process.env.PM_AUTHOR, options.after, buildContextCursorFingerprint(options), shouldPageContextFocus(options, corpus.fullCorpus.length));
1471
+ const author = process.env.PM_AUTHOR ?? runtime.settings.author_default;
1472
+ const focusGroups = await resolveContextFocusGroups(corpus.listedItemMetadata, corpus.allItems, runtime.statusRegistry, runtime.sectionsIncluded, runtime.limit, nowIso(), author, options.after, buildContextCursorFingerprint(options), shouldPageContextFocus(options, corpus.fullCorpus.length), pmRoot);
1394
1473
  const agendaContext = await buildContextAgenda(options, global, runtime, corpus.subtreeIds);
1395
1474
  const warnings = mergeSortedWarnings(corpus.listed.warnings, agendaContext.agenda.warnings, focusGroups.ranking.warnings);
1396
1475
  const inProgressCount = countContextStatus(focusGroups.activeItems, normalizeStatusInput("in_progress", runtime.statusRegistry), runtime.statusRegistry);
@@ -1453,13 +1532,16 @@ export async function runContext(options, global) {
1453
1532
  ...focusGroups.pageExtras,
1454
1533
  };
1455
1534
  attachOptionalContextSections(result, sections);
1456
- if (options.explainRanking === true)
1535
+ if (options.explainRanking === true) {
1457
1536
  result.ranking = toContextRankingSummary(focusGroups.ranking);
1537
+ result.packing = toContextPackingSummary(focusGroups.packing);
1538
+ }
1458
1539
  applyContextFocusProjection(result, runtime.focusFields);
1459
1540
  if (warnings.length > 0)
1460
1541
  result.warnings = warnings;
1461
1542
  maybeAttachEmptyContextSuggestions(result, focusGroups.activeItems, focusGroups.blockedItems);
1543
+ await attachContextUsageFeedback(result, focusGroups, pmRoot, author);
1462
1544
  return result;
1463
1545
  }
1464
1546
  //# sourceMappingURL=context.js.map
1465
- //# debugId=a1564ad2-3e32-5b66-9327-7ff92b7aee37
1547
+ //# debugId=7563a6df-9229-5af9-9849-85a058c01a46