@unbrained/pm-cli 2026.7.1 → 2026.7.3

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 (625) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/CHANGELOG.md +25 -0
  3. package/CONTRIBUTING.md +2 -2
  4. package/README.md +1 -1
  5. package/dist/cli/commander-usage.d.ts +2 -0
  6. package/dist/cli/commander-usage.js +110 -86
  7. package/dist/cli/commander-usage.js.map +1 -1
  8. package/dist/cli/commands/activity.js +79 -57
  9. package/dist/cli/commands/activity.js.map +1 -1
  10. package/dist/cli/commands/aggregate.js +102 -79
  11. package/dist/cli/commands/aggregate.js.map +1 -1
  12. package/dist/cli/commands/calendar.js +278 -243
  13. package/dist/cli/commands/calendar.js.map +1 -1
  14. package/dist/cli/commands/close-many.js +176 -114
  15. package/dist/cli/commands/close-many.js.map +1 -1
  16. package/dist/cli/commands/close.js +157 -129
  17. package/dist/cli/commands/close.js.map +1 -1
  18. package/dist/cli/commands/comments-audit.js +50 -42
  19. package/dist/cli/commands/comments-audit.js.map +1 -1
  20. package/dist/cli/commands/config.d.ts +2 -0
  21. package/dist/cli/commands/config.js +443 -879
  22. package/dist/cli/commands/config.js.map +1 -1
  23. package/dist/cli/commands/context.js +365 -287
  24. package/dist/cli/commands/context.js.map +1 -1
  25. package/dist/cli/commands/contracts.js +352 -238
  26. package/dist/cli/commands/contracts.js.map +1 -1
  27. package/dist/cli/commands/create.js +32 -17
  28. package/dist/cli/commands/create.js.map +1 -1
  29. package/dist/cli/commands/dedupe-audit.js +46 -39
  30. package/dist/cli/commands/dedupe-audit.js.map +1 -1
  31. package/dist/cli/commands/dedupe-merge.js +88 -69
  32. package/dist/cli/commands/dedupe-merge.js.map +1 -1
  33. package/dist/cli/commands/extension/doctor.js +56 -67
  34. package/dist/cli/commands/extension/doctor.js.map +1 -1
  35. package/dist/cli/commands/extension/shared.js +21 -15
  36. package/dist/cli/commands/extension/shared.js.map +1 -1
  37. package/dist/cli/commands/get.js +114 -81
  38. package/dist/cli/commands/get.js.map +1 -1
  39. package/dist/cli/commands/health.d.ts +17 -0
  40. package/dist/cli/commands/health.js +545 -417
  41. package/dist/cli/commands/health.js.map +1 -1
  42. package/dist/cli/commands/history-compact.js +209 -140
  43. package/dist/cli/commands/history-compact.js.map +1 -1
  44. package/dist/cli/commands/history-redact.js +162 -119
  45. package/dist/cli/commands/history-redact.js.map +1 -1
  46. package/dist/cli/commands/history-repair.js +120 -85
  47. package/dist/cli/commands/history-repair.js.map +1 -1
  48. package/dist/cli/commands/init-agent-guidance.js +32 -19
  49. package/dist/cli/commands/init-agent-guidance.js.map +1 -1
  50. package/dist/cli/commands/init.d.ts +8 -2
  51. package/dist/cli/commands/init.js +263 -162
  52. package/dist/cli/commands/init.js.map +1 -1
  53. package/dist/cli/commands/list.js +152 -102
  54. package/dist/cli/commands/list.js.map +1 -1
  55. package/dist/cli/commands/next.js +60 -40
  56. package/dist/cli/commands/next.js.map +1 -1
  57. package/dist/cli/commands/plan.js +373 -298
  58. package/dist/cli/commands/plan.js.map +1 -1
  59. package/dist/cli/commands/profile.js +23 -15
  60. package/dist/cli/commands/profile.js.map +1 -1
  61. package/dist/cli/commands/recurrence-parsers.js +43 -25
  62. package/dist/cli/commands/recurrence-parsers.js.map +1 -1
  63. package/dist/cli/commands/reindex.d.ts +21 -5
  64. package/dist/cli/commands/reindex.js +345 -205
  65. package/dist/cli/commands/reindex.js.map +1 -1
  66. package/dist/cli/commands/restore.d.ts +8 -7
  67. package/dist/cli/commands/restore.js +105 -69
  68. package/dist/cli/commands/restore.js.map +1 -1
  69. package/dist/cli/commands/schema.js +33 -30
  70. package/dist/cli/commands/schema.js.map +1 -1
  71. package/dist/cli/commands/search.d.ts +10 -2
  72. package/dist/cli/commands/search.js +503 -470
  73. package/dist/cli/commands/search.js.map +1 -1
  74. package/dist/cli/commands/telemetry.js +98 -87
  75. package/dist/cli/commands/telemetry.js.map +1 -1
  76. package/dist/cli/commands/test-all.js +237 -168
  77. package/dist/cli/commands/test-all.js.map +1 -1
  78. package/dist/cli/commands/test.d.ts +6 -5
  79. package/dist/cli/commands/test.js +424 -344
  80. package/dist/cli/commands/test.js.map +1 -1
  81. package/dist/cli/commands/update-many.js +57 -42
  82. package/dist/cli/commands/update-many.js.map +1 -1
  83. package/dist/cli/commands/update.d.ts +1 -1
  84. package/dist/cli/commands/update.js +738 -671
  85. package/dist/cli/commands/update.js.map +1 -1
  86. package/dist/cli/commands/validate.d.ts +20 -1
  87. package/dist/cli/commands/validate.js +478 -343
  88. package/dist/cli/commands/validate.js.map +1 -1
  89. package/dist/cli/error-guidance.js +406 -361
  90. package/dist/cli/error-guidance.js.map +1 -1
  91. package/dist/cli/extension-command-help.js +27 -19
  92. package/dist/cli/extension-command-help.js.map +1 -1
  93. package/dist/cli/help-json-payload.js +57 -49
  94. package/dist/cli/help-json-payload.js.map +1 -1
  95. package/dist/cli/main.d.ts +47 -0
  96. package/dist/cli/main.js +474 -371
  97. package/dist/cli/main.js.map +1 -1
  98. package/dist/cli/migration-gates.js +22 -45
  99. package/dist/cli/migration-gates.js.map +1 -1
  100. package/dist/cli/register-list-query.js +299 -310
  101. package/dist/cli/register-list-query.js.map +1 -1
  102. package/dist/cli/register-mutation.js +763 -779
  103. package/dist/cli/register-mutation.js.map +1 -1
  104. package/dist/cli/register-operations.js +386 -362
  105. package/dist/cli/register-operations.js.map +1 -1
  106. package/dist/cli/register-setup.js +120 -101
  107. package/dist/cli/register-setup.js.map +1 -1
  108. package/dist/cli/registration-helpers.d.ts +4 -0
  109. package/dist/cli/registration-helpers.js +45 -56
  110. package/dist/cli/registration-helpers.js.map +1 -1
  111. package/dist/cli-bundle/chunks/{activity-DBLQVIP6.js → activity-5YWLSPGE.js} +9 -9
  112. package/dist/cli-bundle/chunks/activity-BIML7K2D.js +16 -0
  113. package/dist/cli-bundle/chunks/{aggregate-SDF7DUOD.js → aggregate-2V2M3JZU.js} +107 -83
  114. package/dist/cli-bundle/chunks/{aggregate-SDF7DUOD.js.map → aggregate-2V2M3JZU.js.map} +2 -2
  115. package/dist/cli-bundle/chunks/{aggregate-JTEF4BP7.js → aggregate-EK7DXML7.js} +108 -84
  116. package/dist/cli-bundle/chunks/aggregate-EK7DXML7.js.map +1 -0
  117. package/dist/cli-bundle/chunks/{append-LOVPGVPT.js → append-EZESUVJT.js} +8 -8
  118. package/dist/cli-bundle/chunks/{append-QCFJSDFL.js → append-JFG4WQMG.js} +8 -8
  119. package/dist/cli-bundle/chunks/{chunk-TP5Q5ZD3.js → chunk-32IUNTG4.js} +158 -119
  120. package/dist/cli-bundle/chunks/chunk-32IUNTG4.js.map +1 -0
  121. package/dist/cli-bundle/chunks/{chunk-BHO33VBQ.js → chunk-3W2HJKJX.js} +3 -3
  122. package/dist/cli-bundle/chunks/{chunk-VARHOHYV.js → chunk-4EXFFP7T.js} +86 -52
  123. package/dist/cli-bundle/chunks/chunk-4EXFFP7T.js.map +7 -0
  124. package/dist/cli-bundle/chunks/{chunk-4DUVCVLZ.js → chunk-4PFVUUYV.js} +2 -2
  125. package/dist/cli-bundle/chunks/{chunk-JSU5P7VS.js → chunk-4WB6S4YX.js} +308 -184
  126. package/dist/cli-bundle/chunks/chunk-4WB6S4YX.js.map +1 -0
  127. package/dist/cli-bundle/chunks/{chunk-HXTQJXWT.js → chunk-572FKBRL.js} +61 -102
  128. package/dist/cli-bundle/chunks/chunk-572FKBRL.js.map +1 -0
  129. package/dist/cli-bundle/chunks/{chunk-IJYK2T43.js → chunk-5E7N4T2Z.js} +2 -2
  130. package/dist/cli-bundle/chunks/{chunk-NKZAN7BD.js → chunk-5IZUBZBR.js} +3 -3
  131. package/dist/cli-bundle/chunks/{chunk-NOLPZMSV.js → chunk-5JIWFWOZ.js} +2 -2
  132. package/dist/cli-bundle/chunks/{chunk-FFMQB7WR.js → chunk-67LARBDL.js} +493 -404
  133. package/dist/cli-bundle/chunks/chunk-67LARBDL.js.map +1 -0
  134. package/dist/cli-bundle/chunks/{chunk-6AQZPVHQ.js → chunk-6CDCWKSX.js} +4 -4
  135. package/dist/cli-bundle/chunks/{chunk-3K2M5OYU.js → chunk-6KRFL33E.js} +308 -184
  136. package/dist/cli-bundle/chunks/chunk-6KRFL33E.js.map +7 -0
  137. package/dist/cli-bundle/chunks/{chunk-LB6TP6MC.js → chunk-6NYJGMTY.js} +2 -2
  138. package/dist/cli-bundle/chunks/{chunk-SLMUGTK3.js → chunk-7CLLC75T.js} +4 -4
  139. package/dist/cli-bundle/chunks/{chunk-2466X6E4.js → chunk-7LYO6S5A.js} +8 -8
  140. package/dist/cli-bundle/chunks/{chunk-W4ULYO7Z.js → chunk-A3OQ7TFW.js} +8 -8
  141. package/dist/cli-bundle/chunks/{chunk-5CGRF3L5.js → chunk-AIKU3IIL.js} +153 -90
  142. package/dist/cli-bundle/chunks/chunk-AIKU3IIL.js.map +1 -0
  143. package/dist/cli-bundle/chunks/{chunk-WYDHYJPO.js → chunk-AJHYQCBJ.js} +39 -5
  144. package/dist/cli-bundle/chunks/chunk-AJHYQCBJ.js.map +7 -0
  145. package/dist/cli-bundle/chunks/{chunk-VZDBVEZR.js → chunk-B4O5S7I3.js} +79 -57
  146. package/dist/cli-bundle/chunks/{chunk-VZDBVEZR.js.map → chunk-B4O5S7I3.js.map} +2 -2
  147. package/dist/cli-bundle/chunks/{chunk-OTUHB4HS.js → chunk-BE2SR6QL.js} +92 -77
  148. package/dist/cli-bundle/chunks/chunk-BE2SR6QL.js.map +1 -0
  149. package/dist/cli-bundle/chunks/{chunk-JLM7BHI7.js → chunk-BI4R7HI2.js} +75 -53
  150. package/dist/cli-bundle/chunks/chunk-BI4R7HI2.js.map +7 -0
  151. package/dist/cli-bundle/chunks/{chunk-AXIDKKAT.js → chunk-CXR3CMBQ.js} +33 -6
  152. package/dist/cli-bundle/chunks/chunk-CXR3CMBQ.js.map +1 -0
  153. package/dist/cli-bundle/chunks/{chunk-ZETXE4SE.js → chunk-ECU6MMTQ.js} +713 -613
  154. package/dist/cli-bundle/chunks/chunk-ECU6MMTQ.js.map +1 -0
  155. package/dist/cli-bundle/chunks/{chunk-2D4HATP2.js → chunk-EJ2OCBHF.js} +54 -30
  156. package/dist/cli-bundle/chunks/chunk-EJ2OCBHF.js.map +1 -0
  157. package/dist/cli-bundle/chunks/{chunk-BDTISOSD.js → chunk-EQURFOMH.js} +41 -26
  158. package/dist/cli-bundle/chunks/chunk-EQURFOMH.js.map +7 -0
  159. package/dist/cli-bundle/chunks/{chunk-GJ326ZKX.js → chunk-ER4ME5U2.js} +3 -3
  160. package/dist/cli-bundle/chunks/{chunk-HZZEHPRG.js → chunk-ERG65A2L.js} +2 -2
  161. package/dist/cli-bundle/chunks/{chunk-IZBR4NRW.js → chunk-F6WNBITZ.js} +157 -113
  162. package/dist/cli-bundle/chunks/chunk-F6WNBITZ.js.map +7 -0
  163. package/dist/cli-bundle/chunks/{chunk-L5OEFZQG.js → chunk-FH2H3CBD.js} +3 -3
  164. package/dist/cli-bundle/chunks/{chunk-JPECA746.js → chunk-FUFFPIYA.js} +2 -2
  165. package/dist/cli-bundle/chunks/{chunk-CF7RL6FR.js → chunk-FZJM2TXF.js} +110 -73
  166. package/dist/cli-bundle/chunks/chunk-FZJM2TXF.js.map +1 -0
  167. package/dist/cli-bundle/chunks/{chunk-27BXPBAY.js → chunk-GUYNUXQT.js} +3 -3
  168. package/dist/cli-bundle/chunks/{chunk-MAUKX7JC.js → chunk-GVJE5T7Q.js} +2 -2
  169. package/dist/cli-bundle/chunks/{chunk-3J6JRJ3I.js → chunk-HB4FAT3O.js} +42 -60
  170. package/dist/cli-bundle/chunks/chunk-HB4FAT3O.js.map +7 -0
  171. package/dist/cli-bundle/chunks/{chunk-55SNVXRQ.js → chunk-HQAF23Q2.js} +626 -484
  172. package/dist/cli-bundle/chunks/chunk-HQAF23Q2.js.map +7 -0
  173. package/dist/cli-bundle/chunks/{chunk-ZRP4VG5U.js → chunk-JBZ2NTKX.js} +2 -2
  174. package/dist/cli-bundle/chunks/{chunk-RMMQ74TG.js → chunk-JPATY4SE.js} +54 -30
  175. package/dist/cli-bundle/chunks/chunk-JPATY4SE.js.map +7 -0
  176. package/dist/cli-bundle/chunks/{chunk-IPYBJWTE.js → chunk-K5DT2YKM.js} +109 -72
  177. package/dist/cli-bundle/chunks/chunk-K5DT2YKM.js.map +7 -0
  178. package/dist/cli-bundle/chunks/{chunk-EJUDVUYZ.js → chunk-KEZOIPCR.js} +3 -3
  179. package/dist/cli-bundle/chunks/{chunk-RVUALSJF.js → chunk-KHVGM5CS.js} +466 -365
  180. package/dist/cli-bundle/chunks/chunk-KHVGM5CS.js.map +7 -0
  181. package/dist/cli-bundle/chunks/{chunk-YITK2PJ6.js → chunk-KS6ATO47.js} +288 -175
  182. package/dist/cli-bundle/chunks/chunk-KS6ATO47.js.map +7 -0
  183. package/dist/cli-bundle/chunks/{chunk-7R4QEMZZ.js → chunk-L4SLHV6G.js} +463 -362
  184. package/dist/cli-bundle/chunks/chunk-L4SLHV6G.js.map +1 -0
  185. package/dist/cli-bundle/chunks/{chunk-RLDHZHQS.js → chunk-LBE5QFMZ.js} +158 -114
  186. package/dist/cli-bundle/chunks/chunk-LBE5QFMZ.js.map +1 -0
  187. package/dist/cli-bundle/chunks/{chunk-22WKIL3H.js → chunk-LCWQP6NM.js} +76 -54
  188. package/dist/cli-bundle/chunks/chunk-LCWQP6NM.js.map +1 -0
  189. package/dist/cli-bundle/chunks/{chunk-KNPEF7QG.js → chunk-LOWVNZBZ.js} +91 -76
  190. package/dist/cli-bundle/chunks/chunk-LOWVNZBZ.js.map +7 -0
  191. package/dist/cli-bundle/chunks/{chunk-HYTGA6GI.js → chunk-MDHWWBNZ.js} +3 -3
  192. package/dist/cli-bundle/chunks/{chunk-N74UMG5H.js → chunk-MEZZZBYX.js} +2 -2
  193. package/dist/cli-bundle/chunks/{chunk-V3NOKJF2.js → chunk-MHRS5FUX.js} +288 -175
  194. package/dist/cli-bundle/chunks/chunk-MHRS5FUX.js.map +1 -0
  195. package/dist/cli-bundle/chunks/{chunk-3XZCOZ5J.js → chunk-NOIEVOK5.js} +391 -313
  196. package/dist/cli-bundle/chunks/chunk-NOIEVOK5.js.map +1 -0
  197. package/dist/cli-bundle/chunks/{chunk-SDR5J34Q.js → chunk-NZ7QIUP5.js} +4 -4
  198. package/dist/cli-bundle/chunks/{chunk-UYUYDGIB.js → chunk-OGLGI22K.js} +115 -67
  199. package/dist/cli-bundle/chunks/{chunk-UYUYDGIB.js.map → chunk-OGLGI22K.js.map} +1 -1
  200. package/dist/cli-bundle/chunks/{chunk-DDPTYJIM.js → chunk-P5L7Z2O6.js} +2 -2
  201. package/dist/cli-bundle/chunks/{chunk-BZCEN4JA.js → chunk-PULUSQAV.js} +492 -403
  202. package/dist/cli-bundle/chunks/chunk-PULUSQAV.js.map +7 -0
  203. package/dist/cli-bundle/chunks/{chunk-3VGN2UWE.js → chunk-QCDTQCMW.js} +22 -30
  204. package/dist/cli-bundle/chunks/chunk-QCDTQCMW.js.map +1 -0
  205. package/dist/cli-bundle/chunks/{chunk-4A3BJ675.js → chunk-QNNQAAZ5.js} +24 -18
  206. package/dist/cli-bundle/chunks/{chunk-4A3BJ675.js.map → chunk-QNNQAAZ5.js.map} +1 -1
  207. package/dist/cli-bundle/chunks/{chunk-MDPEOIGN.js → chunk-RAHINBVP.js} +60 -101
  208. package/dist/cli-bundle/chunks/chunk-RAHINBVP.js.map +7 -0
  209. package/dist/cli-bundle/chunks/{chunk-CWFNTKQJ.js → chunk-RJH5VQHW.js} +43 -61
  210. package/dist/cli-bundle/chunks/chunk-RJH5VQHW.js.map +1 -0
  211. package/dist/cli-bundle/chunks/{chunk-OGXLACHC.js → chunk-SU2E4AWU.js} +6 -6
  212. package/dist/cli-bundle/chunks/{chunk-HPPFYYOV.js → chunk-SU3TB4NS.js} +2 -2
  213. package/dist/cli-bundle/chunks/{chunk-JWXRETDF.js → chunk-SYE6WMV6.js} +626 -484
  214. package/dist/cli-bundle/chunks/chunk-SYE6WMV6.js.map +1 -0
  215. package/dist/cli-bundle/chunks/{chunk-NWMZWYYB.js → chunk-T3P7PMZP.js} +42 -27
  216. package/dist/cli-bundle/chunks/chunk-T3P7PMZP.js.map +1 -0
  217. package/dist/cli-bundle/chunks/{chunk-G7I7DEZA.js → chunk-T4XBKJ3F.js} +4 -4
  218. package/dist/cli-bundle/chunks/{chunk-RH5ZBYFD.js → chunk-T6AXEBOP.js} +23 -17
  219. package/dist/cli-bundle/chunks/{chunk-RH5ZBYFD.js.map → chunk-T6AXEBOP.js.map} +2 -2
  220. package/dist/cli-bundle/chunks/{chunk-5QFDBI4F.js → chunk-TQ6AX5SQ.js} +58 -69
  221. package/dist/cli-bundle/chunks/{chunk-5QFDBI4F.js.map → chunk-TQ6AX5SQ.js.map} +2 -2
  222. package/dist/cli-bundle/chunks/{chunk-4XOIEKSD.js → chunk-U3S2B7TA.js} +86 -52
  223. package/dist/cli-bundle/chunks/chunk-U3S2B7TA.js.map +1 -0
  224. package/dist/cli-bundle/chunks/{chunk-VICZWYGZ.js → chunk-U5TR4N7J.js} +7 -7
  225. package/dist/cli-bundle/chunks/{chunk-EVMTBV6V.js → chunk-UMNQZS4H.js} +3 -3
  226. package/dist/cli-bundle/chunks/{chunk-A7FPBAQS.js → chunk-WJA3PXW7.js} +7 -7
  227. package/dist/cli-bundle/chunks/{chunk-RGEMWD6Q.js → chunk-WRYERRZX.js} +157 -118
  228. package/dist/cli-bundle/chunks/chunk-WRYERRZX.js.map +7 -0
  229. package/dist/cli-bundle/chunks/{chunk-NUHHPVVS.js → chunk-WYOIIFSE.js} +712 -612
  230. package/dist/cli-bundle/chunks/chunk-WYOIIFSE.js.map +7 -0
  231. package/dist/cli-bundle/chunks/{chunk-4DSGXSBL.js → chunk-XRYSCRZR.js} +116 -68
  232. package/dist/cli-bundle/chunks/{chunk-4DSGXSBL.js.map → chunk-XRYSCRZR.js.map} +3 -3
  233. package/dist/cli-bundle/chunks/{chunk-NU2UEROZ.js → chunk-YF746GTH.js} +59 -70
  234. package/dist/cli-bundle/chunks/{chunk-NU2UEROZ.js.map → chunk-YF746GTH.js.map} +1 -1
  235. package/dist/cli-bundle/chunks/{chunk-JMP4E6D7.js → chunk-YPWUSH72.js} +390 -312
  236. package/dist/cli-bundle/chunks/{chunk-JMP4E6D7.js.map → chunk-YPWUSH72.js.map} +2 -2
  237. package/dist/cli-bundle/chunks/{chunk-QCWF6IYD.js → chunk-YSDFIY7N.js} +3 -3
  238. package/dist/cli-bundle/chunks/{chunk-UZIWVBE6.js → chunk-YSGTMDWC.js} +2 -2
  239. package/dist/cli-bundle/chunks/{chunk-NFDPYAIP.js → chunk-YVKZ3ANP.js} +21 -29
  240. package/dist/cli-bundle/chunks/chunk-YVKZ3ANP.js.map +7 -0
  241. package/dist/cli-bundle/chunks/{chunk-OKQ22KTH.js → chunk-Z4DGFQDH.js} +80 -58
  242. package/dist/cli-bundle/chunks/{chunk-OKQ22KTH.js.map → chunk-Z4DGFQDH.js.map} +1 -1
  243. package/dist/cli-bundle/chunks/{chunk-64HNBBFQ.js → chunk-Z5F6XZXE.js} +6 -6
  244. package/dist/cli-bundle/chunks/{chunk-AVEE5EHK.js → chunk-Z7RPDF2Y.js} +3 -3
  245. package/dist/cli-bundle/chunks/{chunk-3S2KT7NG.js → chunk-ZFTKYWIF.js} +152 -89
  246. package/dist/cli-bundle/chunks/chunk-ZFTKYWIF.js.map +7 -0
  247. package/dist/cli-bundle/chunks/{claim-T3GCKV7C.js → claim-2BGBGSVI.js} +8 -8
  248. package/dist/cli-bundle/chunks/{claim-EMQLYPRW.js → claim-5GU7OE67.js} +8 -8
  249. package/dist/cli-bundle/chunks/close-6YODBUIV.js +14 -0
  250. package/dist/cli-bundle/chunks/{close-TQYAAFJP.js → close-AFVKPR57.js} +7 -7
  251. package/dist/cli-bundle/chunks/{close-many-BG5QQIDQ.js → close-many-7KLOSYLP.js} +186 -122
  252. package/dist/cli-bundle/chunks/close-many-7KLOSYLP.js.map +7 -0
  253. package/dist/cli-bundle/chunks/{close-many-LDRVEQY2.js → close-many-JKUJMHLG.js} +187 -123
  254. package/dist/cli-bundle/chunks/close-many-JKUJMHLG.js.map +1 -0
  255. package/dist/cli-bundle/chunks/{comments-YUXJRZPQ.js → comments-DNWHEBOS.js} +9 -9
  256. package/dist/cli-bundle/chunks/{comments-QCKR2YY2.js → comments-RW23R3VE.js} +9 -9
  257. package/dist/cli-bundle/chunks/config-AUM5WBYA.js +1072 -0
  258. package/dist/cli-bundle/chunks/config-AUM5WBYA.js.map +7 -0
  259. package/dist/cli-bundle/chunks/config-OZWSA2NP.js +1062 -0
  260. package/dist/cli-bundle/chunks/config-OZWSA2NP.js.map +1 -0
  261. package/dist/cli-bundle/chunks/{context-B6275WPX.js → context-OYXRGY7S.js} +12 -12
  262. package/dist/cli-bundle/chunks/{context-OCZ3FJ4Z.js → context-PKCEHQY3.js} +12 -12
  263. package/dist/cli-bundle/chunks/{contracts-HN7ABKLP.js → contracts-L6ODXNUM.js} +320 -199
  264. package/dist/cli-bundle/chunks/contracts-L6ODXNUM.js.map +7 -0
  265. package/dist/cli-bundle/chunks/{contracts-W4FZVVD6.js → contracts-X74F2GSM.js} +321 -200
  266. package/dist/cli-bundle/chunks/contracts-X74F2GSM.js.map +1 -0
  267. package/dist/cli-bundle/chunks/{copy-DEM4DATS.js → copy-6XOR3HKN.js} +5 -5
  268. package/dist/cli-bundle/chunks/{copy-BTJOSKKT.js → copy-I4NCLBR4.js} +5 -5
  269. package/dist/cli-bundle/chunks/{create-RLRJMRTM.js → create-PM45M6PE.js} +12 -12
  270. package/dist/cli-bundle/chunks/create-Z7YCH3BE.js +28 -0
  271. package/dist/cli-bundle/chunks/{delete-BHK7VB2Z.js → delete-7YXHYG67.js} +5 -5
  272. package/dist/cli-bundle/chunks/{delete-LSVHAB4Y.js → delete-LPISP43T.js} +5 -5
  273. package/dist/cli-bundle/chunks/{deps-XHYXWEPT.js → deps-N2T26FME.js} +5 -5
  274. package/dist/cli-bundle/chunks/{deps-4UDFJRUA.js → deps-WATKQDE3.js} +5 -5
  275. package/dist/cli-bundle/chunks/{docs-GYZNVS26.js → docs-6LQ3GLM7.js} +7 -7
  276. package/dist/cli-bundle/chunks/{docs-26S44RXU.js → docs-Z3X6JZLT.js} +7 -7
  277. package/dist/cli-bundle/chunks/{eval-UYF3ZPVO.js → eval-6DCLG52D.js} +10 -10
  278. package/dist/cli-bundle/chunks/{eval-PGRVIJQU.js → eval-Y3ZCUTHK.js} +10 -10
  279. package/dist/cli-bundle/chunks/{extension-CPSLJQVE.js → extension-BNINIMT7.js} +11 -11
  280. package/dist/cli-bundle/chunks/{extension-CXJ6RELI.js → extension-QWE4YYK5.js} +11 -11
  281. package/dist/cli-bundle/chunks/{files-NQHEXUZD.js → files-6SGKHS6O.js} +7 -7
  282. package/dist/cli-bundle/chunks/{files-MBNICQFM.js → files-FUYPSOFJ.js} +7 -7
  283. package/dist/cli-bundle/chunks/{focus-DWYIG7GU.js → focus-2Q3K76G2.js} +6 -6
  284. package/dist/cli-bundle/chunks/{focus-XZW5423D.js → focus-ATLBWXXD.js} +6 -6
  285. package/dist/cli-bundle/chunks/{gc-LPVMKJQJ.js → gc-RUYEMNRF.js} +3 -3
  286. package/dist/cli-bundle/chunks/{gc-7GQYOS2G.js → gc-TDWSDR66.js} +3 -3
  287. package/dist/cli-bundle/chunks/{get-A7MAOHCU.js → get-2WGLX74N.js} +120 -80
  288. package/dist/cli-bundle/chunks/get-2WGLX74N.js.map +7 -0
  289. package/dist/cli-bundle/chunks/{get-DSDEKJ3L.js → get-LY6M2JIM.js} +121 -81
  290. package/dist/cli-bundle/chunks/get-LY6M2JIM.js.map +1 -0
  291. package/dist/cli-bundle/chunks/{health-3IPFLKXB.js → health-4RKHYS3T.js} +535 -371
  292. package/dist/cli-bundle/chunks/health-4RKHYS3T.js.map +1 -0
  293. package/dist/cli-bundle/chunks/{health-GZXGBZ36.js → health-TMFVNYRA.js} +534 -370
  294. package/dist/cli-bundle/chunks/health-TMFVNYRA.js.map +7 -0
  295. package/dist/cli-bundle/chunks/history-CGNQJXFE.js +18 -0
  296. package/dist/cli-bundle/chunks/{history-NERDJNUB.js → history-SGRRS72R.js} +8 -8
  297. package/dist/cli-bundle/chunks/{history-compact-2WRZ2WK4.js → history-compact-LOED43R3.js} +213 -134
  298. package/dist/cli-bundle/chunks/history-compact-LOED43R3.js.map +7 -0
  299. package/dist/cli-bundle/chunks/{history-compact-HR7BB4LR.js → history-compact-V5DNAQHH.js} +214 -135
  300. package/dist/cli-bundle/chunks/history-compact-V5DNAQHH.js.map +1 -0
  301. package/dist/cli-bundle/chunks/{history-redact-O3NBCNWC.js → history-redact-IRL7WJ3E.js} +9 -9
  302. package/dist/cli-bundle/chunks/history-redact-N3JK7VBW.js +19 -0
  303. package/dist/cli-bundle/chunks/{history-repair-XA3LC4GA.js → history-repair-4WVBVHFR.js} +124 -84
  304. package/dist/cli-bundle/chunks/history-repair-4WVBVHFR.js.map +1 -0
  305. package/dist/cli-bundle/chunks/{history-repair-LCMOS45X.js → history-repair-PGYQJMGD.js} +123 -83
  306. package/dist/cli-bundle/chunks/history-repair-PGYQJMGD.js.map +7 -0
  307. package/dist/cli-bundle/chunks/{init-64XDLQJB.js → init-4GESW7RM.js} +12 -12
  308. package/dist/cli-bundle/chunks/init-XIDPABA4.js +22 -0
  309. package/dist/cli-bundle/chunks/{learnings-LPKCSJX7.js → learnings-4BHWFFUV.js} +9 -9
  310. package/dist/cli-bundle/chunks/{learnings-JR6MA5TI.js → learnings-4FJY7WIW.js} +9 -9
  311. package/dist/cli-bundle/chunks/{list-G5Y65VF6.js → list-472TIOVK.js} +8 -8
  312. package/dist/cli-bundle/chunks/{list-DNBJVO3E.js → list-D7BF5CL2.js} +8 -8
  313. package/dist/cli-bundle/chunks/{next-FYTQF6HG.js → next-D5STGWI2.js} +71 -46
  314. package/dist/cli-bundle/chunks/next-D5STGWI2.js.map +1 -0
  315. package/dist/cli-bundle/chunks/{next-BCERKDUR.js → next-SFQZVX2B.js} +70 -45
  316. package/dist/cli-bundle/chunks/next-SFQZVX2B.js.map +7 -0
  317. package/dist/cli-bundle/chunks/{notes-2BMU3VVQ.js → notes-6KNOSLIT.js} +9 -9
  318. package/dist/cli-bundle/chunks/{notes-6KTGO2OJ.js → notes-W4UEICGF.js} +9 -9
  319. package/dist/cli-bundle/chunks/{plan-RKZHQVXR.js → plan-JO6V7BXO.js} +373 -279
  320. package/dist/cli-bundle/chunks/plan-JO6V7BXO.js.map +1 -0
  321. package/dist/cli-bundle/chunks/{plan-4WXEQCTN.js → plan-MJQW5XK3.js} +372 -278
  322. package/dist/cli-bundle/chunks/plan-MJQW5XK3.js.map +7 -0
  323. package/dist/cli-bundle/chunks/{profile-4OMM32CD.js → profile-3TOTMUR4.js} +27 -19
  324. package/dist/cli-bundle/chunks/profile-3TOTMUR4.js.map +7 -0
  325. package/dist/cli-bundle/chunks/{profile-QLER5ENE.js → profile-WIQY2KCV.js} +28 -20
  326. package/dist/cli-bundle/chunks/profile-WIQY2KCV.js.map +1 -0
  327. package/dist/cli-bundle/chunks/register-list-query-ELBHCCFI.js +416 -0
  328. package/dist/cli-bundle/chunks/register-list-query-ELBHCCFI.js.map +7 -0
  329. package/dist/cli-bundle/chunks/register-list-query-GAPQ6DM3.js +406 -0
  330. package/dist/cli-bundle/chunks/register-list-query-GAPQ6DM3.js.map +1 -0
  331. package/dist/cli-bundle/chunks/{register-mutation-KK7PHYYU.js → register-mutation-ROFE2YPC.js} +729 -702
  332. package/dist/cli-bundle/chunks/register-mutation-ROFE2YPC.js.map +7 -0
  333. package/dist/cli-bundle/chunks/{register-mutation-ENNDUAZG.js → register-mutation-SJWMVIJ2.js} +730 -703
  334. package/dist/cli-bundle/chunks/register-mutation-SJWMVIJ2.js.map +1 -0
  335. package/dist/cli-bundle/chunks/{register-operations-HZ6XERQG.js → register-operations-IADFVH53.js} +389 -365
  336. package/dist/cli-bundle/chunks/register-operations-IADFVH53.js.map +7 -0
  337. package/dist/cli-bundle/chunks/register-operations-MEKU3AKC.js +510 -0
  338. package/dist/cli-bundle/chunks/register-operations-MEKU3AKC.js.map +1 -0
  339. package/dist/cli-bundle/chunks/{register-setup-ZKJ53RS7.js → register-setup-3QJY43CY.js} +128 -103
  340. package/dist/cli-bundle/chunks/register-setup-3QJY43CY.js.map +7 -0
  341. package/dist/cli-bundle/chunks/{register-setup-P67EMBDJ.js → register-setup-AJWUSSQX.js} +129 -104
  342. package/dist/cli-bundle/chunks/register-setup-AJWUSSQX.js.map +1 -0
  343. package/dist/cli-bundle/chunks/{restore-4MHZFJ2E.js → restore-44IHMMZZ.js} +9 -9
  344. package/dist/cli-bundle/chunks/restore-EXHU34EU.js +17 -0
  345. package/dist/cli-bundle/chunks/{scheduling-shortcuts-LB6DOLRL.js → scheduling-shortcuts-OLHNLAZY.js} +12 -12
  346. package/dist/cli-bundle/chunks/{scheduling-shortcuts-UTOYKLXQ.js → scheduling-shortcuts-TSBK4AY5.js} +12 -12
  347. package/dist/cli-bundle/chunks/{schema-73HR2OJW.js → schema-IB2NZZWD.js} +7 -7
  348. package/dist/cli-bundle/chunks/{schema-U6LJKSIR.js → schema-VBCELP5G.js} +7 -7
  349. package/dist/cli-bundle/chunks/{search-AXPXKZER.js → search-7UBETML4.js} +10 -10
  350. package/dist/cli-bundle/chunks/{search-KILGT37L.js → search-R227JOL6.js} +10 -10
  351. package/dist/cli-bundle/chunks/{stats-W5KNVJWQ.js → stats-FAG7COEH.js} +6 -6
  352. package/dist/cli-bundle/chunks/{stats-PSYVVTNZ.js → stats-MCK7PLYS.js} +6 -6
  353. package/dist/cli-bundle/chunks/{telemetry-GAHHQTOS.js → telemetry-DRPDZMAO.js} +84 -70
  354. package/dist/cli-bundle/chunks/telemetry-DRPDZMAO.js.map +7 -0
  355. package/dist/cli-bundle/chunks/{telemetry-BZUF6H7G.js → telemetry-GVVUQSJQ.js} +85 -71
  356. package/dist/cli-bundle/chunks/telemetry-GVVUQSJQ.js.map +1 -0
  357. package/dist/cli-bundle/chunks/{test-PWDIZ255.js → test-QY44WAMR.js} +15 -15
  358. package/dist/cli-bundle/chunks/{test-ACD52Z3S.js → test-SY76DZTO.js} +15 -15
  359. package/dist/cli-bundle/chunks/test-all-QD6QAEG7.js +430 -0
  360. package/dist/cli-bundle/chunks/test-all-QD6QAEG7.js.map +7 -0
  361. package/dist/cli-bundle/chunks/test-all-USPJHXFR.js +427 -0
  362. package/dist/cli-bundle/chunks/test-all-USPJHXFR.js.map +1 -0
  363. package/dist/cli-bundle/chunks/{test-runs-UXIXPDKU.js → test-runs-MG5VIGSK.js} +185 -147
  364. package/dist/cli-bundle/chunks/test-runs-MG5VIGSK.js.map +1 -0
  365. package/dist/cli-bundle/chunks/{test-runs-PLRAZEFW.js → test-runs-QIR5MJPL.js} +184 -146
  366. package/dist/cli-bundle/chunks/test-runs-QIR5MJPL.js.map +7 -0
  367. package/dist/cli-bundle/chunks/update-A7EICML6.js +24 -0
  368. package/dist/cli-bundle/chunks/{update-KFX2SIAC.js → update-IKJZWLQC.js} +15 -15
  369. package/dist/cli-bundle/chunks/{update-many-RNSBX2TA.js → update-many-BEMTDA2X.js} +84 -69
  370. package/dist/cli-bundle/chunks/{update-many-RNSBX2TA.js.map → update-many-BEMTDA2X.js.map} +1 -1
  371. package/dist/cli-bundle/chunks/{update-many-Z5GJS5LC.js → update-many-RATAARHU.js} +83 -68
  372. package/dist/cli-bundle/chunks/{update-many-Z5GJS5LC.js.map → update-many-RATAARHU.js.map} +2 -2
  373. package/dist/cli-bundle/chunks/{upgrade-BRL6KCOJ.js → upgrade-NWMR3VQL.js} +11 -11
  374. package/dist/cli-bundle/chunks/{upgrade-HAK6JG2O.js → upgrade-VU46BLJZ.js} +11 -11
  375. package/dist/cli-bundle/chunks/{validate-X5W76YJL.js → validate-GAJ6FUSI.js} +451 -321
  376. package/dist/cli-bundle/chunks/validate-GAJ6FUSI.js.map +1 -0
  377. package/dist/cli-bundle/chunks/{validate-MTUVL5VC.js → validate-NRY6MFXN.js} +450 -320
  378. package/dist/cli-bundle/chunks/validate-NRY6MFXN.js.map +7 -0
  379. package/dist/cli-bundle/main.js +1107 -916
  380. package/dist/cli-bundle/main.js.map +3 -3
  381. package/dist/core/config/nested-settings.js +89 -67
  382. package/dist/core/config/nested-settings.js.map +1 -1
  383. package/dist/core/governance/metadata-coverage.js +20 -28
  384. package/dist/core/governance/metadata-coverage.js.map +1 -1
  385. package/dist/core/history/drift-scan.js +93 -81
  386. package/dist/core/history/drift-scan.js.map +1 -1
  387. package/dist/core/item/item-type-definition.js +14 -14
  388. package/dist/core/item/item-type-definition.js.map +1 -1
  389. package/dist/core/item/type-registry.js +114 -99
  390. package/dist/core/item/type-registry.js.map +1 -1
  391. package/dist/core/output/mutation-projection.js +42 -26
  392. package/dist/core/output/mutation-projection.js.map +1 -1
  393. package/dist/core/schema/runtime-schema.js +97 -80
  394. package/dist/core/schema/runtime-schema.js.map +1 -1
  395. package/dist/core/schema/status-defs-file.js +26 -3
  396. package/dist/core/schema/status-defs-file.js.map +1 -1
  397. package/dist/core/search/corpus.js +25 -19
  398. package/dist/core/search/corpus.js.map +1 -1
  399. package/dist/core/search/semantic-defaults.js +64 -37
  400. package/dist/core/search/semantic-defaults.js.map +1 -1
  401. package/dist/core/search/vector-stores.js +32 -17
  402. package/dist/core/search/vector-stores.js.map +1 -1
  403. package/dist/core/sentry/helpers.js +31 -28
  404. package/dist/core/sentry/helpers.js.map +1 -1
  405. package/dist/core/sentry/instrument.js +54 -43
  406. package/dist/core/sentry/instrument.js.map +1 -1
  407. package/dist/core/shared/memo.d.ts +12 -0
  408. package/dist/core/shared/memo.js +25 -0
  409. package/dist/core/shared/memo.js.map +1 -0
  410. package/dist/core/shared/serialization.js +24 -14
  411. package/dist/core/shared/serialization.js.map +1 -1
  412. package/dist/core/shared/time.js +26 -4
  413. package/dist/core/shared/time.js.map +1 -1
  414. package/dist/core/store/front-matter-cache.d.ts +5 -0
  415. package/dist/core/store/front-matter-cache.js +316 -171
  416. package/dist/core/store/front-matter-cache.js.map +1 -1
  417. package/dist/core/store/item-store.js +33 -26
  418. package/dist/core/store/item-store.js.map +1 -1
  419. package/dist/core/store/settings.js +247 -203
  420. package/dist/core/store/settings.js.map +1 -1
  421. package/dist/core/test/background-runs.js +189 -160
  422. package/dist/core/test/background-runs.js.map +1 -1
  423. package/dist/sdk/cli-contracts/flag-contracts.js +71 -99
  424. package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
  425. package/dist/sdk/compose.js +51 -42
  426. package/dist/sdk/compose.js.map +1 -1
  427. package/docs/AGENT_GUIDE.md +2 -2
  428. package/docs/ARCHITECTURE.md +2 -2
  429. package/docs/COMMANDS.md +8 -4
  430. package/docs/CONFIGURATION.md +1 -1
  431. package/docs/EXTENSIONS.md +12 -12
  432. package/docs/ONBOARDING.md +4 -2
  433. package/docs/README.md +2 -0
  434. package/docs/examples/starter-extension/README.md +11 -10
  435. package/marketplace.json +3 -3
  436. package/package.json +2 -2
  437. package/packages/pm-beads/extensions/beads/runtime.ts +240 -167
  438. package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +65 -58
  439. package/packages/pm-todos/extensions/todos/runtime.ts +65 -42
  440. package/plugins/pm-claude/.claude-plugin/plugin.json +2 -2
  441. package/plugins/pm-claude/README.md +6 -3
  442. package/plugins/pm-claude/commands/pm-init.md +1 -1
  443. package/dist/cli-bundle/chunks/activity-AW6XVFH6.js +0 -16
  444. package/dist/cli-bundle/chunks/aggregate-JTEF4BP7.js.map +0 -1
  445. package/dist/cli-bundle/chunks/chunk-22WKIL3H.js.map +0 -1
  446. package/dist/cli-bundle/chunks/chunk-2D4HATP2.js.map +0 -1
  447. package/dist/cli-bundle/chunks/chunk-3J6JRJ3I.js.map +0 -7
  448. package/dist/cli-bundle/chunks/chunk-3K2M5OYU.js.map +0 -7
  449. package/dist/cli-bundle/chunks/chunk-3S2KT7NG.js.map +0 -7
  450. package/dist/cli-bundle/chunks/chunk-3VGN2UWE.js.map +0 -1
  451. package/dist/cli-bundle/chunks/chunk-3XZCOZ5J.js.map +0 -1
  452. package/dist/cli-bundle/chunks/chunk-4XOIEKSD.js.map +0 -1
  453. package/dist/cli-bundle/chunks/chunk-55SNVXRQ.js.map +0 -7
  454. package/dist/cli-bundle/chunks/chunk-5CGRF3L5.js.map +0 -1
  455. package/dist/cli-bundle/chunks/chunk-7R4QEMZZ.js.map +0 -1
  456. package/dist/cli-bundle/chunks/chunk-AXIDKKAT.js.map +0 -1
  457. package/dist/cli-bundle/chunks/chunk-BDTISOSD.js.map +0 -7
  458. package/dist/cli-bundle/chunks/chunk-BZCEN4JA.js.map +0 -7
  459. package/dist/cli-bundle/chunks/chunk-CF7RL6FR.js.map +0 -1
  460. package/dist/cli-bundle/chunks/chunk-CWFNTKQJ.js.map +0 -1
  461. package/dist/cli-bundle/chunks/chunk-FFMQB7WR.js.map +0 -1
  462. package/dist/cli-bundle/chunks/chunk-HXTQJXWT.js.map +0 -1
  463. package/dist/cli-bundle/chunks/chunk-IPYBJWTE.js.map +0 -7
  464. package/dist/cli-bundle/chunks/chunk-IZBR4NRW.js.map +0 -7
  465. package/dist/cli-bundle/chunks/chunk-JLM7BHI7.js.map +0 -7
  466. package/dist/cli-bundle/chunks/chunk-JSU5P7VS.js.map +0 -1
  467. package/dist/cli-bundle/chunks/chunk-JWXRETDF.js.map +0 -1
  468. package/dist/cli-bundle/chunks/chunk-KNPEF7QG.js.map +0 -7
  469. package/dist/cli-bundle/chunks/chunk-MDPEOIGN.js.map +0 -7
  470. package/dist/cli-bundle/chunks/chunk-NFDPYAIP.js.map +0 -7
  471. package/dist/cli-bundle/chunks/chunk-NUHHPVVS.js.map +0 -7
  472. package/dist/cli-bundle/chunks/chunk-NWMZWYYB.js.map +0 -1
  473. package/dist/cli-bundle/chunks/chunk-OTUHB4HS.js.map +0 -1
  474. package/dist/cli-bundle/chunks/chunk-RGEMWD6Q.js.map +0 -7
  475. package/dist/cli-bundle/chunks/chunk-RLDHZHQS.js.map +0 -1
  476. package/dist/cli-bundle/chunks/chunk-RMMQ74TG.js.map +0 -7
  477. package/dist/cli-bundle/chunks/chunk-RVUALSJF.js.map +0 -7
  478. package/dist/cli-bundle/chunks/chunk-TP5Q5ZD3.js.map +0 -1
  479. package/dist/cli-bundle/chunks/chunk-V3NOKJF2.js.map +0 -1
  480. package/dist/cli-bundle/chunks/chunk-VARHOHYV.js.map +0 -7
  481. package/dist/cli-bundle/chunks/chunk-WYDHYJPO.js.map +0 -7
  482. package/dist/cli-bundle/chunks/chunk-YITK2PJ6.js.map +0 -7
  483. package/dist/cli-bundle/chunks/chunk-ZETXE4SE.js.map +0 -1
  484. package/dist/cli-bundle/chunks/close-E6ZZGCJY.js +0 -14
  485. package/dist/cli-bundle/chunks/close-many-BG5QQIDQ.js.map +0 -7
  486. package/dist/cli-bundle/chunks/close-many-LDRVEQY2.js.map +0 -1
  487. package/dist/cli-bundle/chunks/config-DMSU64QO.js +0 -1541
  488. package/dist/cli-bundle/chunks/config-DMSU64QO.js.map +0 -7
  489. package/dist/cli-bundle/chunks/config-QH2DICD6.js +0 -1531
  490. package/dist/cli-bundle/chunks/config-QH2DICD6.js.map +0 -1
  491. package/dist/cli-bundle/chunks/contracts-HN7ABKLP.js.map +0 -7
  492. package/dist/cli-bundle/chunks/contracts-W4FZVVD6.js.map +0 -1
  493. package/dist/cli-bundle/chunks/create-OH3BDGBB.js +0 -28
  494. package/dist/cli-bundle/chunks/get-A7MAOHCU.js.map +0 -7
  495. package/dist/cli-bundle/chunks/get-DSDEKJ3L.js.map +0 -1
  496. package/dist/cli-bundle/chunks/health-3IPFLKXB.js.map +0 -1
  497. package/dist/cli-bundle/chunks/health-GZXGBZ36.js.map +0 -7
  498. package/dist/cli-bundle/chunks/history-WSZHY3PN.js +0 -18
  499. package/dist/cli-bundle/chunks/history-compact-2WRZ2WK4.js.map +0 -7
  500. package/dist/cli-bundle/chunks/history-compact-HR7BB4LR.js.map +0 -1
  501. package/dist/cli-bundle/chunks/history-redact-MP6CH7U5.js +0 -19
  502. package/dist/cli-bundle/chunks/history-repair-LCMOS45X.js.map +0 -7
  503. package/dist/cli-bundle/chunks/history-repair-XA3LC4GA.js.map +0 -1
  504. package/dist/cli-bundle/chunks/init-PAX32BJA.js +0 -22
  505. package/dist/cli-bundle/chunks/next-BCERKDUR.js.map +0 -7
  506. package/dist/cli-bundle/chunks/next-FYTQF6HG.js.map +0 -1
  507. package/dist/cli-bundle/chunks/plan-4WXEQCTN.js.map +0 -7
  508. package/dist/cli-bundle/chunks/plan-RKZHQVXR.js.map +0 -1
  509. package/dist/cli-bundle/chunks/profile-4OMM32CD.js.map +0 -7
  510. package/dist/cli-bundle/chunks/profile-QLER5ENE.js.map +0 -1
  511. package/dist/cli-bundle/chunks/register-list-query-7LV46VAU.js +0 -400
  512. package/dist/cli-bundle/chunks/register-list-query-7LV46VAU.js.map +0 -1
  513. package/dist/cli-bundle/chunks/register-list-query-SNG5PGA4.js +0 -410
  514. package/dist/cli-bundle/chunks/register-list-query-SNG5PGA4.js.map +0 -7
  515. package/dist/cli-bundle/chunks/register-mutation-ENNDUAZG.js.map +0 -1
  516. package/dist/cli-bundle/chunks/register-mutation-KK7PHYYU.js.map +0 -7
  517. package/dist/cli-bundle/chunks/register-operations-C6OWLDSH.js +0 -486
  518. package/dist/cli-bundle/chunks/register-operations-C6OWLDSH.js.map +0 -1
  519. package/dist/cli-bundle/chunks/register-operations-HZ6XERQG.js.map +0 -7
  520. package/dist/cli-bundle/chunks/register-setup-P67EMBDJ.js.map +0 -1
  521. package/dist/cli-bundle/chunks/register-setup-ZKJ53RS7.js.map +0 -7
  522. package/dist/cli-bundle/chunks/restore-YALDGTQR.js +0 -17
  523. package/dist/cli-bundle/chunks/telemetry-BZUF6H7G.js.map +0 -1
  524. package/dist/cli-bundle/chunks/telemetry-GAHHQTOS.js.map +0 -7
  525. package/dist/cli-bundle/chunks/test-all-L2MDDUCA.js +0 -358
  526. package/dist/cli-bundle/chunks/test-all-L2MDDUCA.js.map +0 -1
  527. package/dist/cli-bundle/chunks/test-all-RBZ6DLU2.js +0 -361
  528. package/dist/cli-bundle/chunks/test-all-RBZ6DLU2.js.map +0 -7
  529. package/dist/cli-bundle/chunks/test-runs-PLRAZEFW.js.map +0 -7
  530. package/dist/cli-bundle/chunks/test-runs-UXIXPDKU.js.map +0 -1
  531. package/dist/cli-bundle/chunks/update-AMRSOIWP.js +0 -24
  532. package/dist/cli-bundle/chunks/validate-MTUVL5VC.js.map +0 -7
  533. package/dist/cli-bundle/chunks/validate-X5W76YJL.js.map +0 -1
  534. /package/dist/cli-bundle/chunks/{activity-DBLQVIP6.js.map → activity-5YWLSPGE.js.map} +0 -0
  535. /package/dist/cli-bundle/chunks/{activity-AW6XVFH6.js.map → activity-BIML7K2D.js.map} +0 -0
  536. /package/dist/cli-bundle/chunks/{append-LOVPGVPT.js.map → append-EZESUVJT.js.map} +0 -0
  537. /package/dist/cli-bundle/chunks/{append-QCFJSDFL.js.map → append-JFG4WQMG.js.map} +0 -0
  538. /package/dist/cli-bundle/chunks/{chunk-BHO33VBQ.js.map → chunk-3W2HJKJX.js.map} +0 -0
  539. /package/dist/cli-bundle/chunks/{chunk-4DUVCVLZ.js.map → chunk-4PFVUUYV.js.map} +0 -0
  540. /package/dist/cli-bundle/chunks/{chunk-IJYK2T43.js.map → chunk-5E7N4T2Z.js.map} +0 -0
  541. /package/dist/cli-bundle/chunks/{chunk-NKZAN7BD.js.map → chunk-5IZUBZBR.js.map} +0 -0
  542. /package/dist/cli-bundle/chunks/{chunk-NOLPZMSV.js.map → chunk-5JIWFWOZ.js.map} +0 -0
  543. /package/dist/cli-bundle/chunks/{chunk-6AQZPVHQ.js.map → chunk-6CDCWKSX.js.map} +0 -0
  544. /package/dist/cli-bundle/chunks/{chunk-LB6TP6MC.js.map → chunk-6NYJGMTY.js.map} +0 -0
  545. /package/dist/cli-bundle/chunks/{chunk-SLMUGTK3.js.map → chunk-7CLLC75T.js.map} +0 -0
  546. /package/dist/cli-bundle/chunks/{chunk-2466X6E4.js.map → chunk-7LYO6S5A.js.map} +0 -0
  547. /package/dist/cli-bundle/chunks/{chunk-W4ULYO7Z.js.map → chunk-A3OQ7TFW.js.map} +0 -0
  548. /package/dist/cli-bundle/chunks/{chunk-GJ326ZKX.js.map → chunk-ER4ME5U2.js.map} +0 -0
  549. /package/dist/cli-bundle/chunks/{chunk-HZZEHPRG.js.map → chunk-ERG65A2L.js.map} +0 -0
  550. /package/dist/cli-bundle/chunks/{chunk-L5OEFZQG.js.map → chunk-FH2H3CBD.js.map} +0 -0
  551. /package/dist/cli-bundle/chunks/{chunk-JPECA746.js.map → chunk-FUFFPIYA.js.map} +0 -0
  552. /package/dist/cli-bundle/chunks/{chunk-27BXPBAY.js.map → chunk-GUYNUXQT.js.map} +0 -0
  553. /package/dist/cli-bundle/chunks/{chunk-MAUKX7JC.js.map → chunk-GVJE5T7Q.js.map} +0 -0
  554. /package/dist/cli-bundle/chunks/{chunk-ZRP4VG5U.js.map → chunk-JBZ2NTKX.js.map} +0 -0
  555. /package/dist/cli-bundle/chunks/{chunk-EJUDVUYZ.js.map → chunk-KEZOIPCR.js.map} +0 -0
  556. /package/dist/cli-bundle/chunks/{chunk-HYTGA6GI.js.map → chunk-MDHWWBNZ.js.map} +0 -0
  557. /package/dist/cli-bundle/chunks/{chunk-N74UMG5H.js.map → chunk-MEZZZBYX.js.map} +0 -0
  558. /package/dist/cli-bundle/chunks/{chunk-SDR5J34Q.js.map → chunk-NZ7QIUP5.js.map} +0 -0
  559. /package/dist/cli-bundle/chunks/{chunk-DDPTYJIM.js.map → chunk-P5L7Z2O6.js.map} +0 -0
  560. /package/dist/cli-bundle/chunks/{chunk-OGXLACHC.js.map → chunk-SU2E4AWU.js.map} +0 -0
  561. /package/dist/cli-bundle/chunks/{chunk-HPPFYYOV.js.map → chunk-SU3TB4NS.js.map} +0 -0
  562. /package/dist/cli-bundle/chunks/{chunk-G7I7DEZA.js.map → chunk-T4XBKJ3F.js.map} +0 -0
  563. /package/dist/cli-bundle/chunks/{chunk-VICZWYGZ.js.map → chunk-U5TR4N7J.js.map} +0 -0
  564. /package/dist/cli-bundle/chunks/{chunk-EVMTBV6V.js.map → chunk-UMNQZS4H.js.map} +0 -0
  565. /package/dist/cli-bundle/chunks/{chunk-A7FPBAQS.js.map → chunk-WJA3PXW7.js.map} +0 -0
  566. /package/dist/cli-bundle/chunks/{chunk-QCWF6IYD.js.map → chunk-YSDFIY7N.js.map} +0 -0
  567. /package/dist/cli-bundle/chunks/{chunk-UZIWVBE6.js.map → chunk-YSGTMDWC.js.map} +0 -0
  568. /package/dist/cli-bundle/chunks/{chunk-64HNBBFQ.js.map → chunk-Z5F6XZXE.js.map} +0 -0
  569. /package/dist/cli-bundle/chunks/{chunk-AVEE5EHK.js.map → chunk-Z7RPDF2Y.js.map} +0 -0
  570. /package/dist/cli-bundle/chunks/{claim-T3GCKV7C.js.map → claim-2BGBGSVI.js.map} +0 -0
  571. /package/dist/cli-bundle/chunks/{claim-EMQLYPRW.js.map → claim-5GU7OE67.js.map} +0 -0
  572. /package/dist/cli-bundle/chunks/{close-E6ZZGCJY.js.map → close-6YODBUIV.js.map} +0 -0
  573. /package/dist/cli-bundle/chunks/{close-TQYAAFJP.js.map → close-AFVKPR57.js.map} +0 -0
  574. /package/dist/cli-bundle/chunks/{comments-YUXJRZPQ.js.map → comments-DNWHEBOS.js.map} +0 -0
  575. /package/dist/cli-bundle/chunks/{comments-QCKR2YY2.js.map → comments-RW23R3VE.js.map} +0 -0
  576. /package/dist/cli-bundle/chunks/{context-B6275WPX.js.map → context-OYXRGY7S.js.map} +0 -0
  577. /package/dist/cli-bundle/chunks/{context-OCZ3FJ4Z.js.map → context-PKCEHQY3.js.map} +0 -0
  578. /package/dist/cli-bundle/chunks/{copy-DEM4DATS.js.map → copy-6XOR3HKN.js.map} +0 -0
  579. /package/dist/cli-bundle/chunks/{copy-BTJOSKKT.js.map → copy-I4NCLBR4.js.map} +0 -0
  580. /package/dist/cli-bundle/chunks/{create-RLRJMRTM.js.map → create-PM45M6PE.js.map} +0 -0
  581. /package/dist/cli-bundle/chunks/{create-OH3BDGBB.js.map → create-Z7YCH3BE.js.map} +0 -0
  582. /package/dist/cli-bundle/chunks/{delete-BHK7VB2Z.js.map → delete-7YXHYG67.js.map} +0 -0
  583. /package/dist/cli-bundle/chunks/{delete-LSVHAB4Y.js.map → delete-LPISP43T.js.map} +0 -0
  584. /package/dist/cli-bundle/chunks/{deps-XHYXWEPT.js.map → deps-N2T26FME.js.map} +0 -0
  585. /package/dist/cli-bundle/chunks/{deps-4UDFJRUA.js.map → deps-WATKQDE3.js.map} +0 -0
  586. /package/dist/cli-bundle/chunks/{docs-GYZNVS26.js.map → docs-6LQ3GLM7.js.map} +0 -0
  587. /package/dist/cli-bundle/chunks/{docs-26S44RXU.js.map → docs-Z3X6JZLT.js.map} +0 -0
  588. /package/dist/cli-bundle/chunks/{eval-UYF3ZPVO.js.map → eval-6DCLG52D.js.map} +0 -0
  589. /package/dist/cli-bundle/chunks/{eval-PGRVIJQU.js.map → eval-Y3ZCUTHK.js.map} +0 -0
  590. /package/dist/cli-bundle/chunks/{extension-CPSLJQVE.js.map → extension-BNINIMT7.js.map} +0 -0
  591. /package/dist/cli-bundle/chunks/{extension-CXJ6RELI.js.map → extension-QWE4YYK5.js.map} +0 -0
  592. /package/dist/cli-bundle/chunks/{files-NQHEXUZD.js.map → files-6SGKHS6O.js.map} +0 -0
  593. /package/dist/cli-bundle/chunks/{files-MBNICQFM.js.map → files-FUYPSOFJ.js.map} +0 -0
  594. /package/dist/cli-bundle/chunks/{focus-DWYIG7GU.js.map → focus-2Q3K76G2.js.map} +0 -0
  595. /package/dist/cli-bundle/chunks/{focus-XZW5423D.js.map → focus-ATLBWXXD.js.map} +0 -0
  596. /package/dist/cli-bundle/chunks/{gc-LPVMKJQJ.js.map → gc-RUYEMNRF.js.map} +0 -0
  597. /package/dist/cli-bundle/chunks/{gc-7GQYOS2G.js.map → gc-TDWSDR66.js.map} +0 -0
  598. /package/dist/cli-bundle/chunks/{history-WSZHY3PN.js.map → history-CGNQJXFE.js.map} +0 -0
  599. /package/dist/cli-bundle/chunks/{history-NERDJNUB.js.map → history-SGRRS72R.js.map} +0 -0
  600. /package/dist/cli-bundle/chunks/{history-redact-O3NBCNWC.js.map → history-redact-IRL7WJ3E.js.map} +0 -0
  601. /package/dist/cli-bundle/chunks/{history-redact-MP6CH7U5.js.map → history-redact-N3JK7VBW.js.map} +0 -0
  602. /package/dist/cli-bundle/chunks/{init-64XDLQJB.js.map → init-4GESW7RM.js.map} +0 -0
  603. /package/dist/cli-bundle/chunks/{init-PAX32BJA.js.map → init-XIDPABA4.js.map} +0 -0
  604. /package/dist/cli-bundle/chunks/{learnings-LPKCSJX7.js.map → learnings-4BHWFFUV.js.map} +0 -0
  605. /package/dist/cli-bundle/chunks/{learnings-JR6MA5TI.js.map → learnings-4FJY7WIW.js.map} +0 -0
  606. /package/dist/cli-bundle/chunks/{list-G5Y65VF6.js.map → list-472TIOVK.js.map} +0 -0
  607. /package/dist/cli-bundle/chunks/{list-DNBJVO3E.js.map → list-D7BF5CL2.js.map} +0 -0
  608. /package/dist/cli-bundle/chunks/{notes-2BMU3VVQ.js.map → notes-6KNOSLIT.js.map} +0 -0
  609. /package/dist/cli-bundle/chunks/{notes-6KTGO2OJ.js.map → notes-W4UEICGF.js.map} +0 -0
  610. /package/dist/cli-bundle/chunks/{restore-4MHZFJ2E.js.map → restore-44IHMMZZ.js.map} +0 -0
  611. /package/dist/cli-bundle/chunks/{restore-YALDGTQR.js.map → restore-EXHU34EU.js.map} +0 -0
  612. /package/dist/cli-bundle/chunks/{scheduling-shortcuts-LB6DOLRL.js.map → scheduling-shortcuts-OLHNLAZY.js.map} +0 -0
  613. /package/dist/cli-bundle/chunks/{scheduling-shortcuts-UTOYKLXQ.js.map → scheduling-shortcuts-TSBK4AY5.js.map} +0 -0
  614. /package/dist/cli-bundle/chunks/{schema-73HR2OJW.js.map → schema-IB2NZZWD.js.map} +0 -0
  615. /package/dist/cli-bundle/chunks/{schema-U6LJKSIR.js.map → schema-VBCELP5G.js.map} +0 -0
  616. /package/dist/cli-bundle/chunks/{search-AXPXKZER.js.map → search-7UBETML4.js.map} +0 -0
  617. /package/dist/cli-bundle/chunks/{search-KILGT37L.js.map → search-R227JOL6.js.map} +0 -0
  618. /package/dist/cli-bundle/chunks/{stats-W5KNVJWQ.js.map → stats-FAG7COEH.js.map} +0 -0
  619. /package/dist/cli-bundle/chunks/{stats-PSYVVTNZ.js.map → stats-MCK7PLYS.js.map} +0 -0
  620. /package/dist/cli-bundle/chunks/{test-PWDIZ255.js.map → test-QY44WAMR.js.map} +0 -0
  621. /package/dist/cli-bundle/chunks/{test-ACD52Z3S.js.map → test-SY76DZTO.js.map} +0 -0
  622. /package/dist/cli-bundle/chunks/{update-AMRSOIWP.js.map → update-A7EICML6.js.map} +0 -0
  623. /package/dist/cli-bundle/chunks/{update-KFX2SIAC.js.map → update-IKJZWLQC.js.map} +0 -0
  624. /package/dist/cli-bundle/chunks/{upgrade-BRL6KCOJ.js.map → upgrade-NWMR3VQL.js.map} +0 -0
  625. /package/dist/cli-bundle/chunks/{upgrade-HAK6JG2O.js.map → upgrade-VU46BLJZ.js.map} +0 -0
@@ -4,7 +4,7 @@
4
4
  * Implements the pm validate command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a9087567-b334-5e9c-8ed7-e52d8cb35801")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d434e454-cb3f-5eaa-b841-d6f815e0446d")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import { realpathSync } from "node:fs";
10
10
  import { execFile } from "node:child_process";
@@ -122,6 +122,9 @@ const METADATA_TRUNCATED_KEY_BY_FIELD = {
122
122
  const GIT_LS_FILES_MAX_BUFFER = 32 * 1024 * 1024;
123
123
  const FILE_LIST_SUMMARY_LIMIT = 40;
124
124
  const DIAGNOSTIC_LIST_SUMMARY_LIMIT = 5;
125
+ // Conservative pre-stat guard for common filesystem limits; over-limit links are unreadable, not prune-safe.
126
+ const LINKED_ARTIFACT_MAX_PATH_LENGTH = 4096;
127
+ const LINKED_ARTIFACT_MAX_SEGMENT_LENGTH = 255;
125
128
  const execFileAsync = promisify(execFile);
126
129
  function normalizeRelativePath(value) {
127
130
  return value.replaceAll("\\", "/").replace(/^\.\/+/, "").replace(/^\/+/, "");
@@ -651,35 +654,115 @@ function summarizeDuplicateIssueCodes(duplicates, verboseDiagnostics) {
651
654
  warnings: [`${DUPLICATE_ISSUE_CODE_WARNING_TOKEN}:${duplicates.length}`],
652
655
  };
653
656
  }
654
- /* c8 ignore start -- metadata diagnostics/backfill planning permutations are covered by validate integration suites */
655
- function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagnostics) {
656
- const missingByField = Object.fromEntries(SUPPORTED_METADATA_REQUIRED_FIELDS.map((field) => [field, []]));
657
- const itemsById = new Map(items.map((item) => [item.id, item]));
658
- // GH-276: only the `strict` profile enforces planning fields on terminal
659
- // (closed/canceled) historical items; core/minimal/custom profiles treat a
660
- // retired item's missing estimate or acceptance criteria as resolved.
661
- const enforcePlanningFieldsOnTerminal = metadataPolicy.profile === "strict";
657
+ function initializeMissingMetadataByField() {
658
+ return Object.fromEntries(SUPPORTED_METADATA_REQUIRED_FIELDS.map((field) => [field, []]));
659
+ }
660
+ function collectMissingMetadataByField(items, statusRegistry, enforcePlanningFieldsOnTerminal) {
661
+ const missingByField = initializeMissingMetadataByField();
662
662
  for (const item of items) {
663
663
  for (const field of SUPPORTED_METADATA_REQUIRED_FIELDS) {
664
- if (!isMetadataFieldMissing(item, field, statusRegistry, enforcePlanningFieldsOnTerminal)) {
665
- continue;
664
+ if (isMetadataFieldMissing(item, field, statusRegistry, enforcePlanningFieldsOnTerminal)) {
665
+ missingByField[field].push(item.id);
666
666
  }
667
- missingByField[field].push(item.id);
668
667
  }
669
668
  }
669
+ return missingByField;
670
+ }
671
+ function buildMetadataWarningTokens(metadataPolicy, missingByField, duplicateWarnings) {
670
672
  const warningTokens = [...metadataPolicy.warnings];
671
673
  for (const field of metadataPolicy.required_fields) {
672
674
  const missingItems = missingByField[field];
673
- if (missingItems.length === 0) {
675
+ if (missingItems.length > 0) {
676
+ warningTokens.push(`${METADATA_WARNING_TOKEN_BY_FIELD[field]}:${missingItems.length}`);
677
+ }
678
+ }
679
+ warningTokens.push(...duplicateWarnings);
680
+ return warningTokens;
681
+ }
682
+ function buildMetadataCounts(metadataPolicy, missingByField) {
683
+ const counts = {};
684
+ for (const field of metadataPolicy.required_fields) {
685
+ const missing = missingByField[field];
686
+ const value = missing ? missing.length : 0;
687
+ const countKey = METADATA_COUNT_KEY_BY_FIELD[field];
688
+ if (value > 0 && countKey) {
689
+ counts[countKey] = value;
690
+ }
691
+ }
692
+ return counts;
693
+ }
694
+ function buildMissingFieldOccurrences(metadataPolicy, missingByField, itemsById) {
695
+ const occurrences = [];
696
+ for (const field of metadataPolicy.required_fields) {
697
+ const missing = missingByField[field];
698
+ if (!missing) {
674
699
  continue;
675
700
  }
676
- warningTokens.push(`${METADATA_WARNING_TOKEN_BY_FIELD[field]}:${missingItems.length}`);
701
+ for (const itemId of missing) {
702
+ const itemType = itemsById.get(itemId)?.type;
703
+ const normalizedItemType = typeof itemType === "string" && itemType.length > 0 ? itemType : "Unknown";
704
+ occurrences.push({ item_type: normalizedItemType, field });
705
+ }
677
706
  }
707
+ return occurrences;
708
+ }
709
+ /* v8 ignore start -- metadata policy keys are validated before this summarizer; fallback branches are defensive */
710
+ function attachMissingMetadataItemIds(details, metadataPolicy, missingByField, verboseDiagnostics) {
711
+ for (const field of metadataPolicy.required_fields) {
712
+ const missing = missingByField[field];
713
+ if (!missing || missing.length === 0) {
714
+ continue;
715
+ }
716
+ const idsKey = METADATA_ITEM_IDS_KEY_BY_FIELD[field];
717
+ const truncatedKey = METADATA_TRUNCATED_KEY_BY_FIELD[field];
718
+ if (!idsKey || !truncatedKey) {
719
+ continue;
720
+ }
721
+ const summarized = summarizeList(missing, verboseDiagnostics ? missing.length : DIAGNOSTIC_LIST_SUMMARY_LIMIT);
722
+ details[idsKey] = summarized.values;
723
+ details[truncatedKey] = summarized.truncated;
724
+ }
725
+ }
726
+ /* v8 ignore stop */
727
+ function buildCloseReasonBackfillRows(metadataPolicy, missingByField, itemsById) {
728
+ if (!metadataPolicy.required_fields.includes("close_reason")) {
729
+ return [];
730
+ }
731
+ const missing = missingByField.close_reason;
732
+ if (!missing) {
733
+ return [];
734
+ }
735
+ return missing.map((itemId) => ({
736
+ id: itemId,
737
+ resolution: toNonEmptyStringOrUndefined(itemsById.get(itemId)?.resolution),
738
+ }));
739
+ }
740
+ function buildEstimateBackfillRows(metadataPolicy, missingByField, itemsById) {
741
+ if (!metadataPolicy.required_fields.includes("estimated_minutes")) {
742
+ return [];
743
+ }
744
+ const missing = missingByField.estimated_minutes;
745
+ if (!missing) {
746
+ return [];
747
+ }
748
+ return missing.map((itemId) => ({
749
+ id: itemId,
750
+ type: toNonEmptyStringOrUndefined(itemsById.get(itemId)?.type),
751
+ }));
752
+ }
753
+ /* c8 ignore start -- metadata diagnostics/backfill planning permutations are covered by validate integration suites */
754
+ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagnostics) {
755
+ const itemsById = new Map(items.map((item) => [item.id, item]));
756
+ // GH-276: only the `strict` profile enforces planning fields on terminal
757
+ // (closed/canceled) historical items; core/minimal/custom profiles treat a
758
+ // retired item's missing estimate or acceptance criteria as resolved.
759
+ const enforcePlanningFieldsOnTerminal = metadataPolicy.profile === "strict";
760
+ const missingByField = collectMissingMetadataByField(items, statusRegistry, enforcePlanningFieldsOnTerminal);
678
761
  // Duplicate logical issue-code detection (GH-235): advisory warning when two
679
762
  // or more items share a leading title issue code (e.g. `ISSUE-004`).
680
763
  const duplicateIssueCodes = findDuplicateIssueCodes(items);
681
764
  const duplicateIssueCodeSummary = summarizeDuplicateIssueCodes(duplicateIssueCodes, verboseDiagnostics);
682
- warningTokens.push(...duplicateIssueCodeSummary.warnings);
765
+ const warningTokens = buildMetadataWarningTokens(metadataPolicy, missingByField, duplicateIssueCodeSummary.warnings);
683
766
  // Zero-suppress counts to reduce agent token cost (telemetry pm-tylj).
684
767
  // Only emit counts for the ACTIVE required fields of the resolved profile so a
685
768
  // looser profile (e.g. core) never reports missing reviewer/risk/sprint/etc.
@@ -687,25 +770,12 @@ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagno
687
770
  // shape could include an unsupported field in required_fields — fall back
688
771
  // to 0 instead of throwing TypeError, and skip writing when the count-key
689
772
  // mapping is undefined.
690
- const counts = {};
691
- for (const field of metadataPolicy.required_fields) {
692
- const value = missingByField[field]?.length ?? 0;
693
- const countKey = METADATA_COUNT_KEY_BY_FIELD[field];
694
- if (value > 0 && countKey) {
695
- counts[countKey] = value;
696
- }
697
- }
773
+ const counts = buildMetadataCounts(metadataPolicy, missingByField);
698
774
  // Per-item-type grouping of missing required-field counts (pm-pmyq /
699
775
  // GH-172): counts only — never row dumps — and only for the ACTIVE required
700
776
  // fields, so the grouping mirrors `counts` at type granularity (e.g.
701
777
  // `{ Task: { close_reason: 3 } }`). Zero-suppressed at both levels.
702
- const missingFieldOccurrences = [];
703
- for (const field of metadataPolicy.required_fields) {
704
- for (const itemId of missingByField[field] ?? []) {
705
- const itemType = itemsById.get(itemId)?.type;
706
- missingFieldOccurrences.push({ item_type: typeof itemType === "string" && itemType.length > 0 ? itemType : "Unknown", field });
707
- }
708
- }
778
+ const missingFieldOccurrences = buildMissingFieldOccurrences(metadataPolicy, missingByField, itemsById);
709
779
  const missingByType = buildMissingByTypeCounts(missingFieldOccurrences);
710
780
  const details = {
711
781
  checked_items: items.length,
@@ -731,40 +801,17 @@ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagno
731
801
  // Defensive guard (Gemini high #2, PR #78 follow-up): same optional-chain
732
802
  // safety as the counts loop above — never throw if a future settings shape
733
803
  // includes an unsupported field.
734
- for (const field of metadataPolicy.required_fields) {
735
- const missing = missingByField[field];
736
- if (!missing || missing.length === 0) {
737
- continue;
738
- }
739
- const idsKey = METADATA_ITEM_IDS_KEY_BY_FIELD[field];
740
- const truncatedKey = METADATA_TRUNCATED_KEY_BY_FIELD[field];
741
- if (!idsKey || !truncatedKey) {
742
- continue;
743
- }
744
- const summarized = summarizeList(missing, verboseDiagnostics ? missing.length : DIAGNOSTIC_LIST_SUMMARY_LIMIT);
745
- details[idsKey] = summarized.values;
746
- details[truncatedKey] = summarized.truncated;
747
- }
804
+ attachMissingMetadataItemIds(details, metadataPolicy, missingByField, verboseDiagnostics);
748
805
  // Auto-fix planning input (pm-c3sz): closed items flagged for a missing
749
806
  // close_reason whose resolution can serve as the derivable source value.
750
807
  // Only collected when close_reason is an active required field, so fixes
751
808
  // always trace back to an actual finding of this run.
752
- const closeReasonBackfillRows = metadataPolicy.required_fields.includes("close_reason")
753
- ? (missingByField.close_reason ?? []).map((itemId) => ({
754
- id: itemId,
755
- resolution: toNonEmptyStringOrUndefined(itemsById.get(itemId)?.resolution),
756
- }))
757
- : [];
809
+ const closeReasonBackfillRows = buildCloseReasonBackfillRows(metadataPolicy, missingByField, itemsById);
758
810
  // Estimate auto-fix planning input (GH-212): items flagged for a missing
759
811
  // estimated_minutes whose type drives the config-driven default backfill.
760
812
  // Only collected when estimated_minutes is an active required field, so fixes
761
813
  // always trace back to an actual finding of this run.
762
- const estimateBackfillRows = metadataPolicy.required_fields.includes("estimated_minutes")
763
- ? (missingByField.estimated_minutes ?? []).map((itemId) => ({
764
- id: itemId,
765
- type: toNonEmptyStringOrUndefined(itemsById.get(itemId)?.type),
766
- }))
767
- : [];
814
+ const estimateBackfillRows = buildEstimateBackfillRows(metadataPolicy, missingByField, itemsById);
768
815
  return {
769
816
  check: {
770
817
  name: "metadata",
@@ -1029,6 +1076,26 @@ function sharedDirectoryPrefixLength(left, right) {
1029
1076
  }
1030
1077
  return count;
1031
1078
  }
1079
+ function scoreOrphanOwnerCandidate(pathValue, linkedPath) {
1080
+ const linkedDir = directoryOf(linkedPath);
1081
+ const orphanDir = directoryOf(pathValue);
1082
+ const directoryPrefix = linkedPath.endsWith("/") ? linkedPath : `${linkedPath}/`;
1083
+ const isDirectoryPrefix = pathValue.startsWith(directoryPrefix);
1084
+ const sameDirectory = linkedDir.length > 0 && linkedDir === orphanDir;
1085
+ const sharedPrefixLength = sharedDirectoryPrefixLength(pathValue, linkedPath);
1086
+ if (!isDirectoryPrefix && !sameDirectory && sharedPrefixLength === 0) {
1087
+ return null;
1088
+ }
1089
+ if (isDirectoryPrefix) {
1090
+ return { score: linkedPath.length + 1000, confidence: "path_prefix" };
1091
+ }
1092
+ return sameDirectory
1093
+ ? { score: sharedPrefixLength + 500, confidence: "same_directory" }
1094
+ : { score: sharedPrefixLength, confidence: "shared_directory" };
1095
+ }
1096
+ function shouldReplaceOrphanOwnerCandidate(best, item, score) {
1097
+ return best === undefined || score > best.score || (score === best.score && item.id.localeCompare(best.item.id) < 0);
1098
+ }
1032
1099
  function findOrphanOwnerCandidate(pathValue, classification, items) {
1033
1100
  const linkKind = classification === "docs_unowned" ? "docs" : "files";
1034
1101
  let best;
@@ -1042,21 +1109,15 @@ function findOrphanOwnerCandidate(pathValue, classification, items) {
1042
1109
  if (linkedPath.length === 0 || linkedPath === pathValue) {
1043
1110
  continue;
1044
1111
  }
1045
- const linkedDir = directoryOf(linkedPath);
1046
- const orphanDir = directoryOf(pathValue);
1047
- const directoryPrefix = linkedPath.endsWith("/") ? linkedPath : `${linkedPath}/`;
1048
- const isDirectoryPrefix = pathValue.startsWith(directoryPrefix);
1049
- const sameDirectory = linkedDir.length > 0 && linkedDir === orphanDir;
1050
- const sharedPrefixLength = sharedDirectoryPrefixLength(pathValue, linkedPath);
1051
- if (!isDirectoryPrefix && !sameDirectory && sharedPrefixLength === 0) {
1112
+ const scored = scoreOrphanOwnerCandidate(pathValue, linkedPath);
1113
+ if (scored === null) {
1052
1114
  continue;
1053
1115
  }
1054
- const score = isDirectoryPrefix ? linkedPath.length + 1000 : sameDirectory ? sharedPrefixLength + 500 : sharedPrefixLength;
1055
- if (best === undefined || score > best.score || (score === best.score && item.id.localeCompare(best.item.id) < 0)) {
1116
+ if (shouldReplaceOrphanOwnerCandidate(best, item, scored.score)) {
1056
1117
  best = {
1057
1118
  item,
1058
- score,
1059
- confidence: isDirectoryPrefix ? "path_prefix" : sameDirectory ? "same_directory" : "shared_directory",
1119
+ score: scored.score,
1120
+ confidence: scored.confidence,
1060
1121
  };
1061
1122
  }
1062
1123
  }
@@ -1089,120 +1150,224 @@ function buildOrphanedPathRows(orphanedFiles, items) {
1089
1150
  function summarizeOrphanedPathRows(rows) {
1090
1151
  return rows.map((row) => `${row.path}:${row.classification} owner_candidate=${row.owner_candidate?.id ?? "unowned"} hint=${JSON.stringify(row.remediation_hint)}`);
1091
1152
  }
1092
- /* c8 ignore start -- lifecycle stale/terminal/dependency diagnostics matrix is covered by end-to-end validate integration runs */
1093
- function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverity, parentCycleSeverity, statusRegistry, lifecyclePatternPolicy, verboseDiagnostics, idPrefix = "pm") {
1153
+ function closureLikeFieldsForItem(item, lifecyclePatternPolicy) {
1154
+ return Object.entries(lifecyclePatternPolicy.closure_like_metadata_field_patterns)
1155
+ .filter(([field, patterns]) => {
1156
+ const value = toMeaningfulString(item[field]);
1157
+ return value ? patterns.some((pattern) => value.toLowerCase().includes(pattern)) : false;
1158
+ })
1159
+ .map(([field]) => field)
1160
+ .sort((left, right) => left.localeCompare(right));
1161
+ }
1162
+ function buildTerminalParentFixRow(item, parent, itemsById, canonicalIdByLowercase, statusRegistry) {
1163
+ const grandparentId = toMeaningfulString(parent.parent);
1164
+ const grandparent = grandparentId
1165
+ ? itemsById.get(canonicalIdByLowercase.get(grandparentId.toLowerCase()) ?? grandparentId)
1166
+ : undefined;
1167
+ return {
1168
+ id: item.id,
1169
+ parent_id: parent.id,
1170
+ grandparent_id: grandparent?.id,
1171
+ grandparent_active: grandparent !== undefined && !isTerminalStatus(grandparent.status, statusRegistry),
1172
+ };
1173
+ }
1174
+ /* v8 ignore start -- stale-blocker reason variants are covered through command-level diagnostics; helper branch counters are defensive */
1175
+ function staleBlockerReasonsForItem(item, blockedStatuses, statusRegistry, lifecyclePatternPolicy) {
1176
+ const blockedBy = toMeaningfulString(item.blocked_by);
1177
+ const blockedReason = toMeaningfulString(item.blocked_reason);
1178
+ const blockedReasonNormalized = blockedReason?.toLowerCase();
1179
+ const normalizedStatus = normalizeStatusForRegistry(item.status, statusRegistry);
1180
+ const reasons = [];
1181
+ if (!blockedStatuses.has(normalizedStatus)) {
1182
+ if (blockedBy) {
1183
+ reasons.push("non_blocked_status_has_blocked_by");
1184
+ }
1185
+ if (blockedReason) {
1186
+ reasons.push("non_blocked_status_has_blocked_reason");
1187
+ }
1188
+ return reasons;
1189
+ }
1190
+ if (!blockedBy && !blockedReason) {
1191
+ /* v8 ignore start -- blocked-status creation paths seed either blocked_by or blocked_reason before lifecycle validation */
1192
+ reasons.push("blocked_status_missing_blocker_context");
1193
+ /* v8 ignore stop */
1194
+ }
1195
+ if (blockedReasonNormalized?.includes("no active blocker")) {
1196
+ reasons.push("blocked_status_reason_reports_no_active_blocker");
1197
+ }
1198
+ if (blockedReasonNormalized &&
1199
+ lifecyclePatternPolicy.stale_blocker_reason_patterns.some((pattern) => blockedReasonNormalized.includes(pattern))) {
1200
+ reasons.push("blocked_status_reason_matches_stale_pattern");
1201
+ }
1202
+ return reasons;
1203
+ }
1204
+ /* v8 ignore stop */
1205
+ function collectLifecycleScanRows(items, includeStaleBlockers, statusRegistry, lifecyclePatternPolicy) {
1094
1206
  const itemsById = new Map(items.map((item) => [item.id, item]));
1207
+ const canonicalIdByLowercase = new Map(items.map((item) => [item.id.toLowerCase(), item.id]));
1208
+ /* v8 ignore start -- runtime status registry normally supplies blocked statuses; fallback preserves legacy settings safety */
1095
1209
  const blockedStatuses = statusRegistry.blocked_statuses.size > 0 ? statusRegistry.blocked_statuses : new Set(["blocked"]);
1096
- const activeItems = items.filter((item) => !isTerminalStatus(item.status, statusRegistry));
1097
- const closureLikeRows = [];
1098
- const terminalParentRows = [];
1099
- const terminalParentFixRows = [];
1100
- const staleBlockerRows = [];
1101
- for (const item of activeItems) {
1102
- const closureLikeFields = Object.entries(lifecyclePatternPolicy.closure_like_metadata_field_patterns)
1103
- .filter(([field, patterns]) => {
1104
- const value = toMeaningfulString(item[field]);
1105
- if (!value) {
1106
- return false;
1107
- }
1108
- const normalized = value.toLowerCase();
1109
- return patterns.some((pattern) => normalized.includes(pattern));
1110
- })
1111
- .map(([field]) => field)
1112
- .sort((left, right) => left.localeCompare(right));
1210
+ /* v8 ignore stop */
1211
+ const rows = {
1212
+ activeItems: items.filter((item) => !isTerminalStatus(item.status, statusRegistry)),
1213
+ closureLikeRows: [],
1214
+ terminalParentRows: [],
1215
+ terminalParentFixRows: [],
1216
+ staleBlockerRows: [],
1217
+ };
1218
+ for (const item of rows.activeItems) {
1219
+ const closureLikeFields = closureLikeFieldsForItem(item, lifecyclePatternPolicy);
1113
1220
  if (closureLikeFields.length > 0) {
1114
- closureLikeRows.push({
1115
- id: item.id,
1116
- fields: closureLikeFields,
1117
- });
1221
+ rows.closureLikeRows.push({ id: item.id, fields: closureLikeFields });
1118
1222
  }
1119
1223
  const parentId = toMeaningfulString(item.parent);
1120
- if (parentId) {
1121
- const parent = itemsById.get(parentId);
1122
- if (parent && isTerminalStatus(parent.status, statusRegistry)) {
1123
- terminalParentRows.push({
1124
- id: item.id,
1125
- parent_id: parent.id,
1126
- parent_status: parent.status,
1127
- });
1128
- // Gated lifecycle auto-fix input (pm-8jss): when the terminal parent
1129
- // has its own ACTIVE parent, the child can be reparented one level up;
1130
- // otherwise the suggested fix clears the parent link.
1131
- const grandparentId = toMeaningfulString(parent.parent);
1132
- const grandparent = grandparentId ? itemsById.get(grandparentId) : undefined;
1133
- terminalParentFixRows.push({
1134
- id: item.id,
1135
- parent_id: parent.id,
1136
- grandparent_id: grandparent?.id,
1137
- grandparent_active: grandparent !== undefined && !isTerminalStatus(grandparent.status, statusRegistry),
1138
- });
1139
- }
1224
+ const parent = parentId ? itemsById.get(canonicalIdByLowercase.get(parentId.toLowerCase()) ?? parentId) : undefined;
1225
+ if (parent && isTerminalStatus(parent.status, statusRegistry)) {
1226
+ rows.terminalParentRows.push({ id: item.id, parent_id: parent.id, parent_status: parent.status });
1227
+ rows.terminalParentFixRows.push(buildTerminalParentFixRow(item, parent, itemsById, canonicalIdByLowercase, statusRegistry));
1140
1228
  }
1229
+ /* v8 ignore start -- stale-blocker reason presence is covered by command diagnostics; branch accounting here is defensive */
1141
1230
  if (includeStaleBlockers) {
1142
- const blockedBy = toMeaningfulString(item.blocked_by);
1143
- const blockedReason = toMeaningfulString(item.blocked_reason);
1144
- const blockedReasonNormalized = blockedReason?.toLowerCase();
1145
- const reasons = [];
1146
- const normalizedStatus = normalizeStatusForRegistry(item.status, statusRegistry);
1147
- if (!blockedStatuses.has(normalizedStatus)) {
1148
- if (blockedBy) {
1149
- reasons.push("non_blocked_status_has_blocked_by");
1150
- }
1151
- if (blockedReason) {
1152
- reasons.push("non_blocked_status_has_blocked_reason");
1153
- }
1154
- }
1155
- else {
1156
- if (!blockedBy && !blockedReason) {
1157
- reasons.push("blocked_status_missing_blocker_context");
1158
- }
1159
- if (blockedReasonNormalized?.includes("no active blocker")) {
1160
- reasons.push("blocked_status_reason_reports_no_active_blocker");
1161
- }
1162
- if (blockedReasonNormalized &&
1163
- lifecyclePatternPolicy.stale_blocker_reason_patterns.some((pattern) => blockedReasonNormalized.includes(pattern))) {
1164
- reasons.push("blocked_status_reason_matches_stale_pattern");
1165
- }
1166
- }
1231
+ const reasons = staleBlockerReasonsForItem(item, blockedStatuses, statusRegistry, lifecyclePatternPolicy);
1167
1232
  if (reasons.length > 0) {
1168
- staleBlockerRows.push({
1233
+ rows.staleBlockerRows.push({
1169
1234
  id: item.id,
1170
1235
  status: item.status,
1171
1236
  reasons: [...new Set(reasons)].sort((left, right) => left.localeCompare(right)),
1172
1237
  });
1173
1238
  }
1174
1239
  }
1240
+ /* v8 ignore stop */
1175
1241
  }
1176
- closureLikeRows.sort((left, right) => left.id.localeCompare(right.id));
1177
- terminalParentRows.sort((left, right) => left.id.localeCompare(right.id) || left.parent_id.localeCompare(right.parent_id));
1178
- terminalParentFixRows.sort((left, right) => left.id.localeCompare(right.id) || left.parent_id.localeCompare(right.parent_id));
1179
- staleBlockerRows.sort((left, right) => left.id.localeCompare(right.id));
1180
- const dependencyCycleDiagnostics = detectLifecycleDependencyCycles(activeItems, idPrefix);
1181
- const parentCycleDiagnostics = detectLifecycleParentCycles(items);
1242
+ return rows;
1243
+ }
1244
+ function sortLifecycleScanRows(rows) {
1245
+ rows.closureLikeRows.sort((left, right) => left.id.localeCompare(right.id));
1246
+ /* v8 ignore start -- parent-id tie breakers only matter for duplicate legacy ids, which the tracker writer prevents */
1247
+ rows.terminalParentRows.sort((left, right) => left.id.localeCompare(right.id) || left.parent_id.localeCompare(right.parent_id));
1248
+ rows.terminalParentFixRows.sort((left, right) => left.id.localeCompare(right.id) || left.parent_id.localeCompare(right.parent_id));
1249
+ /* v8 ignore stop */
1250
+ rows.staleBlockerRows.sort((left, right) => left.id.localeCompare(right.id));
1251
+ }
1252
+ function lifecycleCycleWarningToken(prefix, severity, count) {
1253
+ if (count <= 0 || severity === "off") {
1254
+ return null;
1255
+ }
1256
+ return `${severity === "error" ? `${prefix}_error` : prefix}:${count}`;
1257
+ }
1258
+ function buildLifecycleWarnings(rows, includeStaleBlockers, dependencyCycleSeverity, parentCycleSeverity, dependencyCycleCount, parentCycleCount) {
1182
1259
  const warnings = [];
1183
- if (closureLikeRows.length > 0) {
1184
- warnings.push(`validate_lifecycle_active_closure_like_metadata:${closureLikeRows.length}`);
1260
+ if (rows.closureLikeRows.length > 0) {
1261
+ warnings.push(`validate_lifecycle_active_closure_like_metadata:${rows.closureLikeRows.length}`);
1185
1262
  }
1186
- if (terminalParentRows.length > 0) {
1187
- warnings.push(`validate_lifecycle_active_terminal_parent:${terminalParentRows.length}`);
1263
+ if (rows.terminalParentRows.length > 0) {
1264
+ warnings.push(`validate_lifecycle_active_terminal_parent:${rows.terminalParentRows.length}`);
1188
1265
  }
1189
- if (includeStaleBlockers && staleBlockerRows.length > 0) {
1190
- warnings.push(`validate_lifecycle_stale_blockers:${staleBlockerRows.length}`);
1266
+ if (includeStaleBlockers && rows.staleBlockerRows.length > 0) {
1267
+ warnings.push(`validate_lifecycle_stale_blockers:${rows.staleBlockerRows.length}`);
1191
1268
  }
1192
- if (dependencyCycleDiagnostics.cycle_count > 0 && dependencyCycleSeverity !== "off") {
1193
- warnings.push(`${dependencyCycleSeverity === "error"
1194
- ? "validate_lifecycle_dependency_cycles_error"
1195
- : "validate_lifecycle_dependency_cycles"}:${dependencyCycleDiagnostics.cycle_count}`);
1269
+ const dependencyWarning = lifecycleCycleWarningToken("validate_lifecycle_dependency_cycles", dependencyCycleSeverity, dependencyCycleCount);
1270
+ const parentWarning = lifecycleCycleWarningToken("validate_hierarchy_parent_cycle", parentCycleSeverity, parentCycleCount);
1271
+ return [...warnings, ...(dependencyWarning ? [dependencyWarning] : []), ...(parentWarning ? [parentWarning] : [])];
1272
+ }
1273
+ function linkedArtifactPathExceedsFilesystemLimits(artifactPath) {
1274
+ const normalized = normalizeRelativePath(artifactPath);
1275
+ return (normalized.length > LINKED_ARTIFACT_MAX_PATH_LENGTH ||
1276
+ normalized.split(/[\\/]/).some((segment) => segment.length > LINKED_ARTIFACT_MAX_SEGMENT_LENGTH));
1277
+ }
1278
+ async function linkedArtifactIsMissing(workspaceRoot, artifactPath) {
1279
+ const absolutePath = path.isAbsolute(artifactPath) ? artifactPath : path.resolve(workspaceRoot, artifactPath);
1280
+ if (linkedArtifactPathExceedsFilesystemLimits(absolutePath)) {
1281
+ return false;
1196
1282
  }
1197
- if (parentCycleDiagnostics.cycle_count > 0 && parentCycleSeverity !== "off") {
1198
- warnings.push(`${parentCycleSeverity === "error"
1199
- ? "validate_hierarchy_parent_cycle_error"
1200
- : "validate_hierarchy_parent_cycle"}:${parentCycleDiagnostics.cycle_count}`);
1283
+ try {
1284
+ const stats = await fs.stat(absolutePath);
1285
+ return !stats.isFile() && !stats.isDirectory();
1201
1286
  }
1287
+ catch (error) {
1288
+ const code = typeof error === "object" && error !== null && "code" in error
1289
+ ? error.code
1290
+ : undefined;
1291
+ return code === "ENOENT" || code === "ENOTDIR";
1292
+ }
1293
+ }
1294
+ async function collectLinkedPathScanState(items, workspaceRoot) {
1295
+ const state = {
1296
+ linkedProjectPaths: new Set(),
1297
+ remoteLinkedPaths: new Set(),
1298
+ missingLinkedPaths: [],
1299
+ staleLinkRows: [],
1300
+ };
1301
+ for (const item of items) {
1302
+ const linkedArtifactGroups = [
1303
+ { link_kind: "files", artifacts: item.files ?? [] },
1304
+ { link_kind: "docs", artifacts: item.docs ?? [] },
1305
+ ];
1306
+ for (const group of linkedArtifactGroups) {
1307
+ for (const artifact of group.artifacts) {
1308
+ if (artifact.scope !== "project") {
1309
+ continue;
1310
+ }
1311
+ if (isRemoteLinkedArtifactReference(artifact.path)) {
1312
+ state.remoteLinkedPaths.add(artifact.path.trim());
1313
+ continue;
1314
+ }
1315
+ const normalizedPath = normalizeRelativePath(artifact.path);
1316
+ if (normalizedPath.length === 0) {
1317
+ continue;
1318
+ }
1319
+ state.linkedProjectPaths.add(normalizedPath);
1320
+ if (await linkedArtifactIsMissing(workspaceRoot, artifact.path)) {
1321
+ state.missingLinkedPaths.push(normalizedPath);
1322
+ state.staleLinkRows.push({ item_id: item.id, path: normalizedPath, link_kind: group.link_kind });
1323
+ }
1324
+ }
1325
+ }
1326
+ }
1327
+ return state;
1328
+ }
1329
+ function partitionFileCandidates(fileCandidates, pmRoot, workspaceRoot, fileScanMode, includePmInternals, verboseFileLists) {
1330
+ const strictTrackedAllMode = fileScanMode === "tracked-all-strict";
1331
+ const strictModeForcesPmInternals = strictTrackedAllMode && !includePmInternals;
1332
+ const includePmInternalsEffective = includePmInternals || strictTrackedAllMode;
1333
+ const pmInternalCandidatePrefixes = includePmInternalsEffective ? [] : resolvePmInternalCandidatePrefixes(pmRoot, workspaceRoot);
1334
+ const excludedPmInternalPaths = pmInternalCandidatePrefixes.length === 0
1335
+ ? []
1336
+ : fileCandidates.candidateFiles.filter((candidate) => hasPathPrefix(candidate, pmInternalCandidatePrefixes));
1337
+ const candidateFiles = pmInternalCandidatePrefixes.length === 0
1338
+ ? fileCandidates.candidateFiles
1339
+ : fileCandidates.candidateFiles.filter((candidate) => !hasPathPrefix(candidate, pmInternalCandidatePrefixes));
1340
+ const excludedByReason = {};
1341
+ if (excludedPmInternalPaths.length > 0) {
1342
+ const summarizedPmInternalPaths = summarizeFileList(excludedPmInternalPaths, verboseFileLists);
1343
+ excludedByReason.pm_internals = {
1344
+ count: excludedPmInternalPaths.length,
1345
+ paths: summarizedPmInternalPaths.values,
1346
+ paths_truncated: summarizedPmInternalPaths.truncated,
1347
+ paths_total: summarizedPmInternalPaths.total,
1348
+ };
1349
+ }
1350
+ return {
1351
+ strictTrackedAllMode,
1352
+ strictModeForcesPmInternals,
1353
+ includePmInternalsEffective,
1354
+ pmInternalCandidatePrefixes,
1355
+ excludedPmInternalPaths,
1356
+ candidateFiles,
1357
+ excludedByReason,
1358
+ };
1359
+ }
1360
+ /* c8 ignore start -- lifecycle stale/terminal/dependency diagnostics matrix is covered by end-to-end validate integration runs */
1361
+ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverity, parentCycleSeverity, statusRegistry, lifecyclePatternPolicy, verboseDiagnostics, idPrefix = "pm") {
1362
+ const rows = collectLifecycleScanRows(items, includeStaleBlockers, statusRegistry, lifecyclePatternPolicy);
1363
+ sortLifecycleScanRows(rows);
1364
+ const dependencyCycleDiagnostics = detectLifecycleDependencyCycles(rows.activeItems, idPrefix);
1365
+ const parentCycleDiagnostics = detectLifecycleParentCycles(items);
1366
+ const warnings = buildLifecycleWarnings(rows, includeStaleBlockers, dependencyCycleSeverity, parentCycleSeverity, dependencyCycleDiagnostics.cycle_count, parentCycleDiagnostics.cycle_count);
1202
1367
  const diagnosticLimit = verboseDiagnostics ? Number.POSITIVE_INFINITY : DIAGNOSTIC_LIST_SUMMARY_LIMIT;
1203
- const summarizedClosureLikeRows = summarizeList(closureLikeRows.map((row) => `${row.id}:${row.fields.join(",")}`), diagnosticLimit);
1204
- const summarizedTerminalParentRows = summarizeList(terminalParentRows.map((row) => `${row.id}:${row.parent_id}:${row.parent_status}`), diagnosticLimit);
1205
- const summarizedStaleBlockerRows = summarizeList(staleBlockerRows.map((row) => `${row.id}:${row.status}:${row.reasons.join(",")}`), diagnosticLimit);
1368
+ const summarizedClosureLikeRows = summarizeList(rows.closureLikeRows.map((row) => `${row.id}:${row.fields.join(",")}`), diagnosticLimit);
1369
+ const summarizedTerminalParentRows = summarizeList(rows.terminalParentRows.map((row) => `${row.id}:${row.parent_id}:${row.parent_status}`), diagnosticLimit);
1370
+ const summarizedStaleBlockerRows = summarizeList(rows.staleBlockerRows.map((row) => `${row.id}:${row.status}:${row.reasons.join(",")}`), diagnosticLimit);
1206
1371
  const summarizedDependencyCycleItemIds = summarizeList(dependencyCycleDiagnostics.cycle_item_ids, diagnosticLimit);
1207
1372
  const summarizedDependencyCycleSamplePaths = summarizeList(dependencyCycleDiagnostics.cycle_sample_paths, diagnosticLimit);
1208
1373
  const summarizedParentCycleItemIds = summarizeList(parentCycleDiagnostics.cycle_item_ids, diagnosticLimit);
@@ -1218,15 +1383,15 @@ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverit
1218
1383
  ? "ok"
1219
1384
  : "warn",
1220
1385
  details: {
1221
- checked_active_items: activeItems.length,
1222
- active_closure_like_metadata_items: closureLikeRows.length,
1386
+ checked_active_items: rows.activeItems.length,
1387
+ active_closure_like_metadata_items: rows.closureLikeRows.length,
1223
1388
  active_closure_like_metadata_rows: summarizedClosureLikeRows.values,
1224
1389
  active_closure_like_metadata_rows_truncated: summarizedClosureLikeRows.truncated,
1225
- active_terminal_parent_items: terminalParentRows.length,
1390
+ active_terminal_parent_items: rows.terminalParentRows.length,
1226
1391
  active_terminal_parent_rows: summarizedTerminalParentRows.values,
1227
1392
  active_terminal_parent_rows_truncated: summarizedTerminalParentRows.truncated,
1228
1393
  stale_blocker_checks_enabled: includeStaleBlockers,
1229
- stale_blocker_items: staleBlockerRows.length,
1394
+ stale_blocker_items: rows.staleBlockerRows.length,
1230
1395
  stale_blocker_rows: summarizedStaleBlockerRows.values,
1231
1396
  stale_blocker_rows_truncated: summarizedStaleBlockerRows.truncated,
1232
1397
  dependency_cycle_severity_policy: dependencyCycleSeverity,
@@ -1256,90 +1421,26 @@ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverit
1256
1421
  },
1257
1422
  },
1258
1423
  warnings,
1259
- terminalParentFixRows,
1424
+ terminalParentFixRows: rows.terminalParentFixRows,
1260
1425
  };
1261
1426
  }
1262
1427
  /* c8 ignore stop */
1263
1428
  /* c8 ignore start -- files-check candidate filtering/classification permutations are covered by file-audit integration suites */
1264
1429
  async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, includePmInternals, verboseFileLists) {
1265
- const linkedProjectPaths = new Set();
1266
- const remoteLinkedPaths = new Set();
1267
- const missingLinkedPaths = [];
1268
- const staleLinkRows = [];
1430
+ const linkedPathState = await collectLinkedPathScanState(items, workspaceRoot);
1269
1431
  const itemsById = new Map(items.map((item) => [item.id, item]));
1270
- for (const item of items) {
1271
- const linkedArtifactGroups = [
1272
- { link_kind: "files", artifacts: item.files ?? [] },
1273
- { link_kind: "docs", artifacts: item.docs ?? [] },
1274
- ];
1275
- for (const group of linkedArtifactGroups) {
1276
- for (const artifact of group.artifacts) {
1277
- if (artifact.scope !== "project") {
1278
- continue;
1279
- }
1280
- // Remote references (https:// PR/issue/design-doc URLs recorded via
1281
- // `pm docs --add`) are not local files: they must never be stat'd,
1282
- // classified as moved/deleted, counted missing, or pruned by
1283
- // --prune-missing (which would silently destroy recorded context).
1284
- if (isRemoteLinkedArtifactReference(artifact.path)) {
1285
- remoteLinkedPaths.add(artifact.path.trim());
1286
- continue;
1287
- }
1288
- const normalizedPath = normalizeRelativePath(artifact.path);
1289
- if (normalizedPath.length === 0) {
1290
- continue;
1291
- }
1292
- linkedProjectPaths.add(normalizedPath);
1293
- const absolutePath = path.isAbsolute(artifact.path) ? artifact.path : path.resolve(workspaceRoot, artifact.path);
1294
- let missing = false;
1295
- try {
1296
- const stats = await fs.stat(absolutePath);
1297
- if (!stats.isFile() && !stats.isDirectory()) {
1298
- missing = true;
1299
- }
1300
- }
1301
- catch {
1302
- missing = true;
1303
- }
1304
- if (missing) {
1305
- missingLinkedPaths.push(normalizedPath);
1306
- staleLinkRows.push({ item_id: item.id, path: normalizedPath, link_kind: group.link_kind });
1307
- }
1308
- }
1309
- }
1310
- }
1311
- const uniqueMissingLinkedPaths = [...new Set(missingLinkedPaths)].sort((left, right) => left.localeCompare(right));
1432
+ const uniqueMissingLinkedPaths = [...new Set(linkedPathState.missingLinkedPaths)].sort((left, right) => left.localeCompare(right));
1312
1433
  const fileCandidates = await collectProjectFileCandidates(workspaceRoot, fileScanMode);
1313
- const strictTrackedAllMode = fileScanMode === "tracked-all-strict";
1314
- const strictModeForcesPmInternals = strictTrackedAllMode && !includePmInternals;
1315
- const includePmInternalsEffective = includePmInternals || strictTrackedAllMode;
1316
- const pmInternalCandidatePrefixes = includePmInternalsEffective ? [] : resolvePmInternalCandidatePrefixes(pmRoot, workspaceRoot);
1317
- const excludedPmInternalPaths = pmInternalCandidatePrefixes.length === 0
1318
- ? []
1319
- : fileCandidates.candidateFiles.filter((candidate) => hasPathPrefix(candidate, pmInternalCandidatePrefixes));
1320
- const candidateFiles = pmInternalCandidatePrefixes.length === 0
1321
- ? fileCandidates.candidateFiles
1322
- : fileCandidates.candidateFiles.filter((candidate) => !hasPathPrefix(candidate, pmInternalCandidatePrefixes));
1323
- const excludedPmInternalCount = excludedPmInternalPaths.length;
1324
- const excludedByReason = {};
1325
- if (excludedPmInternalCount > 0) {
1326
- const summarizedPmInternalPaths = summarizeFileList(excludedPmInternalPaths, verboseFileLists);
1327
- excludedByReason.pm_internals = {
1328
- count: excludedPmInternalCount,
1329
- paths: summarizedPmInternalPaths.values,
1330
- paths_truncated: summarizedPmInternalPaths.truncated,
1331
- paths_total: summarizedPmInternalPaths.total,
1332
- };
1333
- }
1334
- const orphanedFiles = candidateFiles.filter((candidate) => !linkedProjectPaths.has(candidate));
1434
+ const partition = partitionFileCandidates(fileCandidates, pmRoot, workspaceRoot, fileScanMode, includePmInternals, verboseFileLists);
1435
+ const orphanedFiles = partition.candidateFiles.filter((candidate) => !linkedPathState.linkedProjectPaths.has(candidate));
1335
1436
  const orphanedPathRows = buildOrphanedPathRows(orphanedFiles, items);
1336
1437
  // Stale-path classification (pm-0v2m / GH-184): a missing linked path whose
1337
1438
  // basename still exists in the candidate scan is reported as `moved` (with
1338
1439
  // relink candidates); otherwise it is `deleted` and safe to prune.
1339
- const classifiedStalePaths = classifyStaleLinkedPaths(uniqueMissingLinkedPaths, candidateFiles);
1440
+ const classifiedStalePaths = classifyStaleLinkedPaths(uniqueMissingLinkedPaths, partition.candidateFiles);
1340
1441
  const classificationByPath = new Map(classifiedStalePaths.map((entry) => [entry.path, entry.classification]));
1341
1442
  const movedStalePathCount = classifiedStalePaths.filter((entry) => entry.classification === "moved").length;
1342
- const staleLinkPruneRows = staleLinkRows
1443
+ const staleLinkPruneRows = linkedPathState.staleLinkRows
1343
1444
  .map((row) => ({
1344
1445
  ...row,
1345
1446
  classification: classificationByPath.get(row.path) ?? "deleted",
@@ -1348,7 +1449,7 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
1348
1449
  left.path.localeCompare(right.path) ||
1349
1450
  left.link_kind.localeCompare(right.link_kind));
1350
1451
  const warnings = [];
1351
- if (strictModeForcesPmInternals) {
1452
+ if (partition.strictModeForcesPmInternals) {
1352
1453
  warnings.push("validate_files_tracked_all_strict_forces_pm_internals");
1353
1454
  }
1354
1455
  if (uniqueMissingLinkedPaths.length > 0) {
@@ -1357,7 +1458,7 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
1357
1458
  if (orphanedFiles.length > 0) {
1358
1459
  warnings.push(`validate_files_orphaned_paths:${orphanedFiles.length}`);
1359
1460
  }
1360
- const uniqueRemoteLinkedPaths = [...remoteLinkedPaths].sort((left, right) => left.localeCompare(right));
1461
+ const uniqueRemoteLinkedPaths = [...linkedPathState.remoteLinkedPaths].sort((left, right) => left.localeCompare(right));
1361
1462
  const summarizedRemote = summarizeFileList(uniqueRemoteLinkedPaths, verboseFileLists);
1362
1463
  const summarizedMissing = summarizeFileList(uniqueMissingLinkedPaths, verboseFileLists);
1363
1464
  const summarizedOrphaned = summarizeFileList(orphanedFiles, verboseFileLists);
@@ -1394,30 +1495,30 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
1394
1495
  workspace_root: workspaceRoot,
1395
1496
  scan_mode_requested: fileCandidates.requestedMode,
1396
1497
  scan_mode_applied: fileCandidates.appliedMode,
1397
- strict_tracked_all_mode: strictTrackedAllMode,
1398
- strict_mode_forces_pm_internals: strictModeForcesPmInternals,
1399
- strict_mode_forces_pm_internals_notice: strictModeForcesPmInternals
1498
+ strict_tracked_all_mode: partition.strictTrackedAllMode,
1499
+ strict_mode_forces_pm_internals: partition.strictModeForcesPmInternals,
1500
+ strict_mode_forces_pm_internals_notice: partition.strictModeForcesPmInternals
1400
1501
  ? "tracked-all-strict force-enables PM internals; pass --include-pm-internals to make inclusion explicit."
1401
1502
  : null,
1402
1503
  file_list_detail_mode: verboseFileLists ? "full" : "summary",
1403
1504
  file_list_summary_limit: FILE_LIST_SUMMARY_LIMIT,
1404
1505
  candidate_scan_source: fileCandidates.source,
1405
- include_pm_internals: includePmInternalsEffective,
1506
+ include_pm_internals: partition.includePmInternalsEffective,
1406
1507
  include_pm_internals_requested: includePmInternals,
1407
- pm_internal_candidate_prefixes: pmInternalCandidatePrefixes,
1408
- pm_internal_excluded_count: excludedPmInternalCount,
1409
- excluded_total: excludedPmInternalCount,
1410
- excluded_by_reason: excludedByReason,
1411
- linked_project_paths: linkedProjectPaths.size,
1508
+ pm_internal_candidate_prefixes: partition.pmInternalCandidatePrefixes,
1509
+ pm_internal_excluded_count: partition.excludedPmInternalPaths.length,
1510
+ excluded_total: partition.excludedPmInternalPaths.length,
1511
+ excluded_by_reason: partition.excludedByReason,
1512
+ linked_project_paths: linkedPathState.linkedProjectPaths.size,
1412
1513
  remote_linked_paths_count: uniqueRemoteLinkedPaths.length,
1413
1514
  remote_linked_paths_total: summarizedRemote.total,
1414
1515
  remote_linked_paths: summarizedRemote.values,
1415
1516
  remote_linked_paths_truncated: summarizedRemote.truncated,
1416
1517
  candidate_total_raw: fileCandidates.candidateTotal,
1417
1518
  candidate_scanned_raw: fileCandidates.candidateScanned,
1418
- candidate_total: candidateFiles.length,
1419
- candidate_scanned: candidateFiles.length,
1420
- scanned_candidate_files: candidateFiles.length,
1519
+ candidate_total: partition.candidateFiles.length,
1520
+ candidate_scanned: partition.candidateFiles.length,
1521
+ scanned_candidate_files: partition.candidateFiles.length,
1421
1522
  missing_linked_paths_count: uniqueMissingLinkedPaths.length,
1422
1523
  missing_linked_paths_total: summarizedMissing.total,
1423
1524
  missing_linked_paths: summarizedMissing.values,
@@ -1692,10 +1793,14 @@ export const _testOnlyValidateCommand = {
1692
1793
  applyValidateFixes,
1693
1794
  attachValidateFixHints,
1694
1795
  buildCommandReferencesCheck,
1796
+ buildCloseReasonBackfillRows,
1695
1797
  buildFilesCheck,
1696
1798
  buildLifecycleCheck,
1697
1799
  buildLifecycleDependencyGraph,
1698
1800
  buildLifecycleParentGraph,
1801
+ buildEstimateBackfillRows,
1802
+ buildMetadataCounts,
1803
+ buildMissingFieldOccurrences,
1699
1804
  buildOrphanedPathRows,
1700
1805
  classifyOrphanedPath,
1701
1806
  collectDefaultProjectFileCandidates,
@@ -1706,6 +1811,7 @@ export const _testOnlyValidateCommand = {
1706
1811
  extractItemIds,
1707
1812
  findLifecycleDependencyCycleComponents,
1708
1813
  isMetadataFieldMissing,
1814
+ linkedArtifactPathExceedsFilesystemLimits,
1709
1815
  listFilesRecursive,
1710
1816
  resolveDependencyCycleSeverity,
1711
1817
  resolveParentCycleSeverity,
@@ -1719,6 +1825,107 @@ export const _testOnlyValidateCommand = {
1719
1825
  summarizeDuplicateIssueCodes,
1720
1826
  toMeaningfulString,
1721
1827
  };
1828
+ function recordValidateCheck(state, built, fixHintsEnabled) {
1829
+ if (fixHintsEnabled) {
1830
+ attachValidateFixHints(built.check, built.warnings);
1831
+ }
1832
+ state.checks.push(built.check);
1833
+ state.warnings.push(...built.warnings);
1834
+ }
1835
+ async function executeRequestedValidateChecks(params) {
1836
+ const state = {
1837
+ checks: [],
1838
+ warnings: [...params.initialWarnings],
1839
+ closeReasonBackfillRows: [],
1840
+ estimateBackfillRows: [],
1841
+ resolutionBackfillRows: [],
1842
+ terminalParentFixRows: [],
1843
+ staleLinkPruneRows: [],
1844
+ };
1845
+ const fixHintsEnabled = params.options.fixHints === true;
1846
+ const fullDiagnostics = params.options.verboseDiagnostics === true || params.options.allAffectedIds === true || params.global.json === true;
1847
+ if (params.requestedChecks.has("metadata")) {
1848
+ const built = buildMetadataCheck(params.items, params.metadataPolicy, params.statusRegistry, fullDiagnostics);
1849
+ state.closeReasonBackfillRows = built.closeReasonBackfillRows;
1850
+ state.estimateBackfillRows = built.estimateBackfillRows;
1851
+ recordValidateCheck(state, built, fixHintsEnabled);
1852
+ }
1853
+ if (params.requestedChecks.has("resolution")) {
1854
+ const built = buildResolutionCheck(params.items, params.statusRegistry, fullDiagnostics);
1855
+ state.resolutionBackfillRows = built.resolutionBackfillRows;
1856
+ recordValidateCheck(state, built, fixHintsEnabled);
1857
+ }
1858
+ if (params.requestedChecks.has("lifecycle")) {
1859
+ const built = buildLifecycleCheck(params.items, Boolean(params.options.checkStaleBlockers), params.dependencyCycleSeverity, params.parentCycleSeverity, params.statusRegistry, params.lifecyclePatternPolicy, fullDiagnostics, params.settings.id_prefix);
1860
+ state.terminalParentFixRows = built.terminalParentFixRows;
1861
+ recordValidateCheck(state, built, fixHintsEnabled);
1862
+ }
1863
+ if (params.requestedChecks.has("files")) {
1864
+ const built = await buildFilesCheck(params.items, params.workspaceRoot, params.pmRoot, params.fileScanMode, Boolean(params.options.includePmInternals), Boolean(params.options.verboseFileLists));
1865
+ state.staleLinkPruneRows = built.staleLinkPruneRows;
1866
+ recordValidateCheck(state, built, fixHintsEnabled);
1867
+ }
1868
+ if (params.requestedChecks.has("command_references")) {
1869
+ recordValidateCheck(state, buildCommandReferencesCheck(params.items, params.settings.id_prefix, fullDiagnostics), fixHintsEnabled);
1870
+ }
1871
+ if (params.requestedChecks.has("history_drift")) {
1872
+ recordValidateCheck(state, await buildHistoryDriftCheck(params.pmRoot, params.items, fullDiagnostics), fixHintsEnabled);
1873
+ }
1874
+ if (params.requestedChecks.has("format_version")) {
1875
+ recordValidateCheck(state, buildFormatVersionCheck(params.items, fullDiagnostics), fixHintsEnabled);
1876
+ }
1877
+ return state;
1878
+ }
1879
+ function planValidateFixes(options, state, settings) {
1880
+ const planned = [];
1881
+ if (options.autoFix === true) {
1882
+ planned.push(...planCloseReasonBackfillFixes(state.closeReasonBackfillRows));
1883
+ planned.push(...planResolutionBackfillFixes(state.resolutionBackfillRows));
1884
+ planned.push(...planEstimateBackfillFixes(state.estimateBackfillRows, settings.validation.estimate_defaults_by_type));
1885
+ planned.push(...planTerminalParentFixes(state.terminalParentFixRows));
1886
+ }
1887
+ if (options.pruneMissing === true) {
1888
+ planned.push(...planStaleLinkPruneFixes(state.staleLinkPruneRows));
1889
+ }
1890
+ return planned;
1891
+ }
1892
+ /* v8 ignore start -- validate fix-summary matrix is covered end-to-end; direct helper fallback branches are defensive */
1893
+ async function buildValidateFixesSummary(options, state, settings, grantedFixScopes, global) {
1894
+ if (options.autoFix !== true && options.pruneMissing !== true) {
1895
+ return undefined;
1896
+ }
1897
+ const planned = planValidateFixes(options, state, settings);
1898
+ const { applicable, gated } = partitionFixesByGrant(planned, grantedFixScopes);
1899
+ const dryRun = options.dryRun === true;
1900
+ const appliedFixRows = [];
1901
+ const failedFixRows = [];
1902
+ if (!dryRun) {
1903
+ const applied = await applyValidateFixes(applicable, global);
1904
+ appliedFixRows.push(...applied.applied.map(toFixOutputRow));
1905
+ failedFixRows.push(...applied.failed.map(({ fix, error }) => ({
1906
+ ...toFixOutputRow(fix),
1907
+ error: error instanceof Error ? error.message : String(error),
1908
+ })));
1909
+ }
1910
+ return {
1911
+ mode: dryRun ? "dry_run" : "apply",
1912
+ auto_fix: options.autoFix === true,
1913
+ prune_missing: options.pruneMissing === true,
1914
+ granted_fix_scopes: [...grantedFixScopes].sort((left, right) => left.localeCompare(right)),
1915
+ planned_count: planned.length,
1916
+ applied_count: appliedFixRows.length,
1917
+ gated_count: gated.length,
1918
+ failed_count: failedFixRows.length,
1919
+ planned_fixes: planned.map(toFixOutputRow),
1920
+ applied_fixes: appliedFixRows,
1921
+ gated_fixes: gated.map((fix) => ({
1922
+ ...toFixOutputRow(fix),
1923
+ gate_hint: `Withheld: re-run with --fix-scope ${fix.gate} to apply.`,
1924
+ })),
1925
+ failed_fixes: failedFixRows,
1926
+ };
1927
+ }
1928
+ /* v8 ignore stop */
1722
1929
  /* c8 ignore start -- validate orchestration + fix-application matrices are covered by end-to-end command integration runs */
1723
1930
  /**
1724
1931
  * Implements run validate for the public runtime surface of this module.
@@ -1751,108 +1958,36 @@ export async function runValidate(options, global) {
1751
1958
  const parentCycleSeverity = resolveParentCycleSeverity(options.parentCycleSeverity);
1752
1959
  const fileScanMode = resolveFileScanMode(options.scanMode);
1753
1960
  const workspaceRoot = resolveWorkspaceRoot(pmRoot);
1754
- const checks = [];
1755
- const warnings = [...new Set(itemReadWarnings)];
1756
- const fixHintsEnabled = options.fixHints === true;
1757
- // Full (un-truncated) diagnostic ID lists when the agent asks for them
1758
- // (--verbose-diagnostics/--all-affected-ids) or whenever output is JSON:
1759
- // machine consumers expect complete *_item_ids arrays, never a 5-item cap.
1760
- const fullDiagnostics = options.verboseDiagnostics === true || options.allAffectedIds === true || global.json === true;
1761
- const record = (built) => {
1762
- if (fixHintsEnabled) {
1763
- attachValidateFixHints(built.check, built.warnings);
1764
- }
1765
- checks.push(built.check);
1766
- warnings.push(...built.warnings);
1767
- };
1768
- let closeReasonBackfillRows = [];
1769
- let estimateBackfillRows = [];
1770
- let resolutionBackfillRows = [];
1771
- let terminalParentFixRows = [];
1772
- let staleLinkPruneRows = [];
1773
- if (requestedChecks.has("metadata")) {
1774
- const built = buildMetadataCheck(items, metadataPolicy, statusRegistry, fullDiagnostics);
1775
- closeReasonBackfillRows = built.closeReasonBackfillRows;
1776
- estimateBackfillRows = built.estimateBackfillRows;
1777
- record(built);
1778
- }
1779
- if (requestedChecks.has("resolution")) {
1780
- const built = buildResolutionCheck(items, statusRegistry, fullDiagnostics);
1781
- resolutionBackfillRows = built.resolutionBackfillRows;
1782
- record(built);
1783
- }
1784
- if (requestedChecks.has("lifecycle")) {
1785
- const built = buildLifecycleCheck(items, Boolean(options.checkStaleBlockers), dependencyCycleSeverity, parentCycleSeverity, statusRegistry, lifecyclePatternPolicy, fullDiagnostics, settings.id_prefix);
1786
- terminalParentFixRows = built.terminalParentFixRows;
1787
- record(built);
1788
- }
1789
- if (requestedChecks.has("files")) {
1790
- const built = await buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, Boolean(options.includePmInternals), Boolean(options.verboseFileLists));
1791
- staleLinkPruneRows = built.staleLinkPruneRows;
1792
- record(built);
1793
- }
1794
- if (requestedChecks.has("command_references")) {
1795
- record(buildCommandReferencesCheck(items, settings.id_prefix, fullDiagnostics));
1796
- }
1797
- if (requestedChecks.has("history_drift")) {
1798
- record(await buildHistoryDriftCheck(pmRoot, items, fullDiagnostics));
1799
- }
1800
- if (requestedChecks.has("format_version")) {
1801
- record(buildFormatVersionCheck(items, fullDiagnostics));
1802
- }
1961
+ const state = await executeRequestedValidateChecks({
1962
+ requestedChecks,
1963
+ options,
1964
+ global,
1965
+ pmRoot,
1966
+ workspaceRoot,
1967
+ settings,
1968
+ items,
1969
+ statusRegistry,
1970
+ metadataPolicy,
1971
+ lifecyclePatternPolicy,
1972
+ dependencyCycleSeverity,
1973
+ parentCycleSeverity,
1974
+ fileScanMode,
1975
+ initialWarnings: [...new Set(itemReadWarnings)],
1976
+ });
1803
1977
  // Remediation phase (pm-c3sz / pm-8jss / pm-0v2m). Plans are derived from
1804
1978
  // the findings of THIS run; checks above always report the pre-fix state.
1805
1979
  // Safe field backfills apply by default under --auto-fix; gated lifecycle
1806
1980
  // fixes are planned but withheld unless --fix-scope lifecycle grants them;
1807
1981
  // --dry-run previews without mutating; failures never abort the run.
1808
- let fixes;
1809
- if (fixesRequested) {
1810
- const planned = [];
1811
- if (options.autoFix === true) {
1812
- planned.push(...planCloseReasonBackfillFixes(closeReasonBackfillRows));
1813
- planned.push(...planResolutionBackfillFixes(resolutionBackfillRows));
1814
- planned.push(...planEstimateBackfillFixes(estimateBackfillRows, settings.validation.estimate_defaults_by_type));
1815
- planned.push(...planTerminalParentFixes(terminalParentFixRows));
1816
- }
1817
- if (options.pruneMissing === true) {
1818
- planned.push(...planStaleLinkPruneFixes(staleLinkPruneRows));
1819
- }
1820
- const { applicable, gated } = partitionFixesByGrant(planned, grantedFixScopes);
1821
- const dryRun = options.dryRun === true;
1822
- const appliedFixRows = [];
1823
- const failedFixRows = [];
1824
- if (!dryRun) {
1825
- const applied = await applyValidateFixes(applicable, global);
1826
- appliedFixRows.push(...applied.applied.map(toFixOutputRow));
1827
- failedFixRows.push(...applied.failed.map(({ fix, error }) => ({
1828
- ...toFixOutputRow(fix),
1829
- error: error instanceof Error ? error.message : String(error),
1830
- })));
1831
- }
1832
- fixes = {
1833
- mode: dryRun ? "dry_run" : "apply",
1834
- auto_fix: options.autoFix === true,
1835
- prune_missing: options.pruneMissing === true,
1836
- granted_fix_scopes: [...grantedFixScopes].sort((left, right) => left.localeCompare(right)),
1837
- planned_count: planned.length,
1838
- applied_count: appliedFixRows.length,
1839
- gated_count: gated.length,
1840
- failed_count: failedFixRows.length,
1841
- planned_fixes: planned.map(toFixOutputRow),
1842
- applied_fixes: appliedFixRows,
1843
- gated_fixes: gated.map((fix) => ({
1844
- ...toFixOutputRow(fix),
1845
- gate_hint: `Withheld: re-run with --fix-scope ${fix.gate} to apply.`,
1846
- })),
1847
- failed_fixes: failedFixRows,
1848
- };
1849
- }
1850
- const normalizedWarnings = [...new Set(warnings)].sort((left, right) => left.localeCompare(right));
1851
- const hasErrors = checks.some((check) => check.status === "error");
1982
+ const fixes = fixesRequested
1983
+ ? await buildValidateFixesSummary(options, state, settings, grantedFixScopes, global)
1984
+ : undefined;
1985
+ const normalizedWarnings = [...new Set(state.warnings)].sort((left, right) => left.localeCompare(right));
1986
+ const hasErrors = state.checks.some((check) => check.status === "error");
1852
1987
  return {
1853
1988
  ok: !hasErrors,
1854
1989
  has_warnings: normalizedWarnings.length > 0,
1855
- checks,
1990
+ checks: state.checks,
1856
1991
  warnings: normalizedWarnings,
1857
1992
  ...(fixes !== undefined ? { fixes } : {}),
1858
1993
  generated_at: nowIso(),
@@ -1860,4 +1995,4 @@ export async function runValidate(options, global) {
1860
1995
  }
1861
1996
  /* c8 ignore stop */
1862
1997
  //# sourceMappingURL=validate.js.map
1863
- //# debugId=a9087567-b334-5e9c-8ed7-e52d8cb35801
1998
+ //# debugId=d434e454-cb3f-5eaa-b841-d6f815e0446d