@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
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../cli/commands/aggregate.ts","../../../../../../../../cli/commands/search.ts","../../../../../../../../core/shared/text-normalization.ts","../../../../../../../../core/search/relevance.ts","../../../../../../../../core/search/bm25.ts","../../../../../../../../cli/commands/search-rendering.ts","../../../../../../../../cli/commands/search-pagination.ts","../../../../../../../../cli/commands/eval.ts","../../../../../../../../core/search/eval.ts","../../../../../../../../cli/commands/get.ts"],"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","/**\n * @module cli/commands/search\n *\n * Implements the pm search command surface and its agent-facing runtime behavior.\n */\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n coerceNumberInRange,\n toNonEmptyStringOrUndefined,\n} from \"../../core/shared/primitives.js\";\nimport { isPathWithinDirectory } from \"../../core/fs/path-utils.js\";\nimport {\n getActiveExtensionRegistrations,\n runActiveOnReadHooks,\n} from \"../../core/extensions/index.js\";\nimport { collectRegisteredItemFieldNames } from \"../../core/extensions/item-fields.js\";\nimport {\n resolveRegisteredSearchProvider,\n resolveRegisteredVectorStoreAdapter,\n} from \"../../core/extensions/runtime-registrations.js\";\nimport {\n resolveItemTypeRegistry,\n type ItemTypeRegistry,\n} from \"../../core/item/type-registry.js\";\nimport { parseLimit, parsePriority, parseType } from \"../shared-parsers.js\";\nimport {\n executeEmbeddingRequest,\n resolveEmbeddingProviders,\n type EmbeddingProviderConfig,\n type EmbeddingProviderResolution,\n} from \"../../core/search/providers.js\";\nimport {\n buildDeterministicQueryExpansions,\n mergeQueryExpansions,\n normalizeQueryExpansionOutput,\n normalizeRerankOutput,\n rerankCandidatesWithEmbeddings,\n resolveQueryExpansionConfig,\n resolveRerankConfig,\n type QueryExpansionConfig,\n type RerankCandidate,\n type RerankConfig,\n} from \"../../core/search/relevance.js\";\nimport { resolveSettingsWithSemanticRuntimeDefaults } from \"../../core/search/semantic-defaults.js\";\nimport {\n executeVectorQuery,\n resolveVectorStores,\n type VectorQueryHit,\n type VectorStoreConfig,\n type VectorStoreResolution,\n} from \"../../core/search/vector-stores.js\";\nimport { readVectorizationStatusLedger } from \"../../core/search/cache.js\";\nimport {\n buildEventCorpus,\n buildPlanFlatCorpus,\n buildReminderCorpus,\n buildSearchCorpus,\n resolveSearchCorpusFields,\n} from \"../../core/search/corpus.js\";\nimport {\n buildBm25Index,\n flattenSearchCorpusText,\n resolveBm25Params,\n scoreBm25Query,\n tokenizeBm25,\n type Bm25Params,\n} from \"../../core/search/bm25.js\";\nimport { collectStaleVectorizationIds } from \"../../core/search/staleness.js\";\nimport { pathExists } from \"../../core/fs/fs-utils.js\";\nimport { parseItemDocument } from \"../../core/item/item-format.js\";\nimport { toItemRecord } from \"../../core/item/item-record.js\";\nimport { isTerminalStatus } from \"../../core/item/status.js\";\nimport { parseStatusFilterCsv } from \"../../core/item/status-filter.js\";\nimport {\n collectRuntimeFilterValues,\n matchesRuntimeFilters,\n} from \"../../core/schema/runtime-field-filters.js\";\nimport {\n hasMissingMetadataFilter,\n itemMatchesMissingMetadata,\n lifecycleClassifierFromStatusRegistry,\n type LifecycleClassifier,\n} from \"../../core/governance/metadata-coverage.js\";\nimport {\n hasContentFieldFilter,\n itemMatchesContentFilters,\n} from \"../../core/governance/content-fields.js\";\nimport { resolveContentFieldFilters, resolveMissingMetadataFilters } from \"./list.js\";\nimport {\n buildCompactSearchFilterSummary,\n buildVerboseSearchFilters,\n type SearchMode,\n} from \"./search-rendering.js\";\nimport {\n resolveRuntimeFieldRegistry,\n resolveRuntimeStatusRegistry,\n type RuntimeFieldRegistry,\n type RuntimeStatusRegistry,\n} from \"../../core/schema/runtime-schema.js\";\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 { tokenizeAlphaNumeric } from \"../../core/shared/text-normalization.js\";\nimport {\n compareTimestampStrings,\n matchesTimestampFilters,\n nowIso,\n resolveIsoOrRelative,\n} from \"../../core/shared/time.js\";\nimport { listAllDocumentCandidatesCached } from \"../../core/store/item-metadata-cache.js\";\nimport { listAllItemMetadata } from \"../../core/store/item-store.js\";\nimport {\n getItemPath,\n getSettingsPath,\n resolveGlobalPmRoot,\n resolvePmRoot,\n} from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport type {\n ItemDocument,\n ItemFormat,\n ItemMetadata,\n ItemStatus,\n ItemType,\n PmSettings,\n} from \"../../types/index.js\";\nimport type { SharedItemFilterOptions } from \"./item-filter-options.js\";\nimport { resolveSearchPage } from \"./search-pagination.js\";\n\n/** Documents the search options payload exchanged by command, SDK, and package integrations. */\nexport interface SearchOptions extends SharedItemFilterOptions {\n /** Value that configures or reports mode for this contract. */\n mode?: string;\n /** Strategy used to control match behavior. */\n matchMode?: string;\n /** Value that configures or reports min score for this contract. */\n minScore?: string | number;\n /** Value that configures or reports count for this contract. */\n count?: boolean;\n /** Value that configures or reports semantic weight for this contract. */\n semanticWeight?: string | number;\n /** Value that configures or reports include linked for this contract. */\n includeLinked?: boolean;\n /** Value that configures or reports title exact for this contract. */\n titleExact?: boolean;\n /** Value that configures or reports phrase exact for this contract. */\n phraseExact?: boolean;\n /** Value that configures or reports limit for this contract. */\n limit?: string;\n /** Opaque cursor returned by a previous search page. */\n after?: string;\n /** Value that configures or reports compact for this contract. */\n compact?: boolean;\n /** Value that configures or reports full for this contract. */\n full?: boolean;\n /** Value that configures or reports fields for this contract. */\n fields?: string;\n // GH-157: emit per-field matched-text snippets on each hit (off by default for\n // token efficiency). Highlighted spans are wrapped with the «…» markers.\n /** Value that configures or reports highlight for this contract. */\n highlight?: boolean;\n}\n\n/** Restricts search match mode values accepted by command, SDK, and storage contracts. */\nexport type SearchMatchMode = \"and\" | \"or\" | \"exact\";\n\ntype SearchProjectionMode = \"compact\" | \"full\" | \"fields\";\n\ninterface SearchProjectionConfig {\n mode: SearchProjectionMode;\n fields: string[];\n}\n\nconst DEFAULT_COMPACT_SEARCH_FIELDS = [\n \"id\",\n \"title\",\n \"status\",\n \"type\",\n \"priority\",\n \"updated_at\",\n \"score\",\n \"matched_fields\",\n] as const;\n\nconst SEARCH_HIT_FIELD_KEYS = new Set([\n \"score\",\n \"matched_fields\",\n \"highlights\",\n]);\nconst SEARCH_ITEM_FIELD_KEYS = new Set([\n \"id\",\n \"title\",\n \"description\",\n \"type\",\n \"status\",\n \"priority\",\n \"tags\",\n \"created_at\",\n \"updated_at\",\n \"deadline\",\n \"assignee\",\n \"author\",\n \"estimated_minutes\",\n \"acceptance_criteria\",\n \"dependencies\",\n \"comments\",\n \"notes\",\n \"learnings\",\n \"reminders\",\n \"events\",\n \"files\",\n \"tests\",\n \"docs\",\n \"close_reason\",\n \"parent\",\n \"reviewer\",\n \"risk\",\n \"confidence\",\n \"sprint\",\n \"release\",\n \"blocked_by\",\n \"blocked_reason\",\n \"reporter\",\n \"severity\",\n \"environment\",\n \"repro_steps\",\n \"resolution\",\n \"expected_result\",\n \"actual_result\",\n \"affected_version\",\n \"fixed_version\",\n \"component\",\n \"regression\",\n \"customer_impact\",\n \"definition_of_ready\",\n \"order\",\n \"rank\",\n \"goal\",\n \"objective\",\n \"value\",\n \"impact\",\n \"outcome\",\n \"why_now\",\n \"plan\",\n]);\n\nconst LONG_QUERY_TOKEN_THRESHOLD = 2;\nconst LONG_QUERY_TITLE_EXACT_BONUS = 120;\nconst LONG_QUERY_PHRASE_MULTIPLIER = 6;\n// GH-181: in default (OR) match mode, multi-token queries that match EVERY\n// distinct query token in some searchable field get an additive ranking bonus so\n// items covering all terms outrank items matching only a subset. This is a\n// RANKING preference, not a hard filter (use --match-mode and for that).\nconst ALL_TERMS_COVERAGE_BONUS = 40;\nconst EXACT_ID_MATCH_SCORE = 1_000;\nconst SHORT_ID_MATCH_SCORE = 900;\n\n// GH-157 matched-text highlighting (--highlight): markers wrapping each matching\n// token run, and the number of characters of surrounding context retained on\n// each side of the first match in a field. The «…» guillemets are single\n// characters with negligible collision risk against item text, keeping the\n// snippet token-cheap while staying visually unambiguous for agents.\nconst HIGHLIGHT_OPEN = \"«\";\nconst HIGHLIGHT_CLOSE = \"»\";\nconst HIGHLIGHT_SNIPPET_RADIUS = 60;\n\n// GH-157 inline query syntax: bare `field:value` tokens parsed out of the query\n// string and applied as the equivalent filter. The value may itself contain\n// colons (e.g. `tag:area:search`), so only the FIRST colon delimits field from\n// value. Explicit --field flags take precedence over an inline token (see\n// resolveInlineQueryFilters).\nconst INLINE_QUERY_FILTER_FIELDS = [\n \"tag\",\n \"status\",\n \"type\",\n \"priority\",\n] as const;\ntype InlineQueryFilterField = (typeof INLINE_QUERY_FILTER_FIELDS)[number];\n\n/** Documents the search hit payload exchanged by command, SDK, and package integrations. */\nexport interface SearchHit {\n /** Value that configures or reports item for this contract. */\n item: ItemMetadata;\n /** Value that configures or reports score for this contract. */\n score: number;\n /** Value that configures or reports matched fields for this contract. */\n matched_fields: string[];\n // GH-181: whether every distinct query token matched some searchable field.\n // Used by --match-mode and (hard filter) and the default all-terms ranking\n // bonus. Not projected into output rows.\n /** Value that configures or reports matched all terms for this contract. */\n matched_all_terms?: boolean;\n // GH-281: marks the keyword hit produced by the exact full-ID / short-ID\n // early-return in scoreDocument(). The semantic & hybrid ranking paths use it\n // to guarantee the exact-ID target ALWAYS ranks #1 (and is exempt from the\n // score threshold / limit), so the keyword-mode exact-ID guarantee is never\n // lost once vector blending is active. SHORT_ID matches keep score=900 and\n // full-ID matches keep score=1000, so sortHits still orders full above short.\n // Not projected into output rows.\n /** Value that configures or reports exact id match for this contract. */\n exact_id_match?: boolean;\n // GH-157: per-field matched-text snippets, populated only when the caller\n // passes --highlight. Each entry pairs a matched field name with a snippet of\n // its text where the matching token runs are wrapped in the «…» markers.\n /** Value that configures or reports highlights for this contract. */\n highlights?: SearchHitHighlight[];\n}\n\n/**\n * Pairs a matched field name with a snippet of its text where every matching\n * token run is wrapped in the {@link HIGHLIGHT_OPEN}/{@link HIGHLIGHT_CLOSE}\n * markers. Emitted on {@link SearchHit.highlights} when `--highlight` is set.\n */\nexport interface SearchHitHighlight {\n /** Value that configures or reports field for this contract. */\n field: string;\n /** Value that configures or reports snippet for this contract. */\n snippet: string;\n}\n\n/** Restricts search result item values accepted by command, SDK, and storage contracts. */\nexport type SearchResultItem = SearchHit | Record<string, unknown>;\n\ninterface SearchResultBase {\n query: string;\n mode: SearchMode;\n items: SearchResultItem[];\n count: number;\n // GH-181: total matched hits after filters/threshold but BEFORE the limit\n // truncation. Lets callers see how many matched before the (now-default)\n // keyword limit dropped rows. Only emitted when it differs from count.\n total?: number;\n /** Whether additional ranked hits remain after this page. */\n has_more?: boolean;\n /** Opaque continuation cursor when additional hits remain. */\n next_cursor?: string;\n /** Effective page size for this response. */\n applied_limit?: number;\n /** Explicit marker that the response is a bounded page. */\n truncated?: true;\n // --count mode: count-only response carries the matched total and skips the\n // hit rows entirely (items is empty). `count` reflects the same total.\n count_only?: boolean;\n warnings?: string[];\n}\n\n/** Documents the search compact result payload exchanged by command, SDK, and package integrations. */\nexport interface SearchCompactResult extends SearchResultBase {\n /** Value that configures or reports filters for this contract. */\n filters: Record<string, unknown>;\n /** Value that configures or reports projection for this contract. */\n projection?: undefined;\n /** Value that configures or reports now for this contract. */\n now?: undefined;\n}\n\n/** Documents the search verbose result payload exchanged by command, SDK, and package integrations. */\nexport interface SearchVerboseResult extends SearchResultBase {\n /** Value that configures or reports filters for this contract. */\n filters: Record<string, unknown>;\n /** Value that configures or reports projection for this contract. */\n projection: {\n mode: SearchProjectionMode;\n fields: string[] | null;\n };\n /** Value that configures or reports now for this contract. */\n now: string;\n}\n\n/** Restricts search result values accepted by command, SDK, and storage contracts. */\nexport type SearchResult = SearchCompactResult | SearchVerboseResult;\n\ninterface ExtensionSearchProviderContext {\n query: string;\n mode: SearchMode;\n tokens: string[];\n options: SearchOptions;\n settings: PmSettings;\n documents: ItemDocument[];\n}\n\ninterface ExtensionSearchProviderHit {\n id: string;\n score: number;\n matched_fields?: string[];\n}\n\ntype ExtensionSearchProviderQuery = (\n context: ExtensionSearchProviderContext,\n) =>\n | Promise<\n ExtensionSearchProviderHit[] | { hits?: ExtensionSearchProviderHit[] }\n >\n | ExtensionSearchProviderHit[]\n | { hits?: ExtensionSearchProviderHit[] };\n\ninterface ExtensionSearchProviderQueryExpansionContext {\n query: string;\n mode: Exclude<SearchMode, \"keyword\">;\n settings: PmSettings;\n}\n\ntype ExtensionSearchProviderQueryExpansion = (\n context: ExtensionSearchProviderQueryExpansionContext,\n) =>\n | Promise<string[] | { queries?: string[] }>\n | string[]\n | { queries?: string[] };\n\ninterface ExtensionSearchProviderRerankCandidate {\n id: string;\n text: string;\n score: number;\n}\n\ninterface ExtensionSearchProviderRerankContext {\n query: string;\n mode: \"hybrid\";\n model: string;\n top_k: number;\n settings: PmSettings;\n candidates: ExtensionSearchProviderRerankCandidate[];\n}\n\ntype ExtensionSearchProviderRerank = (\n context: ExtensionSearchProviderRerankContext,\n) =>\n | Promise<\n | Array<{ id?: unknown; score?: unknown }>\n | { hits?: Array<{ id?: unknown; score?: unknown }> }\n >\n | Array<{ id?: unknown; score?: unknown }>\n | { hits?: Array<{ id?: unknown; score?: unknown }> };\n\ntype ExtensionVectorQuery = (context: {\n vector: number[];\n limit: number;\n settings: PmSettings;\n}) => Promise<VectorQueryHit[]> | VectorQueryHit[];\n\ntype ExtensionVectorUpsert = (context: {\n points: Array<{\n id: string;\n vector: number[];\n payload: Record<string, unknown>;\n }>;\n settings: PmSettings;\n}) => Promise<void> | void;\n\ntype ExtensionVectorAdapter = {\n adapterName: string;\n query?: ExtensionVectorQuery;\n upsert?: ExtensionVectorUpsert;\n};\n\ninterface SearchModeContext {\n hasProvider: boolean;\n hasVectorStore: boolean;\n}\n\ntype ImplicitSemanticFallbackReason = \"timeout\" | \"connection\" | \"error\";\n\n/**\n * Aggregate the `code` strings found along an error's `cause` chain.\n *\n * undici (Node's fetch) collapses connection errors to the generic message\n * \"fetch failed\" and stashes the real syscall code (e.g. `ECONNREFUSED`) on\n * `error.cause.code`. Walking the chain (bounded depth) lets the fallback\n * classifier label a downed/unreachable Ollama backend as \"connection\" rather\n * than the catch-all \"error\".\n */\nexport function collectErrorCauseCodes(error: unknown): string {\n const codes: string[] = [];\n let current: unknown = error;\n for (\n let depth = 0;\n depth < 5 && current && typeof current === \"object\";\n depth += 1\n ) {\n const code = (current as { code?: unknown }).code;\n if (typeof code === \"string\") {\n codes.push(code.toLowerCase());\n }\n current = (current as { cause?: unknown }).cause;\n }\n return codes.join(\" \");\n}\n\n/**\n * Classify why an implicit/explicit semantic search degraded to keyword mode,\n * inspecting both the error message and the {@link collectErrorCauseCodes} chain\n * so undici's generic \"fetch failed\" is recognised as a connection failure.\n */\nexport function classifyImplicitSemanticFallbackReason(\n error: unknown,\n): ImplicitSemanticFallbackReason {\n const message = (\n error instanceof Error ? error.message : String(error)\n ).toLowerCase();\n const causeCodes = collectErrorCauseCodes(error);\n const haystack = `${message} ${causeCodes}`;\n if (\n haystack.includes(\"timed out\") ||\n haystack.includes(\"timeout\") ||\n haystack.includes(\"etimedout\")\n ) {\n return \"timeout\";\n }\n if (\n haystack.includes(\"econnrefused\") ||\n haystack.includes(\"connection refused\") ||\n haystack.includes(\"connect \") ||\n haystack.includes(\"enotfound\") ||\n haystack.includes(\"eai_again\") ||\n haystack.includes(\"econnreset\") ||\n haystack.includes(\"fetch failed\")\n ) {\n return \"connection\";\n }\n return \"error\";\n}\n\n// Explicit --semantic/--hybrid searches must never hard-fail an agent when the\n// embedding/vector backend is unreachable or unconfigured: degrade to keyword\n// search and surface a machine-readable warning instead of an unknown_error.\nfunction buildExplicitSemanticFallbackWarning(\n requestedMode: SearchMode,\n error: unknown,\n): string {\n const reason = classifyImplicitSemanticFallbackReason(error);\n return `search_${requestedMode}_fallback:${reason}:using_keyword_mode`;\n}\n\n/** Compare the vectorization-status ledger against the filtered corpus and, when the vector index is behind, emit a one-line stderr warning plus a structured `vector_index_stale:N` entry in the JSON warnings array. Best-effort: ledger read failures fall through silently — the existing semantic/hybrid fallback paths cover backend errors. */\nasync function maybeEmitVectorIndexStaleWarning(\n pmRoot: string,\n filteredDocuments: ItemDocument[],\n warnings: string[],\n): Promise<void> {\n try {\n const ledger = await readVectorizationStatusLedger(pmRoot);\n if (ledger.warnings.length > 0) {\n warnings.push(...ledger.warnings);\n }\n const staleIds = collectStaleVectorizationIds(\n filteredDocuments.map((document) => ({\n id: document.metadata.id,\n updated_at: document.metadata.updated_at,\n })),\n ledger.entries,\n );\n if (staleIds.length === 0) {\n return;\n }\n warnings.push(`vector_index_stale:${staleIds.length}`);\n /* c8 ignore start -- singular/plural warning text branches are cosmetic and validated in integration UX tests */\n process.stderr.write(\n `[pm] warning: ${staleIds.length} item${staleIds.length === 1 ? \" is\" : \"s are\"} new or modified since the last reindex and ${staleIds.length === 1 ? \"is\" : \"are\"} NOT in the semantic index yet — they will be missing from semantic/hybrid results until you run 'pm reindex --mode hybrid'. (Write-time embedding is governed by search.mutation_refresh_policy; staleness means the embed was skipped, failed, or the backend was unreachable.)\\n`,\n );\n /* c8 ignore stop */\n } catch {\n // Best-effort: missing/unreadable ledger is not a query-blocking concern.\n }\n}\n\nfunction parseMode(\n raw: string | undefined,\n _context: SearchModeContext,\n): SearchMode {\n if (raw === undefined) {\n return \"keyword\";\n }\n const normalized = raw.trim().toLowerCase();\n if (\n normalized !== \"keyword\" &&\n normalized !== \"semantic\" &&\n normalized !== \"hybrid\"\n ) {\n throw new PmCliError(\n \"Search mode must be one of keyword|semantic|hybrid\",\n EXIT_CODE.USAGE,\n );\n }\n return normalized;\n}\n\nfunction parseIncludeLinked(raw: boolean | undefined): boolean {\n return raw === true;\n}\n\nfunction parseTitleExact(raw: boolean | undefined): boolean {\n return raw === true;\n}\n\nfunction parsePhraseExact(raw: boolean | undefined): boolean {\n return raw === true;\n}\n\nfunction parseSemanticWeightOverride(raw: unknown): number | undefined {\n return coerceNumberInRange(raw, 0, 1) ?? undefined;\n}\n\nfunction parseMatchMode(raw: string | undefined): SearchMatchMode {\n if (raw === undefined) {\n return \"or\";\n }\n const normalized = raw.trim().toLowerCase();\n if (normalized !== \"and\" && normalized !== \"or\" && normalized !== \"exact\") {\n throw new PmCliError(\n \"Search --match-mode must be one of and|or|exact\",\n EXIT_CODE.USAGE,\n );\n }\n return normalized;\n}\n\n// Per-query --min-score overrides the persistent search.score_threshold for this\n// query only. Accepts a finite number >= 0; anything else is a usage error.\nfunction parseMinScoreOverride(raw: unknown): number | undefined {\n if (raw === undefined || raw === null || raw === \"\") {\n return undefined;\n }\n /* c8 ignore start -- numeric-vs-string coercion branch is exercised via integration CLI parsing */\n const parsed = typeof raw === \"number\" ? raw : Number(String(raw).trim());\n /* c8 ignore stop */\n if (!Number.isFinite(parsed) || parsed < 0) {\n throw new PmCliError(\n \"Search --min-score must be a finite number >= 0\",\n EXIT_CODE.USAGE,\n );\n }\n return parsed;\n}\n\n// updated/created date-window filters share the deadline ISO+relative resolver\n// so `pm search` matches `pm list` semantics exactly: pass an ISO timestamp or a\n// SIGNED relative offset (\"-2h\"/\"-7d\" reach into the past, \"+1d\" the future;\n// units h/d/w/m, m = months — there is no minutes unit).\nfunction parseTimestampWindow(\n raw: unknown,\n fieldLabel: string,\n): string | undefined {\n if (raw == null) return undefined;\n const value = String(raw).trim();\n if (value.length === 0) return undefined;\n return resolveIsoOrRelative(value, new Date(), fieldLabel);\n}\n\nfunction normalizeSearchPhrase(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\nfunction parseDeadline(\n raw: string | undefined,\n fieldLabel: string,\n): string | undefined {\n if (raw === undefined) return undefined;\n return resolveIsoOrRelative(raw, new Date(), fieldLabel);\n}\n\nfunction parseFieldSelectors(raw: string | undefined): string[] | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const selectors = raw\n .split(\",\")\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n if (selectors.length === 0) {\n throw new PmCliError(\n \"Search --fields requires a comma-separated list of field names\",\n EXIT_CODE.USAGE,\n );\n }\n return [...new Set(selectors)];\n}\n\nfunction parseProjectionConfig(options: SearchOptions): SearchProjectionConfig {\n const compactRequested = options.compact === true;\n const fullRequested = options.full === true;\n const fieldSelectors = parseFieldSelectors(options.fields);\n const enabledModes =\n Number(compactRequested) +\n Number(fullRequested) +\n Number(fieldSelectors !== undefined);\n if (enabledModes > 1) {\n throw new PmCliError(\n \"Search projection options are mutually exclusive. Use one of --compact, --full, or --fields.\",\n EXIT_CODE.USAGE,\n );\n }\n if (compactRequested) {\n return {\n mode: \"compact\",\n fields: [...DEFAULT_COMPACT_SEARCH_FIELDS],\n };\n }\n if (fullRequested) {\n return {\n mode: \"full\",\n fields: [],\n };\n }\n if (fieldSelectors) {\n return {\n mode: \"fields\",\n fields: fieldSelectors,\n };\n }\n return {\n mode: \"full\",\n fields: [],\n };\n}\n\n/** Public contract for test only search command, shared by SDK and presentation-layer consumers. */\nexport const _testOnlySearchCommand = {\n applyFilters,\n applyExactQueryFilters,\n applyInlineQueryFilters,\n buildHitHighlights,\n buildVerboseSearchFilters,\n buildExplicitSemanticFallbackWarning,\n buildCompactSearchFilterSummary,\n buildHybridLexicalScore,\n buildRerankCorpus,\n buildSemanticHits,\n classifyImplicitSemanticFallbackReason,\n collectErrorCauseCodes,\n collectExactPhraseFields,\n collectLinkedPaths,\n combineHybridHits,\n computeBuiltInBm25Hits,\n computeSemanticOrHybridHits,\n resolveBuiltInBm25Mode,\n countOccurrences,\n dependencyEntries,\n documentContainsExactPhrase,\n emptySearchResult,\n highlightFieldSnippet,\n loadDocuments,\n markTokenRuns,\n parseInlineQueryFilters,\n maybeEmitVectorIndexStaleWarning,\n loadLinkedCorpus,\n mergeVectorHitsById,\n normalizeExtensionProviderHits,\n normalizeScoreMap,\n parseProjectionConfig,\n parseTimestampWindow,\n parseTokens,\n readSearchFieldValue,\n requireSemanticDependencies,\n resolveExtensionSearchProvider,\n resolveExtensionSearchProviderByName,\n resolveExtensionVectorAdapter,\n resolveLinkedCorpusRoots,\n scoreDocument,\n sortHits,\n stringArray,\n textEntries,\n validateSearchProjectionFields,\n};\n\n/* c8 ignore start -- projection/runtime-field validation edge permutations are covered by integration query-contract tests */\nfunction validateSearchProjectionFields(\n projection: SearchProjectionConfig,\n runtimeFieldRegistry: RuntimeFieldRegistry,\n): void {\n if (projection.mode !== \"fields\") {\n return;\n }\n const runtimeKeys = new Set(\n runtimeFieldRegistry.definitions.flatMap((field) => [\n field.key,\n field.metadata_key,\n ]),\n );\n const unknown = projection.fields.filter((field) => {\n const normalized = field.trim();\n const itemKey = normalized.startsWith(\"item.\")\n ? normalized.slice(\"item.\".length)\n : normalized;\n return (\n !SEARCH_HIT_FIELD_KEYS.has(normalized) &&\n !SEARCH_ITEM_FIELD_KEYS.has(itemKey) &&\n !runtimeKeys.has(itemKey)\n );\n });\n if (unknown.length > 0) {\n throw new PmCliError(\n `Unknown search --fields value(s): ${unknown.join(\", \")}`,\n EXIT_CODE.USAGE,\n {\n examples: [\n \"pm search <query> --fields id,title,status,score\",\n \"pm search <query> --fields id,title,item.description,matched_fields\",\n ],\n nextSteps: [\n \"Use item.<field> for explicit item metadata fields, or run pm search --help for projection examples.\",\n ],\n },\n );\n }\n}\n/* c8 ignore stop */\n\nfunction parseTokens(query: string): string[] {\n const normalized = normalizeSearchPhrase(query);\n if (!normalized) {\n throw new PmCliError(\"Search query must not be empty\", EXIT_CODE.USAGE);\n }\n return normalized.split(/\\s+/).filter(Boolean);\n}\n\n/** Result of extracting inline `field:value` tokens from a raw search query. */\ninterface InlineQueryParse {\n /** The query with all recognized inline filter tokens removed. */\n residualQuery: string;\n /** Recognized inline filters keyed by field name; first occurrence per field wins. */\n inlineFilters: Partial<Record<InlineQueryFilterField, string>>;\n}\n\n/**\n * Split a raw search query into its residual keyword text and any inline\n * `field:value` filter tokens (GH-157). Recognized fields are\n * {@link INLINE_QUERY_FILTER_FIELDS}; the value runs to the end of the token so\n * colon-bearing values like `tag:area:search` parse as `{ tag: \"area:search\" }`.\n * Only the first occurrence of each field is captured — later duplicates are left\n * in the residual query so they are never silently dropped. Tokens whose prefix\n * is not a recognized field (`foo:bar`) stay in the residual query verbatim.\n */\nfunction parseInlineQueryFilters(query: string): InlineQueryParse {\n const inlineFilters: Partial<Record<InlineQueryFilterField, string>> = {};\n const residualTokens: string[] = [];\n for (const token of query.split(/\\s+/).filter((entry) => entry.length > 0)) {\n const separatorIndex = token.indexOf(\":\");\n const field =\n separatorIndex > 0 ? token.slice(0, separatorIndex).toLowerCase() : \"\";\n const value = separatorIndex > 0 ? token.slice(separatorIndex + 1) : \"\";\n const matchedField = (\n INLINE_QUERY_FILTER_FIELDS as ReadonlyArray<string>\n ).includes(field)\n ? (field as InlineQueryFilterField)\n : undefined;\n if (\n matchedField &&\n value.length > 0 &&\n inlineFilters[matchedField] === undefined\n ) {\n inlineFilters[matchedField] = value;\n continue;\n }\n residualTokens.push(token);\n }\n return {\n residualQuery: residualTokens.join(\" \"),\n inlineFilters,\n };\n}\n\n/** Merge inline `field:value` filters into a search options object (GH-157). Explicit `--field` flags always win: an inline token is applied only when the corresponding option is not already set, and a conflicting inline token is recorded as a `search_inline_filter_ignored:<field>:flag_takes_precedence` warning so the override is observable rather than silent. Returns a fresh options object — the caller's input is never mutated. */\nfunction applyInlineQueryFilters(\n options: SearchOptions,\n inlineFilters: Partial<Record<InlineQueryFilterField, string>>,\n warnings: string[],\n): SearchOptions {\n const merged: SearchOptions = { ...options };\n for (const field of INLINE_QUERY_FILTER_FIELDS) {\n const inlineValue = inlineFilters[field];\n if (inlineValue === undefined) {\n continue;\n }\n if (toNonEmptyStringOrUndefined(merged[field]) !== undefined) {\n warnings.push(\n `search_inline_filter_ignored:${field}:flag_takes_precedence`,\n );\n continue;\n }\n merged[field] = inlineValue;\n }\n return merged;\n}\n\nfunction stringArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((entry): entry is string => typeof entry === \"string\")\n : [];\n}\n\nfunction textEntries(value: unknown): Array<{ text: string }> {\n return Array.isArray(value)\n ? value.filter(\n (entry): entry is { text: string } =>\n typeof entry === \"object\" &&\n entry !== null &&\n typeof (entry as { text?: unknown }).text === \"string\",\n )\n : [];\n}\n\nfunction dependencyEntries(\n value: unknown,\n): Array<{ id: string; kind: string }> {\n return Array.isArray(value)\n ? value.filter(\n (entry): entry is { id: string; kind: string } =>\n typeof entry === \"object\" &&\n entry !== null &&\n typeof (entry as { id?: unknown }).id === \"string\" &&\n typeof (entry as { kind?: unknown }).kind === \"string\",\n )\n : [];\n}\n\nfunction collectExactPhraseFields(document: ItemDocument): string[] {\n const item = document.metadata;\n return [\n item.title,\n item.description,\n item.status,\n stringArray(item.tags).join(\" \"),\n document.body,\n textEntries(item.comments)\n .map((entry) => entry.text)\n .join(\" \"),\n textEntries(item.notes)\n .map((entry) => entry.text)\n .join(\" \"),\n textEntries(item.learnings)\n .map((entry) => entry.text)\n .join(\" \"),\n buildReminderCorpus(item).join(\" \"),\n buildEventCorpus(item).join(\" \"),\n dependencyEntries(item.dependencies)\n .map((entry) => `${entry.id} ${entry.kind}`)\n .join(\" \"),\n buildPlanFlatCorpus(item),\n ];\n}\n\nfunction documentContainsExactPhrase(\n document: ItemDocument,\n normalizedQuery: string,\n): boolean {\n return collectExactPhraseFields(document).some((fieldValue) =>\n normalizeSearchPhrase(fieldValue).includes(normalizedQuery),\n );\n}\n\nfunction applyExactQueryFilters(\n items: ItemDocument[],\n normalizedQuery: string,\n options: { titleExact: boolean; phraseExact: boolean },\n): ItemDocument[] {\n if (!options.titleExact && !options.phraseExact) {\n return items;\n }\n return items.filter((document) => {\n if (\n options.titleExact &&\n normalizeSearchPhrase(document.metadata.title) !== normalizedQuery\n ) {\n return false;\n }\n if (\n options.phraseExact &&\n !documentContainsExactPhrase(document, normalizedQuery)\n ) {\n return false;\n }\n return true;\n });\n}\n\ntype SearchMissingMetadataFilters = ReturnType<\n typeof resolveMissingMetadataFilters\n>;\ntype SearchContentFieldFilters = ReturnType<typeof resolveContentFieldFilters>;\n\ninterface SearchMetadataFilterSet {\n typeFilter: ItemType | undefined;\n tagFilter: string | undefined;\n priorityFilter: number | undefined;\n deadlineBefore: string | undefined;\n deadlineAfter: string | undefined;\n updatedAfter: string | undefined;\n updatedBefore: string | undefined;\n createdAfter: string | undefined;\n createdBefore: string | undefined;\n assigneeFilter: string | undefined;\n sprintFilter: string | undefined;\n releaseFilter: string | undefined;\n parentFilter: string | undefined;\n statusSet: Set<ItemStatus> | undefined;\n missingMetadataFilters: SearchMissingMetadataFilters;\n missingMetadataActive: boolean;\n contentFieldFilters: SearchContentFieldFilters;\n contentFiltersActive: boolean;\n}\n\nfunction assertSearchAssigneeFilter(assigneeFilter: string | undefined): void {\n // Match pm list: --assignee no longer accepts none/null (unassigned filtering\n // belongs to a dedicated flag there; pm search has no presence flag so reject\n // the sentinel values explicitly rather than silently matching a literal).\n if (\n assigneeFilter &&\n (assigneeFilter.toLowerCase() === \"none\" ||\n assigneeFilter.toLowerCase() === \"null\")\n ) {\n throw new PmCliError(\n '--assignee no longer accepts \"none\" or \"null\".',\n EXIT_CODE.USAGE,\n );\n }\n}\n\nfunction resolveSearchMetadataFilterSet(\n options: SearchOptions,\n typeRegistry: ItemTypeRegistry,\n statusFilter: ItemStatus[] | undefined,\n): SearchMetadataFilterSet {\n const assigneeFilter = options.assignee?.trim();\n assertSearchAssigneeFilter(assigneeFilter);\n const missingMetadataFilters = resolveMissingMetadataFilters(options);\n const contentFieldFilters = resolveContentFieldFilters(\n options as Record<string, unknown>,\n );\n return {\n typeFilter: parseType(options.type, typeRegistry),\n tagFilter: options.tag?.trim().toLowerCase(),\n priorityFilter: parsePriority(options.priority),\n deadlineBefore: parseDeadline(options.deadlineBefore, \"deadline-before\"),\n deadlineAfter: parseDeadline(options.deadlineAfter, \"deadline-after\"),\n updatedAfter: parseTimestampWindow(options.updatedAfter, \"updated-after\"),\n updatedBefore: parseTimestampWindow(\n options.updatedBefore,\n \"updated-before\",\n ),\n createdAfter: parseTimestampWindow(options.createdAfter, \"created-after\"),\n createdBefore: parseTimestampWindow(\n options.createdBefore,\n \"created-before\",\n ),\n assigneeFilter,\n sprintFilter: options.sprint?.trim(),\n releaseFilter: options.release?.trim(),\n parentFilter: options.parent?.trim(),\n statusSet:\n statusFilter && statusFilter.length > 0\n ? new Set<ItemStatus>(statusFilter)\n : undefined,\n missingMetadataFilters,\n missingMetadataActive: hasMissingMetadataFilter(missingMetadataFilters),\n contentFieldFilters,\n contentFiltersActive: hasContentFieldFilter(contentFieldFilters),\n };\n}\n\nfunction matchesScalarSearchFilters(\n item: ItemMetadata,\n filters: SearchMetadataFilterSet,\n): boolean {\n return (\n matchesIdentitySearchFilters(item, filters) &&\n matchesTimestampSearchFilters(item, filters) &&\n matchesOwnerSearchFilters(item, filters)\n );\n}\n\nfunction matchesIdentitySearchFilters(\n item: ItemMetadata,\n filters: SearchMetadataFilterSet,\n): boolean {\n if (filters.statusSet && !filters.statusSet.has(item.status)) return false;\n if (filters.typeFilter && item.type !== filters.typeFilter) return false;\n if (filters.tagFilter && !stringArray(item.tags).includes(filters.tagFilter))\n return false;\n if (\n filters.priorityFilter !== undefined &&\n item.priority !== filters.priorityFilter\n )\n return false;\n return true;\n}\n\nfunction matchesTimestampSearchFilters(\n item: ItemMetadata,\n filters: SearchMetadataFilterSet,\n): boolean {\n return matchesTimestampFilters(item, filters);\n}\n\nfunction matchesOwnerSearchFilters(\n item: ItemMetadata,\n filters: SearchMetadataFilterSet,\n): boolean {\n if (\n filters.assigneeFilter !== undefined &&\n item.assignee !== filters.assigneeFilter\n )\n return false;\n if (\n filters.sprintFilter !== undefined &&\n item.sprint !== filters.sprintFilter\n )\n return false;\n /* c8 ignore start -- release/parent metadata filter combinations are covered by integration search fixtures */\n if (\n filters.releaseFilter !== undefined &&\n item.release !== filters.releaseFilter\n )\n return false;\n if (\n filters.parentFilter !== undefined &&\n item.parent !== filters.parentFilter\n )\n return false;\n /* c8 ignore stop */\n return true;\n}\n\nfunction matchesSearchMetadataFilters(\n document: ItemDocument,\n filters: SearchMetadataFilterSet,\n runtimeFieldFilters: Record<string, unknown>,\n lifecycleClassifier: LifecycleClassifier,\n): boolean {\n const item = document.metadata;\n if (!matchesScalarSearchFilters(item, filters)) {\n return false;\n }\n if (\n !matchesRuntimeFilters(item as Record<string, unknown>, runtimeFieldFilters)\n ) {\n return false;\n }\n if (\n filters.missingMetadataActive &&\n !itemMatchesMissingMetadata(\n item,\n filters.missingMetadataFilters,\n lifecycleClassifier,\n )\n ) {\n return false;\n }\n if (\n filters.contentFiltersActive &&\n !itemMatchesContentFilters(item, filters.contentFieldFilters)\n ) {\n return false;\n }\n return true;\n}\n\nfunction applyFilters(\n items: ItemDocument[],\n options: SearchOptions,\n typeRegistry: ItemTypeRegistry,\n runtimeFieldFilters: Record<string, unknown>,\n statusFilter: ItemStatus[] | undefined,\n lifecycleClassifier: LifecycleClassifier,\n): ItemDocument[] {\n const filters = resolveSearchMetadataFilterSet(\n options,\n typeRegistry,\n statusFilter,\n );\n return items.filter((document) =>\n matchesSearchMetadataFilters(\n document,\n filters,\n runtimeFieldFilters,\n lifecycleClassifier,\n ),\n );\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n let count = 0;\n let index = 0;\n while (true) {\n const foundAt = haystack.indexOf(needle, index);\n if (foundAt < 0) {\n return count;\n }\n count += 1;\n index = foundAt + needle.length;\n }\n}\n\nfunction tokenizeForExactTokenMatch(value: string): string[] {\n return tokenizeAlphaNumeric(value);\n}\n\nfunction collectLinkedPaths(\n item: ItemMetadata,\n): Array<{ scope: \"project\" | \"global\"; path: string }> {\n const fromFiles = (item.files ?? []).map((entry) => ({\n scope: entry.scope,\n path: entry.path.trim(),\n }));\n const fromDocs = (item.docs ?? []).map((entry) => ({\n scope: entry.scope,\n path: entry.path.trim(),\n }));\n const fromTests = (item.tests ?? [])\n .filter(\n (entry): entry is typeof entry & { path: string } =>\n typeof entry.path === \"string\" && entry.path.trim().length > 0,\n )\n .map((entry) => ({\n scope: entry.scope,\n path: entry.path.trim(),\n }));\n const sorted = [...fromFiles, ...fromDocs, ...fromTests]\n .filter((entry) => entry.path.length > 0)\n .sort(\n (a, b) => a.scope.localeCompare(b.scope) || a.path.localeCompare(b.path),\n );\n const deduped = new Map<\n string,\n { scope: \"project\" | \"global\"; path: string }\n >();\n for (const entry of sorted) {\n deduped.set(`${entry.scope}:${entry.path}`, entry);\n }\n return [...deduped.values()];\n}\n\ninterface ContainmentRoot {\n resolved: string;\n realpath: string;\n}\n\ninterface LinkedCorpusRoots {\n projectContainmentRoot: ContainmentRoot | null;\n globalContainmentRoot: ContainmentRoot | null;\n}\n\nasync function resolveContainmentRoot(\n root: string,\n): Promise<ContainmentRoot | null> {\n const resolved = path.resolve(root);\n try {\n const realpathRoot = await fs.realpath(resolved);\n return {\n resolved,\n realpath: realpathRoot,\n };\n } catch {\n return null;\n }\n}\n\nasync function resolveLinkedCorpusRoots(\n projectRoot: string,\n globalRoot: string,\n): Promise<LinkedCorpusRoots> {\n const [projectContainmentRoot, globalContainmentRoot] = await Promise.all([\n resolveContainmentRoot(projectRoot),\n resolveContainmentRoot(globalRoot),\n ]);\n return {\n projectContainmentRoot,\n globalContainmentRoot,\n };\n}\n\nasync function loadLinkedCorpus(\n document: ItemDocument,\n roots: LinkedCorpusRoots,\n): Promise<string> {\n const linkedPaths = collectLinkedPaths(document.metadata);\n const chunks: string[] = [];\n for (const linkedPath of linkedPaths) {\n const containmentRoot =\n linkedPath.scope === \"global\"\n ? roots.globalContainmentRoot\n : roots.projectContainmentRoot;\n if (!containmentRoot) {\n continue;\n }\n const resolved = path.resolve(containmentRoot.resolved, linkedPath.path);\n if (!isPathWithinDirectory(containmentRoot.resolved, resolved)) {\n continue;\n }\n let linkedRealpath: string;\n try {\n linkedRealpath = await fs.realpath(resolved);\n } catch {\n continue;\n }\n if (!isPathWithinDirectory(containmentRoot.realpath, linkedRealpath)) {\n continue;\n }\n try {\n await runActiveOnReadHooks({\n path: resolved,\n scope: linkedPath.scope,\n });\n chunks.push(await fs.readFile(resolved, \"utf8\"));\n } catch {\n // Best-effort linked-content indexing: unreadable paths are ignored.\n }\n }\n return chunks.join(\"\\n\");\n}\n\n/** Documents the search tuning payload exchanged by command, SDK, and package integrations. */\nexport interface SearchTuning {\n /** Value that configures or reports title exact bonus for this contract. */\n title_exact_bonus: number;\n /** Value that configures or reports title weight for this contract. */\n title_weight: number;\n /** Value that configures or reports description weight for this contract. */\n description_weight: number;\n /** Value that configures or reports tags weight for this contract. */\n tags_weight: number;\n /** Value that configures or reports status weight for this contract. */\n status_weight: number;\n /** Value that configures or reports body weight for this contract. */\n body_weight: number;\n /** Value that configures or reports comments weight for this contract. */\n comments_weight: number;\n /** Value that configures or reports notes weight for this contract. */\n notes_weight: number;\n /** Value that configures or reports learnings weight for this contract. */\n learnings_weight: number;\n /** Value that configures or reports reminders weight for this contract. */\n reminders_weight: number;\n /** Value that configures or reports events weight for this contract. */\n events_weight: number;\n /** Value that configures or reports dependencies weight for this contract. */\n dependencies_weight: number;\n /** Value that configures or reports linked content weight for this contract. */\n linked_content_weight: number;\n}\n\n/**\n * Canonical definition of the document-derived searchable fields shared by the\n * lexical scorer ({@link scoreDocument}) and the matched-text highlighter\n * ({@link buildHitHighlights}). Keeping a single source of field name → text\n * extractor → tuning weight guarantees the highlighter can only ever produce\n * snippets for fields the scorer actually inspected. The `linked_content` field\n * is appended separately by the scorer because its text is supplied per-query\n * rather than derived from the document.\n */\nconst SEARCHABLE_FIELD_BUILDERS: ReadonlyArray<{\n name: string;\n weightKey: keyof SearchTuning;\n value: (document: ItemDocument) => string;\n}> = [\n {\n name: \"title\",\n weightKey: \"title_weight\",\n value: (document) => document.metadata.title,\n },\n {\n name: \"description\",\n weightKey: \"description_weight\",\n value: (document) => document.metadata.description,\n },\n {\n name: \"tags\",\n weightKey: \"tags_weight\",\n value: (document) => stringArray(document.metadata.tags).join(\" \"),\n },\n {\n name: \"status\",\n weightKey: \"status_weight\",\n value: (document) =>\n typeof document.metadata.status === \"string\"\n ? document.metadata.status\n : \"\",\n },\n {\n name: \"body\",\n weightKey: \"body_weight\",\n value: (document) => document.body,\n },\n {\n name: \"comments\",\n weightKey: \"comments_weight\",\n value: (document) =>\n textEntries(document.metadata.comments)\n .map((entry) => entry.text)\n .join(\" \"),\n },\n {\n name: \"notes\",\n weightKey: \"notes_weight\",\n value: (document) =>\n textEntries(document.metadata.notes)\n .map((entry) => entry.text)\n .join(\" \"),\n },\n {\n name: \"learnings\",\n weightKey: \"learnings_weight\",\n value: (document) =>\n textEntries(document.metadata.learnings)\n .map((entry) => entry.text)\n .join(\" \"),\n },\n {\n name: \"reminders\",\n weightKey: \"reminders_weight\",\n value: (document) => buildReminderCorpus(document.metadata).join(\" \"),\n },\n {\n name: \"events\",\n weightKey: \"events_weight\",\n value: (document) => buildEventCorpus(document.metadata).join(\" \"),\n },\n {\n name: \"dependencies\",\n weightKey: \"dependencies_weight\",\n value: (document) =>\n dependencyEntries(document.metadata.dependencies)\n .map((entry) => `${entry.id} ${entry.kind}`)\n .join(\" \"),\n },\n {\n name: \"plan\",\n weightKey: \"body_weight\",\n value: (document) => buildPlanFlatCorpus(document.metadata),\n },\n];\n\n// Name → builder index so the highlighter can resolve a matched field to its\n// text extractor in O(1) and evaluate ONLY the matched fields' values, instead\n// of materializing all twelve (several of which join/build corpora) per hit.\nconst SEARCHABLE_FIELD_BUILDER_BY_NAME = new Map(\n SEARCHABLE_FIELD_BUILDERS.map((builder) => [builder.name, builder]),\n);\n\nfunction escapeRegExpLiteral(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Wrap every case-insensitive occurrence of any query token in `text` with the\n * {@link HIGHLIGHT_OPEN}/{@link HIGHLIGHT_CLOSE} markers. Token boundaries follow\n * the same substring semantics as the lexical scorer (a token highlights inside\n * longer words, matching how it scored), and overlapping matches are coalesced\n * by the single combined alternation so markers never nest.\n */\nfunction markTokenRuns(text: string, tokens: string[]): string {\n // Sort by length descending before building the alternation so a longer token\n // wins over a shorter token that is its prefix (regex alternation is greedy\n // left-to-right, so `auth|authority` would mark «auth»ority instead of\n // «authority»). `.filter` already returns a fresh array, so the in-place sort\n // never mutates the caller's token list.\n const escaped = tokens\n .filter((token) => token.length > 0)\n .sort((left, right) => right.length - left.length)\n .map(escapeRegExpLiteral);\n if (escaped.length === 0) {\n return text;\n }\n const pattern = new RegExp(escaped.join(\"|\"), \"gi\");\n return text.replace(\n pattern,\n (match) => `${HIGHLIGHT_OPEN}${match}${HIGHLIGHT_CLOSE}`,\n );\n}\n\n/**\n * Build a single highlighted snippet for one field value (GH-157), or null when\n * no token matches. The snippet is a window of {@link HIGHLIGHT_SNIPPET_RADIUS}\n * characters on each side of the first match with the matching token runs\n * wrapped in markers, prefixed/suffixed with an ellipsis when the field text was\n * trimmed. Returning null lets the caller skip fields with no concrete textual\n * match (e.g. a field flagged purely by the phrase-coverage bonus).\n */\nfunction highlightFieldSnippet(text: string, tokens: string[]): string | null {\n if (text.length === 0) {\n return null;\n }\n const lowerText = text.toLowerCase();\n let firstMatchIndex = -1;\n for (const token of tokens) {\n if (token.length === 0) {\n continue;\n }\n const index = lowerText.indexOf(token);\n if (index >= 0 && (firstMatchIndex < 0 || index < firstMatchIndex)) {\n firstMatchIndex = index;\n }\n }\n if (firstMatchIndex < 0) {\n return null;\n }\n const windowStart = Math.max(0, firstMatchIndex - HIGHLIGHT_SNIPPET_RADIUS);\n const windowEnd = Math.min(\n text.length,\n firstMatchIndex + HIGHLIGHT_SNIPPET_RADIUS,\n );\n const marked = markTokenRuns(text.slice(windowStart, windowEnd), tokens);\n const prefix = windowStart > 0 ? \"…\" : \"\";\n const suffix = windowEnd < text.length ? \"…\" : \"\";\n return `${prefix}${marked}${suffix}`;\n}\n\n/** Produce per-field matched-text snippets for a hit (GH-157, `--highlight`). Iterates the hit's already-sorted `matched_fields`, retains only the document-derived searchable fields (skipping synthetic markers like `id`, `semantic`, `rerank`, and `linked_content`), and emits a snippet for each field that still contains a concrete token match. */\nfunction buildHitHighlights(\n document: ItemDocument,\n matchedFields: string[],\n tokens: string[],\n): SearchHitHighlight[] {\n const highlights: SearchHitHighlight[] = [];\n for (const field of matchedFields) {\n const builder = SEARCHABLE_FIELD_BUILDER_BY_NAME.get(field);\n if (builder === undefined) {\n continue;\n }\n const snippet = highlightFieldSnippet(builder.value(document), tokens);\n if (snippet !== null) {\n highlights.push({ field, snippet });\n }\n }\n return highlights;\n}\n\ninterface SearchableScoringField {\n name: string;\n value: string;\n weight: number;\n}\n\ninterface SearchScoreState {\n score: number;\n matched: Set<string>;\n matchedTokens: Set<string>;\n}\n\nfunction buildSearchableScoringFields(\n document: ItemDocument,\n linkedCorpus: string,\n tuning: SearchTuning,\n): SearchableScoringField[] {\n return [\n ...SEARCHABLE_FIELD_BUILDERS.map((builder) => ({\n name: builder.name,\n value: builder.value(document),\n weight: tuning[builder.weightKey],\n })),\n {\n name: \"linked_content\",\n value: linkedCorpus,\n weight: tuning.linked_content_weight,\n },\n ];\n}\n\nfunction buildExactIdSearchHit(\n item: ItemMetadata,\n normalizedQuery: string,\n idPrefix: string,\n): SearchHit | null {\n const normalizedId = normalizeSearchPhrase(item.id);\n const normalizedIdPrefix =\n typeof idPrefix === \"string\" ? idPrefix.trim().toLowerCase() : \"\";\n const normalizedIdPrefixPhrase = normalizeSearchPhrase(normalizedIdPrefix);\n const normalizedShortId =\n normalizedIdPrefixPhrase.length > 0 &&\n normalizedId.startsWith(normalizedIdPrefixPhrase)\n ? normalizedId.slice(normalizedIdPrefixPhrase.length).trim()\n : normalizedId;\n if (\n normalizedQuery !== normalizedId &&\n normalizedQuery !== normalizedShortId\n ) {\n return null;\n }\n return {\n item,\n score:\n normalizedQuery === normalizedId\n ? EXACT_ID_MATCH_SCORE\n : SHORT_ID_MATCH_SCORE,\n matched_fields: [\"id\"],\n matched_all_terms: true,\n exact_id_match: true,\n };\n}\n\nfunction scoreTokenMatches(\n tokens: string[],\n titleTokenCounts: Map<string, number>,\n searchableFields: SearchableScoringField[],\n tuning: SearchTuning,\n state: SearchScoreState,\n): void {\n for (const token of tokens) {\n const exactTitleMatches = titleTokenCounts.get(token) ?? 0;\n if (exactTitleMatches > 0) {\n state.score += exactTitleMatches * tuning.title_exact_bonus;\n state.matched.add(\"title\");\n state.matchedTokens.add(token);\n }\n for (const field of searchableFields) {\n const occurrences = countOccurrences(field.value.toLowerCase(), token);\n if (occurrences > 0) {\n state.score += occurrences * field.weight;\n state.matched.add(field.name);\n state.matchedTokens.add(token);\n }\n }\n }\n}\n\nfunction scorePhraseMatches(\n item: ItemMetadata,\n normalizedQuery: string,\n searchableFields: SearchableScoringField[],\n state: SearchScoreState,\n): void {\n const normalizedTitle = normalizeSearchPhrase(item.title);\n if (normalizedTitle === normalizedQuery) {\n state.score += LONG_QUERY_TITLE_EXACT_BONUS;\n state.matched.add(\"title\");\n }\n for (const field of searchableFields) {\n const phraseOccurrences = countOccurrences(\n normalizeSearchPhrase(field.value),\n normalizedQuery,\n );\n if (phraseOccurrences > 0) {\n state.score +=\n phraseOccurrences * field.weight * LONG_QUERY_PHRASE_MULTIPLIER;\n state.matched.add(field.name);\n }\n }\n}\n\nfunction scoreDocument(\n document: ItemDocument,\n tokens: string[],\n normalizedQuery: string,\n linkedCorpus: string,\n tuning: SearchTuning,\n idPrefix: string,\n applyCoverageBonus = false,\n): SearchHit | null {\n const item = document.metadata;\n const exactIdHit = buildExactIdSearchHit(item, normalizedQuery, idPrefix);\n if (exactIdHit) {\n return exactIdHit;\n }\n const titleTokenCounts = new Map<string, number>();\n for (const token of tokenizeForExactTokenMatch(item.title)) {\n titleTokenCounts.set(token, (titleTokenCounts.get(token) ?? 0) + 1);\n }\n const searchableFields = buildSearchableScoringFields(\n document,\n linkedCorpus,\n tuning,\n );\n const state: SearchScoreState = {\n score: 0,\n matched: new Set(),\n matchedTokens: new Set(),\n };\n scoreTokenMatches(tokens, titleTokenCounts, searchableFields, tuning, state);\n const distinctTokens = new Set(tokens);\n // matchedTokens only ever holds entries drawn from `tokens`, so it is always a\n // subset of distinctTokens — exact size equality means every distinct term matched.\n const matchedAllTerms =\n distinctTokens.size > 0 && state.matchedTokens.size === distinctTokens.size;\n // GH-181 default-mode all-terms ranking bonus: only meaningful for multi-token\n // queries where every distinct token matched somewhere.\n if (applyCoverageBonus && distinctTokens.size > 1 && matchedAllTerms) {\n state.score += ALL_TERMS_COVERAGE_BONUS;\n }\n\n const isLongPhraseQuery =\n tokens.length >= LONG_QUERY_TOKEN_THRESHOLD &&\n normalizedQuery.includes(\" \");\n if (isLongPhraseQuery) {\n scorePhraseMatches(item, normalizedQuery, searchableFields, state);\n }\n\n if (state.score <= 0) {\n return null;\n }\n\n return {\n item,\n score: state.score,\n matched_fields: [...state.matched].sort((a, b) => a.localeCompare(b)),\n matched_all_terms: matchedAllTerms,\n };\n}\n\nfunction sortHits(\n items: SearchHit[],\n statusRegistry: RuntimeStatusRegistry,\n): SearchHit[] {\n return [...items].sort((a, b) => {\n const byScore = b.score - a.score;\n if (byScore !== 0) return byScore;\n const aTerminal = isTerminalStatus(a.item.status, statusRegistry);\n const bTerminal = isTerminalStatus(b.item.status, statusRegistry);\n if (aTerminal !== bTerminal) {\n return aTerminal ? 1 : -1;\n }\n const byPriority = a.item.priority - b.item.priority;\n if (byPriority !== 0) return byPriority;\n const byUpdated = compareTimestampStrings(\n b.item.updated_at,\n a.item.updated_at,\n );\n if (byUpdated !== 0) return byUpdated;\n return a.item.id.localeCompare(b.item.id);\n });\n}\n\nfunction buildHybridLexicalScore(\n document: ItemDocument,\n tokens: string[],\n normalizedQuery: string,\n includeLinked: boolean,\n linkedCorpusById: Map<string, string>,\n tuning: SearchTuning,\n idPrefix: string,\n applyCoverageBonus = false,\n): SearchHit | null {\n /* c8 ignore start -- linked corpus presence branch is covered by keyword/hybrid integration query tests */\n return scoreDocument(\n document,\n tokens,\n normalizedQuery,\n includeLinked ? (linkedCorpusById.get(document.metadata.id) ?? \"\") : \"\",\n tuning,\n idPrefix,\n applyCoverageBonus,\n );\n /* c8 ignore stop */\n}\n\nfunction normalizeScoreMap(\n scoreById: Map<string, number>,\n): Map<string, number> {\n if (scoreById.size === 0) {\n return new Map();\n }\n const values = [...scoreById.values()];\n const minScore = Math.min(...values);\n const maxScore = Math.max(...values);\n if (maxScore === minScore) {\n return new Map([...scoreById.keys()].map((id) => [id, 1]));\n }\n const normalized = new Map<string, number>();\n for (const [id, score] of scoreById) {\n normalized.set(id, (score - minScore) / (maxScore - minScore));\n }\n return normalized;\n}\n\n/** Implements resolve search max results for the public runtime surface of this module. */\nexport function resolveSearchMaxResults(settings: unknown): number {\n const candidate = (settings as { search?: { max_results?: unknown } }).search\n ?.max_results;\n if (\n typeof candidate === \"number\" &&\n Number.isFinite(candidate) &&\n candidate > 0\n ) {\n return Math.floor(candidate);\n }\n return 50;\n}\n\n/** Implements resolve search score threshold for the public runtime surface of this module. */\nexport function resolveSearchScoreThreshold(settings: unknown): number {\n const candidate = (settings as { search?: { score_threshold?: unknown } })\n .search?.score_threshold;\n if (typeof candidate === \"number\" && Number.isFinite(candidate)) {\n return candidate;\n }\n return 0;\n}\n\n/** Implements resolve hybrid semantic weight for the public runtime surface of this module. */\nexport function resolveHybridSemanticWeight(settings: unknown): number {\n const candidate = (\n settings as { search?: { hybrid_semantic_weight?: unknown } }\n ).search?.hybrid_semantic_weight;\n if (\n typeof candidate === \"number\" &&\n Number.isFinite(candidate) &&\n candidate >= 0 &&\n candidate <= 1\n ) {\n return candidate;\n }\n return 0.7;\n}\n\n/** Implements resolve search tuning for the public runtime surface of this module. */\nexport function resolveSearchTuning(settings: unknown): SearchTuning {\n const defaults: SearchTuning = {\n title_exact_bonus: 10,\n title_weight: 8,\n description_weight: 5,\n tags_weight: 6,\n status_weight: 2,\n body_weight: 1,\n comments_weight: 1,\n notes_weight: 1,\n learnings_weight: 1,\n reminders_weight: 2,\n events_weight: 2,\n dependencies_weight: 3,\n linked_content_weight: 1,\n };\n const tuning = (settings as { search?: { tuning?: Partial<SearchTuning> } })\n .search?.tuning;\n if (!tuning) return defaults;\n\n const resolveWeight = (candidate: unknown, fallback: number) => {\n if (\n typeof candidate === \"number\" &&\n Number.isFinite(candidate) &&\n candidate >= 0\n ) {\n return candidate;\n }\n return fallback;\n };\n\n return {\n title_exact_bonus: resolveWeight(\n tuning.title_exact_bonus,\n defaults.title_exact_bonus,\n ),\n title_weight: resolveWeight(tuning.title_weight, defaults.title_weight),\n description_weight: resolveWeight(\n tuning.description_weight,\n defaults.description_weight,\n ),\n tags_weight: resolveWeight(tuning.tags_weight, defaults.tags_weight),\n status_weight: resolveWeight(tuning.status_weight, defaults.status_weight),\n body_weight: resolveWeight(tuning.body_weight, defaults.body_weight),\n comments_weight: resolveWeight(\n tuning.comments_weight,\n defaults.comments_weight,\n ),\n notes_weight: resolveWeight(tuning.notes_weight, defaults.notes_weight),\n learnings_weight: resolveWeight(\n tuning.learnings_weight,\n defaults.learnings_weight,\n ),\n reminders_weight: resolveWeight(\n tuning.reminders_weight,\n defaults.reminders_weight,\n ),\n events_weight: resolveWeight(tuning.events_weight, defaults.events_weight),\n dependencies_weight: resolveWeight(\n tuning.dependencies_weight,\n defaults.dependencies_weight,\n ),\n linked_content_weight: resolveWeight(\n tuning.linked_content_weight,\n defaults.linked_content_weight,\n ),\n };\n}\n\n/* c8 ignore start -- empty-result projection/count/warnings shape matrix is validated by integration response-contract tests */\nfunction emptySearchResult(\n query: string,\n mode: SearchMode,\n matchMode: SearchMatchMode,\n options: SearchOptions,\n includeLinked: boolean,\n scoreThreshold: number,\n hybridSemanticWeight: number,\n queryExpansion: QueryExpansionConfig,\n rerank: RerankConfig,\n projection: SearchProjectionConfig,\n warnings: string[],\n runtimeFieldFilters?: Record<string, unknown>,\n countOnly = false,\n): SearchResult {\n // --count consistency: a count-only query that matches nothing must still\n // carry the same { count_only: true, total } shape as the non-empty path.\n const countExtras = countOnly ? { total: 0, count_only: true } : {};\n const compactSummaryMode =\n projection.mode === \"compact\" && options.compact === true;\n if (compactSummaryMode) {\n const compactFilters = buildCompactSearchFilterSummary({\n mode,\n matchMode,\n options,\n includeLinked,\n titleExact: options.titleExact === true,\n phraseExact: options.phraseExact === true,\n scoreThreshold,\n hybridSemanticWeight,\n runtimeFieldFilters,\n });\n return {\n query: query.trim(),\n mode,\n items: [],\n count: 0,\n ...countExtras,\n filters: compactFilters,\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n const projectionFields =\n projection.mode === \"full\" ? null : [...projection.fields];\n return {\n query: query.trim(),\n mode,\n items: [],\n count: 0,\n ...countExtras,\n filters: buildVerboseSearchFilters({\n effectiveMode: mode,\n matchMode,\n options,\n includeLinked,\n titleExact: options.titleExact === true,\n phraseExact: options.phraseExact === true,\n scoreThreshold,\n hybridSemanticWeight,\n queryExpansion,\n rerank,\n runtimeFieldFilters: runtimeFieldFilters ?? {},\n }),\n projection: {\n mode: projection.mode,\n fields: projectionFields,\n },\n now: nowIso(),\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n}\n/* c8 ignore stop */\n\nfunction requireSemanticDependencies(\n requestedMode: Exclude<SearchMode, \"keyword\">,\n providerResolution: EmbeddingProviderResolution,\n vectorResolution: VectorStoreResolution,\n hasExtensionVectorQuery: boolean,\n): {\n provider: EmbeddingProviderConfig;\n vectorStore: VectorStoreConfig | null;\n} {\n if (!providerResolution.active) {\n throw new PmCliError(\n `Search mode '${requestedMode}' requires a configured embedding provider in settings.providers.openai or settings.providers.ollama`,\n EXIT_CODE.USAGE,\n );\n }\n if (!vectorResolution.active && !hasExtensionVectorQuery) {\n throw new PmCliError(\n `Search mode '${requestedMode}' requires a configured vector store in settings.vector_store.qdrant/settings.vector_store.lancedb or an extension adapter selected by settings.vector_store.adapter`,\n EXIT_CODE.USAGE,\n );\n }\n return {\n provider: providerResolution.active,\n vectorStore: vectorResolution.active ?? null,\n };\n}\n\nconst toOptionalNonEmptyString = toNonEmptyStringOrUndefined;\n\ninterface ExtensionSearchProviderHooks {\n providerName: string;\n query?: ExtensionSearchProviderQuery;\n queryExpansion?: ExtensionSearchProviderQueryExpansion;\n rerank?: ExtensionSearchProviderRerank;\n}\n\n/* c8 ignore start -- extension search-provider registration permutations are covered by extension integration suites */\nfunction resolveExtensionSearchProviderByName(\n providerName: string | undefined,\n): ExtensionSearchProviderHooks | null {\n const registrations = getActiveExtensionRegistrations();\n const resolved = resolveRegisteredSearchProvider(registrations, providerName);\n if (!resolved) {\n return null;\n }\n const runtimeDefinition = resolved.runtime_definition ?? resolved.definition;\n const query = (runtimeDefinition as { query?: unknown }).query;\n const queryExpansion =\n (\n runtimeDefinition as {\n queryExpansion?: unknown;\n query_expansion?: unknown;\n }\n ).queryExpansion ??\n (\n runtimeDefinition as {\n queryExpansion?: unknown;\n query_expansion?: unknown;\n }\n ).query_expansion;\n const rerank = (runtimeDefinition as { rerank?: unknown }).rerank;\n const registeredName =\n toOptionalNonEmptyString((runtimeDefinition as { name?: unknown }).name) ??\n toOptionalNonEmptyString(\n (resolved.definition as { name?: unknown }).name,\n ) ??\n providerName;\n /* c8 ignore next 2 -- providerName is required for lookup and remains a non-empty fallback */\n if (!registeredName) {\n return null;\n }\n const hooks: ExtensionSearchProviderHooks = {\n providerName: registeredName,\n ...(typeof query === \"function\"\n ? { query: query as ExtensionSearchProviderQuery }\n : {}),\n ...(typeof queryExpansion === \"function\"\n ? {\n queryExpansion:\n queryExpansion as ExtensionSearchProviderQueryExpansion,\n }\n : {}),\n ...(typeof rerank === \"function\"\n ? { rerank: rerank as ExtensionSearchProviderRerank }\n : {}),\n };\n if (!hooks.query && !hooks.queryExpansion && !hooks.rerank) {\n return null;\n }\n return hooks;\n}\n/* c8 ignore stop */\n\nfunction resolveExtensionSearchProvider(\n settings: PmSettings,\n): { providerName: string; query: ExtensionSearchProviderQuery } | null {\n const providerName = toOptionalNonEmptyString(\n (settings.search as { provider?: unknown } | undefined)?.provider,\n );\n const resolved = resolveExtensionSearchProviderByName(providerName);\n if (!resolved?.query) {\n return null;\n }\n return {\n providerName: resolved.providerName,\n query: resolved.query,\n };\n}\n\n/* c8 ignore start -- vector adapter runtime definition permutations are covered by extension integration suites */\nfunction resolveExtensionVectorAdapter(\n settings: PmSettings,\n): ExtensionVectorAdapter | null {\n const registrations = getActiveExtensionRegistrations();\n const adapterName = toOptionalNonEmptyString(\n (settings.vector_store as { adapter?: unknown } | undefined)?.adapter,\n );\n const resolved = resolveRegisteredVectorStoreAdapter(\n registrations,\n adapterName,\n );\n if (!resolved) {\n return null;\n }\n const runtimeDefinition = resolved.runtime_definition ?? resolved.definition;\n const query = (runtimeDefinition as { query?: unknown }).query;\n if (typeof query !== \"function\") {\n return null;\n }\n const upsert = (runtimeDefinition as { upsert?: unknown }).upsert;\n const runtimeAdapterName =\n toOptionalNonEmptyString((runtimeDefinition as { name?: unknown }).name) ??\n toOptionalNonEmptyString(\n (resolved.definition as { name?: unknown }).name,\n ) ??\n adapterName ??\n \"extension\";\n return {\n adapterName: runtimeAdapterName,\n query: query as ExtensionVectorQuery,\n ...(typeof upsert === \"function\"\n ? { upsert: upsert as ExtensionVectorUpsert }\n : {}),\n };\n}\n/* c8 ignore stop */\n\nfunction normalizeExtensionProviderHits(\n providerName: string,\n raw: unknown,\n filteredById: Map<string, ItemDocument>,\n): SearchHit[] {\n const rawHits = Array.isArray(raw)\n ? raw\n : (raw as { hits?: unknown } | null | undefined)?.hits;\n if (!Array.isArray(rawHits)) {\n throw new PmCliError(\n `Extension search provider \"${providerName}\" must return an array of hits or { hits: [...] }`,\n EXIT_CODE.GENERIC_FAILURE,\n );\n }\n\n const seen = new Set<string>();\n const hits: SearchHit[] = [];\n for (const rawHit of rawHits) {\n if (typeof rawHit !== \"object\" || rawHit === null) {\n continue;\n }\n const id = toOptionalNonEmptyString((rawHit as { id?: unknown }).id);\n const score = (rawHit as { score?: unknown }).score;\n if (\n !id ||\n typeof score !== \"number\" ||\n !Number.isFinite(score) ||\n seen.has(id)\n ) {\n continue;\n }\n const document = filteredById.get(id);\n if (!document) {\n continue;\n }\n const matchedFieldsRaw = (rawHit as { matched_fields?: unknown })\n .matched_fields;\n const matchedFields =\n Array.isArray(matchedFieldsRaw) &&\n matchedFieldsRaw.every((entry) => typeof entry === \"string\")\n ? [\n ...new Set(\n (matchedFieldsRaw as string[])\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0),\n ),\n ].sort((a, b) => a.localeCompare(b))\n : [`provider:${providerName}`];\n seen.add(id);\n hits.push({\n item: document.metadata,\n score,\n matched_fields: matchedFields,\n });\n }\n return hits;\n}\n\nfunction buildSemanticHits(\n vectorHits: VectorQueryHit[],\n filteredById: Map<string, ItemDocument>,\n): { semanticHits: SearchHit[]; semanticScores: Map<string, number> } {\n const semanticHits: SearchHit[] = [];\n const semanticScores = new Map<string, number>();\n for (const vectorHit of vectorHits) {\n if (semanticScores.has(vectorHit.id)) {\n continue;\n }\n const document = filteredById.get(vectorHit.id);\n if (!document) {\n continue;\n }\n semanticScores.set(vectorHit.id, vectorHit.score);\n semanticHits.push({\n item: document.metadata,\n score: vectorHit.score,\n matched_fields: [\"semantic\"],\n });\n }\n return {\n semanticHits,\n semanticScores,\n };\n}\n\n// GH-281: in semantic & hybrid mode the blended/vector scores live on an\n// arbitrary scale (blended hybrid scores are [0,1]; raw vector similarities are\n// provider-defined), so an exact full-ID or short-ID keyword match can be\n// out-ranked by a high-semantic body mention. This reattaches the exact-ID\n// keyword hit(s) to the top of the ranked set in a reserved band ABOVE every\n// other hit, preserving matched_fields:[\"id\"] and keeping full-ID above\n// short-ID. The reserved scores are derived from the current max so the\n// guarantee holds no matter what scale the backend returns, and the hit is\n// re-inserted even if it was dropped from `rankedHits` (e.g. it had no semantic\n// vector match) so it is never lost to the threshold or the result-limit slice.\nfunction forceExactIdHitsToTop(\n rankedHits: SearchHit[],\n keywordHits: SearchHit[],\n): SearchHit[] {\n const exactIdHits = keywordHits.filter((hit) => hit.exact_id_match === true);\n if (exactIdHits.length === 0) {\n return rankedHits;\n }\n const exactIdIds = new Set(exactIdHits.map((hit) => hit.item.id));\n const remaining = rankedHits.filter((hit) => !exactIdIds.has(hit.item.id));\n // reduce (not Math.max(...spread)) so a very large pre-truncation candidate\n // set can never overflow the call stack.\n const maxRemainingScore = remaining.reduce(\n (max, hit) => Math.max(max, hit.score),\n 0,\n );\n // Full-ID hits (score 1000) must rank above short-ID hits (score 900): rank\n // within the exact-ID band by the original keyword score (descending) so a\n // full-ID match always precedes a short-ID match for the same query, then\n // offset the whole band above every remaining hit. ids are unique, so two\n // exact-ID hits can never tie on score — sorting on score alone is total.\n // exactIdHits is already a fresh array from keywordHits.filter(...), so sort\n // it in place — no defensive copy needed.\n const orderedExactHits = exactIdHits.sort(\n (left, right) => right.score - left.score,\n );\n const bandBase = maxRemainingScore + orderedExactHits.length + 1;\n const promoted = orderedExactHits.map((hit, index) => ({\n // Spread the original keyword hit so flags like matched_all_terms /\n // exact_id_match are preserved; only the band-slot score and the id-only\n // matched_fields are overridden.\n ...hit,\n // Higher band slot for earlier (higher original keyword score) hits.\n score: bandBase - index,\n matched_fields: [\"id\"],\n }));\n return [...promoted, ...remaining];\n}\n\nfunction combineHybridHits(\n filteredById: Map<string, ItemDocument>,\n semanticScores: Map<string, number>,\n keywordHits: SearchHit[],\n hybridSemanticWeight: number,\n // Matched-field label for the dense-ranking component. Defaults to \"semantic\"\n // (vector retrieval); the offline BM25 hybrid path passes \"bm25\" so hits carry\n // an honest provenance marker instead of implying a vector match (pm-75k9).\n semanticFieldLabel = \"semantic\",\n): SearchHit[] {\n const keywordScores = new Map(\n keywordHits.map((entry) => [entry.item.id, entry.score]),\n );\n const keywordMatches = new Map(\n keywordHits.map((entry) => [entry.item.id, entry.matched_fields]),\n );\n const normalizedSemantic = normalizeScoreMap(semanticScores);\n const normalizedKeyword = normalizeScoreMap(keywordScores);\n const candidateIds = new Set<string>([\n ...semanticScores.keys(),\n ...keywordScores.keys(),\n ]);\n const keywordWeight = 1 - hybridSemanticWeight;\n return [...candidateIds]\n .map((id) => {\n const document = filteredById.get(id)!;\n const semanticScore = normalizedSemantic.get(id) ?? 0;\n const keywordScore = normalizedKeyword.get(id) ?? 0;\n const combinedScore =\n semanticScore * hybridSemanticWeight + keywordScore * keywordWeight;\n if (combinedScore <= 0) {\n return null;\n }\n const matchedFields = new Set<string>();\n if (semanticScores.has(id)) {\n matchedFields.add(semanticFieldLabel);\n }\n for (const field of keywordMatches.get(id) ?? []) {\n matchedFields.add(field);\n }\n return {\n item: document.metadata,\n score: combinedScore,\n matched_fields: [...matchedFields].sort((a, b) => a.localeCompare(b)),\n };\n })\n .filter((entry): entry is SearchHit => entry !== null);\n}\n\n/** Built-in BM25 activation outcome for semantic/hybrid search (pm-75k9): - `\"explicit\"`: `search.provider` is `bm25` — the user opted into offline lexical ranking, so it is used even if an embedding provider is configured. - `\"auto-fallback\"`: `search.provider` is `auto` and neither an embedding provider nor an extension search provider is available — BM25 is used in place of degrading to the naive field-weighted keyword scorer. - `null`: BM25 does not apply; the existing embedding/extension path runs. */\ntype BuiltInBm25Mode = \"explicit\" | \"auto-fallback\";\n\nfunction resolveBuiltInBm25Mode(params: {\n configuredProvider: string | undefined;\n hasEmbeddingProvider: boolean;\n hasExtensionSearchProvider: boolean;\n}): BuiltInBm25Mode | null {\n const normalized = params.configuredProvider?.trim().toLowerCase();\n if (normalized === \"bm25\") {\n return \"explicit\";\n }\n if (\n normalized === \"auto\" &&\n !params.hasEmbeddingProvider &&\n !params.hasExtensionSearchProvider\n ) {\n return \"auto-fallback\";\n }\n return null;\n}\n\n/**\n * Rank the filtered corpus with the offline BM25 provider (pm-75k9). Builds a\n * BM25 index over each document's resolved search corpus (honoring\n * `search.corpus_fields`), scores the query, and shapes hits for the requested\n * mode: semantic mode returns pure BM25-ranked hits tagged\n * `matched_fields: [\"bm25\"]`, while hybrid mode blends the BM25 scores with the\n * locally computed keyword scores via {@link combineHybridHits}. The exact\n * full-ID / short-ID guarantee is preserved in both modes via\n * {@link forceExactIdHitsToTop}. No network, embedding service, or vector store\n * is involved, so this path cannot fail on a backend error.\n */\nfunction computeBuiltInBm25Hits(params: {\n requestedMode: Exclude<SearchMode, \"keyword\">;\n query: string;\n filteredDocuments: ItemDocument[];\n keywordHits: SearchHit[];\n corpusFields: string[];\n bm25Params: Bm25Params;\n hybridSemanticWeight: number;\n}): SearchHit[] {\n const bm25Documents = params.filteredDocuments.map((document) => ({\n id: document.metadata.id,\n text: flattenSearchCorpusText(\n buildSearchCorpus(document, { fields: params.corpusFields }),\n ),\n }));\n const index = buildBm25Index(bm25Documents);\n const bm25Scores = scoreBm25Query(\n index,\n tokenizeBm25(params.query),\n params.bm25Params,\n );\n const filteredById = new Map(\n params.filteredDocuments.map((document) => [\n document.metadata.id,\n document,\n ]),\n );\n if (params.requestedMode === \"semantic\") {\n const semanticHits: SearchHit[] = [...bm25Scores].map(([id, score]) => ({\n item: filteredById.get(id)!.metadata,\n score,\n matched_fields: [\"bm25\"],\n }));\n return forceExactIdHitsToTop(semanticHits, params.keywordHits);\n }\n const hybridHits = combineHybridHits(\n filteredById,\n bm25Scores,\n params.keywordHits,\n params.hybridSemanticWeight,\n \"bm25\",\n );\n return forceExactIdHitsToTop(hybridHits, params.keywordHits);\n}\n\ninterface SemanticQueryContext {\n requestedMode: Exclude<SearchMode, \"keyword\">;\n query: string;\n filteredDocuments: ItemDocument[];\n keywordHits: SearchHit[];\n hybridSemanticWeight: number;\n limit: number | undefined;\n maxResults: number;\n provider: EmbeddingProviderConfig;\n vectorStore: VectorStoreConfig | null;\n extensionVectorAdapter: ExtensionVectorAdapter | null;\n queryExpansion: QueryExpansionConfig;\n queryExpansionExtension: {\n providerName: string;\n expand: ExtensionSearchProviderQueryExpansion;\n } | null;\n rerank: RerankConfig;\n rerankExtension: {\n providerName: string;\n rerank: ExtensionSearchProviderRerank;\n } | null;\n warnings: string[];\n settings: PmSettings;\n embeddingTimeoutMs?: number;\n vectorQueryTimeoutMs?: number;\n}\n\ninterface SemanticQueryResult {\n hits: SearchHit[];\n // Number of documents returned by the vector stage for this query after the\n // current metadata filters. When this is 0 the semantic/hybrid query ran\n // successfully, but vector ranking contributed nothing to the returned hits.\n vectorMatchCount: number;\n}\n\nfunction mergeVectorHitsById(\n vectorHitGroups: VectorQueryHit[][],\n): VectorQueryHit[] {\n const bestById = new Map<string, VectorQueryHit>();\n for (const group of vectorHitGroups) {\n for (const hit of group) {\n const existing = bestById.get(hit.id);\n if (!existing || hit.score > existing.score) {\n bestById.set(hit.id, hit);\n }\n }\n }\n const merged = [...bestById.values()];\n merged.sort((left, right) => {\n if (left.score !== right.score) {\n return right.score - left.score;\n }\n return left.id.localeCompare(right.id);\n });\n return merged;\n}\n\n/* c8 ignore start -- rerank corpus metadata-shape permutations are covered by semantic integration tests */\nfunction buildRerankCorpus(document: ItemDocument): string {\n const metadata = (document as { metadata?: ItemDocument[\"metadata\"] | null })\n .metadata;\n const tags = Array.isArray(metadata?.tags) ? metadata.tags.join(\" \") : \"\";\n return [\n metadata?.title,\n metadata?.description,\n metadata?.type,\n metadata?.status,\n tags,\n document.body,\n ]\n .map((entry) => (typeof entry === \"string\" ? entry.trim() : \"\"))\n .filter((entry) => entry.length > 0)\n .join(\"\\n\");\n}\n/* c8 ignore stop */\n\n/* c8 ignore start -- semantic expansion/rerank fallback matrices are covered by end-to-end semantic search tests */\nasync function resolveExpandedSemanticQueries(\n context: SemanticQueryContext,\n queryTrimmed: string,\n): Promise<string[]> {\n const baseExpandedQueries = context.queryExpansion.enabled\n ? buildDeterministicQueryExpansions(\n queryTrimmed,\n context.queryExpansion.max_queries,\n )\n : [queryTrimmed];\n const expandedQueries =\n baseExpandedQueries.length > 0 ? baseExpandedQueries : [queryTrimmed];\n if (!context.queryExpansion.enabled) {\n return expandedQueries;\n }\n if (context.queryExpansionExtension?.expand) {\n try {\n const rawExpansion = await Promise.resolve(\n context.queryExpansionExtension.expand({\n query: queryTrimmed,\n mode: context.requestedMode,\n settings: context.settings,\n }),\n );\n return mergeQueryExpansions(\n expandedQueries,\n normalizeQueryExpansionOutput(rawExpansion),\n context.queryExpansion.max_queries,\n );\n } catch {\n context.warnings.push(\n `search_query_expansion_provider_failed:${context.queryExpansionExtension.providerName}:using_builtin`,\n );\n return expandedQueries;\n }\n }\n if (\n context.queryExpansion.provider &&\n context.queryExpansion.provider !== \"openai\" &&\n context.queryExpansion.provider !== \"ollama\"\n ) {\n context.warnings.push(\n `search_query_expansion_provider_unavailable:${context.queryExpansion.provider}:using_builtin`,\n );\n }\n return expandedQueries;\n}\n\nasync function executeSemanticVectorQuery(\n context: SemanticQueryContext,\n semanticVector: number[],\n semanticLimit: number,\n vectorQueryOptions: { timeout_ms?: number },\n): Promise<VectorQueryHit[]> {\n if (context.extensionVectorAdapter?.query) {\n try {\n return await Promise.resolve(\n context.extensionVectorAdapter.query({\n vector: semanticVector,\n limit: semanticLimit,\n settings: context.settings,\n }),\n );\n } catch (error: unknown) {\n if (!context.vectorStore) {\n throw new PmCliError(\n `Extension vector adapter query failed and no built-in fallback store is configured (${error instanceof Error ? error.message : String(error)})`,\n EXIT_CODE.GENERIC_FAILURE,\n );\n }\n context.warnings.push(\n `search_vector_adapter_failed:${context.extensionVectorAdapter.adapterName}:using_builtin`,\n );\n return await executeVectorQuery(\n context.vectorStore,\n semanticVector,\n semanticLimit,\n vectorQueryOptions,\n );\n }\n }\n if (context.vectorStore) {\n return await executeVectorQuery(\n context.vectorStore,\n semanticVector,\n semanticLimit,\n vectorQueryOptions,\n );\n }\n throw new PmCliError(\n \"Semantic search requires either a configured vector store or an extension vector adapter query handler\",\n EXIT_CODE.USAGE,\n );\n}\n\nfunction buildRerankCandidateContexts(\n hybridHits: SearchHit[],\n filteredById: Map<string, ItemDocument>,\n topK: number,\n): Array<{ hit: SearchHit; text: string }> {\n const sortedForCandidates = [...hybridHits].sort((left, right) => {\n if (left.score !== right.score) {\n return right.score - left.score;\n }\n return left.item.id.localeCompare(right.item.id);\n });\n return sortedForCandidates\n .slice(0, topK)\n .map((hit) => {\n const document = filteredById.get(hit.item.id);\n return document ? { hit, text: buildRerankCorpus(document) } : null;\n })\n .filter(\n (entry): entry is { hit: SearchHit; text: string } => entry !== null,\n );\n}\n\nasync function resolveExtensionRerankScores(\n context: SemanticQueryContext,\n queryTrimmed: string,\n candidateContexts: Array<{ hit: SearchHit; text: string }>,\n): Promise<Map<string, number> | null> {\n if (!context.rerankExtension?.rerank) {\n return null;\n }\n try {\n const rawRerank = await Promise.resolve(\n context.rerankExtension.rerank({\n query: queryTrimmed,\n mode: \"hybrid\",\n model: context.rerank.model,\n top_k: context.rerank.top_k,\n settings: context.settings,\n candidates: candidateContexts.map((entry) => ({\n id: entry.hit.item.id,\n text: entry.text,\n score: entry.hit.score,\n })),\n }),\n );\n const normalizedRerank = normalizeRerankOutput(rawRerank);\n if (normalizedRerank.length > 0) {\n return new Map(normalizedRerank.map((entry) => [entry.id, entry.score]));\n }\n context.warnings.push(\n `search_rerank_provider_invalid_response:${context.rerankExtension.providerName}:using_builtin`,\n );\n return null;\n } catch {\n context.warnings.push(\n `search_rerank_provider_failed:${context.rerankExtension.providerName}:using_builtin`,\n );\n return null;\n }\n}\n\nasync function resolveRerankScores(\n context: SemanticQueryContext,\n queryTrimmed: string,\n candidateContexts: Array<{ hit: SearchHit; text: string }>,\n): Promise<Map<string, number> | null> {\n const extensionScores = await resolveExtensionRerankScores(\n context,\n queryTrimmed,\n candidateContexts,\n );\n if (extensionScores) {\n return extensionScores;\n }\n const rerankCandidates: RerankCandidate[] = candidateContexts.map(\n (entry) => ({\n id: entry.hit.item.id,\n text: entry.text,\n }),\n );\n try {\n return await rerankCandidatesWithEmbeddings(\n context.provider,\n context.rerank.model,\n queryTrimmed,\n rerankCandidates,\n context.embeddingTimeoutMs,\n );\n } catch {\n context.warnings.push(\"search_rerank_failed:using_hybrid_scores\");\n return null;\n }\n}\n\nfunction applyRerankScores(\n hybridHits: SearchHit[],\n rerankScores: Map<string, number>,\n): SearchHit[] {\n const rerankedIds = new Set(rerankScores.keys());\n const rerankedHits = hybridHits.map((hit) => {\n const rerankScore = rerankScores.get(hit.item.id);\n if (rerankScore === undefined) {\n return hit;\n }\n const matchedFields = new Set(hit.matched_fields);\n matchedFields.add(\"rerank\");\n return {\n ...hit,\n score: rerankScore,\n matched_fields: [...matchedFields].sort((left, right) =>\n left.localeCompare(right),\n ),\n };\n });\n rerankedHits.sort((left, right) => {\n const leftWasReranked = rerankedIds.has(left.item.id);\n const rightWasReranked = rerankedIds.has(right.item.id);\n if (leftWasReranked !== rightWasReranked) {\n return leftWasReranked ? -1 : 1;\n }\n if (left.score !== right.score) {\n return right.score - left.score;\n }\n return left.item.id.localeCompare(right.item.id);\n });\n return rerankedHits;\n}\n\nasync function applyHybridRerank(\n context: SemanticQueryContext,\n queryTrimmed: string,\n hybridHits: SearchHit[],\n filteredById: Map<string, ItemDocument>,\n): Promise<SearchHit[]> {\n if (!context.rerank.enabled || hybridHits.length <= 1) {\n return hybridHits;\n }\n const candidateContexts = buildRerankCandidateContexts(\n hybridHits,\n filteredById,\n context.rerank.top_k,\n );\n const rerankScores = await resolveRerankScores(\n context,\n queryTrimmed,\n candidateContexts,\n );\n return rerankScores && rerankScores.size > 0\n ? applyRerankScores(hybridHits, rerankScores)\n : hybridHits;\n}\n\nasync function computeSemanticOrHybridHits(\n context: SemanticQueryContext,\n): Promise<SemanticQueryResult> {\n const semanticLimit = Math.max(\n context.limit ?? context.maxResults,\n context.maxResults,\n );\n const embeddingOptions =\n context.embeddingTimeoutMs !== undefined\n ? { timeout_ms: context.embeddingTimeoutMs }\n : {};\n const vectorQueryOptions =\n context.vectorQueryTimeoutMs !== undefined\n ? { timeout_ms: context.vectorQueryTimeoutMs }\n : {};\n const queryTrimmed = context.query.trim();\n const expandedQueries = await resolveExpandedSemanticQueries(\n context,\n queryTrimmed,\n );\n const queryVectors = await executeEmbeddingRequest(\n context.provider,\n expandedQueries,\n embeddingOptions,\n );\n const queryVectorGroups = await Promise.all(\n queryVectors.map(\n async (semanticVector) =>\n await executeSemanticVectorQuery(\n context,\n semanticVector,\n semanticLimit,\n vectorQueryOptions,\n ),\n ),\n );\n const vectorHits = mergeVectorHitsById(queryVectorGroups);\n const filteredById = new Map(\n context.filteredDocuments.map((document) => [\n document.metadata.id,\n document,\n ]),\n );\n const { semanticHits, semanticScores } = buildSemanticHits(\n vectorHits,\n filteredById,\n );\n const vectorMatchCount = semanticScores.size;\n if (context.requestedMode === \"semantic\") {\n // GH-281: guarantee an exact full-ID / short-ID match ranks #1 even in pure\n // semantic mode, where it otherwise carries no vector hit at all.\n return {\n hits: forceExactIdHitsToTop(semanticHits, context.keywordHits),\n vectorMatchCount,\n };\n }\n const hybridHits = await applyHybridRerank(\n context,\n queryTrimmed,\n combineHybridHits(\n filteredById,\n semanticScores,\n context.keywordHits,\n context.hybridSemanticWeight,\n ),\n filteredById,\n );\n return {\n // GH-281: applied LAST (after any rerank reordering) so an exact full-ID /\n // short-ID keyword match always ranks #1 in hybrid mode regardless of the\n // semantic blend weight or rerank scores.\n hits: forceExactIdHitsToTop(hybridHits, context.keywordHits),\n vectorMatchCount,\n };\n}\n/* c8 ignore stop */\n\n/* c8 ignore start -- item body fallback read-path combinations are covered by document-cache integration tests */\nasync function loadDocuments(\n pmRoot: string,\n itemFormat: ItemFormat,\n typeToFolder: Record<string, string>,\n schema: PmSettings[\"schema\"],\n): Promise<{ documents: ItemDocument[]; warnings: string[] }> {\n const extensionFieldNames = collectRegisteredItemFieldNames(\n getActiveExtensionRegistrations(),\n );\n const readDocumentBody = async (\n metadata: ItemMetadata,\n preferredPath: string,\n preferredFormat: ItemFormat,\n ): Promise<string> => {\n const tryRead = async (\n targetPath: string,\n format: ItemFormat,\n ): Promise<string> => {\n await runActiveOnReadHooks({ path: targetPath, scope: \"project\" });\n const raw = await fs.readFile(targetPath, \"utf8\");\n const parsed = parseItemDocument(raw, {\n format,\n schema,\n extensionFieldNames,\n onWarning: (warning) => listWarnings.push(warning),\n });\n return parsed.body;\n };\n\n try {\n return await tryRead(preferredPath, preferredFormat);\n } catch {\n const alternateFormat: ItemFormat =\n preferredFormat === \"toon\" ? \"json_markdown\" : \"toon\";\n const alternatePath = getItemPath(\n pmRoot,\n metadata.type as ItemType,\n metadata.id,\n alternateFormat,\n typeToFolder,\n );\n try {\n return await tryRead(alternatePath, alternateFormat);\n } catch {\n listWarnings.push(\n `item_list_item_read_failed:${path.relative(pmRoot, alternatePath)}`,\n );\n return \"\";\n }\n }\n };\n\n const listWarnings: string[] = [];\n const cachedDocuments = await listAllDocumentCandidatesCached(\n pmRoot,\n itemFormat,\n typeToFolder,\n listWarnings,\n schema,\n );\n const documents: ItemDocument[] = [];\n if (cachedDocuments.length === 0) {\n const itemMetadataDocuments = await listAllItemMetadata(\n pmRoot,\n itemFormat,\n typeToFolder,\n listWarnings,\n schema,\n );\n for (const metadata of itemMetadataDocuments) {\n const preferredPath = getItemPath(\n pmRoot,\n metadata.type as ItemType,\n metadata.id,\n itemFormat,\n typeToFolder,\n );\n const body = await readDocumentBody(metadata, preferredPath, itemFormat);\n documents.push({ metadata, body });\n }\n return {\n documents,\n warnings: [...new Set(listWarnings)].sort((left, right) =>\n left.localeCompare(right),\n ),\n };\n }\n\n for (const cachedDocument of cachedDocuments) {\n if (typeof cachedDocument.body === \"string\") {\n documents.push({\n metadata: cachedDocument.metadata,\n body: cachedDocument.body,\n });\n continue;\n }\n const body = await readDocumentBody(\n cachedDocument.metadata,\n cachedDocument.item_path,\n cachedDocument.item_format,\n );\n documents.push({\n metadata: cachedDocument.metadata,\n body,\n });\n }\n return {\n documents,\n warnings: [...new Set(listWarnings)].sort((left, right) =>\n left.localeCompare(right),\n ),\n };\n}\n/* c8 ignore stop */\n\n/* c8 ignore start -- field projection lookup precedence is validated by output-shaping integration tests */\nfunction readSearchFieldValue(hit: SearchHit, field: string): unknown {\n const normalized = field.trim();\n if (normalized.length === 0) {\n return null;\n }\n if (normalized === \"score\") {\n return hit.score;\n }\n if (normalized === \"matched_fields\") {\n return hit.matched_fields;\n }\n if (normalized.startsWith(\"item.\")) {\n const itemKey = normalized.slice(\"item.\".length);\n if (itemKey.length === 0) {\n return null;\n }\n const itemRecord = toItemRecord(hit.item);\n return itemRecord[itemKey] ?? null;\n }\n const hitRecord = hit as unknown as Record<string, unknown>;\n const itemRecord = toItemRecord(hit.item);\n if (Object.prototype.hasOwnProperty.call(itemRecord, normalized)) {\n return itemRecord[normalized] ?? null;\n }\n if (Object.prototype.hasOwnProperty.call(hitRecord, normalized)) {\n return hitRecord[normalized] ?? null;\n }\n return null;\n}\n/* c8 ignore stop */\n\nfunction projectSearchHits(\n hits: SearchHit[],\n projection: SearchProjectionConfig,\n): SearchResultItem[] {\n if (projection.mode === \"full\") {\n // matched_all_terms is an internal ranking signal (GH-181); strip it from\n // full-mode output rows so the public hit shape stays { item, score, matched_fields }.\n return hits.map(({ matched_all_terms: _matchedAllTerms, ...hit }) => hit);\n }\n return hits.map((hit) => {\n const projected: Record<string, unknown> = {};\n for (const field of projection.fields) {\n projected[field] = readSearchFieldValue(hit, field);\n }\n return projected;\n });\n}\n\ninterface PreparedSearchInput {\n query: string;\n options: SearchOptions;\n inlineWarnings: string[];\n highlight: boolean;\n includeLinked: boolean;\n titleExact: boolean;\n phraseExact: boolean;\n matchMode: SearchMatchMode;\n minScoreOverride: number | undefined;\n countOnly: boolean;\n tokens: string[];\n normalizedQuery: string;\n limit: number | undefined;\n projection: SearchProjectionConfig;\n modeWasExplicit: boolean;\n}\n\ninterface SearchRuntimeContext {\n pmRoot: string;\n settings: PmSettings;\n statusRegistry: RuntimeStatusRegistry;\n runtimeFieldRegistry: RuntimeFieldRegistry;\n runtimeFieldFilters: Record<string, unknown>;\n typeRegistry: ItemTypeRegistry;\n maxResults: number;\n scoreThreshold: number;\n semanticWeightProvided: boolean;\n semanticWeightOverride: number | undefined;\n hybridSemanticWeight: number;\n tuning: SearchTuning;\n providerResolution: EmbeddingProviderResolution;\n vectorResolution: VectorStoreResolution;\n extensionSearchProvider: ReturnType<typeof resolveExtensionSearchProvider>;\n extensionVectorAdapter: ReturnType<typeof resolveExtensionVectorAdapter>;\n bm25Mode: BuiltInBm25Mode | null;\n queryExpansion: QueryExpansionConfig;\n queryExpansionExtension: {\n providerName: string;\n expand: ExtensionSearchProviderQueryExpansion;\n } | null;\n rerank: RerankConfig;\n rerankExtension: {\n providerName: string;\n rerank: ExtensionSearchProviderRerank;\n } | null;\n effectiveMode: SearchMode;\n}\n\ninterface FilteredSearchCorpus {\n warnings: string[];\n allDocuments: ItemDocument[];\n filteredDocuments: ItemDocument[];\n}\n\ninterface SearchResponseContext {\n query: string;\n effectiveMode: SearchMode;\n matchMode: SearchMatchMode;\n options: SearchOptions;\n includeLinked: boolean;\n titleExact: boolean;\n phraseExact: boolean;\n scoreThreshold: number;\n hybridSemanticWeight: number;\n queryExpansion: QueryExpansionConfig;\n rerank: RerankConfig;\n projection: SearchProjectionConfig;\n warnings: string[];\n runtimeFieldFilters: Record<string, unknown>;\n}\n\ninterface SearchModeExecutionInput {\n prepared: PreparedSearchInput;\n runtime: SearchRuntimeContext;\n filteredDocuments: ItemDocument[];\n keywordHits: SearchHit[];\n warnings: string[];\n modeWasExplicit: boolean;\n}\n\ninterface SearchModeExecutionResult {\n effectiveMode: SearchMode;\n hits: SearchHit[];\n}\n\nfunction resolveQueryExpansionExtension(\n queryExpansion: QueryExpansionConfig,\n): {\n providerName: string;\n expand: ExtensionSearchProviderQueryExpansion;\n} | null {\n const provider = resolveExtensionSearchProviderByName(\n queryExpansion.provider ?? undefined,\n );\n return provider?.queryExpansion\n ? { providerName: provider.providerName, expand: provider.queryExpansion }\n : null;\n}\n\nfunction resolveRerankExtension(\n settings: PmSettings,\n): { providerName: string; rerank: ExtensionSearchProviderRerank } | null {\n const provider = resolveExtensionSearchProviderByName(\n toOptionalNonEmptyString(settings.search?.provider),\n );\n return provider?.rerank\n ? { providerName: provider.providerName, rerank: provider.rerank }\n : null;\n}\n\nfunction prepareSearchInput(\n rawQuery: string,\n rawOptions: SearchOptions,\n): PreparedSearchInput {\n const inlineWarnings: string[] = [];\n const inlineParse = parseInlineQueryFilters(rawQuery);\n const hasInlineFilters = Object.keys(inlineParse.inlineFilters).length > 0;\n if (hasInlineFilters && inlineParse.residualQuery.trim().length === 0) {\n throw new PmCliError(\n \"Inline field:value tokens consumed the entire query, leaving no search terms.\",\n EXIT_CODE.USAGE,\n {\n examples: [\n \"pm search auth tag:area:search\",\n \"pm list --tag area:search --status open\",\n ],\n nextSteps: [\n \"Add keyword terms alongside the inline filters, or use pm list for pure tag/status/type/priority filtering.\",\n ],\n },\n );\n }\n const query = hasInlineFilters ? inlineParse.residualQuery : rawQuery;\n const options = applyInlineQueryFilters(\n rawOptions,\n inlineParse.inlineFilters,\n inlineWarnings,\n );\n return {\n query,\n options,\n inlineWarnings,\n highlight: options.highlight === true,\n includeLinked: parseIncludeLinked(options.includeLinked),\n titleExact: parseTitleExact(options.titleExact),\n phraseExact: parsePhraseExact(options.phraseExact),\n matchMode: parseMatchMode(\n typeof options.matchMode === \"string\" ? options.matchMode : undefined,\n ),\n minScoreOverride: parseMinScoreOverride(options.minScore),\n countOnly: options.count === true,\n tokens: parseTokens(query),\n normalizedQuery: normalizeSearchPhrase(query),\n limit: parseLimit(options.limit),\n projection: parseProjectionConfig(options),\n modeWasExplicit:\n typeof options.mode === \"string\" && options.mode.trim().length > 0,\n };\n}\n\nasync function resolveSearchRuntimeContext(\n prepared: PreparedSearchInput,\n global: GlobalOptions,\n): Promise<SearchRuntimeContext> {\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(\n `Tracker is not initialized at ${pmRoot}. Run pm init first.`,\n EXIT_CODE.NOT_FOUND,\n );\n }\n const storedSettings = await readSettings(pmRoot);\n const settings =\n resolveSettingsWithSemanticRuntimeDefaults(storedSettings).settings;\n const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);\n const runtimeFieldRegistry = resolveRuntimeFieldRegistry(settings.schema);\n validateSearchProjectionFields(prepared.projection, runtimeFieldRegistry);\n const runtimeFieldFilters = collectRuntimeFilterValues(\n prepared.options as Record<string, unknown>,\n runtimeFieldRegistry,\n \"search\",\n );\n const typeRegistry = resolveItemTypeRegistry(\n settings,\n getActiveExtensionRegistrations(),\n );\n const providerResolution = resolveEmbeddingProviders(settings);\n const vectorResolution = resolveVectorStores(settings, pmRoot);\n const extensionSearchProvider = resolveExtensionSearchProvider(settings);\n const extensionVectorAdapter = resolveExtensionVectorAdapter(settings);\n const semanticWeightOverride = parseSemanticWeightOverride(\n prepared.options.semanticWeight,\n );\n const queryExpansion = resolveQueryExpansionConfig(\n settings,\n providerResolution.active?.name ?? null,\n );\n const rerank = resolveRerankConfig(\n settings,\n providerResolution.active?.model ??\n toOptionalNonEmptyString(settings.search?.embedding_model) ??\n \"text-embedding-3-small\",\n );\n return {\n pmRoot,\n settings,\n statusRegistry,\n runtimeFieldRegistry,\n runtimeFieldFilters,\n typeRegistry,\n maxResults: resolveSearchMaxResults(settings),\n scoreThreshold:\n prepared.minScoreOverride ?? resolveSearchScoreThreshold(settings),\n semanticWeightProvided: prepared.options.semanticWeight !== undefined,\n semanticWeightOverride,\n hybridSemanticWeight:\n semanticWeightOverride ?? resolveHybridSemanticWeight(settings),\n tuning: resolveSearchTuning(settings),\n providerResolution,\n vectorResolution,\n extensionSearchProvider,\n extensionVectorAdapter,\n bm25Mode: resolveBuiltInBm25Mode({\n configuredProvider: toOptionalNonEmptyString(settings.search?.provider),\n hasEmbeddingProvider: providerResolution.active !== null,\n hasExtensionSearchProvider: extensionSearchProvider !== null,\n }),\n queryExpansion,\n queryExpansionExtension: resolveQueryExpansionExtension(queryExpansion),\n rerank,\n rerankExtension: resolveRerankExtension(settings),\n effectiveMode: parseMode(prepared.options.mode, {\n hasProvider:\n providerResolution.active !== null || extensionSearchProvider !== null,\n hasVectorStore:\n vectorResolution.active !== null || extensionVectorAdapter !== null,\n }),\n };\n}\n\nasync function loadFilteredSearchCorpus(\n prepared: PreparedSearchInput,\n runtime: SearchRuntimeContext,\n): Promise<FilteredSearchCorpus> {\n const loadedDocuments = await loadDocuments(\n runtime.pmRoot,\n runtime.settings.item_format ?? \"toon\",\n runtime.typeRegistry.type_to_folder,\n runtime.settings.schema,\n );\n const statusFilter = parseStatusFilterCsv(\n typeof prepared.options.status === \"string\"\n ? prepared.options.status\n : undefined,\n runtime.statusRegistry,\n { strict: true },\n );\n const lifecycleClassifier = lifecycleClassifierFromStatusRegistry(\n runtime.statusRegistry,\n );\n const metadataFilteredDocuments = applyFilters(\n loadedDocuments.documents,\n prepared.options,\n runtime.typeRegistry,\n runtime.runtimeFieldFilters,\n statusFilter,\n lifecycleClassifier,\n );\n return {\n warnings: loadedDocuments.warnings,\n allDocuments: loadedDocuments.documents,\n filteredDocuments: applyExactQueryFilters(\n metadataFilteredDocuments,\n prepared.normalizedQuery,\n {\n titleExact: prepared.titleExact,\n phraseExact: prepared.phraseExact || prepared.matchMode === \"exact\",\n },\n ),\n };\n}\n\nasync function collectLinkedCorpusById(\n includeLinked: boolean,\n effectiveMode: SearchMode,\n filteredDocuments: ItemDocument[],\n): Promise<Map<string, string>> {\n const linkedCorpusById = new Map<string, string>();\n if (\n !includeLinked ||\n (effectiveMode !== \"keyword\" && effectiveMode !== \"hybrid\")\n ) {\n return linkedCorpusById;\n }\n const projectRoot = process.cwd();\n const linkedCorpusRoots = await resolveLinkedCorpusRoots(\n projectRoot,\n resolveGlobalPmRoot(projectRoot),\n );\n const linkedCorpusEntries = await Promise.all(\n filteredDocuments.map(\n async (document) =>\n [\n document.metadata.id,\n await loadLinkedCorpus(document, linkedCorpusRoots),\n ] as const,\n ),\n );\n for (const [id, corpus] of linkedCorpusEntries) {\n linkedCorpusById.set(id, corpus);\n }\n return linkedCorpusById;\n}\n\nasync function computeKeywordSearchHits(\n prepared: PreparedSearchInput,\n runtime: SearchRuntimeContext,\n filteredDocuments: ItemDocument[],\n): Promise<SearchHit[]> {\n const linkedCorpusById = await collectLinkedCorpusById(\n prepared.includeLinked,\n runtime.effectiveMode,\n filteredDocuments,\n );\n const applyCoverageBonus = prepared.matchMode === \"or\";\n return filteredDocuments\n .map((document) =>\n buildHybridLexicalScore(\n document,\n prepared.tokens,\n prepared.normalizedQuery,\n prepared.includeLinked,\n linkedCorpusById,\n runtime.tuning,\n runtime.settings.id_prefix,\n applyCoverageBonus,\n ),\n )\n .filter((entry): entry is SearchHit => entry !== null)\n .filter(\n (entry) =>\n prepared.matchMode !== \"and\" || entry.matched_all_terms === true,\n );\n}\n\nfunction buildEmptySearchResultFromContext(\n response: SearchResponseContext,\n countOnly: boolean,\n): SearchResult {\n return emptySearchResult(\n response.query,\n response.effectiveMode,\n response.matchMode,\n response.options,\n response.includeLinked,\n response.scoreThreshold,\n response.hybridSemanticWeight,\n response.queryExpansion,\n response.rerank,\n response.projection,\n response.warnings,\n response.runtimeFieldFilters,\n countOnly,\n );\n}\n\nasync function executeBuiltInBm25Search(\n prepared: PreparedSearchInput,\n runtime: SearchRuntimeContext,\n filteredDocuments: ItemDocument[],\n keywordHits: SearchHit[],\n warnings: string[],\n): Promise<SearchHit[] | null> {\n if (runtime.bm25Mode === null || runtime.effectiveMode === \"keyword\") {\n return null;\n }\n const hits = computeBuiltInBm25Hits({\n requestedMode: runtime.effectiveMode,\n query: prepared.query,\n filteredDocuments,\n keywordHits,\n corpusFields: resolveSearchCorpusFields(runtime.settings),\n bm25Params: resolveBm25Params(runtime.settings),\n hybridSemanticWeight: runtime.hybridSemanticWeight,\n });\n if (runtime.bm25Mode === \"auto-fallback\") {\n warnings.push(\n `search_${runtime.effectiveMode}_offline_bm25:no_embedding_provider:using_lexical_bm25`,\n );\n }\n return hits;\n}\n\nasync function executeExtensionSearchProvider(\n prepared: PreparedSearchInput,\n runtime: SearchRuntimeContext,\n filteredDocuments: ItemDocument[],\n filteredById: Map<string, ItemDocument>,\n): Promise<SearchHit[] | null> {\n if (!runtime.extensionSearchProvider) {\n return null;\n }\n const canUseBuiltInSemantic =\n runtime.providerResolution.active !== null &&\n (runtime.vectorResolution.active !== null ||\n runtime.extensionVectorAdapter !== null);\n try {\n const providerResponse = await Promise.resolve(\n runtime.extensionSearchProvider.query({\n query: prepared.query,\n mode: runtime.effectiveMode,\n tokens: prepared.tokens,\n options: prepared.options,\n settings: runtime.settings,\n documents: filteredDocuments,\n }),\n );\n return normalizeExtensionProviderHits(\n runtime.extensionSearchProvider.providerName,\n providerResponse,\n filteredById,\n );\n } catch (error: unknown) {\n if (!canUseBuiltInSemantic) {\n throw new PmCliError(\n `Extension search provider \"${runtime.extensionSearchProvider.providerName}\" failed: ${error instanceof Error ? error.message : String(error)}`,\n EXIT_CODE.GENERIC_FAILURE,\n );\n }\n return null;\n }\n}\n\nfunction maybeApplyNoVectorFallback(\n effectiveMode: Exclude<SearchMode, \"keyword\">,\n semanticResult: Awaited<ReturnType<typeof computeSemanticOrHybridHits>>,\n keywordHits: SearchHit[],\n warnings: string[],\n): SearchHit[] {\n if (semanticResult.vectorMatchCount > 0) {\n return semanticResult.hits;\n }\n warnings.push(\n `search_${effectiveMode}_degraded:no_vector_matches:results_are_lexical`,\n );\n return effectiveMode === \"semantic\" ? keywordHits : semanticResult.hits;\n}\n\nasync function prepareBuiltInSemanticSearch(\n runtime: SearchRuntimeContext,\n effectiveMode: Exclude<SearchMode, \"keyword\">,\n filteredDocuments: ItemDocument[],\n warnings: string[],\n modeWasExplicit: boolean,\n): Promise<void> {\n const builtInSemanticWillRun =\n !runtime.extensionSearchProvider &&\n runtime.providerResolution.active !== null &&\n (runtime.vectorResolution.active !== null ||\n runtime.extensionVectorAdapter !== null);\n if (modeWasExplicit && builtInSemanticWillRun) {\n await maybeEmitVectorIndexStaleWarning(\n runtime.pmRoot,\n filteredDocuments,\n warnings,\n );\n }\n if (!runtime.extensionSearchProvider) {\n requireSemanticDependencies(\n effectiveMode,\n runtime.providerResolution,\n runtime.vectorResolution,\n runtime.extensionVectorAdapter !== null,\n );\n }\n}\n\nasync function executeSemanticSearch(\n input: SearchModeExecutionInput,\n): Promise<SearchModeExecutionResult> {\n const {\n prepared,\n runtime,\n filteredDocuments,\n keywordHits,\n warnings,\n modeWasExplicit,\n } = input;\n let hits = keywordHits;\n const bm25Hits = await executeBuiltInBm25Search(\n prepared,\n runtime,\n filteredDocuments,\n keywordHits,\n warnings,\n );\n const semanticMode = runtime.effectiveMode;\n if (bm25Hits !== null || semanticMode === \"keyword\") {\n return { effectiveMode: runtime.effectiveMode, hits: bm25Hits ?? hits };\n }\n try {\n await prepareBuiltInSemanticSearch(\n runtime,\n semanticMode,\n filteredDocuments,\n warnings,\n modeWasExplicit,\n );\n if (filteredDocuments.length === 0 || prepared.limit === 0) {\n return { effectiveMode: runtime.effectiveMode, hits: [] };\n }\n const filteredById = new Map(\n filteredDocuments.map((document) => [document.metadata.id, document]),\n );\n hits =\n (await executeExtensionSearchProvider(\n prepared,\n runtime,\n filteredDocuments,\n filteredById,\n )) ?? hits;\n if (hits === keywordHits) {\n const { provider, vectorStore } = requireSemanticDependencies(\n semanticMode,\n runtime.providerResolution,\n runtime.vectorResolution,\n runtime.extensionVectorAdapter !== null,\n );\n const semanticResult = await computeSemanticOrHybridHits({\n requestedMode: semanticMode,\n query: prepared.query,\n filteredDocuments,\n keywordHits,\n hybridSemanticWeight: runtime.hybridSemanticWeight,\n limit: prepared.limit,\n maxResults: runtime.maxResults,\n provider,\n vectorStore,\n extensionVectorAdapter: runtime.extensionVectorAdapter,\n queryExpansion: runtime.queryExpansion,\n queryExpansionExtension: runtime.queryExpansionExtension,\n rerank: runtime.rerank,\n rerankExtension: runtime.rerankExtension,\n warnings,\n settings: runtime.settings,\n });\n hits = maybeApplyNoVectorFallback(\n semanticMode,\n semanticResult,\n keywordHits,\n warnings,\n );\n }\n return { effectiveMode: runtime.effectiveMode, hits };\n } catch (error: unknown) {\n warnings.push(\n buildExplicitSemanticFallbackWarning(runtime.effectiveMode, error),\n );\n return { effectiveMode: \"keyword\", hits: keywordHits };\n }\n}\n\nfunction buildCountOnlySearchResult(\n response: SearchResponseContext,\n total: number,\n): SearchResult {\n if (\n response.projection.mode === \"compact\" &&\n response.options.compact === true\n ) {\n return withSearchWarnings(\n {\n query: response.query.trim(),\n mode: response.effectiveMode,\n items: [],\n count: total,\n total,\n count_only: true,\n filters: buildCompactSearchFilterSummary({\n mode: response.effectiveMode,\n matchMode: response.matchMode,\n options: response.options,\n includeLinked: response.includeLinked,\n titleExact: response.titleExact,\n phraseExact: response.phraseExact,\n scoreThreshold: response.scoreThreshold,\n hybridSemanticWeight: response.hybridSemanticWeight,\n runtimeFieldFilters: response.runtimeFieldFilters,\n }),\n },\n response.warnings,\n );\n }\n const projectionFields =\n response.projection.mode === \"full\"\n ? null\n : [...response.projection.fields];\n return withSearchWarnings(\n {\n query: response.query.trim(),\n mode: response.effectiveMode,\n items: [],\n count: total,\n total,\n count_only: true,\n filters: buildVerboseSearchFilters({\n effectiveMode: response.effectiveMode,\n matchMode: response.matchMode,\n options: response.options,\n includeLinked: response.includeLinked,\n titleExact: response.titleExact,\n phraseExact: response.phraseExact,\n scoreThreshold: response.scoreThreshold,\n hybridSemanticWeight: response.hybridSemanticWeight,\n queryExpansion: response.queryExpansion,\n rerank: response.rerank,\n runtimeFieldFilters: response.runtimeFieldFilters,\n }),\n projection: {\n mode: response.projection.mode,\n fields: projectionFields,\n },\n now: nowIso(),\n },\n response.warnings,\n );\n}\n\nfunction withSearchWarnings(\n result: SearchResult,\n warnings: string[],\n): SearchResult {\n if (warnings.length === 0) {\n return result;\n }\n return { ...result, warnings };\n}\n\nfunction attachSearchHighlights(\n prepared: PreparedSearchInput,\n filteredDocuments: ItemDocument[],\n limited: SearchHit[],\n): { hits: SearchHit[]; projection: SearchProjectionConfig } {\n if (!prepared.highlight) {\n return { hits: limited, projection: prepared.projection };\n }\n const documentById = new Map(\n filteredDocuments.map((document) => [document.metadata.id, document]),\n );\n const hits = limited.map((hit) => ({\n ...hit,\n highlights: buildHitHighlights(\n documentById.get(hit.item.id)!,\n hit.matched_fields,\n prepared.tokens,\n ),\n }));\n if (\n prepared.projection.mode === \"full\" ||\n prepared.projection.fields.includes(\"highlights\")\n ) {\n return { hits, projection: prepared.projection };\n }\n return {\n hits,\n projection: {\n mode: prepared.projection.mode,\n fields: [...prepared.projection.fields, \"highlights\"],\n },\n };\n}\n\nfunction buildSearchResultForHits(\n response: SearchResponseContext,\n projectedItems: SearchResultItem[],\n total: number,\n limitedCount: number,\n effectiveProjection: SearchProjectionConfig,\n pageExtras: {\n has_more?: boolean;\n next_cursor?: string;\n applied_limit: number;\n truncated?: true;\n },\n): SearchResult {\n const truncationExtras = limitedCount < total ? { total } : {};\n if (\n response.projection.mode === \"compact\" &&\n response.options.compact === true\n ) {\n return withSearchWarnings(\n {\n query: response.query.trim(),\n mode: response.effectiveMode,\n items: projectedItems,\n count: projectedItems.length,\n ...truncationExtras,\n ...pageExtras,\n filters: buildCompactSearchFilterSummary({\n mode: response.effectiveMode,\n matchMode: response.matchMode,\n options: response.options,\n includeLinked: response.includeLinked,\n titleExact: response.titleExact,\n phraseExact: response.phraseExact,\n scoreThreshold: response.scoreThreshold,\n hybridSemanticWeight: response.hybridSemanticWeight,\n runtimeFieldFilters: response.runtimeFieldFilters,\n }),\n },\n response.warnings,\n );\n }\n const finalProjectionFields =\n effectiveProjection.mode === \"full\"\n ? null\n : [...effectiveProjection.fields];\n return {\n query: response.query.trim(),\n mode: response.effectiveMode,\n items: projectedItems,\n count: projectedItems.length,\n ...truncationExtras,\n ...pageExtras,\n filters: buildVerboseSearchFilters({\n effectiveMode: response.effectiveMode,\n matchMode: response.matchMode,\n options: response.options,\n includeLinked: response.includeLinked,\n titleExact: response.titleExact,\n phraseExact: response.phraseExact,\n scoreThreshold: response.scoreThreshold,\n hybridSemanticWeight: response.hybridSemanticWeight,\n queryExpansion: response.queryExpansion,\n rerank: response.rerank,\n runtimeFieldFilters: response.runtimeFieldFilters,\n }),\n projection: {\n mode: effectiveProjection.mode,\n fields: finalProjectionFields,\n },\n now: nowIso(),\n ...(response.warnings.length > 0 ? { warnings: response.warnings } : {}),\n };\n}\n\nfunction assertSearchPagingOptions(options: SearchOptions): void {\n if (options.after !== undefined && options.count === true) {\n throw new PmCliError(\n \"Search --after cannot be combined with --count.\",\n EXIT_CODE.USAGE,\n );\n }\n}\n\n/** Implements run search for the public runtime surface of this module. */\nexport async function runSearch(\n rawQuery: string,\n rawOptions: SearchOptions,\n global: GlobalOptions,\n): Promise<SearchResult> {\n assertSearchPagingOptions(rawOptions);\n const prepared = prepareSearchInput(rawQuery, rawOptions);\n const runtime = await resolveSearchRuntimeContext(prepared, global);\n const corpus = await loadFilteredSearchCorpus(prepared, runtime);\n const warnings = corpus.warnings;\n warnings.push(...prepared.inlineWarnings);\n if (\n runtime.effectiveMode === \"hybrid\" &&\n runtime.semanticWeightProvided &&\n runtime.semanticWeightOverride === undefined\n ) {\n warnings.push(\n \"search_hybrid_semantic_weight_override_invalid:using_settings_default\",\n );\n }\n const responseBase = {\n query: prepared.query,\n matchMode: prepared.matchMode,\n options: prepared.options,\n includeLinked: prepared.includeLinked,\n titleExact: prepared.titleExact,\n phraseExact: prepared.phraseExact,\n scoreThreshold: runtime.scoreThreshold,\n hybridSemanticWeight: runtime.hybridSemanticWeight,\n queryExpansion: runtime.queryExpansion,\n rerank: runtime.rerank,\n projection: prepared.projection,\n warnings,\n runtimeFieldFilters: runtime.runtimeFieldFilters,\n };\n if (\n runtime.effectiveMode === \"keyword\" &&\n (corpus.filteredDocuments.length === 0 || prepared.limit === 0)\n ) {\n return buildEmptySearchResultFromContext(\n { ...responseBase, effectiveMode: runtime.effectiveMode },\n prepared.countOnly,\n );\n }\n const keywordHits = await computeKeywordSearchHits(\n prepared,\n runtime,\n corpus.filteredDocuments,\n );\n const modeResult = await executeSemanticSearch({\n prepared,\n runtime,\n filteredDocuments: corpus.filteredDocuments,\n keywordHits,\n warnings,\n modeWasExplicit: prepared.modeWasExplicit,\n });\n if (\n modeResult.effectiveMode !== \"keyword\" &&\n modeResult.hits.length === 0 &&\n (corpus.filteredDocuments.length === 0 || prepared.limit === 0)\n ) {\n return buildEmptySearchResultFromContext(\n { ...responseBase, effectiveMode: modeResult.effectiveMode },\n prepared.countOnly,\n );\n }\n const thresholded = modeResult.hits.filter(\n (entry) =>\n entry.exact_id_match === true || entry.score >= runtime.scoreThreshold,\n );\n const sorted = sortHits(thresholded, runtime.statusRegistry);\n const total = sorted.length;\n const page = resolveSearchPage({\n sorted,\n query: prepared.query,\n mode: modeResult.effectiveMode,\n searchOptions: prepared.options,\n limit: prepared.limit ?? runtime.maxResults,\n });\n const response = { ...responseBase, effectiveMode: modeResult.effectiveMode };\n if (prepared.countOnly) {\n return buildCountOnlySearchResult(response, total);\n }\n const { hits: projectedHits, projection: effectiveProjection } =\n attachSearchHighlights(prepared, corpus.filteredDocuments, page.limited);\n const projectedItems = projectSearchHits(projectedHits, effectiveProjection);\n return buildSearchResultForHits(\n response,\n projectedItems,\n total,\n page.limited.length,\n effectiveProjection,\n page.pageExtras,\n );\n}\n","/**\n * @module core/shared/text-normalization\n *\n * Provides shared primitives and utilities for Text Normalization.\n */\n/** Normalizes text to lowercase whitespace-collapsed form for stable matching and comparison. */\nexport function normalizeLowercaseWhitespace(value: string): string {\n return value.trim().toLowerCase().replace(/\\s+/g, \" \");\n}\n\n/** Implements tokenize alpha numeric for the public runtime surface of this module. */\nexport function tokenizeAlphaNumeric(value: string): string[] {\n return normalizeLowercaseWhitespace(value)\n .split(/[^a-z0-9]+/)\n .filter((token) => token.length > 0);\n}\n\n/** Implements jaccard similarity for the public runtime surface of this module. */\nexport function jaccardSimilarity(\n leftTokens: string[],\n rightTokens: string[],\n): number {\n if (leftTokens.length === 0 && rightTokens.length === 0) {\n return 1;\n }\n if (leftTokens.length === 0 || rightTokens.length === 0) {\n return 0;\n }\n const leftSet = new Set(leftTokens);\n const rightSet = new Set(rightTokens);\n let intersection = 0;\n for (const token of leftSet) {\n if (rightSet.has(token)) {\n intersection += 1;\n }\n }\n // Both token sets are non-empty here (guarded above), so union is always >= 1.\n const union = new Set([...leftSet, ...rightSet]).size;\n return intersection / union;\n}\n","/**\n * @module core/search/relevance\n *\n * Powers search, embeddings, and semantic retrieval behavior for Relevance.\n */\nimport type { PmSettings } from \"../../types.js\";\nimport {\n coercePositiveInteger,\n toNonEmptyString,\n} from \"../shared/primitives.js\";\nimport { tokenizeAlphaNumeric } from \"../shared/text-normalization.js\";\nimport {\n executeEmbeddingRequest,\n type EmbeddingProviderConfig,\n} from \"./providers.js\";\n\n/** Fallback query expansion max queries used when callers do not provide an override. */\nexport const DEFAULT_QUERY_EXPANSION_MAX_QUERIES = 4;\n/** Fallback rerank top k used when callers do not provide an override. */\nexport const DEFAULT_RERANK_TOP_K = 20;\nconst MAX_RERANK_TOP_K = 200;\n\nconst QUERY_EXPANSION_STOP_WORDS = new Set([\n \"a\",\n \"an\",\n \"and\",\n \"for\",\n \"from\",\n \"in\",\n \"into\",\n \"of\",\n \"on\",\n \"or\",\n \"the\",\n \"to\",\n \"with\",\n]);\n\n/** Documents the query expansion config payload exchanged by command, SDK, and package integrations. */\nexport interface QueryExpansionConfig {\n /** Whether enabled applies to this operation. */\n enabled: boolean;\n /** Value that configures or reports provider for this contract. */\n provider: string | null;\n /** Value that configures or reports max queries for this contract. */\n max_queries: number;\n}\n\n/** Documents the rerank config payload exchanged by command, SDK, and package integrations. */\nexport interface RerankConfig {\n /** Whether enabled applies to this operation. */\n enabled: boolean;\n /** Value that configures or reports model for this contract. */\n model: string;\n /** Value that configures or reports top k for this contract. */\n top_k: number;\n}\n\n/** Documents the rerank candidate payload exchanged by command, SDK, and package integrations. */\nexport interface RerankCandidate {\n /** Stable identifier used to reference this record across commands and storage. */\n id: string;\n /** Value that configures or reports text for this contract. */\n text: string;\n}\n\n/** Documents the rerank scored hit payload exchanged by command, SDK, and package integrations. */\nexport interface RerankScoredHit {\n /** Stable identifier used to reference this record across commands and storage. */\n id: string;\n /** Value that configures or reports score for this contract. */\n score: number;\n}\n\nfunction dedupeQueries(values: string[], limit: number): string[] {\n const deduped: string[] = [];\n const seen = new Set<string>();\n for (const entry of values) {\n const normalized = entry.trim().replaceAll(/\\s+/g, \" \");\n if (normalized.length === 0) {\n continue;\n }\n const dedupeKey = normalized.toLowerCase();\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n deduped.push(normalized);\n if (deduped.length >= limit) {\n break;\n }\n }\n return deduped;\n}\n\nfunction singularizeSimple(token: string): string {\n const normalizedToken = token.toLowerCase();\n if (normalizedToken.length > 4 && normalizedToken.endsWith(\"ies\")) {\n return `${normalizedToken.slice(0, -3)}y`;\n }\n if (\n normalizedToken.length > 4 &&\n (normalizedToken.endsWith(\"ches\") ||\n normalizedToken.endsWith(\"shes\") ||\n normalizedToken.endsWith(\"xes\") ||\n normalizedToken.endsWith(\"zes\") ||\n normalizedToken.endsWith(\"sses\"))\n ) {\n return normalizedToken.slice(0, -2);\n }\n if (\n normalizedToken.length > 3 &&\n normalizedToken.endsWith(\"s\") &&\n !normalizedToken.endsWith(\"ss\") &&\n !normalizedToken.endsWith(\"us\") &&\n !normalizedToken.endsWith(\"is\") &&\n !normalizedToken.endsWith(\"as\")\n ) {\n return normalizedToken.slice(0, -1);\n }\n return normalizedToken;\n}\n\nfunction pluralizeSimple(token: string): string {\n const normalizedToken = token.toLowerCase();\n if (\n normalizedToken.length > 2 &&\n (!normalizedToken.endsWith(\"s\") || normalizedToken.endsWith(\"ss\"))\n ) {\n if (normalizedToken.endsWith(\"y\") && !/[aeiou]y$/u.test(normalizedToken)) {\n return `${normalizedToken.slice(0, -1)}ies`;\n }\n if (\n normalizedToken.endsWith(\"ch\") ||\n normalizedToken.endsWith(\"sh\") ||\n normalizedToken.endsWith(\"x\") ||\n normalizedToken.endsWith(\"z\") ||\n normalizedToken.endsWith(\"ss\")\n ) {\n return `${normalizedToken}es`;\n }\n return `${normalizedToken}s`;\n }\n return normalizedToken;\n}\n\n/** Implements build deterministic query expansions for the public runtime surface of this module. */\nexport function buildDeterministicQueryExpansions(\n query: string,\n maxQueries = DEFAULT_QUERY_EXPANSION_MAX_QUERIES,\n): string[] {\n const normalizedQuery = query.trim().replaceAll(/\\s+/g, \" \");\n if (normalizedQuery.length === 0) {\n return [];\n }\n const tokens = tokenizeAlphaNumeric(normalizedQuery);\n if (tokens.length === 0) {\n return [normalizedQuery];\n }\n const contentTokens = tokens.filter(\n (token) => !QUERY_EXPANSION_STOP_WORDS.has(token.toLowerCase()),\n );\n const singularized = tokens.map((token) => singularizeSimple(token));\n const pluralized = contentTokens.map((token) => pluralizeSimple(token));\n return dedupeQueries(\n [\n normalizedQuery,\n tokens.join(\" \"),\n contentTokens.join(\" \"),\n singularized.join(\" \"),\n pluralized.join(\" \"),\n ],\n Math.max(1, maxQueries),\n );\n}\n\n/** Implements normalize query expansion output for the public runtime surface of this module. */\nexport function normalizeQueryExpansionOutput(raw: unknown): string[] {\n const rawQueries = Array.isArray(raw)\n ? raw\n : (raw as { queries?: unknown } | null | undefined)?.queries;\n if (!Array.isArray(rawQueries)) {\n return [];\n }\n return dedupeQueries(\n rawQueries.filter((entry): entry is string => typeof entry === \"string\"),\n DEFAULT_QUERY_EXPANSION_MAX_QUERIES,\n );\n}\n\n/** Implements merge query expansions for the public runtime surface of this module. */\nexport function mergeQueryExpansions(\n base: string[],\n extra: string[],\n maxQueries: number,\n): string[] {\n return dedupeQueries([...base, ...extra], Math.max(1, maxQueries));\n}\n\n/** Implements resolve query expansion config for the public runtime surface of this module. */\nexport function resolveQueryExpansionConfig(\n settings: PmSettings,\n fallbackProviderName: string | null,\n): QueryExpansionConfig {\n const search = (\n settings as {\n search?: { query_expansion?: { enabled?: unknown; provider?: unknown } };\n }\n ).search;\n const queryExpansion = search?.query_expansion;\n const configuredProvider = toNonEmptyString(queryExpansion?.provider);\n return {\n enabled: queryExpansion?.enabled === true,\n provider: configuredProvider ?? fallbackProviderName,\n max_queries: DEFAULT_QUERY_EXPANSION_MAX_QUERIES,\n };\n}\n\n/** Implements resolve rerank config for the public runtime surface of this module. */\nexport function resolveRerankConfig(\n settings: PmSettings,\n fallbackModel: string,\n): RerankConfig {\n const search = (\n settings as {\n search?: {\n rerank?: { enabled?: unknown; model?: unknown; top_k?: unknown };\n };\n }\n ).search;\n const rerank = search?.rerank;\n const configuredModel = toNonEmptyString(rerank?.model);\n const configuredTopK = coercePositiveInteger(rerank?.top_k);\n const normalizedTopK = configuredTopK ?? DEFAULT_RERANK_TOP_K;\n return {\n enabled: rerank?.enabled === true,\n model: configuredModel ?? fallbackModel,\n top_k: Math.min(MAX_RERANK_TOP_K, normalizedTopK),\n };\n}\n\n/** Implements normalize rerank output for the public runtime surface of this module. */\nexport function normalizeRerankOutput(raw: unknown): RerankScoredHit[] {\n const rawHits = Array.isArray(raw)\n ? raw\n : (raw as { hits?: unknown } | null | undefined)?.hits;\n if (!Array.isArray(rawHits)) {\n return [];\n }\n const bestById = new Map<string, number>();\n for (const entry of rawHits) {\n if (typeof entry !== \"object\" || entry === null) {\n continue;\n }\n const id = toNonEmptyString((entry as { id?: unknown }).id);\n const score = (entry as { score?: unknown }).score;\n if (!id || typeof score !== \"number\" || !Number.isFinite(score)) {\n continue;\n }\n const existing = bestById.get(id);\n if (existing === undefined || score > existing) {\n bestById.set(id, score);\n }\n }\n const normalized = [...bestById.entries()].map(([id, score]) => ({\n id,\n score,\n }));\n normalized.sort((left, right) => {\n if (left.score !== right.score) {\n return right.score - left.score;\n }\n return left.id.localeCompare(right.id);\n });\n return normalized;\n}\n\nfunction dotProduct(left: number[], right: number[]): number {\n const size = left.length;\n let result = 0;\n for (let index = 0; index < size; index += 1) {\n result += left[index] * right[index];\n }\n return result;\n}\n\nfunction l2Norm(vector: number[]): number {\n let sumSquares = 0;\n for (let index = 0; index < vector.length; index += 1) {\n sumSquares += vector[index] * vector[index];\n }\n return Math.sqrt(sumSquares);\n}\n\nfunction cosineSimilarityWithKnownLeftNorm(\n left: number[] | null | undefined,\n right: number[] | null | undefined,\n leftNorm: number,\n): number {\n if (\n !left ||\n !right ||\n left.length === 0 ||\n right.length === 0 ||\n left.length !== right.length\n ) {\n return 0;\n }\n const numerator = dotProduct(left, right);\n const rightNorm = l2Norm(right);\n const denominator = leftNorm * rightNorm;\n if (\n !Number.isFinite(numerator) ||\n !Number.isFinite(leftNorm) ||\n !Number.isFinite(rightNorm) ||\n !Number.isFinite(denominator) ||\n denominator === 0\n ) {\n return 0;\n }\n return Math.max(-1, Math.min(1, numerator / denominator));\n}\n\n/** Implements rerank candidates with embeddings for the public runtime surface of this module. */\nexport async function rerankCandidatesWithEmbeddings(\n provider: EmbeddingProviderConfig,\n model: string,\n query: string,\n candidates: RerankCandidate[],\n timeoutMs?: number,\n): Promise<Map<string, number>> {\n if (candidates.length === 0) {\n return new Map();\n }\n const effectiveModel = toNonEmptyString(model) ?? provider.model;\n const rerankProvider: EmbeddingProviderConfig =\n effectiveModel === provider.model\n ? provider\n : { ...provider, model: effectiveModel };\n const payload = [query.trim(), ...candidates.map((entry) => entry.text)];\n const vectors = await executeEmbeddingRequest(\n rerankProvider,\n payload,\n timeoutMs ? { timeout_ms: timeoutMs } : {},\n );\n const queryVector = vectors[0];\n if (!queryVector) {\n return new Map();\n }\n const queryNorm = l2Norm(queryVector);\n const scoreById = new Map<string, number>();\n for (let index = 0; index < candidates.length; index += 1) {\n const candidate = candidates[index];\n const candidateVector = vectors[index + 1];\n if (!candidateVector) {\n continue;\n }\n const similarity = cosineSimilarityWithKnownLeftNorm(\n queryVector,\n candidateVector,\n queryNorm,\n );\n scoreById.set(candidate.id, Math.max(0, Math.min(1, (similarity + 1) / 2)));\n }\n return scoreById;\n}\n","/**\n * @module core/search/bm25\n *\n * Offline BM25 lexical retrieval (pm-75k9). Provides an Okapi BM25 ranker that\n * scores the in-memory item corpus with no embedding service, vector store, or\n * network dependency, so semantic/hybrid search degrades to a dense-quality\n * lexical ranker — rather than the naive field-weighted scorer — in air-gapped,\n * CI, and zero-setup environments.\n *\n * BM25 improves on raw term-frequency counting in three ways the legacy keyword\n * scorer cannot: inverse document frequency down-weights terms common across the\n * whole corpus, term-frequency saturation (`k1`) caps the contribution of a term\n * repeated many times in one document, and length normalization (`b`) prevents\n * long documents from dominating purely by size.\n */\nimport type { PmSettings } from \"../../types/index.js\";\nimport { tokenizeAlphaNumeric } from \"../shared/text-normalization.js\";\n\n/** Default Okapi BM25 term-frequency saturation parameter. `1.2` is the widely used Lucene/Elasticsearch default: higher values reduce the diminishing returns of repeated terms more slowly (terms keep accruing weight), lower values saturate sooner. */\nexport const DEFAULT_BM25_K1 = 1.2;\n\n/** Default Okapi BM25 length-normalization parameter. `0.75` is the Lucene default: `0` disables length normalization entirely, `1` fully normalizes a document's score by its length relative to the corpus average. */\nexport const DEFAULT_BM25_B = 0.75;\n\n/**\n * Resolved BM25 tuning parameters. Both are clamped to sane ranges by\n * {@link resolveBm25Params} before scoring.\n */\nexport interface Bm25Params {\n /** Term-frequency saturation (`k1`); finite and `>= 0`. */\n k1: number;\n /** Length normalization (`b`); finite and within `[0, 1]`. */\n b: number;\n}\n\n/**\n * One corpus document supplied to {@link buildBm25Index}: a stable id and the\n * already-concatenated searchable text. Callers build the text from whichever\n * fields they want indexed (typically the resolved `search.corpus_fields`).\n */\nexport interface Bm25Document {\n /** Stable identifier used to reference this record across commands and storage. */\n id: string;\n /** Value that configures or reports text for this contract. */\n text: string;\n}\n\n/**\n * Per-document statistics retained in a {@link Bm25Index}: the term-frequency\n * map and the document length (total token count) used for length\n * normalization.\n */\ninterface Bm25DocumentStats {\n id: string;\n termFrequencies: Map<string, number>;\n length: number;\n}\n\n/**\n * An immutable BM25 index built from a document set. Carries the per-document\n * term frequencies, per-term document frequencies, corpus size, and average\n * document length needed to score any query. Build once per query batch with\n * {@link buildBm25Index}, then score with {@link scoreBm25Query}.\n */\nexport interface Bm25Index {\n /** Value that configures or reports documents for this contract. */\n documents: Bm25DocumentStats[];\n /** Value that configures or reports document frequency for this contract. */\n documentFrequency: Map<string, number>;\n /** Number of document entries represented by this result. */\n documentCount: number;\n /** Value that configures or reports average document length for this contract. */\n averageDocumentLength: number;\n}\n\n/**\n * Tokenize a document/query string into BM25 terms. Shares\n * {@link tokenizeAlphaNumeric} with the lexical scorer so the BM25 vocabulary is\n * identical to the rest of search: lowercase, alphanumeric runs, no stop-word\n * removal or stemming (kept deliberately simple and language-agnostic).\n */\nexport function tokenizeBm25(text: string): string[] {\n return tokenizeAlphaNumeric(text);\n}\n\n/** Count occurrences of each token in a token list. */\nfunction buildTermFrequencies(tokens: string[]): Map<string, number> {\n const frequencies = new Map<string, number>();\n for (const token of tokens) {\n frequencies.set(token, (frequencies.get(token) ?? 0) + 1);\n }\n return frequencies;\n}\n\n/**\n * Build a BM25 index from a corpus. Computes each document's term frequencies\n * and length, the per-term document frequency, the corpus size, and the average\n * document length. Empty documents (no tokens) are retained with length `0` so\n * they can still be scored (they simply never match a query term). An empty\n * corpus yields an index with `averageDocumentLength` `0`, which\n * {@link scoreBm25Query} handles without dividing by zero.\n */\nexport function buildBm25Index(documents: Bm25Document[]): Bm25Index {\n const stats: Bm25DocumentStats[] = [];\n const documentFrequency = new Map<string, number>();\n let totalLength = 0;\n for (const document of documents) {\n const tokens = tokenizeBm25(document.text);\n const termFrequencies = buildTermFrequencies(tokens);\n totalLength += tokens.length;\n for (const term of termFrequencies.keys()) {\n documentFrequency.set(term, (documentFrequency.get(term) ?? 0) + 1);\n }\n stats.push({ id: document.id, termFrequencies, length: tokens.length });\n }\n const documentCount = stats.length;\n return {\n documents: stats,\n documentFrequency,\n documentCount,\n averageDocumentLength: documentCount > 0 ? totalLength / documentCount : 0,\n };\n}\n\n/** Inverse document frequency for one term using the BM25 \"plus-one\" variant (`ln(1 + (N - n + 0.5) / (n + 0.5))`) used by Lucene. The `1 +` inside the logarithm keeps the IDF strictly non-negative even for a term that appears in every document, so a common term can never subtract from a document's score. */\nfunction inverseDocumentFrequency(\n documentCount: number,\n termDocumentFrequency: number,\n): number {\n return Math.log(\n 1 +\n (documentCount - termDocumentFrequency + 0.5) /\n (termDocumentFrequency + 0.5),\n );\n}\n\n/** Score every document in the index against a query and return an id → score map containing only documents with a strictly positive score (a document that matches no query term is omitted, mirroring the lexical scorer's \"no match → no hit\" contract). Query tokens are de-duplicated so a token repeated in the query does not multiply its own contribution. Returns an empty map for an empty index, an empty query, or a query whose terms appear in no document. */\nexport function scoreBm25Query(\n index: Bm25Index,\n queryTokens: string[],\n params: Bm25Params,\n): Map<string, number> {\n const scores = new Map<string, number>();\n // Empty corpus, or a corpus where every document is empty (avgdl 0): no term\n // can match, so return early. Guarding here also guarantees a non-zero\n // average document length below, keeping the length-normalization division\n // safe without an unreachable fallback branch.\n if (index.documentCount === 0 || index.averageDocumentLength === 0) {\n return scores;\n }\n const distinctQueryTerms = [\n ...new Set(queryTokens.filter((token) => token.length > 0)),\n ];\n if (distinctQueryTerms.length === 0) {\n return scores;\n }\n // Precompute the IDF for each query term once rather than per document.\n const idfByTerm = new Map<string, number>();\n for (const term of distinctQueryTerms) {\n const termDocumentFrequency = index.documentFrequency.get(term);\n if (termDocumentFrequency === undefined) {\n continue;\n }\n idfByTerm.set(\n term,\n inverseDocumentFrequency(index.documentCount, termDocumentFrequency),\n );\n }\n if (idfByTerm.size === 0) {\n return scores;\n }\n for (const document of index.documents) {\n let score = 0;\n for (const [term, idf] of idfByTerm) {\n const termFrequency = document.termFrequencies.get(term);\n if (termFrequency === undefined) {\n continue;\n }\n const lengthNormalization =\n 1 -\n params.b +\n (params.b * document.length) / index.averageDocumentLength;\n const denominator = termFrequency + params.k1 * lengthNormalization;\n score += idf * ((termFrequency * (params.k1 + 1)) / denominator);\n }\n if (score > 0) {\n scores.set(document.id, score);\n }\n }\n return scores;\n}\n\n/** Coerce one persisted BM25 parameter to a finite number within `[min, max]`. A finite number is clamped to the range (preserving user intent — e.g. `k1=5000` becomes `1000` rather than being silently ignored); any non-number or non-finite value (string, `NaN`, `Infinity`, missing) falls back to `fallback` so a malformed `settings.json` can never crash or skew scoring. */\nfunction resolveClampedParam(\n candidate: unknown,\n fallback: number,\n min: number,\n max: number,\n): number {\n if (typeof candidate !== \"number\" || !Number.isFinite(candidate)) {\n return fallback;\n }\n return Math.min(max, Math.max(min, candidate));\n}\n\n/** Flatten a structured search-corpus record (the shape produced by `buildSearchCorpus`) into a single whitespace-joined string of its *values* only — field names/object keys are deliberately excluded so corpus-wide keys (`title`, `description`, …) never enter the BM25 vocabulary and skew IDF. Strings and numbers contribute their text; arrays and nested objects (tags, dependencies, the plan corpus) are walked recursively; everything else is dropped. */\nexport function flattenSearchCorpusText(\n corpus: Record<string, unknown>,\n): string {\n const collectValueText = (value: unknown): string[] => {\n if (typeof value === \"string\") {\n return [value];\n }\n if (typeof value === \"number\") {\n return [String(value)];\n }\n if (Array.isArray(value)) {\n return value.flatMap(collectValueText);\n }\n if (typeof value === \"object\" && value !== null) {\n return Object.values(value).flatMap(collectValueText);\n }\n return [];\n };\n return collectValueText(Object.values(corpus)).join(\" \");\n}\n\n/**\n * Resolve the effective BM25 parameters from `settings.search.bm25`, applying\n * {@link DEFAULT_BM25_K1}/{@link DEFAULT_BM25_B} when unset and clamping `k1` to\n * `[0, 1000]` and `b` to `[0, 1]`. Tolerant of partial/invalid config: each\n * knob is resolved independently so one bad value does not discard the other.\n */\nexport function resolveBm25Params(\n settings: Pick<PmSettings, \"search\"> | undefined,\n): Bm25Params {\n const bm25 = (\n settings?.search as { bm25?: { k1?: unknown; b?: unknown } } | undefined\n )?.bm25;\n return {\n k1: resolveClampedParam(bm25?.k1, DEFAULT_BM25_K1, 0, 1_000),\n b: resolveClampedParam(bm25?.b, DEFAULT_BM25_B, 0, 1),\n };\n}\n","/**\n * @module cli/commands/search-rendering\n *\n * Builds stable compact and verbose filter projections for search responses.\n */\nimport {\n applyFilterValueEcho,\n buildContentFilterEcho,\n buildGovernanceMissingFilterEcho,\n} from \"./list.js\";\nimport type { SearchMatchMode, SearchOptions } from \"./search.js\";\n\n/** Search execution modes represented in response metadata. */\nexport type SearchMode = \"keyword\" | \"semantic\" | \"hybrid\";\n\ninterface SearchRenderingQueryExpansion {\n enabled: boolean;\n provider: string | null;\n}\n\ninterface SearchRenderingRerank {\n enabled: boolean;\n model: string;\n top_k: number;\n}\n\nfunction isAllStatuses(value: unknown): boolean {\n if (typeof value !== \"string\") return false;\n const tokens = value\n .split(\",\")\n .map((entry) => entry.trim().toLowerCase())\n .filter(Boolean);\n return tokens.length === 1 && tokens[0] === \"all\";\n}\n\nconst COMPACT_SEARCH_VALUE_FILTER_ECHO_ENTRIES = [\n {\n optionKey: \"status\",\n summaryKey: \"status\",\n normalize: (value: unknown) => (isAllStatuses(value) ? \"all\" : value),\n },\n { optionKey: \"type\", summaryKey: \"type\" },\n { optionKey: \"tag\", summaryKey: \"tag\" },\n { optionKey: \"priority\", summaryKey: \"priority\" },\n { optionKey: \"deadlineBefore\", summaryKey: \"deadline_before\" },\n { optionKey: \"deadlineAfter\", summaryKey: \"deadline_after\" },\n { optionKey: \"updatedAfter\", summaryKey: \"updated_after\" },\n { optionKey: \"updatedBefore\", summaryKey: \"updated_before\" },\n { optionKey: \"createdAfter\", summaryKey: \"created_after\" },\n { optionKey: \"createdBefore\", summaryKey: \"created_before\" },\n { optionKey: \"assignee\", summaryKey: \"assignee\" },\n { optionKey: \"sprint\", summaryKey: \"sprint\" },\n { optionKey: \"release\", summaryKey: \"release\" },\n { optionKey: \"parent\", summaryKey: \"parent\" },\n] as const;\n\n/** Builds the token-efficient filter echo used by compact search results. */\nexport function buildCompactSearchFilterSummary(params: {\n mode: SearchMode;\n matchMode: SearchMatchMode;\n options: SearchOptions;\n includeLinked: boolean;\n titleExact: boolean;\n phraseExact: boolean;\n scoreThreshold: number;\n hybridSemanticWeight: number;\n runtimeFieldFilters?: Record<string, unknown>;\n}): Record<string, unknown> {\n const { mode, matchMode, options, includeLinked, titleExact, phraseExact, scoreThreshold, hybridSemanticWeight, runtimeFieldFilters } = params;\n const filters: Record<string, unknown> = {};\n applyFilterValueEcho(filters, options, COMPACT_SEARCH_VALUE_FILTER_ECHO_ENTRIES);\n Object.assign(filters, buildGovernanceMissingFilterEcho(options as Record<string, unknown>));\n Object.assign(filters, buildContentFilterEcho(options as Record<string, unknown>));\n if (matchMode !== \"or\") filters.match_mode = matchMode;\n if (includeLinked) filters.include_linked = true;\n if (titleExact) filters.title_exact = true;\n if (phraseExact) filters.phrase_exact = true;\n if (scoreThreshold > 0) filters.score_threshold = scoreThreshold;\n if (mode === \"hybrid\" && options.semanticWeight !== undefined) {\n filters.hybrid_semantic_weight = hybridSemanticWeight;\n }\n if (options.limit !== undefined) filters.limit = options.limit;\n if (runtimeFieldFilters && Object.keys(runtimeFieldFilters).length > 0) {\n filters.runtime_filters = runtimeFieldFilters;\n }\n return filters;\n}\n\n/** Builds the complete filter echo shared by verbose search response paths. */\nexport function buildVerboseSearchFilters(params: {\n effectiveMode: SearchMode;\n matchMode: SearchMatchMode;\n options: SearchOptions;\n includeLinked: boolean;\n titleExact: boolean;\n phraseExact: boolean;\n scoreThreshold: number;\n hybridSemanticWeight: number;\n queryExpansion: SearchRenderingQueryExpansion;\n rerank: SearchRenderingRerank;\n runtimeFieldFilters: Record<string, unknown>;\n}): Record<string, unknown> {\n const { effectiveMode, matchMode, options, includeLinked, titleExact, phraseExact, scoreThreshold, hybridSemanticWeight, queryExpansion, rerank, runtimeFieldFilters } = params;\n const valueOrNull = (value: unknown): unknown => value ?? null;\n return {\n mode: effectiveMode,\n match_mode: matchMode,\n status: isAllStatuses(options.status) ? \"all\" : valueOrNull(options.status),\n type: valueOrNull(options.type),\n tag: valueOrNull(options.tag),\n priority: valueOrNull(options.priority),\n deadline_before: valueOrNull(options.deadlineBefore),\n deadline_after: valueOrNull(options.deadlineAfter),\n updated_after: valueOrNull(options.updatedAfter),\n updated_before: valueOrNull(options.updatedBefore),\n created_after: valueOrNull(options.createdAfter),\n created_before: valueOrNull(options.createdBefore),\n assignee: valueOrNull(options.assignee),\n sprint: valueOrNull(options.sprint),\n release: valueOrNull(options.release),\n parent: valueOrNull(options.parent),\n ...buildGovernanceMissingFilterEcho(options as Record<string, unknown>),\n ...buildContentFilterEcho(options as Record<string, unknown>),\n include_linked: includeLinked,\n title_exact: titleExact,\n phrase_exact: phraseExact,\n score_threshold: scoreThreshold,\n hybrid_semantic_weight: effectiveMode === \"hybrid\" ? hybridSemanticWeight : null,\n query_expansion_enabled: queryExpansion.enabled,\n query_expansion_provider: queryExpansion.provider,\n rerank_enabled: rerank.enabled,\n rerank_model: rerank.model,\n rerank_top_k: rerank.top_k,\n limit: valueOrNull(options.limit),\n runtime_filters: runtimeFieldFilters,\n };\n}\n","/**\n * @module cli/commands/search-pagination\n *\n * Applies the shared SDK cursor contract to ranked search results.\n */\nimport {\n createQueryFingerprint,\n paginateQueryRows,\n} from \"../../sdk/pagination.js\";\nimport type { SearchHit, SearchOptions } from \"./search.js\";\nimport type { SearchMode } from \"./search-rendering.js\";\n\n/** Build the query-only fingerprint shared by search retrieval and paging. */\nexport function createSearchCursorFingerprint(options: {\n query: string;\n mode: SearchMode;\n searchOptions: SearchOptions;\n}): string {\n const normalizedOptions: Record<string, unknown> = {\n ...options.searchOptions,\n };\n delete normalizedOptions.after;\n delete normalizedOptions.limit;\n delete normalizedOptions.compact;\n delete normalizedOptions.full;\n delete normalizedOptions.fields;\n delete normalizedOptions.highlight;\n delete normalizedOptions.format;\n return createQueryFingerprint(\"search\", {\n query: options.query.trim(),\n mode: options.mode,\n options: normalizedOptions,\n });\n}\n\n/** Page ranked search hits without coupling cursor mechanics to search scoring. */\nexport function resolveSearchPage(options: {\n sorted: SearchHit[];\n query: string;\n mode: SearchMode;\n searchOptions: SearchOptions;\n limit: number;\n}): {\n limited: SearchHit[];\n pageExtras: {\n has_more?: boolean;\n next_cursor?: string;\n applied_limit: number;\n truncated?: true;\n };\n} {\n const page = paginateQueryRows(options.sorted, {\n cursor: options.searchOptions.after,\n fingerprint: createSearchCursorFingerprint(options),\n limit: options.limit,\n readId: (hit) => hit.item.id,\n });\n return {\n limited: page.rows,\n pageExtras: {\n applied_limit: options.limit,\n ...(page.has_more ? { has_more: true, truncated: true } : {}),\n ...(page.next_cursor ? { next_cursor: page.next_cursor } : {}),\n },\n };\n}\n","/**\n * @module cli/commands/eval\n *\n * Implements the `pm eval` command surface (pm-u8n5): a search-relevance\n * evaluation runner that scores a human-curated golden-query set against the\n * live retrieval path and reports nDCG@k, MRR@k, precision@k, and recall@k per\n * query plus the macro average. With `--fail-under` it doubles as a CI gate so\n * relevance regressions — from corpus changes, hybrid-weight changes, or\n * provider swaps (including the offline BM25 provider, pm-75k9) — fail the build\n * instead of silently degrading retrieval quality.\n */\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n aggregateEvalMetrics,\n DEFAULT_EVAL_K,\n evaluateRanking,\n parseEvalQuerySet,\n type EvalSearchMode,\n type QueryEvalMetrics,\n} from \"../../core/search/eval.js\";\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 { coercePositiveInteger } from \"../../core/shared/primitives.js\";\nimport { pathExists } from \"../../core/fs/fs-utils.js\";\nimport { getSettingsPath, resolvePmRoot } from \"../../core/store/paths.js\";\nimport { runSearch } from \"./search.js\";\n\n/** Relative location (under the pm root) of the default golden-query set. A git-tracked, human-curated file so relevance ground truth lives alongside the tracker it evaluates. */\nexport const DEFAULT_EVAL_QUERIES_RELATIVE_PATH = path.join(\n \"search\",\n \"eval-queries.json\",\n);\n\n/** Documents the eval command options payload exchanged by command, SDK, and package integrations. */\nexport interface EvalOptions {\n /** Default retrieval mode for queries that do not set their own (keyword|semantic|hybrid). */\n mode?: string;\n /** Metric cutoff (`@k`); positive integer, defaults to {@link DEFAULT_EVAL_K}. */\n k?: string | number;\n /** Gate threshold: exit non-zero when the aggregate nDCG@k falls below this `[0,1]` value. */\n failUnder?: string | number;\n /** Override path to the golden-query JSON file (defaults to `<pmRoot>/search/eval-queries.json`). */\n queries?: string;\n /** Output format override: json|toon. */\n format?: string;\n}\n\n/** Per-query relevance report row emitted by {@link runEval}. */\nexport interface EvalQueryReport {\n /** Value that configures or reports query for this contract. */\n query: string;\n /** Value that configures or reports mode for this contract. */\n mode: EvalSearchMode;\n /** Value that configures or reports relevant total for this contract. */\n relevant_total: number;\n /** Value that configures or reports retrieved relevant for this contract. */\n retrieved_relevant: number;\n /** Value that configures or reports ndcg for this contract. */\n ndcg: number;\n /** Value that configures or reports mrr for this contract. */\n mrr: number;\n /** Value that configures or reports precision for this contract. */\n precision: number;\n /** Value that configures or reports recall for this contract. */\n recall: number;\n}\n\n/** Documents the eval result payload exchanged by command, SDK, and package integrations. */\nexport interface EvalResult {\n /** Value that configures or reports k for this contract. */\n k: number;\n /** Number of query entries represented by this result. */\n query_count: number;\n /** Value that configures or reports aggregate for this contract. */\n aggregate: {\n ndcg: number;\n mrr: number;\n precision: number;\n recall: number;\n };\n /** Value that configures or reports queries for this contract. */\n queries: EvalQueryReport[];\n /** Present only when `--fail-under` was supplied. */\n fail_under?: number;\n /** Whether the aggregate nDCG met the gate (always true when no gate is set). */\n passed: boolean;\n}\n\nconst VALID_EVAL_MODES: ReadonlySet<string> = new Set<EvalSearchMode>([\n \"keyword\",\n \"semantic\",\n \"hybrid\",\n]);\n\nfunction parseEvalMode(raw: string | undefined): EvalSearchMode {\n if (raw === undefined) {\n return \"keyword\";\n }\n const normalized = raw.trim().toLowerCase();\n if (!VALID_EVAL_MODES.has(normalized)) {\n throw new PmCliError(\n \"Eval --mode must be one of keyword|semantic|hybrid\",\n EXIT_CODE.USAGE,\n );\n }\n return normalized as EvalSearchMode;\n}\n\nfunction parseEvalK(raw: string | number | undefined): number {\n if (raw === undefined || raw === \"\") {\n return DEFAULT_EVAL_K;\n }\n const parsed = coercePositiveInteger(raw);\n if (parsed === null) {\n throw new PmCliError(\n \"Eval --k must be a positive integer\",\n EXIT_CODE.USAGE,\n );\n }\n return parsed;\n}\n\nfunction parseFailUnder(raw: string | number | undefined): number | undefined {\n if (raw === undefined || raw === \"\") {\n return undefined;\n }\n const parsed = typeof raw === \"number\" ? raw : Number(String(raw).trim());\n if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {\n throw new PmCliError(\n \"Eval --fail-under must be a number in the range [0, 1]\",\n EXIT_CODE.USAGE,\n );\n }\n return parsed;\n}\n\n/** Round a metric to four decimals to keep the JSON output compact and stable. */\nfunction roundMetric(value: number): number {\n return Math.round(value * 10_000) / 10_000;\n}\n\nasync function loadEvalQuerySet(\n queriesPath: string,\n): Promise<ReturnType<typeof parseEvalQuerySet>> {\n let raw: string;\n try {\n raw = await fs.readFile(queriesPath, \"utf8\");\n } catch {\n throw new PmCliError(\n `Eval query set not found at ${queriesPath}`,\n EXIT_CODE.NOT_FOUND,\n {\n examples: [\n 'echo \\'[{\"query\":\"offline search\",\"relevant_ids\":[\"pm-75k9\"]}]\\' > ' +\n queriesPath,\n \"pm eval --queries ./my-eval.json\",\n ],\n nextSteps: [\n \"Create a git-tracked golden-query JSON file (an array of {query, relevant_ids, mode?} objects), then re-run pm eval.\",\n ],\n },\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error: unknown) {\n // JSON.parse only ever throws a SyntaxError (an Error subclass).\n throw new PmCliError(\n `Eval query set at ${queriesPath} is not valid JSON: ${(error as Error).message}`,\n EXIT_CODE.USAGE,\n );\n }\n try {\n return parseEvalQuerySet(parsed);\n } catch (error: unknown) {\n // parseEvalQuerySet only ever throws EvalQuerySetError (an Error subclass\n // with a precise, author-actionable message) — surface it as a usage error.\n throw new PmCliError((error as Error).message, EXIT_CODE.USAGE);\n }\n}\n\n/**\n * Run the search-relevance evaluation (pm-u8n5). Loads the golden-query set\n * (default `<pmRoot>/search/eval-queries.json`, overridable via `--queries`),\n * runs each query through {@link runSearch} at the resolved mode, scores the\n * returned ranking with the nDCG/MRR/precision/recall metrics, and macro-averages\n * across queries. When `--fail-under` is supplied, `passed` reflects whether the\n * aggregate nDCG@k cleared the threshold; the CLI layer maps a failed gate to a\n * non-zero exit code.\n */\nexport async function runEval(\n options: EvalOptions,\n global: GlobalOptions,\n): Promise<EvalResult> {\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(\n `Tracker is not initialized at ${pmRoot}. Run pm init first.`,\n EXIT_CODE.NOT_FOUND,\n );\n }\n const k = parseEvalK(options.k);\n const defaultMode = parseEvalMode(options.mode);\n const failUnder = parseFailUnder(options.failUnder);\n const queriesPath = options.queries\n ? path.resolve(process.cwd(), options.queries)\n : path.join(pmRoot, DEFAULT_EVAL_QUERIES_RELATIVE_PATH);\n const querySet = await loadEvalQuerySet(queriesPath);\n\n const reports: EvalQueryReport[] = [];\n // Aggregate and gate on the UNROUNDED metrics; rounding is applied only to the\n // emitted report values so display precision never flips a --fail-under decision.\n const rawMetrics: QueryEvalMetrics[] = [];\n for (const evalQuery of querySet.queries) {\n const mode = evalQuery.mode ?? defaultMode;\n const searchResult = await runSearch(\n evalQuery.query,\n { mode, limit: String(k), fields: \"id\" },\n global,\n );\n const rankedIds = searchResult.items\n .map((item) => (item as { id?: unknown }).id)\n .filter((id): id is string => typeof id === \"string\");\n const metrics = evaluateRanking(\n rankedIds,\n new Set(evalQuery.relevant_ids),\n k,\n );\n rawMetrics.push(metrics);\n reports.push({\n query: evalQuery.query,\n mode,\n relevant_total: metrics.relevant_total,\n retrieved_relevant: metrics.retrieved_relevant,\n ndcg: roundMetric(metrics.ndcg),\n mrr: roundMetric(metrics.mrr),\n precision: roundMetric(metrics.precision),\n recall: roundMetric(metrics.recall),\n });\n }\n\n const aggregate = aggregateEvalMetrics(rawMetrics);\n const passed = failUnder === undefined || aggregate.ndcg >= failUnder;\n return {\n k,\n query_count: querySet.queries.length,\n aggregate: {\n ndcg: roundMetric(aggregate.ndcg),\n mrr: roundMetric(aggregate.mrr),\n precision: roundMetric(aggregate.precision),\n recall: roundMetric(aggregate.recall),\n },\n queries: reports,\n ...(failUnder !== undefined ? { fail_under: failUnder } : {}),\n passed,\n };\n}\n","/**\n * @module core/search/eval\n *\n * Search relevance evaluation primitives (pm-u8n5). Implements the standard\n * offline ranking metrics — nDCG@k, MRR@k, precision@k, recall@k — over a\n * human-curated golden-query set, plus the loader/validator for that set. The\n * `pm eval` command (src/cli/commands/eval.ts) runs each golden query through\n * the live retrieval path and feeds the ranked ids here, so relevance\n * regressions from corpus changes, hybrid-weight changes, or provider swaps are\n * measurable and gateable in CI.\n *\n * Relevance is binary: an id is either in a query's `relevant_ids` set or it is\n * not. This keeps the golden set cheap to curate while still supporting the\n * graded-discount behavior of DCG (earlier hits are worth more).\n */\n\n/** Retrieval mode a golden query is evaluated under. Mirrors the `pm search` mode surface; omitting it on a query defers to the eval run's default mode. */\nexport type EvalSearchMode = \"keyword\" | \"semantic\" | \"hybrid\";\n\n/** Default cutoff (`@k`) used for every metric when the caller does not override it. */\nexport const DEFAULT_EVAL_K = 10;\n\n/** One curated golden query: the query text, the set of item ids considered relevant, an optional per-query retrieval mode override, and an optional human-readable description of the relevance intent. */\nexport interface EvalQuery {\n /** Value that configures or reports query for this contract. */\n query: string;\n /** Value that configures or reports relevant ids for this contract. */\n relevant_ids: string[];\n /** Value that configures or reports mode for this contract. */\n mode?: EvalSearchMode;\n /** Value that configures or reports description for this contract. */\n description?: string;\n}\n\n/** A parsed, validated golden-query set. */\nexport interface EvalQuerySet {\n /** Value that configures or reports queries for this contract. */\n queries: EvalQuery[];\n}\n\n/**\n * Thrown by {@link parseEvalQuerySet} when the raw golden-query payload is\n * structurally invalid. Carries a precise, human-actionable message naming the\n * offending query index/field so an author can fix the JSON directly.\n */\nexport class EvalQuerySetError extends Error {\n /** Construct an error describing why a golden-query set failed validation. */\n constructor(message: string) {\n super(message);\n this.name = \"EvalQuerySetError\";\n }\n}\n\nconst VALID_EVAL_MODES: ReadonlySet<string> = new Set<EvalSearchMode>([\n \"keyword\",\n \"semantic\",\n \"hybrid\",\n]);\n\n/** Compute Discounted Cumulative Gain at cutoff `k` for an ordered list of binary relevance gains (`1` relevant, `0` not). Position `i` (1-based) contributes `gain / log2(i + 1)`, so a relevant hit ranked first is worth `1` and later hits are progressively discounted. Gains beyond `k` are ignored. */\nexport function dcgAtK(relevanceGains: number[], k: number): number {\n let dcg = 0;\n const limit = Math.min(k, relevanceGains.length);\n for (let index = 0; index < limit; index += 1) {\n dcg += relevanceGains[index] / Math.log2(index + 2);\n }\n return dcg;\n}\n\n/** Normalized DCG at cutoff `k`: the ranking's DCG divided by the DCG of the ideal ranking (all relevant ids first). Returns `0` when the query has no relevant ids (the ideal DCG is `0` and the score is undefined), giving a stable lower bound for aggregation. Result is in `[0, 1]`. */\nexport function ndcgAtK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): number {\n if (relevantIds.size === 0) {\n return 0;\n }\n const gains = rankedIds.map((id) => (relevantIds.has(id) ? 1 : 0));\n const dcg = dcgAtK(gains, k);\n const idealGains = Array.from({ length: relevantIds.size }, () => 1);\n const idealDcg = dcgAtK(idealGains, k);\n return idealDcg === 0 ? 0 : dcg / idealDcg;\n}\n\n/**\n * Reciprocal rank of the first relevant id within the top `k` results: `1/rank`\n * (rank is 1-based), or `0` when no relevant id appears in the cutoff. Averaged\n * across queries this is Mean Reciprocal Rank (MRR@k).\n */\nexport function reciprocalRankAtK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): number {\n const limit = Math.min(k, rankedIds.length);\n for (let index = 0; index < limit; index += 1) {\n if (relevantIds.has(rankedIds[index])) {\n return 1 / (index + 1);\n }\n }\n return 0;\n}\n\n/** Count relevant ids within the top `k` results (shared by precision and recall). */\nfunction countRelevantInTopK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): number {\n const limit = Math.min(k, rankedIds.length);\n let hits = 0;\n for (let index = 0; index < limit; index += 1) {\n if (relevantIds.has(rankedIds[index])) {\n hits += 1;\n }\n }\n return hits;\n}\n\n/** Precision at cutoff `k`: relevant ids retrieved in the top `k` divided by `k`. Returns `0` for a non-positive `k`. */\nexport function precisionAtK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): number {\n if (k <= 0) {\n return 0;\n }\n return countRelevantInTopK(rankedIds, relevantIds, k) / k;\n}\n\n/** Recall at cutoff `k`: relevant ids retrieved in the top `k` divided by the total number of relevant ids. Returns `0` when the query has no relevant ids. */\nexport function recallAtK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): number {\n if (relevantIds.size === 0) {\n return 0;\n }\n return countRelevantInTopK(rankedIds, relevantIds, k) / relevantIds.size;\n}\n\n/** The four ranking metrics computed for a single query, plus match counts. */\nexport interface QueryEvalMetrics {\n /** Value that configures or reports ndcg for this contract. */\n ndcg: number;\n /** Value that configures or reports mrr for this contract. */\n mrr: number;\n /** Value that configures or reports precision for this contract. */\n precision: number;\n /** Value that configures or reports recall for this contract. */\n recall: number;\n /** Value that configures or reports relevant total for this contract. */\n relevant_total: number;\n /** Value that configures or reports retrieved relevant for this contract. */\n retrieved_relevant: number;\n}\n\n/** Evaluate one ranking against its relevant-id set at cutoff `k`, returning all four metrics together so callers compute the document ranking once and read every score off the result. */\nexport function evaluateRanking(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): QueryEvalMetrics {\n return {\n ndcg: ndcgAtK(rankedIds, relevantIds, k),\n mrr: reciprocalRankAtK(rankedIds, relevantIds, k),\n precision: precisionAtK(rankedIds, relevantIds, k),\n recall: recallAtK(rankedIds, relevantIds, k),\n relevant_total: relevantIds.size,\n retrieved_relevant: countRelevantInTopK(rankedIds, relevantIds, k),\n };\n}\n\n/** Macro-averaged metrics across all evaluated queries. */\nexport interface AggregateEvalMetrics {\n /** Value that configures or reports ndcg for this contract. */\n ndcg: number;\n /** Value that configures or reports mrr for this contract. */\n mrr: number;\n /** Value that configures or reports precision for this contract. */\n precision: number;\n /** Value that configures or reports recall for this contract. */\n recall: number;\n /** Number of query entries represented by this result. */\n query_count: number;\n}\n\n/** Macro-average per-query metrics (each query weighted equally). Returns all zeros with `query_count: 0` for an empty input so the gate path has a stable shape to compare against. */\nexport function aggregateEvalMetrics(\n perQuery: QueryEvalMetrics[],\n): AggregateEvalMetrics {\n const queryCount = perQuery.length;\n if (queryCount === 0) {\n return { ndcg: 0, mrr: 0, precision: 0, recall: 0, query_count: 0 };\n }\n const sum = perQuery.reduce(\n (accumulator, metrics) => ({\n ndcg: accumulator.ndcg + metrics.ndcg,\n mrr: accumulator.mrr + metrics.mrr,\n precision: accumulator.precision + metrics.precision,\n recall: accumulator.recall + metrics.recall,\n }),\n { ndcg: 0, mrr: 0, precision: 0, recall: 0 },\n );\n return {\n ndcg: sum.ndcg / queryCount,\n mrr: sum.mrr / queryCount,\n precision: sum.precision / queryCount,\n recall: sum.recall / queryCount,\n query_count: queryCount,\n };\n}\n\n/**\n * Validate one raw golden-query entry, returning a typed {@link EvalQuery}.\n * Throws {@link EvalQuerySetError} (with the entry index) for a missing/empty\n * `query`, a `relevant_ids` that is not a non-empty string array, or an invalid\n * `mode`. `relevant_ids` are trimmed and de-duplicated; `description` is kept\n * only when it is a non-empty string.\n */\nfunction parseEvalQueryEntry(raw: unknown, index: number): EvalQuery {\n if (typeof raw !== \"object\" || raw === null) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} must be an object`,\n );\n }\n const entry = raw as {\n query?: unknown;\n relevant_ids?: unknown;\n mode?: unknown;\n description?: unknown;\n };\n const query = typeof entry.query === \"string\" ? entry.query.trim() : \"\";\n if (query.length === 0) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} must have a non-empty \"query\" string`,\n );\n }\n if (!Array.isArray(entry.relevant_ids)) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} must have a \"relevant_ids\" array`,\n );\n }\n if (entry.relevant_ids.some((value) => typeof value !== \"string\")) {\n // Reject (rather than silently drop) non-string members: malformed golden\n // data must fail loudly so it can never quietly change relevance judgments.\n throw new EvalQuerySetError(\n `Eval query at index ${index} must have a \"relevant_ids\" array of strings`,\n );\n }\n const relevantIds = [\n ...new Set(\n (entry.relevant_ids as string[])\n .map((value) => value.trim())\n .filter((value) => value.length > 0),\n ),\n ];\n if (relevantIds.length === 0) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} must list at least one relevant id`,\n );\n }\n if (\n entry.mode !== undefined &&\n (typeof entry.mode !== \"string\" || !VALID_EVAL_MODES.has(entry.mode))\n ) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} has an invalid mode (expected keyword|semantic|hybrid)`,\n );\n }\n return {\n query,\n relevant_ids: relevantIds,\n ...(entry.mode !== undefined ? { mode: entry.mode as EvalSearchMode } : {}),\n ...(typeof entry.description === \"string\" &&\n entry.description.trim().length > 0\n ? { description: entry.description.trim() }\n : {}),\n };\n}\n\n/**\n * Parse and validate a raw golden-query payload (typically `JSON.parse` of\n * `.agents/pm/search/eval-queries.json`). Accepts either a bare array of query\n * entries or an object with a `queries` array. Throws {@link EvalQuerySetError}\n * with a precise message when the payload is not an array/object, when\n * `queries` is missing/not an array, when the set is empty, or when any entry\n * fails {@link parseEvalQueryEntry}.\n */\nexport function parseEvalQuerySet(raw: unknown): EvalQuerySet {\n const rawQueries = Array.isArray(raw)\n ? raw\n : typeof raw === \"object\" && raw !== null\n ? (raw as { queries?: unknown }).queries\n : undefined;\n if (!Array.isArray(rawQueries)) {\n throw new EvalQuerySetError(\n 'Eval query set must be an array of queries or an object with a \"queries\" array',\n );\n }\n if (rawQueries.length === 0) {\n throw new EvalQuerySetError(\n \"Eval query set must contain at least one query\",\n );\n }\n return {\n queries: rawQueries.map((entry, index) =>\n parseEvalQueryEntry(entry, index),\n ),\n };\n}\n","/**\n * @module cli/commands/get\n *\n * Implements the pm get command surface and its agent-facing runtime behavior.\n */\nimport { pathExists } from \"../../core/fs/fs-utils.js\";\nimport { getActiveExtensionRegistrations } from \"../../core/extensions/index.js\";\nimport { toItemRecord } from \"../../core/item/item-record.js\";\nimport { resolveItemTypeRegistry } from \"../../core/item/type-registry.js\";\nimport {\n resolveRuntimeFieldRegistry,\n resolveRuntimeStatusRegistry,\n} from \"../../core/schema/runtime-schema.js\";\nimport { isTerminalStatus } from \"../../core/item/status.js\";\nimport {\n EXIT_CODE,\n ITEM_METADATA_KEY_ORDER,\n} from \"../../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport {\n buildItemNotFoundError,\n listAllItemMetadataLight,\n locateItem,\n readLocatedItem,\n} from \"../../core/store/item-store.js\";\nimport {\n getHistoryPath,\n getSettingsPath,\n resolvePmRoot,\n} from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport { recordContextUsageTouches } from \"../../sdk/context-usage.js\";\nimport { parseIntegerLimit } from \"../shared-parsers.js\";\nimport type {\n ItemMetadata,\n LinkedDoc,\n LinkedFile,\n LinkedTest,\n} from \"../../types/index.js\";\nimport { readHistoryEntries } from \"./history.js\";\nimport { runList } from \"./list.js\";\n\ninterface ClaimHistoryContext {\n ts: string;\n author: string;\n message: string | null;\n}\n\ninterface ClaimHistoryEntry {\n op: string;\n ts: string;\n author: string;\n message?: string;\n}\n\ninterface ClaimStateContext {\n claimed: boolean;\n assignee: string | null;\n last_claim: ClaimHistoryContext | null;\n last_release: ClaimHistoryContext | null;\n}\n\ninterface ChildRollupContext {\n count: number;\n active: number;\n by_status: Record<string, number>;\n}\n\n// GH-155 (pm-gcm3): only container types get the inline child rollup so leaf\n// item reads keep avoiding the corpus scan that the rollup requires.\nconst CHILD_ROLLUP_TYPES = new Set([\"milestone\", \"epic\"]);\n\n/** Documents the get result payload exchanged by command, SDK, and package integrations. */\nexport interface GetResult {\n // `body` lives inside `item` (alongside `description`/`acceptance_criteria`)\n // for parity with `pm list --include-body`, so agents reliably find it at\n // `.item.body` in JSON output instead of a top-level sibling.\n /** Value that configures or reports item for this contract. */\n item: Partial<ItemMetadata> & { body?: string };\n /** Value that configures or reports linked for this contract. */\n linked?: {\n files: LinkedFile[];\n tests: LinkedTest[];\n docs: LinkedDoc[];\n };\n /** Value that configures or reports claim state for this contract. */\n claim_state?: ClaimStateContext;\n /** Value that configures or reports children for this contract. */\n children?: ChildRollupContext;\n /** Value that configures or reports tree for this contract. */\n tree?: {\n root_id: string;\n root_title: string | null;\n depth_limit: number | null;\n count: number;\n items: Record<string, unknown>[];\n };\n}\n\nconst GET_DEPTH_VALUES = [\"brief\", \"standard\", \"deep\"] as const;\n\ntype GetDepth = (typeof GET_DEPTH_VALUES)[number];\n\n/** Documents the get options payload exchanged by command, SDK, and package integrations. */\nexport interface GetOptions {\n /** Value that configures or reports depth for this contract. */\n depth?: string;\n /** Value that configures or reports fields for this contract. */\n fields?: string;\n /** Value that configures or reports full for this contract. */\n full?: boolean;\n /** Value that configures or reports tree for this contract. */\n tree?: boolean;\n /** Value that configures or reports tree depth for this contract. */\n treeDepth?: string;\n}\n\nfunction toClaimHistoryContext(entry: ClaimHistoryEntry): ClaimHistoryContext {\n return {\n ts: entry.ts,\n author: entry.author,\n message: entry.message ?? null,\n };\n}\n\nfunction resolveClaimStateContext(\n assigneeValue: string | undefined,\n history: ClaimHistoryEntry[],\n): ClaimStateContext {\n const assignee = assigneeValue?.trim();\n const normalizedAssignee = assignee && assignee.length > 0 ? assignee : null;\n const lastClaim = [...history]\n .reverse()\n .find((entry) => entry.op === \"claim\");\n const lastRelease = [...history]\n .reverse()\n .find((entry) => entry.op === \"release\");\n return {\n claimed: normalizedAssignee !== null,\n assignee: normalizedAssignee,\n last_claim: lastClaim ? toClaimHistoryContext(lastClaim) : null,\n last_release: lastRelease ? toClaimHistoryContext(lastRelease) : null,\n };\n}\n\nfunction parseGetDepth(raw: string | undefined): GetDepth {\n if (raw === undefined || raw.trim().length === 0) {\n return \"standard\";\n }\n const normalized = raw.trim().toLowerCase();\n if (normalized === \"full\") {\n return \"deep\";\n }\n if (GET_DEPTH_VALUES.includes(normalized as GetDepth)) {\n return normalized as GetDepth;\n }\n throw new PmCliError(\n \"Get --depth must be one of brief|standard|deep|full\",\n EXIT_CODE.USAGE,\n );\n}\n\nfunction projectItemForDepth(\n item: ItemMetadata,\n depth: GetDepth,\n): Partial<ItemMetadata> {\n if (depth === \"deep\") {\n return item;\n }\n const {\n comments: _comments,\n notes: _notes,\n learnings: _learnings,\n files: _files,\n tests: _tests,\n docs: _docs,\n reminders: _reminders,\n events: _events,\n ...projected\n } = item;\n return projected;\n}\n\nfunction parseGetFields(raw: string | undefined): string[] | null {\n if (raw === undefined) {\n return null;\n }\n const fields = raw\n .split(\",\")\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n if (fields.length === 0) {\n throw new PmCliError(\n \"Get --fields requires a comma-separated list of field names\",\n EXIT_CODE.USAGE,\n );\n }\n return fields;\n}\n\nfunction normalizeGetField(field: string): string {\n return field.startsWith(\"item.\") ? field.slice(\"item.\".length) : field;\n}\n\nfunction validateGetFields(\n fields: string[] | null,\n runtimeMetadataKeys: Iterable<string>,\n): void {\n if (fields === null) {\n return;\n }\n const itemFields = new Set([\n ...ITEM_METADATA_KEY_ORDER,\n ...runtimeMetadataKeys,\n ]);\n const allowedRootFields = new Set([\n \"body\",\n \"linked\",\n \"claim_state\",\n \"children\",\n ]);\n const allowedLinkedFields = new Set([\n \"linked.files\",\n \"linked.tests\",\n \"linked.docs\",\n ]);\n const allowedClaimStateFields = new Set([\n \"claim_state.claimed\",\n \"claim_state.assignee\",\n \"claim_state.last_claim\",\n \"claim_state.last_release\",\n ]);\n const unknown = fields.filter((field) => {\n const normalized = normalizeGetField(field);\n return (\n !itemFields.has(normalized) &&\n !allowedRootFields.has(normalized) &&\n !allowedLinkedFields.has(normalized) &&\n !allowedClaimStateFields.has(normalized)\n );\n });\n if (unknown.length > 0) {\n throw new PmCliError(\n `Unknown get --fields value(s): ${unknown.join(\", \")}`,\n EXIT_CODE.USAGE,\n {\n code: \"unknown_field_projection\",\n examples: [\n \"pm get <id> --fields id,title,status,type,updated_at\",\n \"pm get <id> --fields id,title,claim_state\",\n \"pm get <id> --fields id,title,body,linked.files\",\n ],\n },\n );\n }\n}\n\nfunction projectItemForFields(\n item: ItemMetadata,\n fields: string[],\n): Partial<ItemMetadata> {\n const source = toItemRecord(item);\n const projected: Record<string, unknown> = {};\n for (const field of fields) {\n const normalized = field.startsWith(\"item.\")\n ? field.slice(\"item.\".length)\n : field;\n if (\n normalized === \"body\" ||\n normalized === \"linked\" ||\n normalized.startsWith(\"linked.\")\n ) {\n continue;\n }\n projected[normalized] = source[normalized];\n }\n return projected as Partial<ItemMetadata>;\n}\n\nfunction fieldsInclude(fields: string[] | null, name: string): boolean {\n return (\n fields?.some((field) => field === name || field === `item.${name}`) ?? false\n );\n}\n\nfunction fieldsIncludeRoot(fields: string[], name: string): boolean {\n return fields.some((field) => field === name || field.startsWith(`${name}.`));\n}\n\ninterface ResolvedGetProjection {\n depth: GetDepth;\n treeDepth: number | undefined;\n fields: string[] | null;\n fieldProjection: boolean;\n}\n\ninterface GetItemContext {\n pmRoot: string;\n settings: Awaited<ReturnType<typeof readSettings>>;\n typeToFolder: Record<string, string>;\n locatedId: string;\n metadata: ItemMetadata;\n body: string;\n}\n\nfunction resolveGetProjection(options: GetOptions): ResolvedGetProjection {\n if (\n options.full &&\n (options.fields !== undefined || options.depth !== undefined)\n ) {\n throw new PmCliError(\n \"Get projection options are mutually exclusive; remove the extra projection flag and retry.\",\n EXIT_CODE.USAGE,\n );\n }\n if (options.tree !== true && options.treeDepth !== undefined) {\n throw new PmCliError(\"Get --tree-depth requires --tree\", EXIT_CODE.USAGE);\n }\n return {\n depth: options.full ? \"deep\" : parseGetDepth(options.depth),\n treeDepth:\n options.tree === true\n ? parseIntegerLimit(options.treeDepth, \"--tree-depth\")\n : undefined,\n fields: parseGetFields(options.fields),\n fieldProjection: options.fields !== undefined,\n };\n}\n\nasync function loadGetItemContext(\n id: string,\n global: GlobalOptions,\n): Promise<GetItemContext> {\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(\n `Tracker is not initialized at ${pmRoot}. Run pm init first.`,\n EXIT_CODE.NOT_FOUND,\n );\n }\n const settings = await readSettings(pmRoot);\n const typeRegistry = resolveItemTypeRegistry(\n settings,\n getActiveExtensionRegistrations(),\n );\n const located = await locateItem(\n pmRoot,\n id,\n settings.id_prefix,\n settings.item_format,\n typeRegistry.type_to_folder,\n );\n if (!located) {\n throw await buildItemNotFoundError(\n pmRoot,\n id,\n settings.id_prefix,\n typeRegistry.type_to_folder,\n );\n }\n const loaded = await readLocatedItem(located, { schema: settings.schema });\n return {\n pmRoot,\n settings,\n typeToFolder: typeRegistry.type_to_folder,\n locatedId: located.id,\n metadata: loaded.document.metadata,\n body: loaded.document.body,\n };\n}\n\nfunction validateGetProjectionFields(\n fields: string[] | null,\n settings: Awaited<ReturnType<typeof readSettings>>,\n): void {\n const runtimeMetadataKeys = resolveRuntimeFieldRegistry(\n settings.schema,\n ).definitions.map((field) => field.metadata_key);\n validateGetFields(fields, runtimeMetadataKeys);\n}\n\nfunction shouldIncludeGetField(params: {\n fieldProjection: boolean;\n depth: GetDepth;\n fields: string[] | null;\n field: \"body\" | \"linked\" | \"claim_state\" | \"children\";\n itemType?: string;\n}): boolean {\n const { fieldProjection, depth, fields, field, itemType } = params;\n if (fieldProjection) {\n if (field === \"body\" || field === \"linked\") {\n return fieldsInclude(fields, field);\n }\n return fieldsIncludeRoot(fields as string[], field);\n }\n if (field === \"children\") {\n return depth !== \"brief\" && CHILD_ROLLUP_TYPES.has(itemType as string);\n }\n return depth !== \"brief\";\n}\n\nasync function resolveGetClaimState(\n context: GetItemContext,\n includeClaimState: boolean,\n): Promise<ClaimStateContext | undefined> {\n if (!includeClaimState) {\n return undefined;\n }\n const historyPath = getHistoryPath(context.pmRoot, context.locatedId);\n const history = await readHistoryEntries(historyPath, context.locatedId);\n return resolveClaimStateContext(context.metadata.assignee, history);\n}\n\nfunction attachGetLinked(\n result: GetResult,\n context: GetItemContext,\n fields: string[] | null,\n includeLinked: boolean,\n): void {\n const includeLinkedFiles =\n includeLinked || fieldsInclude(fields, \"linked.files\");\n const includeLinkedTests =\n includeLinked || fieldsInclude(fields, \"linked.tests\");\n const includeLinkedDocs =\n includeLinked || fieldsInclude(fields, \"linked.docs\");\n if (\n !includeLinked &&\n !includeLinkedFiles &&\n !includeLinkedTests &&\n !includeLinkedDocs\n ) {\n return;\n }\n result.linked = {\n files: includeLinkedFiles ? (context.metadata.files ?? []) : [],\n tests: includeLinkedTests ? (context.metadata.tests ?? []) : [],\n docs: includeLinkedDocs ? (context.metadata.docs ?? []) : [],\n };\n}\n\nasync function buildGetChildrenRollup(\n context: GetItemContext,\n includeChildren: boolean,\n): Promise<ChildRollupContext | undefined> {\n if (!includeChildren) {\n return undefined;\n }\n const statusRegistry = resolveRuntimeStatusRegistry(context.settings.schema);\n const corpus = await listAllItemMetadataLight(\n context.pmRoot,\n context.settings.item_format,\n context.typeToFolder,\n undefined,\n context.settings.schema,\n );\n const byStatus: Record<string, number> = {};\n let active = 0;\n let count = 0;\n const locatedId = context.locatedId.trim().toLowerCase();\n for (const candidate of corpus) {\n const parentId =\n typeof candidate.parent === \"string\"\n ? candidate.parent.trim().toLowerCase()\n : \"\";\n if (parentId !== locatedId) continue;\n const candidateStatus = candidate.status.trim().toLowerCase();\n count += 1;\n byStatus[candidateStatus] = (byStatus[candidateStatus] ?? 0) + 1;\n if (!isTerminalStatus(candidateStatus, statusRegistry)) {\n active += 1;\n }\n }\n return { count, active, by_status: byStatus };\n}\n\nasync function buildGetTree(\n context: GetItemContext,\n options: GetOptions,\n treeDepth: number | undefined,\n global: GlobalOptions,\n): Promise<GetResult[\"tree\"] | undefined> {\n if (options.tree !== true) {\n return undefined;\n }\n const subtree = await runList(\n undefined,\n {\n parent: context.locatedId,\n tree: true,\n treeDepth: treeDepth === undefined ? undefined : String(treeDepth),\n full: true,\n },\n global,\n );\n return {\n root_id: context.locatedId,\n root_title: context.metadata.title,\n depth_limit: treeDepth ?? null,\n count: subtree.count,\n items: subtree.items.map((entry) => toItemRecord(entry)),\n };\n}\n\n/** Implements run get for the public runtime surface of this module. */\nexport async function runGet(\n id: string,\n global: GlobalOptions,\n options: GetOptions = {},\n): Promise<GetResult> {\n const projection = resolveGetProjection(options);\n const context = await loadGetItemContext(id, global);\n validateGetProjectionFields(projection.fields, context.settings);\n const includeBody = shouldIncludeGetField({ ...projection, field: \"body\" });\n const includeLinked = shouldIncludeGetField({\n ...projection,\n field: \"linked\",\n });\n const includeClaimState = shouldIncludeGetField({\n ...projection,\n field: \"claim_state\",\n });\n const itemType = context.metadata.type.trim().toLowerCase();\n const includeChildren = shouldIncludeGetField({\n ...projection,\n field: \"children\",\n itemType,\n });\n const claimState = await resolveGetClaimState(context, includeClaimState);\n const result: GetResult = {\n item: projection.fieldProjection\n ? projectItemForFields(context.metadata, projection.fields as string[])\n : projectItemForDepth(context.metadata, projection.depth),\n };\n if (includeBody) {\n result.item.body = context.body;\n }\n attachGetLinked(result, context, projection.fields, includeLinked);\n if (claimState) {\n result.claim_state = claimState;\n }\n result.children = await buildGetChildrenRollup(context, includeChildren);\n result.tree = await buildGetTree(\n context,\n options,\n projection.treeDepth,\n global,\n );\n try {\n await recordContextUsageTouches({\n pmRoot: context.pmRoot,\n author:\n (process.env.PM_AUTHOR ?? context.settings.author_default).trim() ||\n \"unknown\",\n itemIds: [context.locatedId],\n intent: \"get\",\n });\n } catch {\n // Derived usage feedback must never make the source-of-truth read fail.\n }\n return result;\n}\n"],"names":["itemRecord","fs","path","path","VALID_EVAL_MODES","fs"],"mappings":"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","debugId":"fa5c921d-05ab-548a-a7c5-6c3c0ca14357"}