@unbrained/pm-cli 2026.6.30 → 2026.7.2

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 (628) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +26 -0
  3. package/dist/cli/bootstrap-args.js +89 -79
  4. package/dist/cli/bootstrap-args.js.map +1 -1
  5. package/dist/cli/commander-usage.d.ts +2 -0
  6. package/dist/cli/commander-usage.js +58 -47
  7. package/dist/cli/commander-usage.js.map +1 -1
  8. package/dist/cli/commands/aggregate.js +102 -79
  9. package/dist/cli/commands/aggregate.js.map +1 -1
  10. package/dist/cli/commands/calendar.js +339 -303
  11. package/dist/cli/commands/calendar.js.map +1 -1
  12. package/dist/cli/commands/close-many.js +89 -68
  13. package/dist/cli/commands/close-many.js.map +1 -1
  14. package/dist/cli/commands/close.js +157 -129
  15. package/dist/cli/commands/close.js.map +1 -1
  16. package/dist/cli/commands/comments-audit.js +50 -42
  17. package/dist/cli/commands/comments-audit.js.map +1 -1
  18. package/dist/cli/commands/config.d.ts +2 -0
  19. package/dist/cli/commands/config.js +443 -879
  20. package/dist/cli/commands/config.js.map +1 -1
  21. package/dist/cli/commands/context.js +365 -287
  22. package/dist/cli/commands/context.js.map +1 -1
  23. package/dist/cli/commands/contracts.js +352 -238
  24. package/dist/cli/commands/contracts.js.map +1 -1
  25. package/dist/cli/commands/create.js +483 -434
  26. package/dist/cli/commands/create.js.map +1 -1
  27. package/dist/cli/commands/dedupe-audit.js +46 -39
  28. package/dist/cli/commands/dedupe-audit.js.map +1 -1
  29. package/dist/cli/commands/dedupe-merge.js +88 -69
  30. package/dist/cli/commands/dedupe-merge.js.map +1 -1
  31. package/dist/cli/commands/extension/bundled-catalog.js +59 -46
  32. package/dist/cli/commands/extension/bundled-catalog.js.map +1 -1
  33. package/dist/cli/commands/extension/doctor.js +129 -78
  34. package/dist/cli/commands/extension/doctor.js.map +1 -1
  35. package/dist/cli/commands/extension/managed-state.js +101 -57
  36. package/dist/cli/commands/extension/managed-state.js.map +1 -1
  37. package/dist/cli/commands/extension/scaffold.d.ts +7 -0
  38. package/dist/cli/commands/extension/scaffold.js +214 -186
  39. package/dist/cli/commands/extension/scaffold.js.map +1 -1
  40. package/dist/cli/commands/extension.d.ts +6 -1
  41. package/dist/cli/commands/extension.js +1034 -902
  42. package/dist/cli/commands/extension.js.map +1 -1
  43. package/dist/cli/commands/get.js +114 -81
  44. package/dist/cli/commands/get.js.map +1 -1
  45. package/dist/cli/commands/health.d.ts +17 -0
  46. package/dist/cli/commands/health.js +446 -307
  47. package/dist/cli/commands/health.js.map +1 -1
  48. package/dist/cli/commands/history-compact.js +209 -140
  49. package/dist/cli/commands/history-compact.js.map +1 -1
  50. package/dist/cli/commands/history-redact.js +162 -119
  51. package/dist/cli/commands/history-redact.js.map +1 -1
  52. package/dist/cli/commands/history-repair.js +120 -85
  53. package/dist/cli/commands/history-repair.js.map +1 -1
  54. package/dist/cli/commands/init.d.ts +8 -2
  55. package/dist/cli/commands/init.js +263 -162
  56. package/dist/cli/commands/init.js.map +1 -1
  57. package/dist/cli/commands/list-filter-shared.js +55 -48
  58. package/dist/cli/commands/list-filter-shared.js.map +1 -1
  59. package/dist/cli/commands/list.js +152 -102
  60. package/dist/cli/commands/list.js.map +1 -1
  61. package/dist/cli/commands/next.js +49 -32
  62. package/dist/cli/commands/next.js.map +1 -1
  63. package/dist/cli/commands/plan.js +373 -298
  64. package/dist/cli/commands/plan.js.map +1 -1
  65. package/dist/cli/commands/recurrence-parsers.js +43 -25
  66. package/dist/cli/commands/recurrence-parsers.js.map +1 -1
  67. package/dist/cli/commands/reindex.d.ts +21 -5
  68. package/dist/cli/commands/reindex.js +345 -205
  69. package/dist/cli/commands/reindex.js.map +1 -1
  70. package/dist/cli/commands/restore.d.ts +8 -7
  71. package/dist/cli/commands/restore.js +105 -69
  72. package/dist/cli/commands/restore.js.map +1 -1
  73. package/dist/cli/commands/schema.js +33 -30
  74. package/dist/cli/commands/schema.js.map +1 -1
  75. package/dist/cli/commands/search.d.ts +10 -2
  76. package/dist/cli/commands/search.js +595 -536
  77. package/dist/cli/commands/search.js.map +1 -1
  78. package/dist/cli/commands/telemetry.js +98 -87
  79. package/dist/cli/commands/telemetry.js.map +1 -1
  80. package/dist/cli/commands/test-all.js +237 -168
  81. package/dist/cli/commands/test-all.js.map +1 -1
  82. package/dist/cli/commands/test.d.ts +6 -5
  83. package/dist/cli/commands/test.js +530 -464
  84. package/dist/cli/commands/test.js.map +1 -1
  85. package/dist/cli/commands/update-many.js +57 -42
  86. package/dist/cli/commands/update-many.js.map +1 -1
  87. package/dist/cli/commands/update.d.ts +1 -1
  88. package/dist/cli/commands/update.js +764 -747
  89. package/dist/cli/commands/update.js.map +1 -1
  90. package/dist/cli/commands/validate.d.ts +18 -1
  91. package/dist/cli/commands/validate.js +466 -343
  92. package/dist/cli/commands/validate.js.map +1 -1
  93. package/dist/cli/error-guidance.js +399 -357
  94. package/dist/cli/error-guidance.js.map +1 -1
  95. package/dist/cli/extension-command-options.js +48 -21
  96. package/dist/cli/extension-command-options.js.map +1 -1
  97. package/dist/cli/main.d.ts +47 -0
  98. package/dist/cli/main.js +428 -341
  99. package/dist/cli/main.js.map +1 -1
  100. package/dist/cli/migration-gates.js +22 -45
  101. package/dist/cli/migration-gates.js.map +1 -1
  102. package/dist/cli/register-list-query.js +94 -105
  103. package/dist/cli/register-list-query.js.map +1 -1
  104. package/dist/cli/register-mutation.js +400 -416
  105. package/dist/cli/register-mutation.js.map +1 -1
  106. package/dist/cli/register-operations.js +86 -66
  107. package/dist/cli/register-operations.js.map +1 -1
  108. package/dist/cli/register-setup.js +120 -101
  109. package/dist/cli/register-setup.js.map +1 -1
  110. package/dist/cli/registration-helpers.js +117 -122
  111. package/dist/cli/registration-helpers.js.map +1 -1
  112. package/dist/cli-bundle/chunks/{activity-MVSEND6D.js → activity-CUC4JY3U.js} +9 -9
  113. package/dist/cli-bundle/chunks/activity-WEIEMM73.js +16 -0
  114. package/dist/cli-bundle/chunks/{aggregate-MOC4TR2G.js → aggregate-DKUTRY6R.js} +109 -85
  115. package/dist/cli-bundle/chunks/aggregate-DKUTRY6R.js.map +1 -0
  116. package/dist/cli-bundle/chunks/{aggregate-XJHLZQ5X.js → aggregate-SW5PNGCS.js} +108 -84
  117. package/dist/cli-bundle/chunks/{aggregate-XJHLZQ5X.js.map → aggregate-SW5PNGCS.js.map} +2 -2
  118. package/dist/cli-bundle/chunks/{append-KDHT4GHI.js → append-H32VOR2Y.js} +6 -6
  119. package/dist/cli-bundle/chunks/{append-LEDBAM3K.js → append-UBM632FK.js} +6 -6
  120. package/dist/cli-bundle/chunks/{chunk-Z55WX4IQ.js → chunk-2227673O.js} +158 -114
  121. package/dist/cli-bundle/chunks/chunk-2227673O.js.map +1 -0
  122. package/dist/cli-bundle/chunks/{chunk-SJZTPVFT.js → chunk-2ASNV4DH.js} +4 -4
  123. package/dist/cli-bundle/chunks/{chunk-JVQ7UOYC.js → chunk-2CHRYUXL.js} +2 -2
  124. package/dist/cli-bundle/chunks/{chunk-QE5UFCCO.js → chunk-2KWL5NPW.js} +42 -27
  125. package/dist/cli-bundle/chunks/chunk-2KWL5NPW.js.map +1 -0
  126. package/dist/cli-bundle/chunks/{chunk-ZEATCVAC.js → chunk-36UGKF4O.js} +21 -29
  127. package/dist/cli-bundle/chunks/chunk-36UGKF4O.js.map +7 -0
  128. package/dist/cli-bundle/chunks/{chunk-JZG5ADVE.js → chunk-3AZUFQK6.js} +1103 -963
  129. package/dist/cli-bundle/chunks/chunk-3AZUFQK6.js.map +1 -0
  130. package/dist/cli-bundle/chunks/{chunk-DRPF274X.js → chunk-3LCUASYG.js} +2 -2
  131. package/dist/cli-bundle/chunks/{chunk-JJ4SG243.js → chunk-3Q2HBMTI.js} +2 -2
  132. package/dist/cli-bundle/chunks/chunk-4BU75MF4.js +87 -0
  133. package/dist/cli-bundle/chunks/chunk-4BU75MF4.js.map +7 -0
  134. package/dist/cli-bundle/chunks/{chunk-GF7EAR22.js → chunk-4NUOWFBT.js} +109 -72
  135. package/dist/cli-bundle/chunks/chunk-4NUOWFBT.js.map +7 -0
  136. package/dist/cli-bundle/chunks/{chunk-TQ6E76BE.js → chunk-55XRYWEG.js} +6 -6
  137. package/dist/cli-bundle/chunks/{chunk-5IRVSKPS.js → chunk-5GVTFFTC.js} +150 -224
  138. package/dist/cli-bundle/chunks/chunk-5GVTFFTC.js.map +1 -0
  139. package/dist/cli-bundle/chunks/{chunk-CHRNYKNI.js → chunk-5PGBHRY3.js} +41 -26
  140. package/dist/cli-bundle/chunks/chunk-5PGBHRY3.js.map +7 -0
  141. package/dist/cli-bundle/chunks/{chunk-53ARXF2O.js → chunk-66Z3X7ZG.js} +261 -161
  142. package/dist/cli-bundle/chunks/chunk-66Z3X7ZG.js.map +7 -0
  143. package/dist/cli-bundle/chunks/{chunk-A3UNLXNJ.js → chunk-6ITZLD4T.js} +738 -688
  144. package/dist/cli-bundle/chunks/chunk-6ITZLD4T.js.map +7 -0
  145. package/dist/cli-bundle/chunks/{chunk-JTRKME24.js → chunk-6YCYF2AI.js} +262 -162
  146. package/dist/cli-bundle/chunks/chunk-6YCYF2AI.js.map +1 -0
  147. package/dist/cli-bundle/chunks/{chunk-RM6MHL6A.js → chunk-6ZMBJRDJ.js} +580 -467
  148. package/dist/cli-bundle/chunks/chunk-6ZMBJRDJ.js.map +7 -0
  149. package/dist/cli-bundle/chunks/{chunk-RPRW26NG.js → chunk-7MYWF4ZX.js} +110 -73
  150. package/dist/cli-bundle/chunks/chunk-7MYWF4ZX.js.map +1 -0
  151. package/dist/cli-bundle/chunks/{chunk-SNUK7H5J.js → chunk-7NSPKJUS.js} +716 -606
  152. package/dist/cli-bundle/chunks/chunk-7NSPKJUS.js.map +7 -0
  153. package/dist/cli-bundle/chunks/{chunk-KYDYQMNW.js → chunk-7TH5NMVB.js} +95 -53
  154. package/dist/cli-bundle/chunks/chunk-7TH5NMVB.js.map +7 -0
  155. package/dist/cli-bundle/chunks/{chunk-VD3LKZFX.js → chunk-7W4H4K26.js} +739 -689
  156. package/dist/cli-bundle/chunks/chunk-7W4H4K26.js.map +1 -0
  157. package/dist/cli-bundle/chunks/{chunk-IBU2LLWM.js → chunk-A6VOGKBA.js} +6 -6
  158. package/dist/cli-bundle/chunks/{chunk-MLHX6DN5.js → chunk-AIAIXG7I.js} +2 -2
  159. package/dist/cli-bundle/chunks/{chunk-NIBP3I7A.js → chunk-AJEBCRIY.js} +128 -126
  160. package/dist/cli-bundle/chunks/chunk-AJEBCRIY.js.map +1 -0
  161. package/dist/cli-bundle/chunks/{chunk-VZDBVEZR.js → chunk-B4O5S7I3.js} +79 -57
  162. package/dist/cli-bundle/chunks/{chunk-VZDBVEZR.js.map → chunk-B4O5S7I3.js.map} +2 -2
  163. package/dist/cli-bundle/chunks/{chunk-5ABGFWR4.js → chunk-BTX5MIQF.js} +2 -2
  164. package/dist/cli-bundle/chunks/chunk-BVZZN2LH.js +809 -0
  165. package/dist/cli-bundle/chunks/chunk-BVZZN2LH.js.map +7 -0
  166. package/dist/cli-bundle/chunks/{chunk-3JWQCLR5.js → chunk-CYBDUHNO.js} +3 -3
  167. package/dist/cli-bundle/chunks/{chunk-WFJZDUM7.js → chunk-CZPVDLD2.js} +4 -4
  168. package/dist/cli-bundle/chunks/{chunk-FDEVKXC4.js → chunk-EMPGXBUF.js} +22 -30
  169. package/dist/cli-bundle/chunks/chunk-EMPGXBUF.js.map +1 -0
  170. package/dist/cli-bundle/chunks/{chunk-HUYYMTGW.js → chunk-EUKTMRN3.js} +2 -2
  171. package/dist/cli-bundle/chunks/{chunk-EVWYAG46.js → chunk-FFOQHGNH.js} +6 -6
  172. package/dist/cli-bundle/chunks/{chunk-IF4ERU6A.js → chunk-GFMSLORL.js} +6 -6
  173. package/dist/cli-bundle/chunks/{chunk-IZQOJR2B.js → chunk-GRRG3MCT.js} +198 -189
  174. package/dist/cli-bundle/chunks/chunk-GRRG3MCT.js.map +7 -0
  175. package/dist/cli-bundle/chunks/{chunk-IDYCAK35.js → chunk-H4GRLYJS.js} +3 -3
  176. package/dist/cli-bundle/chunks/{chunk-VMY7MZEM.js → chunk-HQTPRV4D.js} +6 -6
  177. package/dist/cli-bundle/chunks/{chunk-CY5IJMUM.js → chunk-I66WE2HE.js} +712 -602
  178. package/dist/cli-bundle/chunks/chunk-I66WE2HE.js.map +1 -0
  179. package/dist/cli-bundle/chunks/{chunk-ZFIEEDTJ.js → chunk-IEEJQCZ4.js} +509 -363
  180. package/dist/cli-bundle/chunks/chunk-IEEJQCZ4.js.map +7 -0
  181. package/dist/cli-bundle/chunks/{chunk-DU66JUGT.js → chunk-IG5JYZGU.js} +488 -420
  182. package/dist/cli-bundle/chunks/chunk-IG5JYZGU.js.map +7 -0
  183. package/dist/cli-bundle/chunks/{chunk-7L6TXOOC.js → chunk-JMK5GCK2.js} +2 -2
  184. package/dist/cli-bundle/chunks/{chunk-LBH7UYKY.js → chunk-JXAUVO6X.js} +258 -169
  185. package/dist/cli-bundle/chunks/{chunk-LBH7UYKY.js.map → chunk-JXAUVO6X.js.map} +2 -2
  186. package/dist/cli-bundle/chunks/{chunk-KRASIL6M.js → chunk-K2VYLVX4.js} +2 -2
  187. package/dist/cli-bundle/chunks/{chunk-4YIMPANT.js → chunk-KCO2EAN5.js} +3 -3
  188. package/dist/cli-bundle/chunks/{chunk-T7ZMQI4J.js → chunk-KIYCOJ63.js} +198 -189
  189. package/dist/cli-bundle/chunks/chunk-KIYCOJ63.js.map +1 -0
  190. package/dist/cli-bundle/chunks/{chunk-D6USKAMA.js → chunk-KLXF7NCC.js} +2 -2
  191. package/dist/cli-bundle/chunks/{chunk-V3KLX7U7.js → chunk-KN3URLKS.js} +510 -364
  192. package/dist/cli-bundle/chunks/chunk-KN3URLKS.js.map +1 -0
  193. package/dist/cli-bundle/chunks/{chunk-OB3RJV5F.js → chunk-LRKMWUUV.js} +2 -2
  194. package/dist/cli-bundle/chunks/{chunk-74PUWBGN.js → chunk-LTRAF2D7.js} +3 -3
  195. package/dist/cli-bundle/chunks/{chunk-5T6WPLRO.js → chunk-MNBPX5JS.js} +394 -354
  196. package/dist/cli-bundle/chunks/chunk-MNBPX5JS.js.map +7 -0
  197. package/dist/cli-bundle/chunks/{chunk-4TXTVZL3.js → chunk-MRD4T5LF.js} +2 -2
  198. package/dist/cli-bundle/chunks/{chunk-E2Q2ULMR.js → chunk-N2JSWVWG.js} +4 -4
  199. package/dist/cli-bundle/chunks/{chunk-7WDETKGP.js → chunk-N3QCJS4M.js} +1105 -965
  200. package/dist/cli-bundle/chunks/chunk-N3QCJS4M.js.map +7 -0
  201. package/dist/cli-bundle/chunks/{chunk-KGQ3W65B.js → chunk-NRZS637N.js} +258 -169
  202. package/dist/cli-bundle/chunks/chunk-NRZS637N.js.map +1 -0
  203. package/dist/cli-bundle/chunks/chunk-OTUJZKGI.js +799 -0
  204. package/dist/cli-bundle/chunks/chunk-OTUJZKGI.js.map +1 -0
  205. package/dist/cli-bundle/chunks/{chunk-ZIE6WXJ2.js → chunk-Q6K2OACU.js} +153 -90
  206. package/dist/cli-bundle/chunks/chunk-Q6K2OACU.js.map +1 -0
  207. package/dist/cli-bundle/chunks/{chunk-K46GQ265.js → chunk-Q6NXOHS6.js} +489 -421
  208. package/dist/cli-bundle/chunks/chunk-Q6NXOHS6.js.map +1 -0
  209. package/dist/cli-bundle/chunks/{chunk-7RIJGN4R.js → chunk-QH3FSKRJ.js} +2 -2
  210. package/dist/cli-bundle/chunks/{chunk-UB3V5WUI.js → chunk-RM37OPYK.js} +394 -354
  211. package/dist/cli-bundle/chunks/chunk-RM37OPYK.js.map +1 -0
  212. package/dist/cli-bundle/chunks/{chunk-OUQ5JEFM.js → chunk-S62UANU7.js} +3 -3
  213. package/dist/cli-bundle/chunks/{chunk-NO6Y6FB2.js → chunk-SPM2XLWI.js} +37 -28
  214. package/dist/cli-bundle/chunks/chunk-SPM2XLWI.js.map +7 -0
  215. package/dist/cli-bundle/chunks/{chunk-DORJSBGJ.js → chunk-SYNKD3ZG.js} +127 -125
  216. package/dist/cli-bundle/chunks/chunk-SYNKD3ZG.js.map +7 -0
  217. package/dist/cli-bundle/chunks/{chunk-6YRAMXRS.js → chunk-SYVUU7EK.js} +581 -468
  218. package/dist/cli-bundle/chunks/chunk-SYVUU7EK.js.map +1 -0
  219. package/dist/cli-bundle/chunks/{chunk-D5LYZVGB.js → chunk-TPOFWBMY.js} +95 -53
  220. package/dist/cli-bundle/chunks/chunk-TPOFWBMY.js.map +1 -0
  221. package/dist/cli-bundle/chunks/{chunk-IHXXUIXS.js → chunk-TTHCEV5Q.js} +92 -77
  222. package/dist/cli-bundle/chunks/chunk-TTHCEV5Q.js.map +1 -0
  223. package/dist/cli-bundle/chunks/{chunk-DLDCPF5X.js → chunk-U2BEEM2X.js} +3 -3
  224. package/dist/cli-bundle/chunks/{chunk-Z5BM2FKQ.js → chunk-UGLU6Q2I.js} +91 -76
  225. package/dist/cli-bundle/chunks/chunk-UGLU6Q2I.js.map +7 -0
  226. package/dist/cli-bundle/chunks/{chunk-73PTKMAE.js → chunk-UT73HUPC.js} +3 -3
  227. package/dist/cli-bundle/chunks/{chunk-F7G53BOA.js → chunk-UTSH5GWX.js} +4 -4
  228. package/dist/cli-bundle/chunks/{chunk-AWN4PPH5.js → chunk-UWKEJMZU.js} +157 -113
  229. package/dist/cli-bundle/chunks/chunk-UWKEJMZU.js.map +7 -0
  230. package/dist/cli-bundle/chunks/chunk-VY3VQ22F.js +84 -0
  231. package/dist/cli-bundle/chunks/chunk-VY3VQ22F.js.map +1 -0
  232. package/dist/cli-bundle/chunks/{chunk-KTMMTOIP.js → chunk-W47SML5B.js} +152 -89
  233. package/dist/cli-bundle/chunks/chunk-W47SML5B.js.map +7 -0
  234. package/dist/cli-bundle/chunks/{chunk-UFKNF23C.js → chunk-WJAMWAHZ.js} +157 -118
  235. package/dist/cli-bundle/chunks/chunk-WJAMWAHZ.js.map +7 -0
  236. package/dist/cli-bundle/chunks/{chunk-HIBK6H4S.js → chunk-XCHUVHKU.js} +685 -544
  237. package/dist/cli-bundle/chunks/chunk-XCHUVHKU.js.map +1 -0
  238. package/dist/cli-bundle/chunks/{chunk-DJDXAU74.js → chunk-XEWQKDYZ.js} +685 -544
  239. package/dist/cli-bundle/chunks/chunk-XEWQKDYZ.js.map +7 -0
  240. package/dist/cli-bundle/chunks/{chunk-BOWQWXLI.js → chunk-XTHQWXVC.js} +158 -119
  241. package/dist/cli-bundle/chunks/chunk-XTHQWXVC.js.map +1 -0
  242. package/dist/cli-bundle/chunks/{chunk-6T5ZIWBS.js → chunk-XWGEMNBR.js} +150 -224
  243. package/dist/cli-bundle/chunks/chunk-XWGEMNBR.js.map +7 -0
  244. package/dist/cli-bundle/chunks/{chunk-JIP67N2K.js → chunk-Y4NRKBFW.js} +3 -3
  245. package/dist/cli-bundle/chunks/{chunk-WTRUDJ3R.js → chunk-YLZZ6T54.js} +38 -29
  246. package/dist/cli-bundle/chunks/chunk-YLZZ6T54.js.map +1 -0
  247. package/dist/cli-bundle/chunks/{chunk-FBZ5XAAF.js → chunk-YPKFV2JR.js} +6 -6
  248. package/dist/cli-bundle/chunks/{chunk-OKQ22KTH.js → chunk-Z4DGFQDH.js} +80 -58
  249. package/dist/cli-bundle/chunks/{chunk-OKQ22KTH.js.map → chunk-Z4DGFQDH.js.map} +1 -1
  250. package/dist/cli-bundle/chunks/{chunk-BN3CWK6G.js → chunk-ZNHEYCDD.js} +2 -2
  251. package/dist/cli-bundle/chunks/{chunk-YEDFE4DC.js → chunk-ZNT7KEWE.js} +2 -2
  252. package/dist/cli-bundle/chunks/{claim-HMCLSLUE.js → claim-SENTPZBN.js} +8 -8
  253. package/dist/cli-bundle/chunks/{claim-6NINZYB3.js → claim-Z7MEQCBT.js} +8 -8
  254. package/dist/cli-bundle/chunks/{close-OP3LK7Z2.js → close-424MX4CU.js} +7 -7
  255. package/dist/cli-bundle/chunks/close-YCWQQPDS.js +14 -0
  256. package/dist/cli-bundle/chunks/{close-many-CXJBOWWY.js → close-many-2IV4J2TR.js} +103 -82
  257. package/dist/cli-bundle/chunks/close-many-2IV4J2TR.js.map +1 -0
  258. package/dist/cli-bundle/chunks/{close-many-BFMP6HHK.js → close-many-SWY34BII.js} +102 -81
  259. package/dist/cli-bundle/chunks/close-many-SWY34BII.js.map +7 -0
  260. package/dist/cli-bundle/chunks/{comments-ETHABIY6.js → comments-4FGNTSNV.js} +8 -8
  261. package/dist/cli-bundle/chunks/{comments-MU2WMBUY.js → comments-7YS5MY5X.js} +8 -8
  262. package/dist/cli-bundle/chunks/config-BZJKK7FZ.js +1062 -0
  263. package/dist/cli-bundle/chunks/config-BZJKK7FZ.js.map +1 -0
  264. package/dist/cli-bundle/chunks/config-G74GISC4.js +1072 -0
  265. package/dist/cli-bundle/chunks/config-G74GISC4.js.map +7 -0
  266. package/dist/cli-bundle/chunks/{context-7ZEZV3BV.js → context-LHVKJSPJ.js} +12 -12
  267. package/dist/cli-bundle/chunks/{context-XDI4DKKT.js → context-ZQY54JNS.js} +12 -12
  268. package/dist/cli-bundle/chunks/{contracts-SMOAN5NF.js → contracts-CP2EZJC7.js} +320 -199
  269. package/dist/cli-bundle/chunks/contracts-CP2EZJC7.js.map +7 -0
  270. package/dist/cli-bundle/chunks/{contracts-KP4QAGVW.js → contracts-FIZLMP7O.js} +321 -200
  271. package/dist/cli-bundle/chunks/contracts-FIZLMP7O.js.map +1 -0
  272. package/dist/cli-bundle/chunks/{copy-JJ3KOQW2.js → copy-GYNQQPW2.js} +5 -5
  273. package/dist/cli-bundle/chunks/{copy-CWM6SBY6.js → copy-TLW7JTQT.js} +5 -5
  274. package/dist/cli-bundle/chunks/{create-J5Q2ELZT.js → create-VSKYSOCD.js} +12 -12
  275. package/dist/cli-bundle/chunks/create-XTMAPS7I.js +28 -0
  276. package/dist/cli-bundle/chunks/{delete-2GZLQEUQ.js → delete-4W5JYCEG.js} +5 -5
  277. package/dist/cli-bundle/chunks/{delete-OOQS4KVD.js → delete-ANTOTI2I.js} +5 -5
  278. package/dist/cli-bundle/chunks/{deps-IF4IGL4R.js → deps-HPPE6MJN.js} +5 -5
  279. package/dist/cli-bundle/chunks/{deps-ZVGGCRR6.js → deps-ZQZN54EZ.js} +5 -5
  280. package/dist/cli-bundle/chunks/{docs-NFTBCQQC.js → docs-RPOVFMP3.js} +7 -7
  281. package/dist/cli-bundle/chunks/{docs-2TIFR62T.js → docs-XJNYBJGE.js} +7 -7
  282. package/dist/cli-bundle/chunks/{eval-2F6EH4XN.js → eval-DM6JBZTS.js} +10 -10
  283. package/dist/cli-bundle/chunks/{eval-PFKXQR3B.js → eval-RFBI5FGS.js} +10 -10
  284. package/dist/cli-bundle/chunks/{extension-GMVOIP4O.js → extension-B3YY4WY5.js} +11 -10
  285. package/dist/cli-bundle/chunks/{extension-3LRYX7SW.js → extension-TTSEFQTS.js} +11 -10
  286. package/dist/cli-bundle/chunks/{files-DF3HO6XK.js → files-5D65CHGE.js} +7 -7
  287. package/dist/cli-bundle/chunks/{files-T5ODMETM.js → files-GPIG77EN.js} +7 -7
  288. package/dist/cli-bundle/chunks/{focus-MY5ARIEK.js → focus-C3PEJV2C.js} +6 -6
  289. package/dist/cli-bundle/chunks/{focus-DLXKK4AH.js → focus-ZHN7WIGX.js} +6 -6
  290. package/dist/cli-bundle/chunks/{gc-MDGRR2SU.js → gc-D4JQ6OWN.js} +3 -3
  291. package/dist/cli-bundle/chunks/{gc-FULIVYR4.js → gc-VZIXDL32.js} +3 -3
  292. package/dist/cli-bundle/chunks/{get-VYPIICPC.js → get-GIBRUUOP.js} +121 -81
  293. package/dist/cli-bundle/chunks/get-GIBRUUOP.js.map +1 -0
  294. package/dist/cli-bundle/chunks/{get-AWK324RS.js → get-IOVAN6RU.js} +120 -80
  295. package/dist/cli-bundle/chunks/get-IOVAN6RU.js.map +7 -0
  296. package/dist/cli-bundle/chunks/{health-Q66C43GN.js → health-L2U3AFKV.js} +437 -264
  297. package/dist/cli-bundle/chunks/health-L2U3AFKV.js.map +1 -0
  298. package/dist/cli-bundle/chunks/{health-FBCVZGSX.js → health-MM7AWXYF.js} +436 -263
  299. package/dist/cli-bundle/chunks/health-MM7AWXYF.js.map +7 -0
  300. package/dist/cli-bundle/chunks/history-DD7L7BNL.js +18 -0
  301. package/dist/cli-bundle/chunks/{history-X4OSES6K.js → history-IL7XCEX2.js} +8 -8
  302. package/dist/cli-bundle/chunks/{history-compact-2GHT32UX.js → history-compact-HALOTOU7.js} +214 -135
  303. package/dist/cli-bundle/chunks/history-compact-HALOTOU7.js.map +1 -0
  304. package/dist/cli-bundle/chunks/{history-compact-WLCQEKXS.js → history-compact-MV25P7DM.js} +213 -134
  305. package/dist/cli-bundle/chunks/history-compact-MV25P7DM.js.map +7 -0
  306. package/dist/cli-bundle/chunks/history-redact-IX4YEWMY.js +19 -0
  307. package/dist/cli-bundle/chunks/{history-redact-45YW65BK.js → history-redact-VYCWQFK7.js} +9 -9
  308. package/dist/cli-bundle/chunks/{history-repair-FY75IC26.js → history-repair-44MODPQF.js} +124 -84
  309. package/dist/cli-bundle/chunks/history-repair-44MODPQF.js.map +1 -0
  310. package/dist/cli-bundle/chunks/{history-repair-GABSDSVD.js → history-repair-CPNAOCNF.js} +123 -83
  311. package/dist/cli-bundle/chunks/history-repair-CPNAOCNF.js.map +7 -0
  312. package/dist/cli-bundle/chunks/{init-KO7CGIRQ.js → init-F27NHENZ.js} +12 -11
  313. package/dist/cli-bundle/chunks/init-HHVQQP6C.js +22 -0
  314. package/dist/cli-bundle/chunks/{learnings-LHZT5BHW.js → learnings-HJVDQIGY.js} +8 -8
  315. package/dist/cli-bundle/chunks/{learnings-3F7YLI45.js → learnings-XSFSUUWK.js} +8 -8
  316. package/dist/cli-bundle/chunks/{list-Y6AU5BJS.js → list-HPMEKCAA.js} +8 -8
  317. package/dist/cli-bundle/chunks/{list-ROT7JF62.js → list-VMPWTURB.js} +8 -8
  318. package/dist/cli-bundle/chunks/{next-66BJB4N2.js → next-ETXF2ZCN.js} +59 -37
  319. package/dist/cli-bundle/chunks/next-ETXF2ZCN.js.map +7 -0
  320. package/dist/cli-bundle/chunks/{next-N5MWJTBY.js → next-QM6YJIIS.js} +60 -38
  321. package/dist/cli-bundle/chunks/next-QM6YJIIS.js.map +1 -0
  322. package/dist/cli-bundle/chunks/{notes-FW6YFLND.js → notes-GDZIKGR6.js} +8 -8
  323. package/dist/cli-bundle/chunks/{notes-EVJZ3VAB.js → notes-WDDBPC4D.js} +8 -8
  324. package/dist/cli-bundle/chunks/{plan-ZHKZ7JVF.js → plan-BGDR73Z6.js} +373 -279
  325. package/dist/cli-bundle/chunks/plan-BGDR73Z6.js.map +1 -0
  326. package/dist/cli-bundle/chunks/{plan-DQ7G4EDC.js → plan-C5IMM335.js} +372 -278
  327. package/dist/cli-bundle/chunks/plan-C5IMM335.js.map +7 -0
  328. package/dist/cli-bundle/chunks/{profile-CHAW6SEA.js → profile-CCOKZ2IQ.js} +9 -9
  329. package/dist/cli-bundle/chunks/{profile-UPZGCDOG.js → profile-HUCENIEQ.js} +9 -9
  330. package/dist/cli-bundle/chunks/{register-list-query-Y2VRHPCL.js → register-list-query-ROSNIL52.js} +80 -83
  331. package/dist/cli-bundle/chunks/register-list-query-ROSNIL52.js.map +1 -0
  332. package/dist/cli-bundle/chunks/{register-list-query-KY6Z6WV7.js → register-list-query-XN4ZRHSV.js} +79 -82
  333. package/dist/cli-bundle/chunks/register-list-query-XN4ZRHSV.js.map +7 -0
  334. package/dist/cli-bundle/chunks/{register-mutation-PCARIGZS.js → register-mutation-CFSB2MS3.js} +406 -385
  335. package/dist/cli-bundle/chunks/register-mutation-CFSB2MS3.js.map +1 -0
  336. package/dist/cli-bundle/chunks/{register-mutation-N6AYSKPM.js → register-mutation-KRLAHEL2.js} +405 -384
  337. package/dist/cli-bundle/chunks/register-mutation-KRLAHEL2.js.map +7 -0
  338. package/dist/cli-bundle/chunks/{register-operations-L6CYTOIH.js → register-operations-4PASGJDB.js} +112 -93
  339. package/dist/cli-bundle/chunks/register-operations-4PASGJDB.js.map +7 -0
  340. package/dist/cli-bundle/chunks/{register-operations-YAT6FUUB.js → register-operations-MBN4KGUM.js} +113 -94
  341. package/dist/cli-bundle/chunks/register-operations-MBN4KGUM.js.map +1 -0
  342. package/dist/cli-bundle/chunks/{register-setup-N7UGXYJC.js → register-setup-VIAWYFP5.js} +129 -104
  343. package/dist/cli-bundle/chunks/register-setup-VIAWYFP5.js.map +1 -0
  344. package/dist/cli-bundle/chunks/{register-setup-MPANILQF.js → register-setup-ZCGKHDKL.js} +128 -103
  345. package/dist/cli-bundle/chunks/register-setup-ZCGKHDKL.js.map +7 -0
  346. package/dist/cli-bundle/chunks/{restore-DKMCLPI5.js → restore-4CBWUMCX.js} +9 -9
  347. package/dist/cli-bundle/chunks/restore-5UEAGG3W.js +17 -0
  348. package/dist/cli-bundle/chunks/{scheduling-shortcuts-3F4QUEDH.js → scheduling-shortcuts-6VFKNKCM.js} +12 -12
  349. package/dist/cli-bundle/chunks/{scheduling-shortcuts-BNZLQK36.js → scheduling-shortcuts-ERHCVTEM.js} +12 -12
  350. package/dist/cli-bundle/chunks/{schema-OLT6LVKH.js → schema-TDGK6N3I.js} +7 -7
  351. package/dist/cli-bundle/chunks/{schema-XJXKJQF5.js → schema-UE5KKAUX.js} +7 -7
  352. package/dist/cli-bundle/chunks/{search-KP6H7COV.js → search-FP7MEU4S.js} +10 -10
  353. package/dist/cli-bundle/chunks/{search-CX5UMV4H.js → search-K4CFLQ5S.js} +10 -10
  354. package/dist/cli-bundle/chunks/{stats-QZUG6MX5.js → stats-NJJCALEZ.js} +6 -6
  355. package/dist/cli-bundle/chunks/{stats-7XW4OEMK.js → stats-XT6QRKQY.js} +6 -6
  356. package/dist/cli-bundle/chunks/{telemetry-DIFPXCAT.js → telemetry-5SQ5UDXC.js} +84 -70
  357. package/dist/cli-bundle/chunks/telemetry-5SQ5UDXC.js.map +7 -0
  358. package/dist/cli-bundle/chunks/{telemetry-WTYFUPRL.js → telemetry-HVXFZA2U.js} +85 -71
  359. package/dist/cli-bundle/chunks/telemetry-HVXFZA2U.js.map +1 -0
  360. package/dist/cli-bundle/chunks/{test-QNDXZQCW.js → test-UFSJ5YIO.js} +15 -14
  361. package/dist/cli-bundle/chunks/{test-HU2BS7EY.js → test-YCDAUBWF.js} +15 -14
  362. package/dist/cli-bundle/chunks/test-all-2BWKY3GQ.js +427 -0
  363. package/dist/cli-bundle/chunks/test-all-2BWKY3GQ.js.map +1 -0
  364. package/dist/cli-bundle/chunks/test-all-PM7UYN42.js +430 -0
  365. package/dist/cli-bundle/chunks/test-all-PM7UYN42.js.map +7 -0
  366. package/dist/cli-bundle/chunks/{test-runs-CA6K32RD.js → test-runs-FK5E75AA.js} +185 -147
  367. package/dist/cli-bundle/chunks/test-runs-FK5E75AA.js.map +1 -0
  368. package/dist/cli-bundle/chunks/{test-runs-LANLLPVO.js → test-runs-H4TGWGRN.js} +184 -146
  369. package/dist/cli-bundle/chunks/test-runs-H4TGWGRN.js.map +7 -0
  370. package/dist/cli-bundle/chunks/update-MTCFES6X.js +24 -0
  371. package/dist/cli-bundle/chunks/{update-DJKWLBWJ.js → update-Y5WQVT5O.js} +15 -15
  372. package/dist/cli-bundle/chunks/{update-many-LU3SCNK5.js → update-many-6YAYYRLE.js} +83 -68
  373. package/dist/cli-bundle/chunks/{update-many-LU3SCNK5.js.map → update-many-6YAYYRLE.js.map} +2 -2
  374. package/dist/cli-bundle/chunks/{update-many-VW5DGF3S.js → update-many-JTKKSA7Y.js} +84 -69
  375. package/dist/cli-bundle/chunks/{update-many-VW5DGF3S.js.map → update-many-JTKKSA7Y.js.map} +1 -1
  376. package/dist/cli-bundle/chunks/{upgrade-ICXY244R.js → upgrade-DTAHZ236.js} +11 -10
  377. package/dist/cli-bundle/chunks/{upgrade-ICXY244R.js.map → upgrade-DTAHZ236.js.map} +1 -1
  378. package/dist/cli-bundle/chunks/{upgrade-77FRUAXN.js → upgrade-JUDU7YL4.js} +13 -12
  379. package/dist/cli-bundle/chunks/{upgrade-77FRUAXN.js.map → upgrade-JUDU7YL4.js.map} +1 -1
  380. package/dist/cli-bundle/chunks/{validate-2G566PKQ.js → validate-732RWS5W.js} +440 -319
  381. package/dist/cli-bundle/chunks/validate-732RWS5W.js.map +7 -0
  382. package/dist/cli-bundle/chunks/{validate-BDPVXHHH.js → validate-W7H5TEDC.js} +441 -320
  383. package/dist/cli-bundle/chunks/validate-W7H5TEDC.js.map +1 -0
  384. package/dist/cli-bundle/main.js +986 -1500
  385. package/dist/cli-bundle/main.js.map +4 -4
  386. package/dist/core/config/nested-settings.js +89 -67
  387. package/dist/core/config/nested-settings.js.map +1 -1
  388. package/dist/core/extensions/activation-summary-markdown.js +23 -12
  389. package/dist/core/extensions/activation-summary-markdown.js.map +1 -1
  390. package/dist/core/extensions/extension-policy.d.ts +18 -3
  391. package/dist/core/extensions/extension-policy.js +116 -106
  392. package/dist/core/extensions/extension-policy.js.map +1 -1
  393. package/dist/core/extensions/loader.js +310 -232
  394. package/dist/core/extensions/loader.js.map +1 -1
  395. package/dist/core/governance/metadata-coverage.js +20 -28
  396. package/dist/core/governance/metadata-coverage.js.map +1 -1
  397. package/dist/core/history/drift-scan.js +93 -81
  398. package/dist/core/history/drift-scan.js.map +1 -1
  399. package/dist/core/item/item-format.js +523 -410
  400. package/dist/core/item/item-format.js.map +1 -1
  401. package/dist/core/item/item-type-definition.js +14 -14
  402. package/dist/core/item/item-type-definition.js.map +1 -1
  403. package/dist/core/item/type-registry.js +87 -82
  404. package/dist/core/item/type-registry.js.map +1 -1
  405. package/dist/core/output/mutation-projection.js +42 -26
  406. package/dist/core/output/mutation-projection.js.map +1 -1
  407. package/dist/core/schema/runtime-schema.js +34 -28
  408. package/dist/core/schema/runtime-schema.js.map +1 -1
  409. package/dist/core/search/semantic-defaults.js +64 -37
  410. package/dist/core/search/semantic-defaults.js.map +1 -1
  411. package/dist/core/search/vector-stores.js +32 -17
  412. package/dist/core/search/vector-stores.js.map +1 -1
  413. package/dist/core/sentry/helpers.js +31 -28
  414. package/dist/core/sentry/helpers.js.map +1 -1
  415. package/dist/core/sentry/instrument.js +54 -43
  416. package/dist/core/sentry/instrument.js.map +1 -1
  417. package/dist/core/store/front-matter-cache.js +239 -153
  418. package/dist/core/store/front-matter-cache.js.map +1 -1
  419. package/dist/core/store/item-store.js +33 -26
  420. package/dist/core/store/item-store.js.map +1 -1
  421. package/dist/core/store/settings.js +247 -203
  422. package/dist/core/store/settings.js.map +1 -1
  423. package/dist/core/test/background-runs.js +189 -160
  424. package/dist/core/test/background-runs.js.map +1 -1
  425. package/dist/mcp/server.js +387 -367
  426. package/dist/mcp/server.js.map +1 -1
  427. package/dist/sdk/cli-contracts/flag-contracts.js +111 -180
  428. package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
  429. package/dist/sdk/cli-contracts/tool-schema.js +76 -45
  430. package/dist/sdk/cli-contracts/tool-schema.js.map +1 -1
  431. package/dist/sdk/compose.d.ts +4 -1
  432. package/dist/sdk/compose.js +181 -115
  433. package/dist/sdk/compose.js.map +1 -1
  434. package/docs/RELEASING.md +2 -3
  435. package/package.json +2 -2
  436. package/packages/pm-beads/extensions/beads/runtime.ts +240 -167
  437. package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +65 -58
  438. package/packages/pm-todos/extensions/todos/runtime.ts +65 -42
  439. package/dist/cli-bundle/chunks/activity-EJBMXUBH.js +0 -16
  440. package/dist/cli-bundle/chunks/aggregate-MOC4TR2G.js.map +0 -1
  441. package/dist/cli-bundle/chunks/chunk-53ARXF2O.js.map +0 -7
  442. package/dist/cli-bundle/chunks/chunk-5IRVSKPS.js.map +0 -1
  443. package/dist/cli-bundle/chunks/chunk-5T6WPLRO.js.map +0 -7
  444. package/dist/cli-bundle/chunks/chunk-6T5ZIWBS.js.map +0 -7
  445. package/dist/cli-bundle/chunks/chunk-6YRAMXRS.js.map +0 -1
  446. package/dist/cli-bundle/chunks/chunk-7WDETKGP.js.map +0 -7
  447. package/dist/cli-bundle/chunks/chunk-A3UNLXNJ.js.map +0 -7
  448. package/dist/cli-bundle/chunks/chunk-AWN4PPH5.js.map +0 -7
  449. package/dist/cli-bundle/chunks/chunk-BOWQWXLI.js.map +0 -1
  450. package/dist/cli-bundle/chunks/chunk-C2KCIZKZ.js +0 -115
  451. package/dist/cli-bundle/chunks/chunk-C2KCIZKZ.js.map +0 -1
  452. package/dist/cli-bundle/chunks/chunk-CHRNYKNI.js.map +0 -7
  453. package/dist/cli-bundle/chunks/chunk-CY5IJMUM.js.map +0 -1
  454. package/dist/cli-bundle/chunks/chunk-D5LYZVGB.js.map +0 -1
  455. package/dist/cli-bundle/chunks/chunk-DJDXAU74.js.map +0 -7
  456. package/dist/cli-bundle/chunks/chunk-DORJSBGJ.js.map +0 -7
  457. package/dist/cli-bundle/chunks/chunk-DU66JUGT.js.map +0 -7
  458. package/dist/cli-bundle/chunks/chunk-F6VH3LFC.js +0 -118
  459. package/dist/cli-bundle/chunks/chunk-F6VH3LFC.js.map +0 -7
  460. package/dist/cli-bundle/chunks/chunk-FDEVKXC4.js.map +0 -1
  461. package/dist/cli-bundle/chunks/chunk-GF7EAR22.js.map +0 -7
  462. package/dist/cli-bundle/chunks/chunk-HIBK6H4S.js.map +0 -1
  463. package/dist/cli-bundle/chunks/chunk-IHXXUIXS.js.map +0 -1
  464. package/dist/cli-bundle/chunks/chunk-ISEKN64V.js +0 -35
  465. package/dist/cli-bundle/chunks/chunk-ISEKN64V.js.map +0 -7
  466. package/dist/cli-bundle/chunks/chunk-IZQOJR2B.js.map +0 -7
  467. package/dist/cli-bundle/chunks/chunk-JTRKME24.js.map +0 -1
  468. package/dist/cli-bundle/chunks/chunk-JZG5ADVE.js.map +0 -1
  469. package/dist/cli-bundle/chunks/chunk-K46GQ265.js.map +0 -1
  470. package/dist/cli-bundle/chunks/chunk-KGQ3W65B.js.map +0 -1
  471. package/dist/cli-bundle/chunks/chunk-KTMMTOIP.js.map +0 -7
  472. package/dist/cli-bundle/chunks/chunk-KYDYQMNW.js.map +0 -7
  473. package/dist/cli-bundle/chunks/chunk-NIBP3I7A.js.map +0 -1
  474. package/dist/cli-bundle/chunks/chunk-NO6Y6FB2.js.map +0 -7
  475. package/dist/cli-bundle/chunks/chunk-QE5UFCCO.js.map +0 -1
  476. package/dist/cli-bundle/chunks/chunk-RM6MHL6A.js.map +0 -7
  477. package/dist/cli-bundle/chunks/chunk-RPRW26NG.js.map +0 -1
  478. package/dist/cli-bundle/chunks/chunk-SNUK7H5J.js.map +0 -7
  479. package/dist/cli-bundle/chunks/chunk-T7ZMQI4J.js.map +0 -1
  480. package/dist/cli-bundle/chunks/chunk-UB3V5WUI.js.map +0 -1
  481. package/dist/cli-bundle/chunks/chunk-UFKNF23C.js.map +0 -7
  482. package/dist/cli-bundle/chunks/chunk-V3KLX7U7.js.map +0 -1
  483. package/dist/cli-bundle/chunks/chunk-VD3LKZFX.js.map +0 -1
  484. package/dist/cli-bundle/chunks/chunk-W2VMLL5S.js +0 -32
  485. package/dist/cli-bundle/chunks/chunk-W2VMLL5S.js.map +0 -1
  486. package/dist/cli-bundle/chunks/chunk-WTRUDJ3R.js.map +0 -1
  487. package/dist/cli-bundle/chunks/chunk-Z55WX4IQ.js.map +0 -1
  488. package/dist/cli-bundle/chunks/chunk-Z5BM2FKQ.js.map +0 -7
  489. package/dist/cli-bundle/chunks/chunk-ZEATCVAC.js.map +0 -7
  490. package/dist/cli-bundle/chunks/chunk-ZFIEEDTJ.js.map +0 -7
  491. package/dist/cli-bundle/chunks/chunk-ZIE6WXJ2.js.map +0 -1
  492. package/dist/cli-bundle/chunks/close-37KEHLYM.js +0 -14
  493. package/dist/cli-bundle/chunks/close-many-BFMP6HHK.js.map +0 -7
  494. package/dist/cli-bundle/chunks/close-many-CXJBOWWY.js.map +0 -1
  495. package/dist/cli-bundle/chunks/config-FIXJZEQK.js +0 -1541
  496. package/dist/cli-bundle/chunks/config-FIXJZEQK.js.map +0 -7
  497. package/dist/cli-bundle/chunks/config-X3ZVCUUG.js +0 -1531
  498. package/dist/cli-bundle/chunks/config-X3ZVCUUG.js.map +0 -1
  499. package/dist/cli-bundle/chunks/contracts-KP4QAGVW.js.map +0 -1
  500. package/dist/cli-bundle/chunks/contracts-SMOAN5NF.js.map +0 -7
  501. package/dist/cli-bundle/chunks/create-DFMNBKBS.js +0 -28
  502. package/dist/cli-bundle/chunks/get-AWK324RS.js.map +0 -7
  503. package/dist/cli-bundle/chunks/get-VYPIICPC.js.map +0 -1
  504. package/dist/cli-bundle/chunks/health-FBCVZGSX.js.map +0 -7
  505. package/dist/cli-bundle/chunks/health-Q66C43GN.js.map +0 -1
  506. package/dist/cli-bundle/chunks/history-5XUSLAJA.js +0 -18
  507. package/dist/cli-bundle/chunks/history-compact-2GHT32UX.js.map +0 -1
  508. package/dist/cli-bundle/chunks/history-compact-WLCQEKXS.js.map +0 -7
  509. package/dist/cli-bundle/chunks/history-redact-BVHWDXPR.js +0 -19
  510. package/dist/cli-bundle/chunks/history-repair-FY75IC26.js.map +0 -1
  511. package/dist/cli-bundle/chunks/history-repair-GABSDSVD.js.map +0 -7
  512. package/dist/cli-bundle/chunks/init-TRYJELH4.js +0 -21
  513. package/dist/cli-bundle/chunks/next-66BJB4N2.js.map +0 -7
  514. package/dist/cli-bundle/chunks/next-N5MWJTBY.js.map +0 -1
  515. package/dist/cli-bundle/chunks/plan-DQ7G4EDC.js.map +0 -7
  516. package/dist/cli-bundle/chunks/plan-ZHKZ7JVF.js.map +0 -1
  517. package/dist/cli-bundle/chunks/register-list-query-KY6Z6WV7.js.map +0 -7
  518. package/dist/cli-bundle/chunks/register-list-query-Y2VRHPCL.js.map +0 -1
  519. package/dist/cli-bundle/chunks/register-mutation-N6AYSKPM.js.map +0 -7
  520. package/dist/cli-bundle/chunks/register-mutation-PCARIGZS.js.map +0 -1
  521. package/dist/cli-bundle/chunks/register-operations-L6CYTOIH.js.map +0 -7
  522. package/dist/cli-bundle/chunks/register-operations-YAT6FUUB.js.map +0 -1
  523. package/dist/cli-bundle/chunks/register-setup-MPANILQF.js.map +0 -7
  524. package/dist/cli-bundle/chunks/register-setup-N7UGXYJC.js.map +0 -1
  525. package/dist/cli-bundle/chunks/restore-IRAKSWIW.js +0 -17
  526. package/dist/cli-bundle/chunks/telemetry-DIFPXCAT.js.map +0 -7
  527. package/dist/cli-bundle/chunks/telemetry-WTYFUPRL.js.map +0 -1
  528. package/dist/cli-bundle/chunks/test-all-PZTBLLQ6.js +0 -360
  529. package/dist/cli-bundle/chunks/test-all-PZTBLLQ6.js.map +0 -7
  530. package/dist/cli-bundle/chunks/test-all-XLPI4USF.js +0 -357
  531. package/dist/cli-bundle/chunks/test-all-XLPI4USF.js.map +0 -1
  532. package/dist/cli-bundle/chunks/test-runs-CA6K32RD.js.map +0 -1
  533. package/dist/cli-bundle/chunks/test-runs-LANLLPVO.js.map +0 -7
  534. package/dist/cli-bundle/chunks/update-UXDLTEOZ.js +0 -24
  535. package/dist/cli-bundle/chunks/validate-2G566PKQ.js.map +0 -7
  536. package/dist/cli-bundle/chunks/validate-BDPVXHHH.js.map +0 -1
  537. /package/dist/cli-bundle/chunks/{activity-MVSEND6D.js.map → activity-CUC4JY3U.js.map} +0 -0
  538. /package/dist/cli-bundle/chunks/{activity-EJBMXUBH.js.map → activity-WEIEMM73.js.map} +0 -0
  539. /package/dist/cli-bundle/chunks/{append-KDHT4GHI.js.map → append-H32VOR2Y.js.map} +0 -0
  540. /package/dist/cli-bundle/chunks/{append-LEDBAM3K.js.map → append-UBM632FK.js.map} +0 -0
  541. /package/dist/cli-bundle/chunks/{chunk-SJZTPVFT.js.map → chunk-2ASNV4DH.js.map} +0 -0
  542. /package/dist/cli-bundle/chunks/{chunk-JVQ7UOYC.js.map → chunk-2CHRYUXL.js.map} +0 -0
  543. /package/dist/cli-bundle/chunks/{chunk-DRPF274X.js.map → chunk-3LCUASYG.js.map} +0 -0
  544. /package/dist/cli-bundle/chunks/{chunk-JJ4SG243.js.map → chunk-3Q2HBMTI.js.map} +0 -0
  545. /package/dist/cli-bundle/chunks/{chunk-TQ6E76BE.js.map → chunk-55XRYWEG.js.map} +0 -0
  546. /package/dist/cli-bundle/chunks/{chunk-IBU2LLWM.js.map → chunk-A6VOGKBA.js.map} +0 -0
  547. /package/dist/cli-bundle/chunks/{chunk-MLHX6DN5.js.map → chunk-AIAIXG7I.js.map} +0 -0
  548. /package/dist/cli-bundle/chunks/{chunk-5ABGFWR4.js.map → chunk-BTX5MIQF.js.map} +0 -0
  549. /package/dist/cli-bundle/chunks/{chunk-3JWQCLR5.js.map → chunk-CYBDUHNO.js.map} +0 -0
  550. /package/dist/cli-bundle/chunks/{chunk-WFJZDUM7.js.map → chunk-CZPVDLD2.js.map} +0 -0
  551. /package/dist/cli-bundle/chunks/{chunk-HUYYMTGW.js.map → chunk-EUKTMRN3.js.map} +0 -0
  552. /package/dist/cli-bundle/chunks/{chunk-EVWYAG46.js.map → chunk-FFOQHGNH.js.map} +0 -0
  553. /package/dist/cli-bundle/chunks/{chunk-IF4ERU6A.js.map → chunk-GFMSLORL.js.map} +0 -0
  554. /package/dist/cli-bundle/chunks/{chunk-IDYCAK35.js.map → chunk-H4GRLYJS.js.map} +0 -0
  555. /package/dist/cli-bundle/chunks/{chunk-VMY7MZEM.js.map → chunk-HQTPRV4D.js.map} +0 -0
  556. /package/dist/cli-bundle/chunks/{chunk-7L6TXOOC.js.map → chunk-JMK5GCK2.js.map} +0 -0
  557. /package/dist/cli-bundle/chunks/{chunk-KRASIL6M.js.map → chunk-K2VYLVX4.js.map} +0 -0
  558. /package/dist/cli-bundle/chunks/{chunk-4YIMPANT.js.map → chunk-KCO2EAN5.js.map} +0 -0
  559. /package/dist/cli-bundle/chunks/{chunk-D6USKAMA.js.map → chunk-KLXF7NCC.js.map} +0 -0
  560. /package/dist/cli-bundle/chunks/{chunk-OB3RJV5F.js.map → chunk-LRKMWUUV.js.map} +0 -0
  561. /package/dist/cli-bundle/chunks/{chunk-74PUWBGN.js.map → chunk-LTRAF2D7.js.map} +0 -0
  562. /package/dist/cli-bundle/chunks/{chunk-4TXTVZL3.js.map → chunk-MRD4T5LF.js.map} +0 -0
  563. /package/dist/cli-bundle/chunks/{chunk-E2Q2ULMR.js.map → chunk-N2JSWVWG.js.map} +0 -0
  564. /package/dist/cli-bundle/chunks/{chunk-7RIJGN4R.js.map → chunk-QH3FSKRJ.js.map} +0 -0
  565. /package/dist/cli-bundle/chunks/{chunk-OUQ5JEFM.js.map → chunk-S62UANU7.js.map} +0 -0
  566. /package/dist/cli-bundle/chunks/{chunk-DLDCPF5X.js.map → chunk-U2BEEM2X.js.map} +0 -0
  567. /package/dist/cli-bundle/chunks/{chunk-73PTKMAE.js.map → chunk-UT73HUPC.js.map} +0 -0
  568. /package/dist/cli-bundle/chunks/{chunk-F7G53BOA.js.map → chunk-UTSH5GWX.js.map} +0 -0
  569. /package/dist/cli-bundle/chunks/{chunk-JIP67N2K.js.map → chunk-Y4NRKBFW.js.map} +0 -0
  570. /package/dist/cli-bundle/chunks/{chunk-FBZ5XAAF.js.map → chunk-YPKFV2JR.js.map} +0 -0
  571. /package/dist/cli-bundle/chunks/{chunk-BN3CWK6G.js.map → chunk-ZNHEYCDD.js.map} +0 -0
  572. /package/dist/cli-bundle/chunks/{chunk-YEDFE4DC.js.map → chunk-ZNT7KEWE.js.map} +0 -0
  573. /package/dist/cli-bundle/chunks/{claim-HMCLSLUE.js.map → claim-SENTPZBN.js.map} +0 -0
  574. /package/dist/cli-bundle/chunks/{claim-6NINZYB3.js.map → claim-Z7MEQCBT.js.map} +0 -0
  575. /package/dist/cli-bundle/chunks/{close-OP3LK7Z2.js.map → close-424MX4CU.js.map} +0 -0
  576. /package/dist/cli-bundle/chunks/{close-37KEHLYM.js.map → close-YCWQQPDS.js.map} +0 -0
  577. /package/dist/cli-bundle/chunks/{comments-ETHABIY6.js.map → comments-4FGNTSNV.js.map} +0 -0
  578. /package/dist/cli-bundle/chunks/{comments-MU2WMBUY.js.map → comments-7YS5MY5X.js.map} +0 -0
  579. /package/dist/cli-bundle/chunks/{context-7ZEZV3BV.js.map → context-LHVKJSPJ.js.map} +0 -0
  580. /package/dist/cli-bundle/chunks/{context-XDI4DKKT.js.map → context-ZQY54JNS.js.map} +0 -0
  581. /package/dist/cli-bundle/chunks/{copy-JJ3KOQW2.js.map → copy-GYNQQPW2.js.map} +0 -0
  582. /package/dist/cli-bundle/chunks/{copy-CWM6SBY6.js.map → copy-TLW7JTQT.js.map} +0 -0
  583. /package/dist/cli-bundle/chunks/{create-J5Q2ELZT.js.map → create-VSKYSOCD.js.map} +0 -0
  584. /package/dist/cli-bundle/chunks/{create-DFMNBKBS.js.map → create-XTMAPS7I.js.map} +0 -0
  585. /package/dist/cli-bundle/chunks/{delete-2GZLQEUQ.js.map → delete-4W5JYCEG.js.map} +0 -0
  586. /package/dist/cli-bundle/chunks/{delete-OOQS4KVD.js.map → delete-ANTOTI2I.js.map} +0 -0
  587. /package/dist/cli-bundle/chunks/{deps-IF4IGL4R.js.map → deps-HPPE6MJN.js.map} +0 -0
  588. /package/dist/cli-bundle/chunks/{deps-ZVGGCRR6.js.map → deps-ZQZN54EZ.js.map} +0 -0
  589. /package/dist/cli-bundle/chunks/{docs-NFTBCQQC.js.map → docs-RPOVFMP3.js.map} +0 -0
  590. /package/dist/cli-bundle/chunks/{docs-2TIFR62T.js.map → docs-XJNYBJGE.js.map} +0 -0
  591. /package/dist/cli-bundle/chunks/{eval-2F6EH4XN.js.map → eval-DM6JBZTS.js.map} +0 -0
  592. /package/dist/cli-bundle/chunks/{eval-PFKXQR3B.js.map → eval-RFBI5FGS.js.map} +0 -0
  593. /package/dist/cli-bundle/chunks/{extension-GMVOIP4O.js.map → extension-B3YY4WY5.js.map} +0 -0
  594. /package/dist/cli-bundle/chunks/{extension-3LRYX7SW.js.map → extension-TTSEFQTS.js.map} +0 -0
  595. /package/dist/cli-bundle/chunks/{files-DF3HO6XK.js.map → files-5D65CHGE.js.map} +0 -0
  596. /package/dist/cli-bundle/chunks/{files-T5ODMETM.js.map → files-GPIG77EN.js.map} +0 -0
  597. /package/dist/cli-bundle/chunks/{focus-MY5ARIEK.js.map → focus-C3PEJV2C.js.map} +0 -0
  598. /package/dist/cli-bundle/chunks/{focus-DLXKK4AH.js.map → focus-ZHN7WIGX.js.map} +0 -0
  599. /package/dist/cli-bundle/chunks/{gc-MDGRR2SU.js.map → gc-D4JQ6OWN.js.map} +0 -0
  600. /package/dist/cli-bundle/chunks/{gc-FULIVYR4.js.map → gc-VZIXDL32.js.map} +0 -0
  601. /package/dist/cli-bundle/chunks/{history-5XUSLAJA.js.map → history-DD7L7BNL.js.map} +0 -0
  602. /package/dist/cli-bundle/chunks/{history-X4OSES6K.js.map → history-IL7XCEX2.js.map} +0 -0
  603. /package/dist/cli-bundle/chunks/{history-redact-BVHWDXPR.js.map → history-redact-IX4YEWMY.js.map} +0 -0
  604. /package/dist/cli-bundle/chunks/{history-redact-45YW65BK.js.map → history-redact-VYCWQFK7.js.map} +0 -0
  605. /package/dist/cli-bundle/chunks/{init-KO7CGIRQ.js.map → init-F27NHENZ.js.map} +0 -0
  606. /package/dist/cli-bundle/chunks/{init-TRYJELH4.js.map → init-HHVQQP6C.js.map} +0 -0
  607. /package/dist/cli-bundle/chunks/{learnings-LHZT5BHW.js.map → learnings-HJVDQIGY.js.map} +0 -0
  608. /package/dist/cli-bundle/chunks/{learnings-3F7YLI45.js.map → learnings-XSFSUUWK.js.map} +0 -0
  609. /package/dist/cli-bundle/chunks/{list-Y6AU5BJS.js.map → list-HPMEKCAA.js.map} +0 -0
  610. /package/dist/cli-bundle/chunks/{list-ROT7JF62.js.map → list-VMPWTURB.js.map} +0 -0
  611. /package/dist/cli-bundle/chunks/{notes-FW6YFLND.js.map → notes-GDZIKGR6.js.map} +0 -0
  612. /package/dist/cli-bundle/chunks/{notes-EVJZ3VAB.js.map → notes-WDDBPC4D.js.map} +0 -0
  613. /package/dist/cli-bundle/chunks/{profile-CHAW6SEA.js.map → profile-CCOKZ2IQ.js.map} +0 -0
  614. /package/dist/cli-bundle/chunks/{profile-UPZGCDOG.js.map → profile-HUCENIEQ.js.map} +0 -0
  615. /package/dist/cli-bundle/chunks/{restore-DKMCLPI5.js.map → restore-4CBWUMCX.js.map} +0 -0
  616. /package/dist/cli-bundle/chunks/{restore-IRAKSWIW.js.map → restore-5UEAGG3W.js.map} +0 -0
  617. /package/dist/cli-bundle/chunks/{scheduling-shortcuts-3F4QUEDH.js.map → scheduling-shortcuts-6VFKNKCM.js.map} +0 -0
  618. /package/dist/cli-bundle/chunks/{scheduling-shortcuts-BNZLQK36.js.map → scheduling-shortcuts-ERHCVTEM.js.map} +0 -0
  619. /package/dist/cli-bundle/chunks/{schema-OLT6LVKH.js.map → schema-TDGK6N3I.js.map} +0 -0
  620. /package/dist/cli-bundle/chunks/{schema-XJXKJQF5.js.map → schema-UE5KKAUX.js.map} +0 -0
  621. /package/dist/cli-bundle/chunks/{search-KP6H7COV.js.map → search-FP7MEU4S.js.map} +0 -0
  622. /package/dist/cli-bundle/chunks/{search-CX5UMV4H.js.map → search-K4CFLQ5S.js.map} +0 -0
  623. /package/dist/cli-bundle/chunks/{stats-QZUG6MX5.js.map → stats-NJJCALEZ.js.map} +0 -0
  624. /package/dist/cli-bundle/chunks/{stats-7XW4OEMK.js.map → stats-XT6QRKQY.js.map} +0 -0
  625. /package/dist/cli-bundle/chunks/{test-QNDXZQCW.js.map → test-UFSJ5YIO.js.map} +0 -0
  626. /package/dist/cli-bundle/chunks/{test-HU2BS7EY.js.map → test-YCDAUBWF.js.map} +0 -0
  627. /package/dist/cli-bundle/chunks/{update-UXDLTEOZ.js.map → update-MTCFES6X.js.map} +0 -0
  628. /package/dist/cli-bundle/chunks/{update-DJKWLBWJ.js.map → update-Y5WQVT5O.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]="96011574-703c-57e6-979f-dbae265fd01b")}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";
@@ -651,35 +651,115 @@ function summarizeDuplicateIssueCodes(duplicates, verboseDiagnostics) {
651
651
  warnings: [`${DUPLICATE_ISSUE_CODE_WARNING_TOKEN}:${duplicates.length}`],
652
652
  };
653
653
  }
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";
654
+ function initializeMissingMetadataByField() {
655
+ return Object.fromEntries(SUPPORTED_METADATA_REQUIRED_FIELDS.map((field) => [field, []]));
656
+ }
657
+ function collectMissingMetadataByField(items, statusRegistry, enforcePlanningFieldsOnTerminal) {
658
+ const missingByField = initializeMissingMetadataByField();
662
659
  for (const item of items) {
663
660
  for (const field of SUPPORTED_METADATA_REQUIRED_FIELDS) {
664
- if (!isMetadataFieldMissing(item, field, statusRegistry, enforcePlanningFieldsOnTerminal)) {
665
- continue;
661
+ if (isMetadataFieldMissing(item, field, statusRegistry, enforcePlanningFieldsOnTerminal)) {
662
+ missingByField[field].push(item.id);
666
663
  }
667
- missingByField[field].push(item.id);
668
664
  }
669
665
  }
666
+ return missingByField;
667
+ }
668
+ function buildMetadataWarningTokens(metadataPolicy, missingByField, duplicateWarnings) {
670
669
  const warningTokens = [...metadataPolicy.warnings];
671
670
  for (const field of metadataPolicy.required_fields) {
672
671
  const missingItems = missingByField[field];
673
- if (missingItems.length === 0) {
672
+ if (missingItems.length > 0) {
673
+ warningTokens.push(`${METADATA_WARNING_TOKEN_BY_FIELD[field]}:${missingItems.length}`);
674
+ }
675
+ }
676
+ warningTokens.push(...duplicateWarnings);
677
+ return warningTokens;
678
+ }
679
+ function buildMetadataCounts(metadataPolicy, missingByField) {
680
+ const counts = {};
681
+ for (const field of metadataPolicy.required_fields) {
682
+ const missing = missingByField[field];
683
+ const value = missing ? missing.length : 0;
684
+ const countKey = METADATA_COUNT_KEY_BY_FIELD[field];
685
+ if (value > 0 && countKey) {
686
+ counts[countKey] = value;
687
+ }
688
+ }
689
+ return counts;
690
+ }
691
+ function buildMissingFieldOccurrences(metadataPolicy, missingByField, itemsById) {
692
+ const occurrences = [];
693
+ for (const field of metadataPolicy.required_fields) {
694
+ const missing = missingByField[field];
695
+ if (!missing) {
674
696
  continue;
675
697
  }
676
- warningTokens.push(`${METADATA_WARNING_TOKEN_BY_FIELD[field]}:${missingItems.length}`);
698
+ for (const itemId of missing) {
699
+ const itemType = itemsById.get(itemId)?.type;
700
+ const normalizedItemType = typeof itemType === "string" && itemType.length > 0 ? itemType : "Unknown";
701
+ occurrences.push({ item_type: normalizedItemType, field });
702
+ }
677
703
  }
704
+ return occurrences;
705
+ }
706
+ /* v8 ignore start -- metadata policy keys are validated before this summarizer; fallback branches are defensive */
707
+ function attachMissingMetadataItemIds(details, metadataPolicy, missingByField, verboseDiagnostics) {
708
+ for (const field of metadataPolicy.required_fields) {
709
+ const missing = missingByField[field];
710
+ if (!missing || missing.length === 0) {
711
+ continue;
712
+ }
713
+ const idsKey = METADATA_ITEM_IDS_KEY_BY_FIELD[field];
714
+ const truncatedKey = METADATA_TRUNCATED_KEY_BY_FIELD[field];
715
+ if (!idsKey || !truncatedKey) {
716
+ continue;
717
+ }
718
+ const summarized = summarizeList(missing, verboseDiagnostics ? missing.length : DIAGNOSTIC_LIST_SUMMARY_LIMIT);
719
+ details[idsKey] = summarized.values;
720
+ details[truncatedKey] = summarized.truncated;
721
+ }
722
+ }
723
+ /* v8 ignore stop */
724
+ function buildCloseReasonBackfillRows(metadataPolicy, missingByField, itemsById) {
725
+ if (!metadataPolicy.required_fields.includes("close_reason")) {
726
+ return [];
727
+ }
728
+ const missing = missingByField.close_reason;
729
+ if (!missing) {
730
+ return [];
731
+ }
732
+ return missing.map((itemId) => ({
733
+ id: itemId,
734
+ resolution: toNonEmptyStringOrUndefined(itemsById.get(itemId)?.resolution),
735
+ }));
736
+ }
737
+ function buildEstimateBackfillRows(metadataPolicy, missingByField, itemsById) {
738
+ if (!metadataPolicy.required_fields.includes("estimated_minutes")) {
739
+ return [];
740
+ }
741
+ const missing = missingByField.estimated_minutes;
742
+ if (!missing) {
743
+ return [];
744
+ }
745
+ return missing.map((itemId) => ({
746
+ id: itemId,
747
+ type: toNonEmptyStringOrUndefined(itemsById.get(itemId)?.type),
748
+ }));
749
+ }
750
+ /* c8 ignore start -- metadata diagnostics/backfill planning permutations are covered by validate integration suites */
751
+ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagnostics) {
752
+ const itemsById = new Map(items.map((item) => [item.id, item]));
753
+ // GH-276: only the `strict` profile enforces planning fields on terminal
754
+ // (closed/canceled) historical items; core/minimal/custom profiles treat a
755
+ // retired item's missing estimate or acceptance criteria as resolved.
756
+ const enforcePlanningFieldsOnTerminal = metadataPolicy.profile === "strict";
757
+ const missingByField = collectMissingMetadataByField(items, statusRegistry, enforcePlanningFieldsOnTerminal);
678
758
  // Duplicate logical issue-code detection (GH-235): advisory warning when two
679
759
  // or more items share a leading title issue code (e.g. `ISSUE-004`).
680
760
  const duplicateIssueCodes = findDuplicateIssueCodes(items);
681
761
  const duplicateIssueCodeSummary = summarizeDuplicateIssueCodes(duplicateIssueCodes, verboseDiagnostics);
682
- warningTokens.push(...duplicateIssueCodeSummary.warnings);
762
+ const warningTokens = buildMetadataWarningTokens(metadataPolicy, missingByField, duplicateIssueCodeSummary.warnings);
683
763
  // Zero-suppress counts to reduce agent token cost (telemetry pm-tylj).
684
764
  // Only emit counts for the ACTIVE required fields of the resolved profile so a
685
765
  // looser profile (e.g. core) never reports missing reviewer/risk/sprint/etc.
@@ -687,25 +767,12 @@ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagno
687
767
  // shape could include an unsupported field in required_fields — fall back
688
768
  // to 0 instead of throwing TypeError, and skip writing when the count-key
689
769
  // 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
- }
770
+ const counts = buildMetadataCounts(metadataPolicy, missingByField);
698
771
  // Per-item-type grouping of missing required-field counts (pm-pmyq /
699
772
  // GH-172): counts only — never row dumps — and only for the ACTIVE required
700
773
  // fields, so the grouping mirrors `counts` at type granularity (e.g.
701
774
  // `{ 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
- }
775
+ const missingFieldOccurrences = buildMissingFieldOccurrences(metadataPolicy, missingByField, itemsById);
709
776
  const missingByType = buildMissingByTypeCounts(missingFieldOccurrences);
710
777
  const details = {
711
778
  checked_items: items.length,
@@ -731,40 +798,17 @@ function buildMetadataCheck(items, metadataPolicy, statusRegistry, verboseDiagno
731
798
  // Defensive guard (Gemini high #2, PR #78 follow-up): same optional-chain
732
799
  // safety as the counts loop above — never throw if a future settings shape
733
800
  // 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
- }
801
+ attachMissingMetadataItemIds(details, metadataPolicy, missingByField, verboseDiagnostics);
748
802
  // Auto-fix planning input (pm-c3sz): closed items flagged for a missing
749
803
  // close_reason whose resolution can serve as the derivable source value.
750
804
  // Only collected when close_reason is an active required field, so fixes
751
805
  // 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
- : [];
806
+ const closeReasonBackfillRows = buildCloseReasonBackfillRows(metadataPolicy, missingByField, itemsById);
758
807
  // Estimate auto-fix planning input (GH-212): items flagged for a missing
759
808
  // estimated_minutes whose type drives the config-driven default backfill.
760
809
  // Only collected when estimated_minutes is an active required field, so fixes
761
810
  // 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
- : [];
811
+ const estimateBackfillRows = buildEstimateBackfillRows(metadataPolicy, missingByField, itemsById);
768
812
  return {
769
813
  check: {
770
814
  name: "metadata",
@@ -1029,6 +1073,26 @@ function sharedDirectoryPrefixLength(left, right) {
1029
1073
  }
1030
1074
  return count;
1031
1075
  }
1076
+ function scoreOrphanOwnerCandidate(pathValue, linkedPath) {
1077
+ const linkedDir = directoryOf(linkedPath);
1078
+ const orphanDir = directoryOf(pathValue);
1079
+ const directoryPrefix = linkedPath.endsWith("/") ? linkedPath : `${linkedPath}/`;
1080
+ const isDirectoryPrefix = pathValue.startsWith(directoryPrefix);
1081
+ const sameDirectory = linkedDir.length > 0 && linkedDir === orphanDir;
1082
+ const sharedPrefixLength = sharedDirectoryPrefixLength(pathValue, linkedPath);
1083
+ if (!isDirectoryPrefix && !sameDirectory && sharedPrefixLength === 0) {
1084
+ return null;
1085
+ }
1086
+ if (isDirectoryPrefix) {
1087
+ return { score: linkedPath.length + 1000, confidence: "path_prefix" };
1088
+ }
1089
+ return sameDirectory
1090
+ ? { score: sharedPrefixLength + 500, confidence: "same_directory" }
1091
+ : { score: sharedPrefixLength, confidence: "shared_directory" };
1092
+ }
1093
+ function shouldReplaceOrphanOwnerCandidate(best, item, score) {
1094
+ return best === undefined || score > best.score || (score === best.score && item.id.localeCompare(best.item.id) < 0);
1095
+ }
1032
1096
  function findOrphanOwnerCandidate(pathValue, classification, items) {
1033
1097
  const linkKind = classification === "docs_unowned" ? "docs" : "files";
1034
1098
  let best;
@@ -1042,21 +1106,15 @@ function findOrphanOwnerCandidate(pathValue, classification, items) {
1042
1106
  if (linkedPath.length === 0 || linkedPath === pathValue) {
1043
1107
  continue;
1044
1108
  }
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) {
1109
+ const scored = scoreOrphanOwnerCandidate(pathValue, linkedPath);
1110
+ if (scored === null) {
1052
1111
  continue;
1053
1112
  }
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)) {
1113
+ if (shouldReplaceOrphanOwnerCandidate(best, item, scored.score)) {
1056
1114
  best = {
1057
1115
  item,
1058
- score,
1059
- confidence: isDirectoryPrefix ? "path_prefix" : sameDirectory ? "same_directory" : "shared_directory",
1116
+ score: scored.score,
1117
+ confidence: scored.confidence,
1060
1118
  };
1061
1119
  }
1062
1120
  }
@@ -1089,120 +1147,216 @@ function buildOrphanedPathRows(orphanedFiles, items) {
1089
1147
  function summarizeOrphanedPathRows(rows) {
1090
1148
  return rows.map((row) => `${row.path}:${row.classification} owner_candidate=${row.owner_candidate?.id ?? "unowned"} hint=${JSON.stringify(row.remediation_hint)}`);
1091
1149
  }
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") {
1150
+ function closureLikeFieldsForItem(item, lifecyclePatternPolicy) {
1151
+ return Object.entries(lifecyclePatternPolicy.closure_like_metadata_field_patterns)
1152
+ .filter(([field, patterns]) => {
1153
+ const value = toMeaningfulString(item[field]);
1154
+ return value ? patterns.some((pattern) => value.toLowerCase().includes(pattern)) : false;
1155
+ })
1156
+ .map(([field]) => field)
1157
+ .sort((left, right) => left.localeCompare(right));
1158
+ }
1159
+ function buildTerminalParentFixRow(item, parent, itemsById, canonicalIdByLowercase, statusRegistry) {
1160
+ const grandparentId = toMeaningfulString(parent.parent);
1161
+ const grandparent = grandparentId
1162
+ ? itemsById.get(canonicalIdByLowercase.get(grandparentId.toLowerCase()) ?? grandparentId)
1163
+ : undefined;
1164
+ return {
1165
+ id: item.id,
1166
+ parent_id: parent.id,
1167
+ grandparent_id: grandparent?.id,
1168
+ grandparent_active: grandparent !== undefined && !isTerminalStatus(grandparent.status, statusRegistry),
1169
+ };
1170
+ }
1171
+ /* v8 ignore start -- stale-blocker reason variants are covered through command-level diagnostics; helper branch counters are defensive */
1172
+ function staleBlockerReasonsForItem(item, blockedStatuses, statusRegistry, lifecyclePatternPolicy) {
1173
+ const blockedBy = toMeaningfulString(item.blocked_by);
1174
+ const blockedReason = toMeaningfulString(item.blocked_reason);
1175
+ const blockedReasonNormalized = blockedReason?.toLowerCase();
1176
+ const normalizedStatus = normalizeStatusForRegistry(item.status, statusRegistry);
1177
+ const reasons = [];
1178
+ if (!blockedStatuses.has(normalizedStatus)) {
1179
+ if (blockedBy) {
1180
+ reasons.push("non_blocked_status_has_blocked_by");
1181
+ }
1182
+ if (blockedReason) {
1183
+ reasons.push("non_blocked_status_has_blocked_reason");
1184
+ }
1185
+ return reasons;
1186
+ }
1187
+ if (!blockedBy && !blockedReason) {
1188
+ /* v8 ignore start -- blocked-status creation paths seed either blocked_by or blocked_reason before lifecycle validation */
1189
+ reasons.push("blocked_status_missing_blocker_context");
1190
+ /* v8 ignore stop */
1191
+ }
1192
+ if (blockedReasonNormalized?.includes("no active blocker")) {
1193
+ reasons.push("blocked_status_reason_reports_no_active_blocker");
1194
+ }
1195
+ if (blockedReasonNormalized &&
1196
+ lifecyclePatternPolicy.stale_blocker_reason_patterns.some((pattern) => blockedReasonNormalized.includes(pattern))) {
1197
+ reasons.push("blocked_status_reason_matches_stale_pattern");
1198
+ }
1199
+ return reasons;
1200
+ }
1201
+ /* v8 ignore stop */
1202
+ function collectLifecycleScanRows(items, includeStaleBlockers, statusRegistry, lifecyclePatternPolicy) {
1094
1203
  const itemsById = new Map(items.map((item) => [item.id, item]));
1204
+ const canonicalIdByLowercase = new Map(items.map((item) => [item.id.toLowerCase(), item.id]));
1205
+ /* v8 ignore start -- runtime status registry normally supplies blocked statuses; fallback preserves legacy settings safety */
1095
1206
  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));
1207
+ /* v8 ignore stop */
1208
+ const rows = {
1209
+ activeItems: items.filter((item) => !isTerminalStatus(item.status, statusRegistry)),
1210
+ closureLikeRows: [],
1211
+ terminalParentRows: [],
1212
+ terminalParentFixRows: [],
1213
+ staleBlockerRows: [],
1214
+ };
1215
+ for (const item of rows.activeItems) {
1216
+ const closureLikeFields = closureLikeFieldsForItem(item, lifecyclePatternPolicy);
1113
1217
  if (closureLikeFields.length > 0) {
1114
- closureLikeRows.push({
1115
- id: item.id,
1116
- fields: closureLikeFields,
1117
- });
1218
+ rows.closureLikeRows.push({ id: item.id, fields: closureLikeFields });
1118
1219
  }
1119
1220
  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
- }
1221
+ const parent = parentId ? itemsById.get(canonicalIdByLowercase.get(parentId.toLowerCase()) ?? parentId) : undefined;
1222
+ if (parent && isTerminalStatus(parent.status, statusRegistry)) {
1223
+ rows.terminalParentRows.push({ id: item.id, parent_id: parent.id, parent_status: parent.status });
1224
+ rows.terminalParentFixRows.push(buildTerminalParentFixRow(item, parent, itemsById, canonicalIdByLowercase, statusRegistry));
1140
1225
  }
1226
+ /* v8 ignore start -- stale-blocker reason presence is covered by command diagnostics; branch accounting here is defensive */
1141
1227
  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
- }
1228
+ const reasons = staleBlockerReasonsForItem(item, blockedStatuses, statusRegistry, lifecyclePatternPolicy);
1167
1229
  if (reasons.length > 0) {
1168
- staleBlockerRows.push({
1230
+ rows.staleBlockerRows.push({
1169
1231
  id: item.id,
1170
1232
  status: item.status,
1171
1233
  reasons: [...new Set(reasons)].sort((left, right) => left.localeCompare(right)),
1172
1234
  });
1173
1235
  }
1174
1236
  }
1237
+ /* v8 ignore stop */
1175
1238
  }
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);
1239
+ return rows;
1240
+ }
1241
+ function sortLifecycleScanRows(rows) {
1242
+ rows.closureLikeRows.sort((left, right) => left.id.localeCompare(right.id));
1243
+ /* v8 ignore start -- parent-id tie breakers only matter for duplicate legacy ids, which the tracker writer prevents */
1244
+ rows.terminalParentRows.sort((left, right) => left.id.localeCompare(right.id) || left.parent_id.localeCompare(right.parent_id));
1245
+ rows.terminalParentFixRows.sort((left, right) => left.id.localeCompare(right.id) || left.parent_id.localeCompare(right.parent_id));
1246
+ /* v8 ignore stop */
1247
+ rows.staleBlockerRows.sort((left, right) => left.id.localeCompare(right.id));
1248
+ }
1249
+ function lifecycleCycleWarningToken(prefix, severity, count) {
1250
+ if (count <= 0 || severity === "off") {
1251
+ return null;
1252
+ }
1253
+ return `${severity === "error" ? `${prefix}_error` : prefix}:${count}`;
1254
+ }
1255
+ function buildLifecycleWarnings(rows, includeStaleBlockers, dependencyCycleSeverity, parentCycleSeverity, dependencyCycleCount, parentCycleCount) {
1182
1256
  const warnings = [];
1183
- if (closureLikeRows.length > 0) {
1184
- warnings.push(`validate_lifecycle_active_closure_like_metadata:${closureLikeRows.length}`);
1257
+ if (rows.closureLikeRows.length > 0) {
1258
+ warnings.push(`validate_lifecycle_active_closure_like_metadata:${rows.closureLikeRows.length}`);
1185
1259
  }
1186
- if (terminalParentRows.length > 0) {
1187
- warnings.push(`validate_lifecycle_active_terminal_parent:${terminalParentRows.length}`);
1260
+ if (rows.terminalParentRows.length > 0) {
1261
+ warnings.push(`validate_lifecycle_active_terminal_parent:${rows.terminalParentRows.length}`);
1188
1262
  }
1189
- if (includeStaleBlockers && staleBlockerRows.length > 0) {
1190
- warnings.push(`validate_lifecycle_stale_blockers:${staleBlockerRows.length}`);
1263
+ if (includeStaleBlockers && rows.staleBlockerRows.length > 0) {
1264
+ warnings.push(`validate_lifecycle_stale_blockers:${rows.staleBlockerRows.length}`);
1191
1265
  }
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}`);
1266
+ const dependencyWarning = lifecycleCycleWarningToken("validate_lifecycle_dependency_cycles", dependencyCycleSeverity, dependencyCycleCount);
1267
+ const parentWarning = lifecycleCycleWarningToken("validate_hierarchy_parent_cycle", parentCycleSeverity, parentCycleCount);
1268
+ return [...warnings, ...(dependencyWarning ? [dependencyWarning] : []), ...(parentWarning ? [parentWarning] : [])];
1269
+ }
1270
+ async function linkedArtifactIsMissing(workspaceRoot, artifactPath) {
1271
+ const absolutePath = path.isAbsolute(artifactPath) ? artifactPath : path.resolve(workspaceRoot, artifactPath);
1272
+ try {
1273
+ const stats = await fs.stat(absolutePath);
1274
+ return !stats.isFile() && !stats.isDirectory();
1275
+ }
1276
+ catch (error) {
1277
+ const code = typeof error === "object" && error !== null && "code" in error
1278
+ ? error.code
1279
+ : undefined;
1280
+ return code === "ENOENT" || code === "ENOTDIR";
1281
+ }
1282
+ }
1283
+ async function collectLinkedPathScanState(items, workspaceRoot) {
1284
+ const state = {
1285
+ linkedProjectPaths: new Set(),
1286
+ remoteLinkedPaths: new Set(),
1287
+ missingLinkedPaths: [],
1288
+ staleLinkRows: [],
1289
+ };
1290
+ for (const item of items) {
1291
+ const linkedArtifactGroups = [
1292
+ { link_kind: "files", artifacts: item.files ?? [] },
1293
+ { link_kind: "docs", artifacts: item.docs ?? [] },
1294
+ ];
1295
+ for (const group of linkedArtifactGroups) {
1296
+ for (const artifact of group.artifacts) {
1297
+ if (artifact.scope !== "project") {
1298
+ continue;
1299
+ }
1300
+ if (isRemoteLinkedArtifactReference(artifact.path)) {
1301
+ state.remoteLinkedPaths.add(artifact.path.trim());
1302
+ continue;
1303
+ }
1304
+ const normalizedPath = normalizeRelativePath(artifact.path);
1305
+ if (normalizedPath.length === 0) {
1306
+ continue;
1307
+ }
1308
+ state.linkedProjectPaths.add(normalizedPath);
1309
+ if (await linkedArtifactIsMissing(workspaceRoot, artifact.path)) {
1310
+ state.missingLinkedPaths.push(normalizedPath);
1311
+ state.staleLinkRows.push({ item_id: item.id, path: normalizedPath, link_kind: group.link_kind });
1312
+ }
1313
+ }
1314
+ }
1196
1315
  }
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}`);
1316
+ return state;
1317
+ }
1318
+ function partitionFileCandidates(fileCandidates, pmRoot, workspaceRoot, fileScanMode, includePmInternals, verboseFileLists) {
1319
+ const strictTrackedAllMode = fileScanMode === "tracked-all-strict";
1320
+ const strictModeForcesPmInternals = strictTrackedAllMode && !includePmInternals;
1321
+ const includePmInternalsEffective = includePmInternals || strictTrackedAllMode;
1322
+ const pmInternalCandidatePrefixes = includePmInternalsEffective ? [] : resolvePmInternalCandidatePrefixes(pmRoot, workspaceRoot);
1323
+ const excludedPmInternalPaths = pmInternalCandidatePrefixes.length === 0
1324
+ ? []
1325
+ : fileCandidates.candidateFiles.filter((candidate) => hasPathPrefix(candidate, pmInternalCandidatePrefixes));
1326
+ const candidateFiles = pmInternalCandidatePrefixes.length === 0
1327
+ ? fileCandidates.candidateFiles
1328
+ : fileCandidates.candidateFiles.filter((candidate) => !hasPathPrefix(candidate, pmInternalCandidatePrefixes));
1329
+ const excludedByReason = {};
1330
+ if (excludedPmInternalPaths.length > 0) {
1331
+ const summarizedPmInternalPaths = summarizeFileList(excludedPmInternalPaths, verboseFileLists);
1332
+ excludedByReason.pm_internals = {
1333
+ count: excludedPmInternalPaths.length,
1334
+ paths: summarizedPmInternalPaths.values,
1335
+ paths_truncated: summarizedPmInternalPaths.truncated,
1336
+ paths_total: summarizedPmInternalPaths.total,
1337
+ };
1201
1338
  }
1339
+ return {
1340
+ strictTrackedAllMode,
1341
+ strictModeForcesPmInternals,
1342
+ includePmInternalsEffective,
1343
+ pmInternalCandidatePrefixes,
1344
+ excludedPmInternalPaths,
1345
+ candidateFiles,
1346
+ excludedByReason,
1347
+ };
1348
+ }
1349
+ /* c8 ignore start -- lifecycle stale/terminal/dependency diagnostics matrix is covered by end-to-end validate integration runs */
1350
+ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverity, parentCycleSeverity, statusRegistry, lifecyclePatternPolicy, verboseDiagnostics, idPrefix = "pm") {
1351
+ const rows = collectLifecycleScanRows(items, includeStaleBlockers, statusRegistry, lifecyclePatternPolicy);
1352
+ sortLifecycleScanRows(rows);
1353
+ const dependencyCycleDiagnostics = detectLifecycleDependencyCycles(rows.activeItems, idPrefix);
1354
+ const parentCycleDiagnostics = detectLifecycleParentCycles(items);
1355
+ const warnings = buildLifecycleWarnings(rows, includeStaleBlockers, dependencyCycleSeverity, parentCycleSeverity, dependencyCycleDiagnostics.cycle_count, parentCycleDiagnostics.cycle_count);
1202
1356
  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);
1357
+ const summarizedClosureLikeRows = summarizeList(rows.closureLikeRows.map((row) => `${row.id}:${row.fields.join(",")}`), diagnosticLimit);
1358
+ const summarizedTerminalParentRows = summarizeList(rows.terminalParentRows.map((row) => `${row.id}:${row.parent_id}:${row.parent_status}`), diagnosticLimit);
1359
+ const summarizedStaleBlockerRows = summarizeList(rows.staleBlockerRows.map((row) => `${row.id}:${row.status}:${row.reasons.join(",")}`), diagnosticLimit);
1206
1360
  const summarizedDependencyCycleItemIds = summarizeList(dependencyCycleDiagnostics.cycle_item_ids, diagnosticLimit);
1207
1361
  const summarizedDependencyCycleSamplePaths = summarizeList(dependencyCycleDiagnostics.cycle_sample_paths, diagnosticLimit);
1208
1362
  const summarizedParentCycleItemIds = summarizeList(parentCycleDiagnostics.cycle_item_ids, diagnosticLimit);
@@ -1218,15 +1372,15 @@ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverit
1218
1372
  ? "ok"
1219
1373
  : "warn",
1220
1374
  details: {
1221
- checked_active_items: activeItems.length,
1222
- active_closure_like_metadata_items: closureLikeRows.length,
1375
+ checked_active_items: rows.activeItems.length,
1376
+ active_closure_like_metadata_items: rows.closureLikeRows.length,
1223
1377
  active_closure_like_metadata_rows: summarizedClosureLikeRows.values,
1224
1378
  active_closure_like_metadata_rows_truncated: summarizedClosureLikeRows.truncated,
1225
- active_terminal_parent_items: terminalParentRows.length,
1379
+ active_terminal_parent_items: rows.terminalParentRows.length,
1226
1380
  active_terminal_parent_rows: summarizedTerminalParentRows.values,
1227
1381
  active_terminal_parent_rows_truncated: summarizedTerminalParentRows.truncated,
1228
1382
  stale_blocker_checks_enabled: includeStaleBlockers,
1229
- stale_blocker_items: staleBlockerRows.length,
1383
+ stale_blocker_items: rows.staleBlockerRows.length,
1230
1384
  stale_blocker_rows: summarizedStaleBlockerRows.values,
1231
1385
  stale_blocker_rows_truncated: summarizedStaleBlockerRows.truncated,
1232
1386
  dependency_cycle_severity_policy: dependencyCycleSeverity,
@@ -1256,90 +1410,26 @@ function buildLifecycleCheck(items, includeStaleBlockers, dependencyCycleSeverit
1256
1410
  },
1257
1411
  },
1258
1412
  warnings,
1259
- terminalParentFixRows,
1413
+ terminalParentFixRows: rows.terminalParentFixRows,
1260
1414
  };
1261
1415
  }
1262
1416
  /* c8 ignore stop */
1263
1417
  /* c8 ignore start -- files-check candidate filtering/classification permutations are covered by file-audit integration suites */
1264
1418
  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 = [];
1419
+ const linkedPathState = await collectLinkedPathScanState(items, workspaceRoot);
1269
1420
  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));
1421
+ const uniqueMissingLinkedPaths = [...new Set(linkedPathState.missingLinkedPaths)].sort((left, right) => left.localeCompare(right));
1312
1422
  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));
1423
+ const partition = partitionFileCandidates(fileCandidates, pmRoot, workspaceRoot, fileScanMode, includePmInternals, verboseFileLists);
1424
+ const orphanedFiles = partition.candidateFiles.filter((candidate) => !linkedPathState.linkedProjectPaths.has(candidate));
1335
1425
  const orphanedPathRows = buildOrphanedPathRows(orphanedFiles, items);
1336
1426
  // Stale-path classification (pm-0v2m / GH-184): a missing linked path whose
1337
1427
  // basename still exists in the candidate scan is reported as `moved` (with
1338
1428
  // relink candidates); otherwise it is `deleted` and safe to prune.
1339
- const classifiedStalePaths = classifyStaleLinkedPaths(uniqueMissingLinkedPaths, candidateFiles);
1429
+ const classifiedStalePaths = classifyStaleLinkedPaths(uniqueMissingLinkedPaths, partition.candidateFiles);
1340
1430
  const classificationByPath = new Map(classifiedStalePaths.map((entry) => [entry.path, entry.classification]));
1341
1431
  const movedStalePathCount = classifiedStalePaths.filter((entry) => entry.classification === "moved").length;
1342
- const staleLinkPruneRows = staleLinkRows
1432
+ const staleLinkPruneRows = linkedPathState.staleLinkRows
1343
1433
  .map((row) => ({
1344
1434
  ...row,
1345
1435
  classification: classificationByPath.get(row.path) ?? "deleted",
@@ -1348,7 +1438,7 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
1348
1438
  left.path.localeCompare(right.path) ||
1349
1439
  left.link_kind.localeCompare(right.link_kind));
1350
1440
  const warnings = [];
1351
- if (strictModeForcesPmInternals) {
1441
+ if (partition.strictModeForcesPmInternals) {
1352
1442
  warnings.push("validate_files_tracked_all_strict_forces_pm_internals");
1353
1443
  }
1354
1444
  if (uniqueMissingLinkedPaths.length > 0) {
@@ -1357,7 +1447,7 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
1357
1447
  if (orphanedFiles.length > 0) {
1358
1448
  warnings.push(`validate_files_orphaned_paths:${orphanedFiles.length}`);
1359
1449
  }
1360
- const uniqueRemoteLinkedPaths = [...remoteLinkedPaths].sort((left, right) => left.localeCompare(right));
1450
+ const uniqueRemoteLinkedPaths = [...linkedPathState.remoteLinkedPaths].sort((left, right) => left.localeCompare(right));
1361
1451
  const summarizedRemote = summarizeFileList(uniqueRemoteLinkedPaths, verboseFileLists);
1362
1452
  const summarizedMissing = summarizeFileList(uniqueMissingLinkedPaths, verboseFileLists);
1363
1453
  const summarizedOrphaned = summarizeFileList(orphanedFiles, verboseFileLists);
@@ -1394,30 +1484,30 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
1394
1484
  workspace_root: workspaceRoot,
1395
1485
  scan_mode_requested: fileCandidates.requestedMode,
1396
1486
  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
1487
+ strict_tracked_all_mode: partition.strictTrackedAllMode,
1488
+ strict_mode_forces_pm_internals: partition.strictModeForcesPmInternals,
1489
+ strict_mode_forces_pm_internals_notice: partition.strictModeForcesPmInternals
1400
1490
  ? "tracked-all-strict force-enables PM internals; pass --include-pm-internals to make inclusion explicit."
1401
1491
  : null,
1402
1492
  file_list_detail_mode: verboseFileLists ? "full" : "summary",
1403
1493
  file_list_summary_limit: FILE_LIST_SUMMARY_LIMIT,
1404
1494
  candidate_scan_source: fileCandidates.source,
1405
- include_pm_internals: includePmInternalsEffective,
1495
+ include_pm_internals: partition.includePmInternalsEffective,
1406
1496
  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,
1497
+ pm_internal_candidate_prefixes: partition.pmInternalCandidatePrefixes,
1498
+ pm_internal_excluded_count: partition.excludedPmInternalPaths.length,
1499
+ excluded_total: partition.excludedPmInternalPaths.length,
1500
+ excluded_by_reason: partition.excludedByReason,
1501
+ linked_project_paths: linkedPathState.linkedProjectPaths.size,
1412
1502
  remote_linked_paths_count: uniqueRemoteLinkedPaths.length,
1413
1503
  remote_linked_paths_total: summarizedRemote.total,
1414
1504
  remote_linked_paths: summarizedRemote.values,
1415
1505
  remote_linked_paths_truncated: summarizedRemote.truncated,
1416
1506
  candidate_total_raw: fileCandidates.candidateTotal,
1417
1507
  candidate_scanned_raw: fileCandidates.candidateScanned,
1418
- candidate_total: candidateFiles.length,
1419
- candidate_scanned: candidateFiles.length,
1420
- scanned_candidate_files: candidateFiles.length,
1508
+ candidate_total: partition.candidateFiles.length,
1509
+ candidate_scanned: partition.candidateFiles.length,
1510
+ scanned_candidate_files: partition.candidateFiles.length,
1421
1511
  missing_linked_paths_count: uniqueMissingLinkedPaths.length,
1422
1512
  missing_linked_paths_total: summarizedMissing.total,
1423
1513
  missing_linked_paths: summarizedMissing.values,
@@ -1692,10 +1782,14 @@ export const _testOnlyValidateCommand = {
1692
1782
  applyValidateFixes,
1693
1783
  attachValidateFixHints,
1694
1784
  buildCommandReferencesCheck,
1785
+ buildCloseReasonBackfillRows,
1695
1786
  buildFilesCheck,
1696
1787
  buildLifecycleCheck,
1697
1788
  buildLifecycleDependencyGraph,
1698
1789
  buildLifecycleParentGraph,
1790
+ buildEstimateBackfillRows,
1791
+ buildMetadataCounts,
1792
+ buildMissingFieldOccurrences,
1699
1793
  buildOrphanedPathRows,
1700
1794
  classifyOrphanedPath,
1701
1795
  collectDefaultProjectFileCandidates,
@@ -1719,6 +1813,107 @@ export const _testOnlyValidateCommand = {
1719
1813
  summarizeDuplicateIssueCodes,
1720
1814
  toMeaningfulString,
1721
1815
  };
1816
+ function recordValidateCheck(state, built, fixHintsEnabled) {
1817
+ if (fixHintsEnabled) {
1818
+ attachValidateFixHints(built.check, built.warnings);
1819
+ }
1820
+ state.checks.push(built.check);
1821
+ state.warnings.push(...built.warnings);
1822
+ }
1823
+ async function executeRequestedValidateChecks(params) {
1824
+ const state = {
1825
+ checks: [],
1826
+ warnings: [...params.initialWarnings],
1827
+ closeReasonBackfillRows: [],
1828
+ estimateBackfillRows: [],
1829
+ resolutionBackfillRows: [],
1830
+ terminalParentFixRows: [],
1831
+ staleLinkPruneRows: [],
1832
+ };
1833
+ const fixHintsEnabled = params.options.fixHints === true;
1834
+ const fullDiagnostics = params.options.verboseDiagnostics === true || params.options.allAffectedIds === true || params.global.json === true;
1835
+ if (params.requestedChecks.has("metadata")) {
1836
+ const built = buildMetadataCheck(params.items, params.metadataPolicy, params.statusRegistry, fullDiagnostics);
1837
+ state.closeReasonBackfillRows = built.closeReasonBackfillRows;
1838
+ state.estimateBackfillRows = built.estimateBackfillRows;
1839
+ recordValidateCheck(state, built, fixHintsEnabled);
1840
+ }
1841
+ if (params.requestedChecks.has("resolution")) {
1842
+ const built = buildResolutionCheck(params.items, params.statusRegistry, fullDiagnostics);
1843
+ state.resolutionBackfillRows = built.resolutionBackfillRows;
1844
+ recordValidateCheck(state, built, fixHintsEnabled);
1845
+ }
1846
+ if (params.requestedChecks.has("lifecycle")) {
1847
+ const built = buildLifecycleCheck(params.items, Boolean(params.options.checkStaleBlockers), params.dependencyCycleSeverity, params.parentCycleSeverity, params.statusRegistry, params.lifecyclePatternPolicy, fullDiagnostics, params.settings.id_prefix);
1848
+ state.terminalParentFixRows = built.terminalParentFixRows;
1849
+ recordValidateCheck(state, built, fixHintsEnabled);
1850
+ }
1851
+ if (params.requestedChecks.has("files")) {
1852
+ const built = await buildFilesCheck(params.items, params.workspaceRoot, params.pmRoot, params.fileScanMode, Boolean(params.options.includePmInternals), Boolean(params.options.verboseFileLists));
1853
+ state.staleLinkPruneRows = built.staleLinkPruneRows;
1854
+ recordValidateCheck(state, built, fixHintsEnabled);
1855
+ }
1856
+ if (params.requestedChecks.has("command_references")) {
1857
+ recordValidateCheck(state, buildCommandReferencesCheck(params.items, params.settings.id_prefix, fullDiagnostics), fixHintsEnabled);
1858
+ }
1859
+ if (params.requestedChecks.has("history_drift")) {
1860
+ recordValidateCheck(state, await buildHistoryDriftCheck(params.pmRoot, params.items, fullDiagnostics), fixHintsEnabled);
1861
+ }
1862
+ if (params.requestedChecks.has("format_version")) {
1863
+ recordValidateCheck(state, buildFormatVersionCheck(params.items, fullDiagnostics), fixHintsEnabled);
1864
+ }
1865
+ return state;
1866
+ }
1867
+ function planValidateFixes(options, state, settings) {
1868
+ const planned = [];
1869
+ if (options.autoFix === true) {
1870
+ planned.push(...planCloseReasonBackfillFixes(state.closeReasonBackfillRows));
1871
+ planned.push(...planResolutionBackfillFixes(state.resolutionBackfillRows));
1872
+ planned.push(...planEstimateBackfillFixes(state.estimateBackfillRows, settings.validation.estimate_defaults_by_type));
1873
+ planned.push(...planTerminalParentFixes(state.terminalParentFixRows));
1874
+ }
1875
+ if (options.pruneMissing === true) {
1876
+ planned.push(...planStaleLinkPruneFixes(state.staleLinkPruneRows));
1877
+ }
1878
+ return planned;
1879
+ }
1880
+ /* v8 ignore start -- validate fix-summary matrix is covered end-to-end; direct helper fallback branches are defensive */
1881
+ async function buildValidateFixesSummary(options, state, settings, grantedFixScopes, global) {
1882
+ if (options.autoFix !== true && options.pruneMissing !== true) {
1883
+ return undefined;
1884
+ }
1885
+ const planned = planValidateFixes(options, state, settings);
1886
+ const { applicable, gated } = partitionFixesByGrant(planned, grantedFixScopes);
1887
+ const dryRun = options.dryRun === true;
1888
+ const appliedFixRows = [];
1889
+ const failedFixRows = [];
1890
+ if (!dryRun) {
1891
+ const applied = await applyValidateFixes(applicable, global);
1892
+ appliedFixRows.push(...applied.applied.map(toFixOutputRow));
1893
+ failedFixRows.push(...applied.failed.map(({ fix, error }) => ({
1894
+ ...toFixOutputRow(fix),
1895
+ error: error instanceof Error ? error.message : String(error),
1896
+ })));
1897
+ }
1898
+ return {
1899
+ mode: dryRun ? "dry_run" : "apply",
1900
+ auto_fix: options.autoFix === true,
1901
+ prune_missing: options.pruneMissing === true,
1902
+ granted_fix_scopes: [...grantedFixScopes].sort((left, right) => left.localeCompare(right)),
1903
+ planned_count: planned.length,
1904
+ applied_count: appliedFixRows.length,
1905
+ gated_count: gated.length,
1906
+ failed_count: failedFixRows.length,
1907
+ planned_fixes: planned.map(toFixOutputRow),
1908
+ applied_fixes: appliedFixRows,
1909
+ gated_fixes: gated.map((fix) => ({
1910
+ ...toFixOutputRow(fix),
1911
+ gate_hint: `Withheld: re-run with --fix-scope ${fix.gate} to apply.`,
1912
+ })),
1913
+ failed_fixes: failedFixRows,
1914
+ };
1915
+ }
1916
+ /* v8 ignore stop */
1722
1917
  /* c8 ignore start -- validate orchestration + fix-application matrices are covered by end-to-end command integration runs */
1723
1918
  /**
1724
1919
  * Implements run validate for the public runtime surface of this module.
@@ -1751,108 +1946,36 @@ export async function runValidate(options, global) {
1751
1946
  const parentCycleSeverity = resolveParentCycleSeverity(options.parentCycleSeverity);
1752
1947
  const fileScanMode = resolveFileScanMode(options.scanMode);
1753
1948
  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
- }
1949
+ const state = await executeRequestedValidateChecks({
1950
+ requestedChecks,
1951
+ options,
1952
+ global,
1953
+ pmRoot,
1954
+ workspaceRoot,
1955
+ settings,
1956
+ items,
1957
+ statusRegistry,
1958
+ metadataPolicy,
1959
+ lifecyclePatternPolicy,
1960
+ dependencyCycleSeverity,
1961
+ parentCycleSeverity,
1962
+ fileScanMode,
1963
+ initialWarnings: [...new Set(itemReadWarnings)],
1964
+ });
1803
1965
  // Remediation phase (pm-c3sz / pm-8jss / pm-0v2m). Plans are derived from
1804
1966
  // the findings of THIS run; checks above always report the pre-fix state.
1805
1967
  // Safe field backfills apply by default under --auto-fix; gated lifecycle
1806
1968
  // fixes are planned but withheld unless --fix-scope lifecycle grants them;
1807
1969
  // --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");
1970
+ const fixes = fixesRequested
1971
+ ? await buildValidateFixesSummary(options, state, settings, grantedFixScopes, global)
1972
+ : undefined;
1973
+ const normalizedWarnings = [...new Set(state.warnings)].sort((left, right) => left.localeCompare(right));
1974
+ const hasErrors = state.checks.some((check) => check.status === "error");
1852
1975
  return {
1853
1976
  ok: !hasErrors,
1854
1977
  has_warnings: normalizedWarnings.length > 0,
1855
- checks,
1978
+ checks: state.checks,
1856
1979
  warnings: normalizedWarnings,
1857
1980
  ...(fixes !== undefined ? { fixes } : {}),
1858
1981
  generated_at: nowIso(),
@@ -1860,4 +1983,4 @@ export async function runValidate(options, global) {
1860
1983
  }
1861
1984
  /* c8 ignore stop */
1862
1985
  //# sourceMappingURL=validate.js.map
1863
- //# debugId=a9087567-b334-5e9c-8ed7-e52d8cb35801
1986
+ //# debugId=96011574-703c-57e6-979f-dbae265fd01b