@unbrained/pm-cli 2026.6.30 → 2026.7.1

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 (452) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +20 -0
  3. package/dist/cli/bootstrap-args.js +89 -79
  4. package/dist/cli/bootstrap-args.js.map +1 -1
  5. package/dist/cli/commands/calendar.js +63 -62
  6. package/dist/cli/commands/calendar.js.map +1 -1
  7. package/dist/cli/commands/create.js +483 -434
  8. package/dist/cli/commands/create.js.map +1 -1
  9. package/dist/cli/commands/extension/bundled-catalog.js +59 -46
  10. package/dist/cli/commands/extension/bundled-catalog.js.map +1 -1
  11. package/dist/cli/commands/extension/doctor.js +129 -78
  12. package/dist/cli/commands/extension/doctor.js.map +1 -1
  13. package/dist/cli/commands/extension/managed-state.js +101 -57
  14. package/dist/cli/commands/extension/managed-state.js.map +1 -1
  15. package/dist/cli/commands/extension/scaffold.d.ts +7 -0
  16. package/dist/cli/commands/extension/scaffold.js +214 -186
  17. package/dist/cli/commands/extension/scaffold.js.map +1 -1
  18. package/dist/cli/commands/extension.d.ts +6 -1
  19. package/dist/cli/commands/extension.js +1034 -902
  20. package/dist/cli/commands/extension.js.map +1 -1
  21. package/dist/cli/commands/list-filter-shared.js +55 -48
  22. package/dist/cli/commands/list-filter-shared.js.map +1 -1
  23. package/dist/cli/commands/search.js +94 -68
  24. package/dist/cli/commands/search.js.map +1 -1
  25. package/dist/cli/commands/test.js +108 -122
  26. package/dist/cli/commands/test.js.map +1 -1
  27. package/dist/cli/commands/update.js +27 -77
  28. package/dist/cli/commands/update.js.map +1 -1
  29. package/dist/cli/extension-command-options.js +48 -21
  30. package/dist/cli/extension-command-options.js.map +1 -1
  31. package/dist/cli/registration-helpers.js +117 -122
  32. package/dist/cli/registration-helpers.js.map +1 -1
  33. package/dist/cli-bundle/chunks/activity-AW6XVFH6.js +16 -0
  34. package/dist/cli-bundle/chunks/{activity-MVSEND6D.js → activity-DBLQVIP6.js} +9 -9
  35. package/dist/cli-bundle/chunks/{aggregate-MOC4TR2G.js → aggregate-JTEF4BP7.js} +9 -9
  36. package/dist/cli-bundle/chunks/{aggregate-XJHLZQ5X.js → aggregate-SDF7DUOD.js} +9 -9
  37. package/dist/cli-bundle/chunks/{append-LEDBAM3K.js → append-LOVPGVPT.js} +6 -6
  38. package/dist/cli-bundle/chunks/{append-KDHT4GHI.js → append-QCFJSDFL.js} +6 -6
  39. package/dist/cli-bundle/chunks/{chunk-FBZ5XAAF.js → chunk-22WKIL3H.js} +6 -6
  40. package/dist/cli-bundle/chunks/{chunk-EVWYAG46.js → chunk-2466X6E4.js} +6 -6
  41. package/dist/cli-bundle/chunks/{chunk-3JWQCLR5.js → chunk-27BXPBAY.js} +3 -3
  42. package/dist/cli-bundle/chunks/{chunk-WTRUDJ3R.js → chunk-2D4HATP2.js} +5 -5
  43. package/dist/cli-bundle/chunks/{chunk-DORJSBGJ.js → chunk-3J6JRJ3I.js} +127 -125
  44. package/dist/cli-bundle/chunks/chunk-3J6JRJ3I.js.map +7 -0
  45. package/dist/cli-bundle/chunks/{chunk-LBH7UYKY.js → chunk-3K2M5OYU.js} +4 -4
  46. package/dist/cli-bundle/chunks/{chunk-KTMMTOIP.js → chunk-3S2KT7NG.js} +7 -7
  47. package/dist/cli-bundle/chunks/{chunk-FDEVKXC4.js → chunk-3VGN2UWE.js} +2 -2
  48. package/dist/cli-bundle/chunks/{chunk-K46GQ265.js → chunk-3XZCOZ5J.js} +107 -117
  49. package/dist/cli-bundle/chunks/chunk-3XZCOZ5J.js.map +1 -0
  50. package/dist/cli-bundle/chunks/chunk-4A3BJ675.js +799 -0
  51. package/dist/cli-bundle/chunks/chunk-4A3BJ675.js.map +1 -0
  52. package/dist/cli-bundle/chunks/chunk-4BU75MF4.js +87 -0
  53. package/dist/cli-bundle/chunks/chunk-4BU75MF4.js.map +7 -0
  54. package/dist/cli-bundle/chunks/{chunk-KYDYQMNW.js → chunk-4DSGXSBL.js} +4 -4
  55. package/dist/cli-bundle/chunks/{chunk-7L6TXOOC.js → chunk-4DUVCVLZ.js} +2 -2
  56. package/dist/cli-bundle/chunks/{chunk-UB3V5WUI.js → chunk-4XOIEKSD.js} +351 -330
  57. package/dist/cli-bundle/chunks/chunk-4XOIEKSD.js.map +1 -0
  58. package/dist/cli-bundle/chunks/{chunk-DJDXAU74.js → chunk-55SNVXRQ.js} +68 -69
  59. package/dist/cli-bundle/chunks/chunk-55SNVXRQ.js.map +7 -0
  60. package/dist/cli-bundle/chunks/{chunk-ZIE6WXJ2.js → chunk-5CGRF3L5.js} +7 -7
  61. package/dist/cli-bundle/chunks/{chunk-7WDETKGP.js → chunk-5QFDBI4F.js} +1105 -965
  62. package/dist/cli-bundle/chunks/chunk-5QFDBI4F.js.map +7 -0
  63. package/dist/cli-bundle/chunks/{chunk-IBU2LLWM.js → chunk-64HNBBFQ.js} +6 -6
  64. package/dist/cli-bundle/chunks/{chunk-T7ZMQI4J.js → chunk-6AQZPVHQ.js} +198 -189
  65. package/dist/cli-bundle/chunks/chunk-6AQZPVHQ.js.map +1 -0
  66. package/dist/cli-bundle/chunks/{chunk-CY5IJMUM.js → chunk-7R4QEMZZ.js} +361 -322
  67. package/dist/cli-bundle/chunks/chunk-7R4QEMZZ.js.map +1 -0
  68. package/dist/cli-bundle/chunks/{chunk-WFJZDUM7.js → chunk-A7FPBAQS.js} +4 -4
  69. package/dist/cli-bundle/chunks/{chunk-74PUWBGN.js → chunk-AVEE5EHK.js} +3 -3
  70. package/dist/cli-bundle/chunks/{chunk-KRASIL6M.js → chunk-AXIDKKAT.js} +2 -2
  71. package/dist/cli-bundle/chunks/{chunk-CHRNYKNI.js → chunk-BDTISOSD.js} +2 -2
  72. package/dist/cli-bundle/chunks/{chunk-ZFIEEDTJ.js → chunk-BHO33VBQ.js} +509 -363
  73. package/dist/cli-bundle/chunks/chunk-BHO33VBQ.js.map +7 -0
  74. package/dist/cli-bundle/chunks/{chunk-RM6MHL6A.js → chunk-BZCEN4JA.js} +98 -74
  75. package/dist/cli-bundle/chunks/chunk-BZCEN4JA.js.map +7 -0
  76. package/dist/cli-bundle/chunks/{chunk-RPRW26NG.js → chunk-CF7RL6FR.js} +7 -7
  77. package/dist/cli-bundle/chunks/{chunk-NIBP3I7A.js → chunk-CWFNTKQJ.js} +128 -126
  78. package/dist/cli-bundle/chunks/chunk-CWFNTKQJ.js.map +1 -0
  79. package/dist/cli-bundle/chunks/{chunk-BN3CWK6G.js → chunk-DDPTYJIM.js} +2 -2
  80. package/dist/cli-bundle/chunks/{chunk-4YIMPANT.js → chunk-EJUDVUYZ.js} +3 -3
  81. package/dist/cli-bundle/chunks/{chunk-73PTKMAE.js → chunk-EVMTBV6V.js} +3 -3
  82. package/dist/cli-bundle/chunks/{chunk-6YRAMXRS.js → chunk-FFMQB7WR.js} +99 -75
  83. package/dist/cli-bundle/chunks/chunk-FFMQB7WR.js.map +1 -0
  84. package/dist/cli-bundle/chunks/{chunk-E2Q2ULMR.js → chunk-G7I7DEZA.js} +4 -4
  85. package/dist/cli-bundle/chunks/{chunk-IDYCAK35.js → chunk-GJ326ZKX.js} +3 -3
  86. package/dist/cli-bundle/chunks/{chunk-JJ4SG243.js → chunk-HPPFYYOV.js} +2 -2
  87. package/dist/cli-bundle/chunks/{chunk-5IRVSKPS.js → chunk-HXTQJXWT.js} +150 -224
  88. package/dist/cli-bundle/chunks/chunk-HXTQJXWT.js.map +1 -0
  89. package/dist/cli-bundle/chunks/{chunk-JIP67N2K.js → chunk-HYTGA6GI.js} +3 -3
  90. package/dist/cli-bundle/chunks/{chunk-7RIJGN4R.js → chunk-HZZEHPRG.js} +2 -2
  91. package/dist/cli-bundle/chunks/{chunk-4TXTVZL3.js → chunk-IJYK2T43.js} +2 -2
  92. package/dist/cli-bundle/chunks/{chunk-GF7EAR22.js → chunk-IPYBJWTE.js} +7 -7
  93. package/dist/cli-bundle/chunks/{chunk-AWN4PPH5.js → chunk-IZBR4NRW.js} +7 -7
  94. package/dist/cli-bundle/chunks/{chunk-IF4ERU6A.js → chunk-JLM7BHI7.js} +6 -6
  95. package/dist/cli-bundle/chunks/{chunk-DU66JUGT.js → chunk-JMP4E6D7.js} +106 -116
  96. package/dist/cli-bundle/chunks/chunk-JMP4E6D7.js.map +7 -0
  97. package/dist/cli-bundle/chunks/{chunk-HUYYMTGW.js → chunk-JPECA746.js} +2 -2
  98. package/dist/cli-bundle/chunks/{chunk-KGQ3W65B.js → chunk-JSU5P7VS.js} +4 -4
  99. package/dist/cli-bundle/chunks/{chunk-HIBK6H4S.js → chunk-JWXRETDF.js} +69 -70
  100. package/dist/cli-bundle/chunks/chunk-JWXRETDF.js.map +1 -0
  101. package/dist/cli-bundle/chunks/{chunk-Z5BM2FKQ.js → chunk-KNPEF7QG.js} +4 -4
  102. package/dist/cli-bundle/chunks/{chunk-DLDCPF5X.js → chunk-L5OEFZQG.js} +3 -3
  103. package/dist/cli-bundle/chunks/{chunk-DRPF274X.js → chunk-LB6TP6MC.js} +2 -2
  104. package/dist/cli-bundle/chunks/{chunk-YEDFE4DC.js → chunk-MAUKX7JC.js} +2 -2
  105. package/dist/cli-bundle/chunks/{chunk-6T5ZIWBS.js → chunk-MDPEOIGN.js} +150 -224
  106. package/dist/cli-bundle/chunks/chunk-MDPEOIGN.js.map +7 -0
  107. package/dist/cli-bundle/chunks/{chunk-OB3RJV5F.js → chunk-N74UMG5H.js} +2 -2
  108. package/dist/cli-bundle/chunks/{chunk-ZEATCVAC.js → chunk-NFDPYAIP.js} +2 -2
  109. package/dist/cli-bundle/chunks/{chunk-OUQ5JEFM.js → chunk-NKZAN7BD.js} +3 -3
  110. package/dist/cli-bundle/chunks/{chunk-5ABGFWR4.js → chunk-NOLPZMSV.js} +2 -2
  111. package/dist/cli-bundle/chunks/{chunk-JZG5ADVE.js → chunk-NU2UEROZ.js} +1103 -963
  112. package/dist/cli-bundle/chunks/chunk-NU2UEROZ.js.map +1 -0
  113. package/dist/cli-bundle/chunks/{chunk-A3UNLXNJ.js → chunk-NUHHPVVS.js} +36 -86
  114. package/dist/cli-bundle/chunks/chunk-NUHHPVVS.js.map +7 -0
  115. package/dist/cli-bundle/chunks/{chunk-QE5UFCCO.js → chunk-NWMZWYYB.js} +2 -2
  116. package/dist/cli-bundle/chunks/{chunk-VMY7MZEM.js → chunk-OGXLACHC.js} +6 -6
  117. package/dist/cli-bundle/chunks/{chunk-IHXXUIXS.js → chunk-OTUHB4HS.js} +4 -4
  118. package/dist/cli-bundle/chunks/{chunk-V3KLX7U7.js → chunk-QCWF6IYD.js} +510 -364
  119. package/dist/cli-bundle/chunks/chunk-QCWF6IYD.js.map +1 -0
  120. package/dist/cli-bundle/chunks/{chunk-UFKNF23C.js → chunk-RGEMWD6Q.js} +5 -5
  121. package/dist/cli-bundle/chunks/chunk-RH5ZBYFD.js +809 -0
  122. package/dist/cli-bundle/chunks/chunk-RH5ZBYFD.js.map +7 -0
  123. package/dist/cli-bundle/chunks/{chunk-Z55WX4IQ.js → chunk-RLDHZHQS.js} +7 -7
  124. package/dist/cli-bundle/chunks/{chunk-NO6Y6FB2.js → chunk-RMMQ74TG.js} +5 -5
  125. package/dist/cli-bundle/chunks/{chunk-SNUK7H5J.js → chunk-RVUALSJF.js} +361 -322
  126. package/dist/cli-bundle/chunks/chunk-RVUALSJF.js.map +7 -0
  127. package/dist/cli-bundle/chunks/{chunk-IZQOJR2B.js → chunk-SDR5J34Q.js} +198 -189
  128. package/dist/cli-bundle/chunks/chunk-SDR5J34Q.js.map +7 -0
  129. package/dist/cli-bundle/chunks/{chunk-SJZTPVFT.js → chunk-SLMUGTK3.js} +4 -4
  130. package/dist/cli-bundle/chunks/{chunk-BOWQWXLI.js → chunk-TP5Q5ZD3.js} +5 -5
  131. package/dist/cli-bundle/chunks/{chunk-D5LYZVGB.js → chunk-UYUYDGIB.js} +4 -4
  132. package/dist/cli-bundle/chunks/{chunk-JVQ7UOYC.js → chunk-UZIWVBE6.js} +2 -2
  133. package/dist/cli-bundle/chunks/{chunk-JTRKME24.js → chunk-V3NOKJF2.js} +6 -6
  134. package/dist/cli-bundle/chunks/{chunk-5T6WPLRO.js → chunk-VARHOHYV.js} +350 -329
  135. package/dist/cli-bundle/chunks/chunk-VARHOHYV.js.map +7 -0
  136. package/dist/cli-bundle/chunks/{chunk-F7G53BOA.js → chunk-VICZWYGZ.js} +4 -4
  137. package/dist/cli-bundle/chunks/chunk-VY3VQ22F.js +84 -0
  138. package/dist/cli-bundle/chunks/chunk-VY3VQ22F.js.map +1 -0
  139. package/dist/cli-bundle/chunks/{chunk-TQ6E76BE.js → chunk-W4ULYO7Z.js} +6 -6
  140. package/dist/cli-bundle/chunks/{chunk-MLHX6DN5.js → chunk-WYDHYJPO.js} +2 -2
  141. package/dist/cli-bundle/chunks/{chunk-53ARXF2O.js → chunk-YITK2PJ6.js} +6 -6
  142. package/dist/cli-bundle/chunks/{chunk-VD3LKZFX.js → chunk-ZETXE4SE.js} +37 -87
  143. package/dist/cli-bundle/chunks/chunk-ZETXE4SE.js.map +1 -0
  144. package/dist/cli-bundle/chunks/{chunk-D6USKAMA.js → chunk-ZRP4VG5U.js} +2 -2
  145. package/dist/cli-bundle/chunks/{claim-6NINZYB3.js → claim-EMQLYPRW.js} +8 -8
  146. package/dist/cli-bundle/chunks/{claim-HMCLSLUE.js → claim-T3GCKV7C.js} +8 -8
  147. package/dist/cli-bundle/chunks/close-E6ZZGCJY.js +14 -0
  148. package/dist/cli-bundle/chunks/{close-OP3LK7Z2.js → close-TQYAAFJP.js} +7 -7
  149. package/dist/cli-bundle/chunks/{close-many-BFMP6HHK.js → close-many-BG5QQIDQ.js} +15 -15
  150. package/dist/cli-bundle/chunks/{close-many-CXJBOWWY.js → close-many-LDRVEQY2.js} +15 -15
  151. package/dist/cli-bundle/chunks/{comments-MU2WMBUY.js → comments-QCKR2YY2.js} +8 -8
  152. package/dist/cli-bundle/chunks/{comments-ETHABIY6.js → comments-YUXJRZPQ.js} +8 -8
  153. package/dist/cli-bundle/chunks/{config-FIXJZEQK.js → config-DMSU64QO.js} +7 -7
  154. package/dist/cli-bundle/chunks/{config-X3ZVCUUG.js → config-QH2DICD6.js} +7 -7
  155. package/dist/cli-bundle/chunks/{context-XDI4DKKT.js → context-B6275WPX.js} +12 -12
  156. package/dist/cli-bundle/chunks/{context-7ZEZV3BV.js → context-OCZ3FJ4Z.js} +12 -12
  157. package/dist/cli-bundle/chunks/{contracts-SMOAN5NF.js → contracts-HN7ABKLP.js} +3 -3
  158. package/dist/cli-bundle/chunks/{contracts-KP4QAGVW.js → contracts-W4FZVVD6.js} +3 -3
  159. package/dist/cli-bundle/chunks/{copy-CWM6SBY6.js → copy-BTJOSKKT.js} +5 -5
  160. package/dist/cli-bundle/chunks/{copy-JJ3KOQW2.js → copy-DEM4DATS.js} +5 -5
  161. package/dist/cli-bundle/chunks/create-OH3BDGBB.js +28 -0
  162. package/dist/cli-bundle/chunks/{create-J5Q2ELZT.js → create-RLRJMRTM.js} +12 -12
  163. package/dist/cli-bundle/chunks/{delete-OOQS4KVD.js → delete-BHK7VB2Z.js} +5 -5
  164. package/dist/cli-bundle/chunks/{delete-2GZLQEUQ.js → delete-LSVHAB4Y.js} +5 -5
  165. package/dist/cli-bundle/chunks/{deps-ZVGGCRR6.js → deps-4UDFJRUA.js} +5 -5
  166. package/dist/cli-bundle/chunks/{deps-IF4IGL4R.js → deps-XHYXWEPT.js} +5 -5
  167. package/dist/cli-bundle/chunks/{docs-2TIFR62T.js → docs-26S44RXU.js} +7 -7
  168. package/dist/cli-bundle/chunks/{docs-NFTBCQQC.js → docs-GYZNVS26.js} +7 -7
  169. package/dist/cli-bundle/chunks/{eval-2F6EH4XN.js → eval-PGRVIJQU.js} +10 -10
  170. package/dist/cli-bundle/chunks/{eval-PFKXQR3B.js → eval-UYF3ZPVO.js} +10 -10
  171. package/dist/cli-bundle/chunks/{extension-GMVOIP4O.js → extension-CPSLJQVE.js} +11 -10
  172. package/dist/cli-bundle/chunks/{extension-3LRYX7SW.js → extension-CXJ6RELI.js} +11 -10
  173. package/dist/cli-bundle/chunks/{files-T5ODMETM.js → files-MBNICQFM.js} +7 -7
  174. package/dist/cli-bundle/chunks/{files-DF3HO6XK.js → files-NQHEXUZD.js} +7 -7
  175. package/dist/cli-bundle/chunks/{focus-DLXKK4AH.js → focus-DWYIG7GU.js} +6 -6
  176. package/dist/cli-bundle/chunks/{focus-MY5ARIEK.js → focus-XZW5423D.js} +6 -6
  177. package/dist/cli-bundle/chunks/{gc-FULIVYR4.js → gc-7GQYOS2G.js} +3 -3
  178. package/dist/cli-bundle/chunks/{gc-MDGRR2SU.js → gc-LPVMKJQJ.js} +3 -3
  179. package/dist/cli-bundle/chunks/{get-AWK324RS.js → get-A7MAOHCU.js} +9 -9
  180. package/dist/cli-bundle/chunks/{get-VYPIICPC.js → get-DSDEKJ3L.js} +9 -9
  181. package/dist/cli-bundle/chunks/{health-Q66C43GN.js → health-3IPFLKXB.js} +17 -16
  182. package/dist/cli-bundle/chunks/{health-Q66C43GN.js.map → health-3IPFLKXB.js.map} +1 -1
  183. package/dist/cli-bundle/chunks/{health-FBCVZGSX.js → health-GZXGBZ36.js} +15 -14
  184. package/dist/cli-bundle/chunks/{health-FBCVZGSX.js.map → health-GZXGBZ36.js.map} +1 -1
  185. package/dist/cli-bundle/chunks/{history-X4OSES6K.js → history-NERDJNUB.js} +8 -8
  186. package/dist/cli-bundle/chunks/history-WSZHY3PN.js +18 -0
  187. package/dist/cli-bundle/chunks/{history-compact-WLCQEKXS.js → history-compact-2WRZ2WK4.js} +10 -10
  188. package/dist/cli-bundle/chunks/{history-compact-2GHT32UX.js → history-compact-HR7BB4LR.js} +10 -10
  189. package/dist/cli-bundle/chunks/history-redact-MP6CH7U5.js +19 -0
  190. package/dist/cli-bundle/chunks/{history-redact-45YW65BK.js → history-redact-O3NBCNWC.js} +9 -9
  191. package/dist/cli-bundle/chunks/{history-repair-GABSDSVD.js → history-repair-LCMOS45X.js} +10 -10
  192. package/dist/cli-bundle/chunks/{history-repair-FY75IC26.js → history-repair-XA3LC4GA.js} +10 -10
  193. package/dist/cli-bundle/chunks/{init-KO7CGIRQ.js → init-64XDLQJB.js} +12 -11
  194. package/dist/cli-bundle/chunks/init-PAX32BJA.js +22 -0
  195. package/dist/cli-bundle/chunks/{learnings-3F7YLI45.js → learnings-JR6MA5TI.js} +8 -8
  196. package/dist/cli-bundle/chunks/{learnings-LHZT5BHW.js → learnings-LPKCSJX7.js} +8 -8
  197. package/dist/cli-bundle/chunks/{list-ROT7JF62.js → list-DNBJVO3E.js} +8 -8
  198. package/dist/cli-bundle/chunks/{list-Y6AU5BJS.js → list-G5Y65VF6.js} +8 -8
  199. package/dist/cli-bundle/chunks/{next-66BJB4N2.js → next-BCERKDUR.js} +13 -13
  200. package/dist/cli-bundle/chunks/{next-N5MWJTBY.js → next-FYTQF6HG.js} +13 -13
  201. package/dist/cli-bundle/chunks/{notes-FW6YFLND.js → notes-2BMU3VVQ.js} +8 -8
  202. package/dist/cli-bundle/chunks/{notes-EVJZ3VAB.js → notes-6KTGO2OJ.js} +8 -8
  203. package/dist/cli-bundle/chunks/{plan-DQ7G4EDC.js → plan-4WXEQCTN.js} +12 -12
  204. package/dist/cli-bundle/chunks/{plan-ZHKZ7JVF.js → plan-RKZHQVXR.js} +12 -12
  205. package/dist/cli-bundle/chunks/{profile-UPZGCDOG.js → profile-4OMM32CD.js} +8 -8
  206. package/dist/cli-bundle/chunks/{profile-CHAW6SEA.js → profile-QLER5ENE.js} +8 -8
  207. package/dist/cli-bundle/chunks/{register-list-query-Y2VRHPCL.js → register-list-query-7LV46VAU.js} +18 -18
  208. package/dist/cli-bundle/chunks/{register-list-query-KY6Z6WV7.js → register-list-query-SNG5PGA4.js} +18 -18
  209. package/dist/cli-bundle/chunks/{register-mutation-PCARIGZS.js → register-mutation-ENNDUAZG.js} +35 -35
  210. package/dist/cli-bundle/chunks/{register-mutation-N6AYSKPM.js → register-mutation-KK7PHYYU.js} +35 -35
  211. package/dist/cli-bundle/chunks/{register-operations-YAT6FUUB.js → register-operations-C6OWLDSH.js} +30 -30
  212. package/dist/cli-bundle/chunks/{register-operations-L6CYTOIH.js → register-operations-HZ6XERQG.js} +30 -30
  213. package/dist/cli-bundle/chunks/{register-setup-N7UGXYJC.js → register-setup-P67EMBDJ.js} +15 -15
  214. package/dist/cli-bundle/chunks/{register-setup-MPANILQF.js → register-setup-ZKJ53RS7.js} +15 -15
  215. package/dist/cli-bundle/chunks/{restore-DKMCLPI5.js → restore-4MHZFJ2E.js} +9 -9
  216. package/dist/cli-bundle/chunks/restore-YALDGTQR.js +17 -0
  217. package/dist/cli-bundle/chunks/{scheduling-shortcuts-3F4QUEDH.js → scheduling-shortcuts-LB6DOLRL.js} +12 -12
  218. package/dist/cli-bundle/chunks/{scheduling-shortcuts-BNZLQK36.js → scheduling-shortcuts-UTOYKLXQ.js} +12 -12
  219. package/dist/cli-bundle/chunks/{schema-OLT6LVKH.js → schema-73HR2OJW.js} +7 -7
  220. package/dist/cli-bundle/chunks/{schema-XJXKJQF5.js → schema-U6LJKSIR.js} +7 -7
  221. package/dist/cli-bundle/chunks/{search-CX5UMV4H.js → search-AXPXKZER.js} +10 -10
  222. package/dist/cli-bundle/chunks/{search-KP6H7COV.js → search-KILGT37L.js} +10 -10
  223. package/dist/cli-bundle/chunks/{stats-QZUG6MX5.js → stats-PSYVVTNZ.js} +6 -6
  224. package/dist/cli-bundle/chunks/{stats-7XW4OEMK.js → stats-W5KNVJWQ.js} +6 -6
  225. package/dist/cli-bundle/chunks/{telemetry-WTYFUPRL.js → telemetry-BZUF6H7G.js} +4 -4
  226. package/dist/cli-bundle/chunks/{telemetry-DIFPXCAT.js → telemetry-GAHHQTOS.js} +4 -4
  227. package/dist/cli-bundle/chunks/{test-QNDXZQCW.js → test-ACD52Z3S.js} +15 -14
  228. package/dist/cli-bundle/chunks/{test-HU2BS7EY.js → test-PWDIZ255.js} +15 -14
  229. package/dist/cli-bundle/chunks/{test-all-XLPI4USF.js → test-all-L2MDDUCA.js} +17 -16
  230. package/dist/cli-bundle/chunks/{test-all-XLPI4USF.js.map → test-all-L2MDDUCA.js.map} +1 -1
  231. package/dist/cli-bundle/chunks/{test-all-PZTBLLQ6.js → test-all-RBZ6DLU2.js} +15 -14
  232. package/dist/cli-bundle/chunks/{test-all-PZTBLLQ6.js.map → test-all-RBZ6DLU2.js.map} +1 -1
  233. package/dist/cli-bundle/chunks/{test-runs-LANLLPVO.js → test-runs-PLRAZEFW.js} +4 -4
  234. package/dist/cli-bundle/chunks/{test-runs-CA6K32RD.js → test-runs-UXIXPDKU.js} +4 -4
  235. package/dist/cli-bundle/chunks/update-AMRSOIWP.js +24 -0
  236. package/dist/cli-bundle/chunks/{update-DJKWLBWJ.js → update-KFX2SIAC.js} +15 -15
  237. package/dist/cli-bundle/chunks/{update-many-VW5DGF3S.js → update-many-RNSBX2TA.js} +23 -23
  238. package/dist/cli-bundle/chunks/{update-many-LU3SCNK5.js → update-many-Z5GJS5LC.js} +23 -23
  239. package/dist/cli-bundle/chunks/{upgrade-77FRUAXN.js → upgrade-BRL6KCOJ.js} +13 -12
  240. package/dist/cli-bundle/chunks/{upgrade-77FRUAXN.js.map → upgrade-BRL6KCOJ.js.map} +1 -1
  241. package/dist/cli-bundle/chunks/{upgrade-ICXY244R.js → upgrade-HAK6JG2O.js} +11 -10
  242. package/dist/cli-bundle/chunks/{upgrade-ICXY244R.js.map → upgrade-HAK6JG2O.js.map} +1 -1
  243. package/dist/cli-bundle/chunks/{validate-2G566PKQ.js → validate-MTUVL5VC.js} +20 -19
  244. package/dist/cli-bundle/chunks/{validate-2G566PKQ.js.map → validate-MTUVL5VC.js.map} +1 -1
  245. package/dist/cli-bundle/chunks/{validate-BDPVXHHH.js → validate-X5W76YJL.js} +22 -21
  246. package/dist/cli-bundle/chunks/{validate-BDPVXHHH.js.map → validate-X5W76YJL.js.map} +1 -1
  247. package/dist/cli-bundle/main.js +55 -702
  248. package/dist/cli-bundle/main.js.map +4 -4
  249. package/dist/core/extensions/activation-summary-markdown.js +23 -12
  250. package/dist/core/extensions/activation-summary-markdown.js.map +1 -1
  251. package/dist/core/extensions/extension-policy.d.ts +18 -3
  252. package/dist/core/extensions/extension-policy.js +116 -106
  253. package/dist/core/extensions/extension-policy.js.map +1 -1
  254. package/dist/core/extensions/loader.js +310 -232
  255. package/dist/core/extensions/loader.js.map +1 -1
  256. package/dist/core/item/item-format.js +523 -410
  257. package/dist/core/item/item-format.js.map +1 -1
  258. package/dist/mcp/server.js +387 -367
  259. package/dist/mcp/server.js.map +1 -1
  260. package/dist/sdk/cli-contracts/flag-contracts.js +111 -180
  261. package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
  262. package/dist/sdk/cli-contracts/tool-schema.js +76 -45
  263. package/dist/sdk/cli-contracts/tool-schema.js.map +1 -1
  264. package/dist/sdk/compose.d.ts +4 -1
  265. package/dist/sdk/compose.js +181 -115
  266. package/dist/sdk/compose.js.map +1 -1
  267. package/docs/RELEASING.md +2 -3
  268. package/package.json +1 -1
  269. package/dist/cli-bundle/chunks/activity-EJBMXUBH.js +0 -16
  270. package/dist/cli-bundle/chunks/chunk-5IRVSKPS.js.map +0 -1
  271. package/dist/cli-bundle/chunks/chunk-5T6WPLRO.js.map +0 -7
  272. package/dist/cli-bundle/chunks/chunk-6T5ZIWBS.js.map +0 -7
  273. package/dist/cli-bundle/chunks/chunk-6YRAMXRS.js.map +0 -1
  274. package/dist/cli-bundle/chunks/chunk-7WDETKGP.js.map +0 -7
  275. package/dist/cli-bundle/chunks/chunk-A3UNLXNJ.js.map +0 -7
  276. package/dist/cli-bundle/chunks/chunk-C2KCIZKZ.js +0 -115
  277. package/dist/cli-bundle/chunks/chunk-C2KCIZKZ.js.map +0 -1
  278. package/dist/cli-bundle/chunks/chunk-CY5IJMUM.js.map +0 -1
  279. package/dist/cli-bundle/chunks/chunk-DJDXAU74.js.map +0 -7
  280. package/dist/cli-bundle/chunks/chunk-DORJSBGJ.js.map +0 -7
  281. package/dist/cli-bundle/chunks/chunk-DU66JUGT.js.map +0 -7
  282. package/dist/cli-bundle/chunks/chunk-F6VH3LFC.js +0 -118
  283. package/dist/cli-bundle/chunks/chunk-F6VH3LFC.js.map +0 -7
  284. package/dist/cli-bundle/chunks/chunk-HIBK6H4S.js.map +0 -1
  285. package/dist/cli-bundle/chunks/chunk-ISEKN64V.js +0 -35
  286. package/dist/cli-bundle/chunks/chunk-ISEKN64V.js.map +0 -7
  287. package/dist/cli-bundle/chunks/chunk-IZQOJR2B.js.map +0 -7
  288. package/dist/cli-bundle/chunks/chunk-JZG5ADVE.js.map +0 -1
  289. package/dist/cli-bundle/chunks/chunk-K46GQ265.js.map +0 -1
  290. package/dist/cli-bundle/chunks/chunk-NIBP3I7A.js.map +0 -1
  291. package/dist/cli-bundle/chunks/chunk-RM6MHL6A.js.map +0 -7
  292. package/dist/cli-bundle/chunks/chunk-SNUK7H5J.js.map +0 -7
  293. package/dist/cli-bundle/chunks/chunk-T7ZMQI4J.js.map +0 -1
  294. package/dist/cli-bundle/chunks/chunk-UB3V5WUI.js.map +0 -1
  295. package/dist/cli-bundle/chunks/chunk-V3KLX7U7.js.map +0 -1
  296. package/dist/cli-bundle/chunks/chunk-VD3LKZFX.js.map +0 -1
  297. package/dist/cli-bundle/chunks/chunk-W2VMLL5S.js +0 -32
  298. package/dist/cli-bundle/chunks/chunk-W2VMLL5S.js.map +0 -1
  299. package/dist/cli-bundle/chunks/chunk-ZFIEEDTJ.js.map +0 -7
  300. package/dist/cli-bundle/chunks/close-37KEHLYM.js +0 -14
  301. package/dist/cli-bundle/chunks/create-DFMNBKBS.js +0 -28
  302. package/dist/cli-bundle/chunks/history-5XUSLAJA.js +0 -18
  303. package/dist/cli-bundle/chunks/history-redact-BVHWDXPR.js +0 -19
  304. package/dist/cli-bundle/chunks/init-TRYJELH4.js +0 -21
  305. package/dist/cli-bundle/chunks/restore-IRAKSWIW.js +0 -17
  306. package/dist/cli-bundle/chunks/update-UXDLTEOZ.js +0 -24
  307. /package/dist/cli-bundle/chunks/{activity-EJBMXUBH.js.map → activity-AW6XVFH6.js.map} +0 -0
  308. /package/dist/cli-bundle/chunks/{activity-MVSEND6D.js.map → activity-DBLQVIP6.js.map} +0 -0
  309. /package/dist/cli-bundle/chunks/{aggregate-MOC4TR2G.js.map → aggregate-JTEF4BP7.js.map} +0 -0
  310. /package/dist/cli-bundle/chunks/{aggregate-XJHLZQ5X.js.map → aggregate-SDF7DUOD.js.map} +0 -0
  311. /package/dist/cli-bundle/chunks/{append-LEDBAM3K.js.map → append-LOVPGVPT.js.map} +0 -0
  312. /package/dist/cli-bundle/chunks/{append-KDHT4GHI.js.map → append-QCFJSDFL.js.map} +0 -0
  313. /package/dist/cli-bundle/chunks/{chunk-FBZ5XAAF.js.map → chunk-22WKIL3H.js.map} +0 -0
  314. /package/dist/cli-bundle/chunks/{chunk-EVWYAG46.js.map → chunk-2466X6E4.js.map} +0 -0
  315. /package/dist/cli-bundle/chunks/{chunk-3JWQCLR5.js.map → chunk-27BXPBAY.js.map} +0 -0
  316. /package/dist/cli-bundle/chunks/{chunk-WTRUDJ3R.js.map → chunk-2D4HATP2.js.map} +0 -0
  317. /package/dist/cli-bundle/chunks/{chunk-LBH7UYKY.js.map → chunk-3K2M5OYU.js.map} +0 -0
  318. /package/dist/cli-bundle/chunks/{chunk-KTMMTOIP.js.map → chunk-3S2KT7NG.js.map} +0 -0
  319. /package/dist/cli-bundle/chunks/{chunk-FDEVKXC4.js.map → chunk-3VGN2UWE.js.map} +0 -0
  320. /package/dist/cli-bundle/chunks/{chunk-KYDYQMNW.js.map → chunk-4DSGXSBL.js.map} +0 -0
  321. /package/dist/cli-bundle/chunks/{chunk-7L6TXOOC.js.map → chunk-4DUVCVLZ.js.map} +0 -0
  322. /package/dist/cli-bundle/chunks/{chunk-ZIE6WXJ2.js.map → chunk-5CGRF3L5.js.map} +0 -0
  323. /package/dist/cli-bundle/chunks/{chunk-IBU2LLWM.js.map → chunk-64HNBBFQ.js.map} +0 -0
  324. /package/dist/cli-bundle/chunks/{chunk-WFJZDUM7.js.map → chunk-A7FPBAQS.js.map} +0 -0
  325. /package/dist/cli-bundle/chunks/{chunk-74PUWBGN.js.map → chunk-AVEE5EHK.js.map} +0 -0
  326. /package/dist/cli-bundle/chunks/{chunk-KRASIL6M.js.map → chunk-AXIDKKAT.js.map} +0 -0
  327. /package/dist/cli-bundle/chunks/{chunk-CHRNYKNI.js.map → chunk-BDTISOSD.js.map} +0 -0
  328. /package/dist/cli-bundle/chunks/{chunk-RPRW26NG.js.map → chunk-CF7RL6FR.js.map} +0 -0
  329. /package/dist/cli-bundle/chunks/{chunk-BN3CWK6G.js.map → chunk-DDPTYJIM.js.map} +0 -0
  330. /package/dist/cli-bundle/chunks/{chunk-4YIMPANT.js.map → chunk-EJUDVUYZ.js.map} +0 -0
  331. /package/dist/cli-bundle/chunks/{chunk-73PTKMAE.js.map → chunk-EVMTBV6V.js.map} +0 -0
  332. /package/dist/cli-bundle/chunks/{chunk-E2Q2ULMR.js.map → chunk-G7I7DEZA.js.map} +0 -0
  333. /package/dist/cli-bundle/chunks/{chunk-IDYCAK35.js.map → chunk-GJ326ZKX.js.map} +0 -0
  334. /package/dist/cli-bundle/chunks/{chunk-JJ4SG243.js.map → chunk-HPPFYYOV.js.map} +0 -0
  335. /package/dist/cli-bundle/chunks/{chunk-JIP67N2K.js.map → chunk-HYTGA6GI.js.map} +0 -0
  336. /package/dist/cli-bundle/chunks/{chunk-7RIJGN4R.js.map → chunk-HZZEHPRG.js.map} +0 -0
  337. /package/dist/cli-bundle/chunks/{chunk-4TXTVZL3.js.map → chunk-IJYK2T43.js.map} +0 -0
  338. /package/dist/cli-bundle/chunks/{chunk-GF7EAR22.js.map → chunk-IPYBJWTE.js.map} +0 -0
  339. /package/dist/cli-bundle/chunks/{chunk-AWN4PPH5.js.map → chunk-IZBR4NRW.js.map} +0 -0
  340. /package/dist/cli-bundle/chunks/{chunk-IF4ERU6A.js.map → chunk-JLM7BHI7.js.map} +0 -0
  341. /package/dist/cli-bundle/chunks/{chunk-HUYYMTGW.js.map → chunk-JPECA746.js.map} +0 -0
  342. /package/dist/cli-bundle/chunks/{chunk-KGQ3W65B.js.map → chunk-JSU5P7VS.js.map} +0 -0
  343. /package/dist/cli-bundle/chunks/{chunk-Z5BM2FKQ.js.map → chunk-KNPEF7QG.js.map} +0 -0
  344. /package/dist/cli-bundle/chunks/{chunk-DLDCPF5X.js.map → chunk-L5OEFZQG.js.map} +0 -0
  345. /package/dist/cli-bundle/chunks/{chunk-DRPF274X.js.map → chunk-LB6TP6MC.js.map} +0 -0
  346. /package/dist/cli-bundle/chunks/{chunk-YEDFE4DC.js.map → chunk-MAUKX7JC.js.map} +0 -0
  347. /package/dist/cli-bundle/chunks/{chunk-OB3RJV5F.js.map → chunk-N74UMG5H.js.map} +0 -0
  348. /package/dist/cli-bundle/chunks/{chunk-ZEATCVAC.js.map → chunk-NFDPYAIP.js.map} +0 -0
  349. /package/dist/cli-bundle/chunks/{chunk-OUQ5JEFM.js.map → chunk-NKZAN7BD.js.map} +0 -0
  350. /package/dist/cli-bundle/chunks/{chunk-5ABGFWR4.js.map → chunk-NOLPZMSV.js.map} +0 -0
  351. /package/dist/cli-bundle/chunks/{chunk-QE5UFCCO.js.map → chunk-NWMZWYYB.js.map} +0 -0
  352. /package/dist/cli-bundle/chunks/{chunk-VMY7MZEM.js.map → chunk-OGXLACHC.js.map} +0 -0
  353. /package/dist/cli-bundle/chunks/{chunk-IHXXUIXS.js.map → chunk-OTUHB4HS.js.map} +0 -0
  354. /package/dist/cli-bundle/chunks/{chunk-UFKNF23C.js.map → chunk-RGEMWD6Q.js.map} +0 -0
  355. /package/dist/cli-bundle/chunks/{chunk-Z55WX4IQ.js.map → chunk-RLDHZHQS.js.map} +0 -0
  356. /package/dist/cli-bundle/chunks/{chunk-NO6Y6FB2.js.map → chunk-RMMQ74TG.js.map} +0 -0
  357. /package/dist/cli-bundle/chunks/{chunk-SJZTPVFT.js.map → chunk-SLMUGTK3.js.map} +0 -0
  358. /package/dist/cli-bundle/chunks/{chunk-BOWQWXLI.js.map → chunk-TP5Q5ZD3.js.map} +0 -0
  359. /package/dist/cli-bundle/chunks/{chunk-D5LYZVGB.js.map → chunk-UYUYDGIB.js.map} +0 -0
  360. /package/dist/cli-bundle/chunks/{chunk-JVQ7UOYC.js.map → chunk-UZIWVBE6.js.map} +0 -0
  361. /package/dist/cli-bundle/chunks/{chunk-JTRKME24.js.map → chunk-V3NOKJF2.js.map} +0 -0
  362. /package/dist/cli-bundle/chunks/{chunk-F7G53BOA.js.map → chunk-VICZWYGZ.js.map} +0 -0
  363. /package/dist/cli-bundle/chunks/{chunk-TQ6E76BE.js.map → chunk-W4ULYO7Z.js.map} +0 -0
  364. /package/dist/cli-bundle/chunks/{chunk-MLHX6DN5.js.map → chunk-WYDHYJPO.js.map} +0 -0
  365. /package/dist/cli-bundle/chunks/{chunk-53ARXF2O.js.map → chunk-YITK2PJ6.js.map} +0 -0
  366. /package/dist/cli-bundle/chunks/{chunk-D6USKAMA.js.map → chunk-ZRP4VG5U.js.map} +0 -0
  367. /package/dist/cli-bundle/chunks/{claim-6NINZYB3.js.map → claim-EMQLYPRW.js.map} +0 -0
  368. /package/dist/cli-bundle/chunks/{claim-HMCLSLUE.js.map → claim-T3GCKV7C.js.map} +0 -0
  369. /package/dist/cli-bundle/chunks/{close-37KEHLYM.js.map → close-E6ZZGCJY.js.map} +0 -0
  370. /package/dist/cli-bundle/chunks/{close-OP3LK7Z2.js.map → close-TQYAAFJP.js.map} +0 -0
  371. /package/dist/cli-bundle/chunks/{close-many-BFMP6HHK.js.map → close-many-BG5QQIDQ.js.map} +0 -0
  372. /package/dist/cli-bundle/chunks/{close-many-CXJBOWWY.js.map → close-many-LDRVEQY2.js.map} +0 -0
  373. /package/dist/cli-bundle/chunks/{comments-MU2WMBUY.js.map → comments-QCKR2YY2.js.map} +0 -0
  374. /package/dist/cli-bundle/chunks/{comments-ETHABIY6.js.map → comments-YUXJRZPQ.js.map} +0 -0
  375. /package/dist/cli-bundle/chunks/{config-FIXJZEQK.js.map → config-DMSU64QO.js.map} +0 -0
  376. /package/dist/cli-bundle/chunks/{config-X3ZVCUUG.js.map → config-QH2DICD6.js.map} +0 -0
  377. /package/dist/cli-bundle/chunks/{context-XDI4DKKT.js.map → context-B6275WPX.js.map} +0 -0
  378. /package/dist/cli-bundle/chunks/{context-7ZEZV3BV.js.map → context-OCZ3FJ4Z.js.map} +0 -0
  379. /package/dist/cli-bundle/chunks/{contracts-SMOAN5NF.js.map → contracts-HN7ABKLP.js.map} +0 -0
  380. /package/dist/cli-bundle/chunks/{contracts-KP4QAGVW.js.map → contracts-W4FZVVD6.js.map} +0 -0
  381. /package/dist/cli-bundle/chunks/{copy-CWM6SBY6.js.map → copy-BTJOSKKT.js.map} +0 -0
  382. /package/dist/cli-bundle/chunks/{copy-JJ3KOQW2.js.map → copy-DEM4DATS.js.map} +0 -0
  383. /package/dist/cli-bundle/chunks/{create-DFMNBKBS.js.map → create-OH3BDGBB.js.map} +0 -0
  384. /package/dist/cli-bundle/chunks/{create-J5Q2ELZT.js.map → create-RLRJMRTM.js.map} +0 -0
  385. /package/dist/cli-bundle/chunks/{delete-OOQS4KVD.js.map → delete-BHK7VB2Z.js.map} +0 -0
  386. /package/dist/cli-bundle/chunks/{delete-2GZLQEUQ.js.map → delete-LSVHAB4Y.js.map} +0 -0
  387. /package/dist/cli-bundle/chunks/{deps-ZVGGCRR6.js.map → deps-4UDFJRUA.js.map} +0 -0
  388. /package/dist/cli-bundle/chunks/{deps-IF4IGL4R.js.map → deps-XHYXWEPT.js.map} +0 -0
  389. /package/dist/cli-bundle/chunks/{docs-2TIFR62T.js.map → docs-26S44RXU.js.map} +0 -0
  390. /package/dist/cli-bundle/chunks/{docs-NFTBCQQC.js.map → docs-GYZNVS26.js.map} +0 -0
  391. /package/dist/cli-bundle/chunks/{eval-2F6EH4XN.js.map → eval-PGRVIJQU.js.map} +0 -0
  392. /package/dist/cli-bundle/chunks/{eval-PFKXQR3B.js.map → eval-UYF3ZPVO.js.map} +0 -0
  393. /package/dist/cli-bundle/chunks/{extension-GMVOIP4O.js.map → extension-CPSLJQVE.js.map} +0 -0
  394. /package/dist/cli-bundle/chunks/{extension-3LRYX7SW.js.map → extension-CXJ6RELI.js.map} +0 -0
  395. /package/dist/cli-bundle/chunks/{files-T5ODMETM.js.map → files-MBNICQFM.js.map} +0 -0
  396. /package/dist/cli-bundle/chunks/{files-DF3HO6XK.js.map → files-NQHEXUZD.js.map} +0 -0
  397. /package/dist/cli-bundle/chunks/{focus-DLXKK4AH.js.map → focus-DWYIG7GU.js.map} +0 -0
  398. /package/dist/cli-bundle/chunks/{focus-MY5ARIEK.js.map → focus-XZW5423D.js.map} +0 -0
  399. /package/dist/cli-bundle/chunks/{gc-FULIVYR4.js.map → gc-7GQYOS2G.js.map} +0 -0
  400. /package/dist/cli-bundle/chunks/{gc-MDGRR2SU.js.map → gc-LPVMKJQJ.js.map} +0 -0
  401. /package/dist/cli-bundle/chunks/{get-AWK324RS.js.map → get-A7MAOHCU.js.map} +0 -0
  402. /package/dist/cli-bundle/chunks/{get-VYPIICPC.js.map → get-DSDEKJ3L.js.map} +0 -0
  403. /package/dist/cli-bundle/chunks/{history-X4OSES6K.js.map → history-NERDJNUB.js.map} +0 -0
  404. /package/dist/cli-bundle/chunks/{history-5XUSLAJA.js.map → history-WSZHY3PN.js.map} +0 -0
  405. /package/dist/cli-bundle/chunks/{history-compact-WLCQEKXS.js.map → history-compact-2WRZ2WK4.js.map} +0 -0
  406. /package/dist/cli-bundle/chunks/{history-compact-2GHT32UX.js.map → history-compact-HR7BB4LR.js.map} +0 -0
  407. /package/dist/cli-bundle/chunks/{history-redact-BVHWDXPR.js.map → history-redact-MP6CH7U5.js.map} +0 -0
  408. /package/dist/cli-bundle/chunks/{history-redact-45YW65BK.js.map → history-redact-O3NBCNWC.js.map} +0 -0
  409. /package/dist/cli-bundle/chunks/{history-repair-GABSDSVD.js.map → history-repair-LCMOS45X.js.map} +0 -0
  410. /package/dist/cli-bundle/chunks/{history-repair-FY75IC26.js.map → history-repair-XA3LC4GA.js.map} +0 -0
  411. /package/dist/cli-bundle/chunks/{init-KO7CGIRQ.js.map → init-64XDLQJB.js.map} +0 -0
  412. /package/dist/cli-bundle/chunks/{init-TRYJELH4.js.map → init-PAX32BJA.js.map} +0 -0
  413. /package/dist/cli-bundle/chunks/{learnings-3F7YLI45.js.map → learnings-JR6MA5TI.js.map} +0 -0
  414. /package/dist/cli-bundle/chunks/{learnings-LHZT5BHW.js.map → learnings-LPKCSJX7.js.map} +0 -0
  415. /package/dist/cli-bundle/chunks/{list-ROT7JF62.js.map → list-DNBJVO3E.js.map} +0 -0
  416. /package/dist/cli-bundle/chunks/{list-Y6AU5BJS.js.map → list-G5Y65VF6.js.map} +0 -0
  417. /package/dist/cli-bundle/chunks/{next-66BJB4N2.js.map → next-BCERKDUR.js.map} +0 -0
  418. /package/dist/cli-bundle/chunks/{next-N5MWJTBY.js.map → next-FYTQF6HG.js.map} +0 -0
  419. /package/dist/cli-bundle/chunks/{notes-FW6YFLND.js.map → notes-2BMU3VVQ.js.map} +0 -0
  420. /package/dist/cli-bundle/chunks/{notes-EVJZ3VAB.js.map → notes-6KTGO2OJ.js.map} +0 -0
  421. /package/dist/cli-bundle/chunks/{plan-DQ7G4EDC.js.map → plan-4WXEQCTN.js.map} +0 -0
  422. /package/dist/cli-bundle/chunks/{plan-ZHKZ7JVF.js.map → plan-RKZHQVXR.js.map} +0 -0
  423. /package/dist/cli-bundle/chunks/{profile-UPZGCDOG.js.map → profile-4OMM32CD.js.map} +0 -0
  424. /package/dist/cli-bundle/chunks/{profile-CHAW6SEA.js.map → profile-QLER5ENE.js.map} +0 -0
  425. /package/dist/cli-bundle/chunks/{register-list-query-Y2VRHPCL.js.map → register-list-query-7LV46VAU.js.map} +0 -0
  426. /package/dist/cli-bundle/chunks/{register-list-query-KY6Z6WV7.js.map → register-list-query-SNG5PGA4.js.map} +0 -0
  427. /package/dist/cli-bundle/chunks/{register-mutation-PCARIGZS.js.map → register-mutation-ENNDUAZG.js.map} +0 -0
  428. /package/dist/cli-bundle/chunks/{register-mutation-N6AYSKPM.js.map → register-mutation-KK7PHYYU.js.map} +0 -0
  429. /package/dist/cli-bundle/chunks/{register-operations-YAT6FUUB.js.map → register-operations-C6OWLDSH.js.map} +0 -0
  430. /package/dist/cli-bundle/chunks/{register-operations-L6CYTOIH.js.map → register-operations-HZ6XERQG.js.map} +0 -0
  431. /package/dist/cli-bundle/chunks/{register-setup-N7UGXYJC.js.map → register-setup-P67EMBDJ.js.map} +0 -0
  432. /package/dist/cli-bundle/chunks/{register-setup-MPANILQF.js.map → register-setup-ZKJ53RS7.js.map} +0 -0
  433. /package/dist/cli-bundle/chunks/{restore-DKMCLPI5.js.map → restore-4MHZFJ2E.js.map} +0 -0
  434. /package/dist/cli-bundle/chunks/{restore-IRAKSWIW.js.map → restore-YALDGTQR.js.map} +0 -0
  435. /package/dist/cli-bundle/chunks/{scheduling-shortcuts-3F4QUEDH.js.map → scheduling-shortcuts-LB6DOLRL.js.map} +0 -0
  436. /package/dist/cli-bundle/chunks/{scheduling-shortcuts-BNZLQK36.js.map → scheduling-shortcuts-UTOYKLXQ.js.map} +0 -0
  437. /package/dist/cli-bundle/chunks/{schema-OLT6LVKH.js.map → schema-73HR2OJW.js.map} +0 -0
  438. /package/dist/cli-bundle/chunks/{schema-XJXKJQF5.js.map → schema-U6LJKSIR.js.map} +0 -0
  439. /package/dist/cli-bundle/chunks/{search-CX5UMV4H.js.map → search-AXPXKZER.js.map} +0 -0
  440. /package/dist/cli-bundle/chunks/{search-KP6H7COV.js.map → search-KILGT37L.js.map} +0 -0
  441. /package/dist/cli-bundle/chunks/{stats-QZUG6MX5.js.map → stats-PSYVVTNZ.js.map} +0 -0
  442. /package/dist/cli-bundle/chunks/{stats-7XW4OEMK.js.map → stats-W5KNVJWQ.js.map} +0 -0
  443. /package/dist/cli-bundle/chunks/{telemetry-WTYFUPRL.js.map → telemetry-BZUF6H7G.js.map} +0 -0
  444. /package/dist/cli-bundle/chunks/{telemetry-DIFPXCAT.js.map → telemetry-GAHHQTOS.js.map} +0 -0
  445. /package/dist/cli-bundle/chunks/{test-QNDXZQCW.js.map → test-ACD52Z3S.js.map} +0 -0
  446. /package/dist/cli-bundle/chunks/{test-HU2BS7EY.js.map → test-PWDIZ255.js.map} +0 -0
  447. /package/dist/cli-bundle/chunks/{test-runs-LANLLPVO.js.map → test-runs-PLRAZEFW.js.map} +0 -0
  448. /package/dist/cli-bundle/chunks/{test-runs-CA6K32RD.js.map → test-runs-UXIXPDKU.js.map} +0 -0
  449. /package/dist/cli-bundle/chunks/{update-UXDLTEOZ.js.map → update-AMRSOIWP.js.map} +0 -0
  450. /package/dist/cli-bundle/chunks/{update-DJKWLBWJ.js.map → update-KFX2SIAC.js.map} +0 -0
  451. /package/dist/cli-bundle/chunks/{update-many-VW5DGF3S.js.map → update-many-RNSBX2TA.js.map} +0 -0
  452. /package/dist/cli-bundle/chunks/{update-many-LU3SCNK5.js.map → update-many-Z5GJS5LC.js.map} +0 -0
@@ -4,7 +4,7 @@
4
4
  * Implements the pm extension 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]="e112e059-bf75-55f5-a0ec-652b037fe54b")}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]="0e9a5528-9595-5a89-89b7-5a5acce477a8")}catch(e){}}();
8
8
  import { execFile } from "node:child_process";
9
9
  import fs from "node:fs/promises";
10
10
  import os from "node:os";
@@ -352,48 +352,68 @@ function buildUnknownLifecycleActionError(target, options) {
352
352
  },
353
353
  });
354
354
  }
355
+ // Maps each boolean action flag to the lifecycle action it selects. `scaffold`
356
+ // aliases `init` and `adoptAll` selects `adopt-all`; every other flag maps to its
357
+ // like-named action. Dispatching through the table keeps `resolveAction` flat.
358
+ const EXTENSION_ACTION_FLAG_SELECTORS = [
359
+ ["install", "install"],
360
+ ["uninstall", "uninstall"],
361
+ ["explore", "explore"],
362
+ ["manage", "manage"],
363
+ ["describe", "describe"],
364
+ ["reload", "reload"],
365
+ ["doctor", "doctor"],
366
+ ["catalog", "catalog"],
367
+ ["init", "init"],
368
+ ["scaffold", "init"],
369
+ ["adopt", "adopt"],
370
+ ["adoptAll", "adopt-all"],
371
+ ["activate", "activate"],
372
+ ["deactivate", "deactivate"],
373
+ ];
374
+ /**
375
+ * Map a bare positional token (already trimmed and lower-cased) to the lifecycle
376
+ * action it implies for `pm extension <token>` / `pm package <token>`: the
377
+ * `doctor`/`reload`/`catalog`/`init`/`scaffold`/`explore`/`manage` keywords, with
378
+ * `list` and the empty string both meaning `explore`. Returns `null` for anything
379
+ * else so the caller can raise a did-you-mean error.
380
+ */
381
+ function resolveImplicitActionFromTarget(normalizedTarget) {
382
+ if (normalizedTarget === "doctor") {
383
+ return "doctor";
384
+ }
385
+ if (normalizedTarget === "reload") {
386
+ return "reload";
387
+ }
388
+ if (normalizedTarget === "catalog") {
389
+ return "catalog";
390
+ }
391
+ if (normalizedTarget === "init" || normalizedTarget === "scaffold") {
392
+ return "init";
393
+ }
394
+ if (normalizedTarget === "explore") {
395
+ return "explore";
396
+ }
397
+ if (normalizedTarget === "manage") {
398
+ return "manage";
399
+ }
400
+ if (normalizedTarget === "list" || normalizedTarget === "") {
401
+ return "explore";
402
+ }
403
+ return null;
404
+ }
355
405
  function resolveAction(target, options) {
356
- const selected = [...new Set([
357
- options.install ? "install" : null,
358
- options.uninstall ? "uninstall" : null,
359
- options.explore ? "explore" : null,
360
- options.manage ? "manage" : null,
361
- options.describe ? "describe" : null,
362
- options.reload ? "reload" : null,
363
- options.doctor ? "doctor" : null,
364
- options.catalog ? "catalog" : null,
365
- options.init ? "init" : null,
366
- options.scaffold ? "init" : null,
367
- options.adopt ? "adopt" : null,
368
- options.adoptAll ? "adopt-all" : null,
369
- options.activate ? "activate" : null,
370
- options.deactivate ? "deactivate" : null,
371
- ].filter((value) => value !== null))];
406
+ const selected = [
407
+ ...new Set(EXTENSION_ACTION_FLAG_SELECTORS.filter(([flag]) => options[flag] === true).map(([, mappedAction]) => mappedAction)),
408
+ ];
372
409
  if (selected.length === 0) {
373
- if (typeof target === "string" && target.trim().toLowerCase() === "doctor") {
374
- return "doctor";
375
- }
376
- if (typeof target === "string" && target.trim().toLowerCase() === "reload") {
377
- return "reload";
378
- }
379
- if (typeof target === "string" && target.trim().toLowerCase() === "catalog") {
380
- return "catalog";
381
- }
382
- if (typeof target === "string" && (target.trim().toLowerCase() === "init" || target.trim().toLowerCase() === "scaffold")) {
383
- return "init";
384
- }
385
- if (typeof target === "string" && target.trim().toLowerCase() === "explore") {
386
- return "explore";
387
- }
388
- if (typeof target === "string" && target.trim().toLowerCase() === "manage") {
389
- return "manage";
390
- }
391
- if (typeof target === "string" && (target.trim().toLowerCase() === "list" || target.trim() === "")) {
392
- return "explore";
393
- }
394
410
  if (target === undefined) {
395
411
  return "explore";
396
412
  }
413
+ const implicitAction = resolveImplicitActionFromTarget(target.trim().toLowerCase());
414
+ if (implicitAction) {
415
+ return implicitAction;
416
+ }
397
417
  throw buildUnknownLifecycleActionError(target, options);
398
418
  }
399
419
  if (selected.length > 1) {
@@ -452,6 +472,34 @@ function resolveUpdateCheckResolution(managedEntry) {
452
472
  reason: "no_update_check_recorded",
453
473
  };
454
474
  }
475
+ /**
476
+ * Assemble a {@link ManagedExtensionSummary} from a directory's resolved identity
477
+ * (name/version/entry/enabled state) and its managed-state record, projecting the
478
+ * managed-source provenance and the resolved update-check status. Runtime
479
+ * activation fields default to "not yet probed" (`runtime_active: null`,
480
+ * `activation_status: "unknown"`) so a later runtime probe can overlay live state.
481
+ */
482
+ function buildInstalledExtensionSummary(identity, scope, managedEntry, updateCheck) {
483
+ return {
484
+ name: identity.name,
485
+ directory: identity.directory,
486
+ version: identity.version,
487
+ entry: identity.entry,
488
+ scope,
489
+ active: identity.enabled,
490
+ enabled: identity.enabled,
491
+ runtime_active: null,
492
+ activation_status: "unknown",
493
+ managed: Boolean(managedEntry),
494
+ source: managedEntry?.source,
495
+ update_available: managedEntry?.update_available,
496
+ last_update_check_at: managedEntry?.last_update_check_at,
497
+ last_update_remote_commit: managedEntry?.last_update_remote_commit,
498
+ update_error: managedEntry?.update_error,
499
+ update_check_status: updateCheck.status,
500
+ update_check_reason: updateCheck.reason,
501
+ };
502
+ }
455
503
  async function listInstalledExtensions(extensionsRoot, scope, settings, state) {
456
504
  if (!(await pathExists(extensionsRoot))) {
457
505
  return {
@@ -478,27 +526,13 @@ async function listInstalledExtensions(extensionsRoot, scope, settings, state) {
478
526
  if (!(await pathExists(manifestPath))) {
479
527
  warnings.push(`extension_manifest_missing:${scope}:${directoryName}`);
480
528
  const managedEntry = managedByDirectory.get(normalizeExtensionNameForMatch(directoryName));
481
- const updateCheck = resolveUpdateCheckResolution(managedEntry);
482
- const enabled = managedEntry ? isExtensionEnabled(settings, managedEntry.name) : false;
483
- summaries.push({
529
+ summaries.push(buildInstalledExtensionSummary({
484
530
  name: managedEntry?.name ?? directoryName,
485
531
  directory: directoryName,
486
532
  version: managedEntry?.manifest_version ?? "unknown",
487
533
  entry: managedEntry?.manifest_entry ?? "unknown",
488
- scope,
489
- active: enabled,
490
- enabled,
491
- runtime_active: null,
492
- activation_status: "unknown",
493
- managed: Boolean(managedEntry),
494
- source: managedEntry?.source,
495
- update_available: managedEntry?.update_available,
496
- last_update_check_at: managedEntry?.last_update_check_at,
497
- last_update_remote_commit: managedEntry?.last_update_remote_commit,
498
- update_error: managedEntry?.update_error,
499
- update_check_status: updateCheck.status,
500
- update_check_reason: updateCheck.reason,
501
- });
534
+ enabled: managedEntry ? isExtensionEnabled(settings, managedEntry.name) : false,
535
+ }, scope, managedEntry, resolveUpdateCheckResolution(managedEntry)));
502
536
  continue;
503
537
  }
504
538
  let rawManifest;
@@ -516,27 +550,13 @@ async function listInstalledExtensions(extensionsRoot, scope, settings, state) {
516
550
  }
517
551
  const managedEntry = managedByName.get(normalizeExtensionNameForMatch(manifest.name)) ??
518
552
  managedByDirectory.get(normalizeExtensionNameForMatch(directoryName));
519
- const updateCheck = resolveUpdateCheckResolution(managedEntry);
520
- const enabled = isExtensionEnabled(settings, manifest.name);
521
- summaries.push({
553
+ summaries.push(buildInstalledExtensionSummary({
522
554
  name: manifest.name,
523
555
  directory: directoryName,
524
556
  version: manifest.version,
525
557
  entry: manifest.entry,
526
- scope,
527
- active: enabled,
528
- enabled,
529
- runtime_active: null,
530
- activation_status: "unknown",
531
- managed: Boolean(managedEntry),
532
- source: managedEntry?.source,
533
- update_available: managedEntry?.update_available,
534
- last_update_check_at: managedEntry?.last_update_check_at,
535
- last_update_remote_commit: managedEntry?.last_update_remote_commit,
536
- update_error: managedEntry?.update_error,
537
- update_check_status: updateCheck.status,
538
- update_check_reason: updateCheck.reason,
539
- });
558
+ enabled: isExtensionEnabled(settings, manifest.name),
559
+ }, scope, managedEntry, resolveUpdateCheckResolution(managedEntry)));
540
560
  }
541
561
  return {
542
562
  extensions: summaries.sort((left, right) => left.name.localeCompare(right.name)),
@@ -844,53 +864,90 @@ function collectSchemaNarrowActivationDoctorWarnings(loadResult, activationResul
844
864
  return [...new Set(warnings)].sort((left, right) => left.localeCompare(right));
845
865
  }
846
866
  /**
847
- * Implements run extension for the public runtime surface of this module.
867
+ * Reject option/action combinations that are only meaningful for a specific
868
+ * lifecycle action — `--trace`/`--strict-exit`/`--fail-on-warn` require `--doctor`,
869
+ * `--watch` requires `--reload`, `--runtime-probe` requires `--manage`,
870
+ * `--fix-managed-state` requires `--manage`/`--doctor`, and
871
+ * `--capability`/`--declarative` require `--init`/`--scaffold`. Each guard pairs a
872
+ * "flag is set" predicate with the action(s) that permit it and throws a USAGE
873
+ * error on the first mismatch.
848
874
  */
849
- export async function runExtension(target, options, global) {
850
- const action = resolveAction(target, options);
851
- if ((options.strictExit === true || options.failOnWarn === true) && action !== "doctor") {
852
- throw new PmCliError("--strict-exit and --fail-on-warn are only valid with --doctor.", EXIT_CODE.USAGE);
853
- }
854
- if (options.trace === true && action !== "doctor") {
855
- throw new PmCliError("--trace is only valid with --doctor.", EXIT_CODE.USAGE);
856
- }
857
- if (options.watch === true && action !== "reload") {
858
- throw new PmCliError("--watch is only valid with --reload.", EXIT_CODE.USAGE);
875
+ function assertExtensionActionOptionScope(action, options) {
876
+ const guards = [
877
+ {
878
+ triggered: options.strictExit === true || options.failOnWarn === true,
879
+ allowed: action === "doctor",
880
+ message: "--strict-exit and --fail-on-warn are only valid with --doctor.",
881
+ },
882
+ { triggered: options.trace === true, allowed: action === "doctor", message: "--trace is only valid with --doctor." },
883
+ { triggered: options.watch === true, allowed: action === "reload", message: "--watch is only valid with --reload." },
884
+ {
885
+ triggered: options.runtimeProbe === true,
886
+ allowed: action === "manage",
887
+ message: "--runtime-probe is only valid with --manage.",
888
+ },
889
+ {
890
+ triggered: options.fixManagedState === true,
891
+ allowed: action === "manage" || action === "doctor",
892
+ message: "--fix-managed-state is only valid with --manage or --doctor.",
893
+ },
894
+ {
895
+ triggered: options.capability !== undefined,
896
+ allowed: action === "init",
897
+ message: "--capability is only valid with --init/--scaffold.",
898
+ },
899
+ {
900
+ triggered: options.declarative === true,
901
+ allowed: action === "init",
902
+ message: "--declarative is only valid with --init/--scaffold.",
903
+ },
904
+ ];
905
+ for (const guard of guards) {
906
+ if (guard.triggered && !guard.allowed) {
907
+ throw new PmCliError(guard.message, EXIT_CODE.USAGE);
908
+ }
859
909
  }
860
- if (options.runtimeProbe === true && action !== "manage") {
861
- throw new PmCliError("--runtime-probe is only valid with --manage.", EXIT_CODE.USAGE);
910
+ }
911
+ /* c8 ignore start -- alias-normalization matrix is covered by resolveAction tests; this only rewrites positional aliases */
912
+ /**
913
+ * Collapse a positional target that merely repeats the action keyword
914
+ * (`pm extension doctor`, `reload`, `catalog`, or `init`/`scaffold`) to
915
+ * `undefined` so the action handlers treat it as "no target" rather than an
916
+ * extension name; otherwise the original target is returned unchanged.
917
+ */
918
+ function resolveNormalizedExtensionTarget(target, action, options) {
919
+ const normalizedInput = target?.trim().toLowerCase();
920
+ if (action === "doctor" && normalizedInput === "doctor") {
921
+ return undefined;
862
922
  }
863
- if (options.fixManagedState === true && action !== "manage" && action !== "doctor") {
864
- throw new PmCliError("--fix-managed-state is only valid with --manage or --doctor.", EXIT_CODE.USAGE);
923
+ if (action === "reload" && normalizedInput === "reload") {
924
+ return undefined;
865
925
  }
866
- if (options.capability !== undefined && action !== "init") {
867
- throw new PmCliError("--capability is only valid with --init/--scaffold.", EXIT_CODE.USAGE);
926
+ if (action === "catalog" && normalizedInput === "catalog") {
927
+ return undefined;
868
928
  }
869
- if (options.declarative === true && action !== "init") {
870
- throw new PmCliError("--declarative is only valid with --init/--scaffold.", EXIT_CODE.USAGE);
929
+ const inferredInitAlias = action === "init" &&
930
+ options.init !== true &&
931
+ options.scaffold !== true &&
932
+ (normalizedInput === "init" || normalizedInput === "scaffold");
933
+ if (inferredInitAlias) {
934
+ return undefined;
871
935
  }
872
- /* c8 ignore start -- alias-normalization matrix is covered by resolveAction tests; this IIFE only rewrites positional aliases */
873
- const normalizedTarget = (() => {
874
- const normalizedInput = target?.trim().toLowerCase();
875
- if (action === "doctor" && normalizedInput === "doctor") {
876
- return undefined;
877
- }
878
- if (action === "reload" && normalizedInput === "reload") {
879
- return undefined;
880
- }
881
- if (action === "catalog" && normalizedInput === "catalog") {
882
- return undefined;
883
- }
884
- const inferredInitAlias = action === "init" &&
885
- options.init !== true &&
886
- options.scaffold !== true &&
887
- (normalizedInput === "init" || normalizedInput === "scaffold");
888
- if (inferredInitAlias) {
889
- return undefined;
890
- }
891
- return target;
892
- })();
893
- /* c8 ignore stop */
936
+ return target;
937
+ }
938
+ /* c8 ignore stop */
939
+ /**
940
+ * Entry point for the `pm extension` / `pm package` command surface. Resolves the
941
+ * requested lifecycle action and scope, rejects out-of-scope option usage,
942
+ * normalizes positional aliases, then dispatches to the matching action handler —
943
+ * each of which reads and writes managed-extension state, runtime-probes, and
944
+ * returns the canonical {@link ExtensionCommandResult}. `--doctor` results are
945
+ * flagged for native (non-JSON-wrapped) output.
946
+ */
947
+ export async function runExtension(target, options, global) {
948
+ const action = resolveAction(target, options);
949
+ assertExtensionActionOptionScope(action, options);
950
+ const normalizedTarget = resolveNormalizedExtensionTarget(target, action, options);
894
951
  const scope = resolveScope(options);
895
952
  const resolvedRoots = resolveExtensionRootsForScope(scope, global);
896
953
  const warnings = [];
@@ -924,492 +981,826 @@ export async function runExtension(target, options, global) {
924
981
  }
925
982
  return result;
926
983
  };
927
- if (action === "init") {
928
- const githubOption = resolveGithubOption(options);
929
- if (githubOption !== undefined || (typeof options.ref === "string" && options.ref.trim().length > 0)) {
930
- throw new PmCliError('Action "init" does not accept --gh/--github/--ref options.', EXIT_CODE.USAGE);
931
- }
932
- const scaffoldTarget = requireTarget(normalizedTarget, action, options);
933
- const scaffold = await scaffoldExtensionProject(scaffoldTarget, options.vocabulary ?? "extension", options.capability, options.declarative === true);
934
- const quotedTargetPath = JSON.stringify(scaffold.target_path);
935
- // Forward-slash the path for the copy-pasteable `cd` hint: Windows cmd.exe /
936
- // PowerShell reject the doubled backslashes JSON.stringify emits, while both
937
- // shells (and POSIX) accept forward slashes.
938
- const quotedShellTargetPath = JSON.stringify(scaffold.target_path.replace(/\\/g, "/"));
939
- return withResult({
940
- scaffolded: scaffold.created_directory || scaffold.files.some((entry) => entry.status === "created"),
941
- extension: {
942
- name: scaffold.extension_name,
943
- command: scaffold.command_name,
944
- },
945
- capability: scaffold.capability,
946
- style: scaffold.style,
947
- target_path: scaffold.target_path,
948
- created_directory: scaffold.created_directory,
949
- files: scaffold.files,
950
- next_steps: [
951
- // Extensions are authored AND loaded as TypeScript (ADR pm-2c28 / pm-m1uz):
952
- // the manifest entry is ./index.ts and pm strips types on load (Node
953
- // >=22.18), so there is no compile/build step — install dependencies, then
954
- // install the scaffold directly.
955
- ...(options.vocabulary === "package"
956
- ? [`Install dependencies: cd ${quotedShellTargetPath}, then run "npm install"`]
957
- : [
958
- `Install type-check dependencies: cd ${quotedShellTargetPath}, then run "npm install -D typescript @types/node @unbrained/pm-cli"`,
959
- ]),
960
- `Install the scaffold: ${options.vocabulary === "package" ? "pm install --project" : "pm extension --install --project"} ${quotedTargetPath}`,
961
- `Smoke-test command path: pm ${scaffold.command_name}`,
962
- ...(options.vocabulary === "package"
963
- ? [`Validate the package: cd ${quotedShellTargetPath}, then run "npm run typecheck" and "npm test"`]
964
- : [`Type-check the source (optional): cd ${quotedShellTargetPath}, then run "npx tsc --noEmit"`]),
965
- `Run diagnostics: ${options.vocabulary === "package" ? "pm package doctor" : "pm extension --doctor"} --project --detail summary`,
966
- ],
967
- });
984
+ const ctx = {
985
+ action,
986
+ normalizedTarget,
987
+ scope,
988
+ resolvedRoots,
989
+ warnings,
990
+ options,
991
+ global,
992
+ withResult,
993
+ };
994
+ return EXTENSION_ACTION_HANDLERS[action](ctx);
995
+ }
996
+ async function runExtensionInitAction(ctx) {
997
+ const { action, normalizedTarget, options, withResult } = ctx;
998
+ const githubOption = resolveGithubOption(options);
999
+ if (githubOption !== undefined || (typeof options.ref === "string" && options.ref.trim().length > 0)) {
1000
+ throw new PmCliError('Action "init" does not accept --gh/--github/--ref options.', EXIT_CODE.USAGE);
968
1001
  }
969
- if (action === "reload") {
970
- if (normalizedTarget !== undefined) {
971
- throw new PmCliError('Action "reload" does not accept a target argument.', EXIT_CODE.USAGE);
972
- }
973
- const settings = await readSettings(resolvedRoots.settings_root);
974
- const reloadToken = nextExtensionReloadToken();
975
- const reloaded = await loadExtensions({
976
- pmRoot: resolvedRoots.settings_root,
977
- settings,
978
- cwd: process.cwd(),
979
- noExtensions: global.noExtensions,
980
- reload_token: reloadToken,
1002
+ const scaffoldTarget = requireTarget(normalizedTarget, action, options);
1003
+ const scaffold = await scaffoldExtensionProject(scaffoldTarget, options.vocabulary ?? "extension", options.capability, options.declarative === true);
1004
+ const quotedTargetPath = JSON.stringify(scaffold.target_path);
1005
+ // Forward-slash the path for the copy-pasteable `cd` hint: Windows cmd.exe /
1006
+ // PowerShell reject the doubled backslashes JSON.stringify emits, while both
1007
+ // shells (and POSIX) accept forward slashes.
1008
+ const quotedShellTargetPath = JSON.stringify(scaffold.target_path.replace(/\\/g, "/"));
1009
+ return withResult({
1010
+ scaffolded: scaffold.created_directory || scaffold.files.some((entry) => entry.status === "created"),
1011
+ extension: {
1012
+ name: scaffold.extension_name,
1013
+ command: scaffold.command_name,
1014
+ },
1015
+ capability: scaffold.capability,
1016
+ style: scaffold.style,
1017
+ target_path: scaffold.target_path,
1018
+ created_directory: scaffold.created_directory,
1019
+ files: scaffold.files,
1020
+ next_steps: [
1021
+ // Extensions are authored AND loaded as TypeScript (ADR pm-2c28 / pm-m1uz):
1022
+ // the manifest entry is ./index.ts and pm strips types on load (Node
1023
+ // >=22.18), so there is no compile/build step — install dependencies, then
1024
+ // install the scaffold directly.
1025
+ ...(options.vocabulary === "package"
1026
+ ? [`Install dependencies: cd ${quotedShellTargetPath}, then run "npm install"`]
1027
+ : [
1028
+ `Install type-check dependencies: cd ${quotedShellTargetPath}, then run "npm install -D typescript @types/node @unbrained/pm-cli"`,
1029
+ ]),
1030
+ `Install the scaffold: ${options.vocabulary === "package" ? "pm install --project" : "pm extension --install --project"} ${quotedTargetPath}`,
1031
+ `Smoke-test command path: pm ${scaffold.command_name}`,
1032
+ ...(options.vocabulary === "package"
1033
+ ? [`Validate the package: cd ${quotedShellTargetPath}, then run "npm run typecheck" and "npm test"`]
1034
+ : [`Type-check the source (optional): cd ${quotedShellTargetPath}, then run "npx tsc --noEmit"`]),
1035
+ `Run diagnostics: ${options.vocabulary === "package" ? "pm package doctor" : "pm extension --doctor"} --project --detail summary`,
1036
+ ],
1037
+ });
1038
+ }
1039
+ async function runExtensionReloadAction(ctx) {
1040
+ const { normalizedTarget, resolvedRoots, warnings, options, global, withResult } = ctx;
1041
+ if (normalizedTarget !== undefined) {
1042
+ throw new PmCliError('Action "reload" does not accept a target argument.', EXIT_CODE.USAGE);
1043
+ }
1044
+ const settings = await readSettings(resolvedRoots.settings_root);
1045
+ const reloadToken = nextExtensionReloadToken();
1046
+ const reloaded = await loadExtensions({
1047
+ pmRoot: resolvedRoots.settings_root,
1048
+ settings,
1049
+ cwd: process.cwd(),
1050
+ noExtensions: global.noExtensions,
1051
+ reload_token: reloadToken,
1052
+ cache_bust: true,
1053
+ });
1054
+ warnings.push(...reloaded.warnings);
1055
+ const activation = await activateExtensions(reloaded);
1056
+ warnings.push(...activation.warnings);
1057
+ const details = {
1058
+ reload: {
1059
+ token: reloadToken,
981
1060
  cache_bust: true,
982
- });
983
- warnings.push(...reloaded.warnings);
984
- const activation = await activateExtensions(reloaded);
985
- warnings.push(...activation.warnings);
986
- const details = {
987
- reload: {
988
- token: reloadToken,
989
- cache_bust: true,
990
- watch: options.watch === true,
991
- },
992
- loaded_count: reloaded.loaded.length,
993
- failed_count: reloaded.failed.length,
994
- activated_count: Math.max(0, reloaded.loaded.length - activation.failed.length),
995
- activation_failed_count: activation.failed.length,
996
- loaded_extensions: reloaded.loaded.map((entry) => ({
997
- name: entry.name,
998
- layer: entry.layer,
999
- version: entry.version,
1000
- })),
1001
- failed_extensions: reloaded.failed.map((entry) => ({
1002
- name: entry.name,
1003
- layer: entry.layer,
1004
- error: entry.error,
1005
- })),
1006
- activation_failures: activation.failed.map((entry) => ({
1007
- name: entry.name,
1008
- layer: entry.layer,
1009
- error: entry.error,
1010
- })),
1061
+ watch: options.watch === true,
1062
+ },
1063
+ loaded_count: reloaded.loaded.length,
1064
+ failed_count: reloaded.failed.length,
1065
+ activated_count: Math.max(0, reloaded.loaded.length - activation.failed.length),
1066
+ activation_failed_count: activation.failed.length,
1067
+ loaded_extensions: reloaded.loaded.map((entry) => ({
1068
+ name: entry.name,
1069
+ layer: entry.layer,
1070
+ version: entry.version,
1071
+ })),
1072
+ failed_extensions: reloaded.failed.map((entry) => ({
1073
+ name: entry.name,
1074
+ layer: entry.layer,
1075
+ error: entry.error,
1076
+ })),
1077
+ activation_failures: activation.failed.map((entry) => ({
1078
+ name: entry.name,
1079
+ layer: entry.layer,
1080
+ error: entry.error,
1081
+ })),
1082
+ };
1083
+ if (options.watch === true) {
1084
+ warnings.push("extension_reload_watch_hint:watch_mode_requested_non_interactive_single_pass_only");
1085
+ }
1086
+ return withResult(details);
1087
+ }
1088
+ async function runExtensionCatalogAction(ctx) {
1089
+ const { normalizedTarget, scope, options, global, withResult } = ctx;
1090
+ if (typeof normalizedTarget === "string" && normalizedTarget.length > 0 && normalizedTarget !== "catalog") {
1091
+ throw new PmCliError('Action "catalog" does not accept a package target.', EXIT_CODE.USAGE);
1092
+ }
1093
+ return withResult(await buildBundledPackageCatalog(scope, global, options));
1094
+ }
1095
+ /* c8 ignore start -- source-shape branch combinations are exercised in install-source focused tests */
1096
+ /**
1097
+ * Build the persisted managed-source record for an install from its resolved
1098
+ * shape: a bundled builtin alias, a local path, an npm package, or (the default) a
1099
+ * GitHub repository, capturing the location/commit/subpath provenance the manage
1100
+ * and upgrade flows later read back.
1101
+ */
1102
+ function buildInstallManagedSource(bundledAliasName, installSource, resolvedSource) {
1103
+ if (bundledAliasName) {
1104
+ return {
1105
+ kind: "builtin",
1106
+ input: bundledAliasName,
1107
+ location: bundledAliasName,
1108
+ name: bundledAliasName,
1011
1109
  };
1012
- if (options.watch === true) {
1013
- warnings.push("extension_reload_watch_hint:watch_mode_requested_non_interactive_single_pass_only");
1014
- }
1015
- return withResult(details);
1016
1110
  }
1017
- if (action === "catalog") {
1018
- if (typeof normalizedTarget === "string" && normalizedTarget.length > 0 && normalizedTarget !== "catalog") {
1019
- throw new PmCliError('Action "catalog" does not accept a package target.', EXIT_CODE.USAGE);
1020
- }
1021
- return withResult(await buildBundledPackageCatalog(scope, global, options));
1022
- }
1023
- if (action === "install") {
1024
- const githubOption = resolveGithubOption(options);
1025
- const explicitSourceInput = githubOption ?? requireTarget(normalizedTarget, action, options);
1026
- if (typeof githubOption !== "string" && isBundledPackageInstallAllTarget(explicitSourceInput)) {
1027
- if (typeof options.ref === "string" && options.ref.trim().length > 0) {
1028
- throw new PmCliError('Action "install all" does not accept --ref.', EXIT_CODE.USAGE);
1029
- }
1030
- const aliases = await listBundledPackageAliases();
1031
- const packages = [];
1032
- for (const alias of aliases) {
1033
- packages.push({
1034
- alias,
1035
- result: await runExtension(alias, { ...options, install: true }, global),
1036
- });
1037
- }
1038
- for (const entry of packages) {
1039
- warnings.push(...entry.result.warnings);
1040
- }
1041
- return withResult({
1042
- installed_all: true,
1043
- installed_count: packages.length,
1044
- packages: packages.map((entry) => ({
1045
- alias: entry.alias,
1046
- ok: entry.result.ok,
1047
- extension: entry.result.details.extension,
1048
- source: entry.result.details.source,
1049
- destination_path: entry.result.details.destination_path,
1050
- activated: entry.result.details.activated,
1051
- settings_changed: entry.result.details.settings_changed,
1052
- command_paths: entry.result.details.command_paths,
1053
- action_paths: entry.result.details.action_paths,
1054
- command_discovery: entry.result.details.command_discovery,
1055
- warnings: entry.result.warnings,
1056
- })),
1057
- });
1058
- }
1059
- /* c8 ignore start -- github/local alias-source split is exercised in install-action integration tests */
1060
- const bundledAliasSource = typeof githubOption === "string" ? null : await resolveBundledExtensionAliasSource(explicitSourceInput);
1061
- /* c8 ignore stop */
1062
- const bundledAliasName = bundledAliasSource === null ? null : explicitSourceInput.trim().toLowerCase();
1063
- const sourceInput = bundledAliasSource ?? explicitSourceInput;
1064
- /* c8 ignore start -- install-source branch combinations are covered in install-sources focused tests */
1065
- const installSource = parseExtensionInstallSource(sourceInput, {
1066
- forceGithub: typeof githubOption === "string",
1067
- ref: options.ref,
1068
- });
1069
- /* c8 ignore stop */
1070
- const resolvedSource = await resolveInstallSource(installSource);
1071
- try {
1072
- const validated = await validateExtensionDirectory(resolvedSource.directory);
1073
- const destinationDirectoryName = normalizeManagedDirectoryName(validated.manifest.name);
1074
- return await withExtensionInstallLock(resolvedRoots.settings_root, destinationDirectoryName, async () => {
1075
- const settings = await readSettings(resolvedRoots.settings_root);
1076
- const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1077
- warnings.push(...managedStateRead.warnings);
1078
- const destinationDirectory = path.join(resolvedRoots.selected_root, destinationDirectoryName);
1079
- const destinationExists = await pathExists(destinationDirectory);
1080
- const installInPlace = await areDirectoriesEquivalent(validated.directory, destinationDirectory);
1081
- await fs.mkdir(resolvedRoots.selected_root, { recursive: true });
1082
- if (!installInPlace) {
1083
- await copyExtensionDirectoryForInstall(validated.directory, destinationDirectory);
1084
- }
1085
- /* c8 ignore start -- source-shape branch combinations are exercised in install-source focused tests */
1086
- const sourceRecord = bundledAliasName
1087
- ? {
1088
- kind: "builtin",
1089
- input: bundledAliasName,
1090
- location: bundledAliasName,
1091
- name: bundledAliasName,
1092
- }
1093
- : installSource.kind === "local"
1094
- ? {
1095
- kind: "local",
1096
- input: installSource.input,
1097
- location: installSource.absolute_path,
1098
- }
1099
- : installSource.kind === "npm"
1100
- ? {
1101
- kind: "npm",
1102
- input: installSource.input,
1103
- location: resolvedSource.resolved_subpath ?? ".",
1104
- package: resolvedSource.npm_package,
1105
- version: resolvedSource.npm_version,
1106
- }
1107
- : {
1108
- kind: "github",
1109
- input: installSource.input,
1110
- location: resolvedSource.resolved_subpath ?? installSource.subpath ?? ".",
1111
- repository: installSource.repository,
1112
- owner: installSource.owner,
1113
- repo: installSource.repo,
1114
- ref: installSource.ref,
1115
- subpath: resolvedSource.resolved_subpath ?? installSource.subpath,
1116
- commit: resolvedSource.commit,
1117
- };
1118
- /* c8 ignore stop */
1119
- const now = nowIso();
1120
- const existingManagedEntry = managedStateRead.state.entries.find((entry) => normalizeExtensionNameForMatch(entry.name) === normalizeExtensionNameForMatch(validated.manifest.name));
1121
- const sourceUnchanged = existingManagedEntry !== undefined &&
1122
- existingManagedEntry.manifest_version === validated.manifest.version &&
1123
- managedExtensionSourcesEquivalent(existingManagedEntry.source, sourceRecord);
1124
- const managedState = upsertManagedEntry(managedStateRead.state, {
1125
- name: validated.manifest.name,
1126
- directory: destinationDirectoryName,
1127
- scope,
1128
- manifest_version: validated.manifest.version,
1129
- manifest_entry: validated.manifest.entry,
1130
- capabilities: [...validated.manifest.capabilities],
1131
- installed_at: existingManagedEntry?.installed_at ?? now,
1132
- updated_at: sourceUnchanged ? existingManagedEntry.updated_at : now,
1133
- source: sourceRecord,
1134
- });
1135
- await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
1136
- const activationChanged = ensureActivated(settings, validated.manifest.name);
1137
- if (activationChanged) {
1138
- await writeSettings(resolvedRoots.settings_root, settings, "settings:write");
1139
- }
1140
- const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
1141
- warnings.push(...refreshedInstalled.warnings);
1142
- const runtimeProbe = await probeRuntimeCommandPathsForInstall(resolvedRoots.pm_root, settings, refreshedInstalled.extensions, global);
1143
- warnings.push(...runtimeProbe.warnings);
1144
- // Scaffold the folders for any item types the installed package contributes
1145
- // so the tracker is immediately healthy — matching `pm schema add-type` and
1146
- // `pm profile apply`, the other paths that register a type. Without this a
1147
- // freshly-installed schema package leaves a `missing_directory` health
1148
- // warning until the first item of its type is created. Scoped to project
1149
- // installs, where `pm_root` is unambiguously the tracker the type folders
1150
- // belong to; a global install is not tied to one tracker, so its folders are
1151
- // created lazily on first use in each project.
1152
- const installedItemTypeDefinitions = runtimeProbe.item_type_registrations
1153
- .filter((entry) => normalizeExtensionNameForMatch(entry.name) === normalizeExtensionNameForMatch(validated.manifest.name))
1154
- .flatMap((entry) => entry.types.map((type) => ({ name: type.name, folder: type.folder })));
1155
- if (scope === "project" && installedItemTypeDefinitions.length > 0) {
1156
- await ensureTypeFolderScaffold(resolvedRoots.pm_root, installedItemTypeDefinitions, warnings, "install:type-folder");
1157
- }
1158
- const commandSummary = summarizeRuntimeCommandPathsForExtension(validated.manifest.name, runtimeProbe.installed);
1159
- const installActivationFailure = findActivationFailureByName(validated.manifest.name, runtimeProbe.activation_failures, scope);
1160
- const runtimeActivationStatus = resolveInstallRuntimeActivationStatus(validated.manifest.name, scope, runtimeProbe.installed, installActivationFailure);
1161
- return withResult({
1162
- extension: {
1163
- name: validated.manifest.name,
1164
- version: validated.manifest.version,
1165
- entry: validated.manifest.entry,
1166
- capabilities: validated.manifest.capabilities,
1167
- directory: destinationDirectoryName,
1168
- },
1169
- source: sourceRecord,
1170
- destination_path: destinationDirectory,
1171
- overwritten: destinationExists && !installInPlace,
1172
- installed_in_place: installInPlace,
1173
- activated: true,
1174
- settings_changed: activationChanged,
1175
- runtime_activation_status: runtimeActivationStatus,
1176
- command_paths: commandSummary.command_paths,
1177
- action_paths: commandSummary.action_paths,
1178
- command_discovery: buildInstallCommandDiscovery(validated.manifest.name, sourceRecord, commandSummary),
1179
- activation_diagnostics: {
1180
- failed_count: runtimeProbe.activation_failures.length,
1181
- failed: runtimeProbe.activation_failures,
1182
- installed_extension_failed: installActivationFailure ?? null,
1183
- },
1184
- });
1185
- });
1186
- }
1187
- finally {
1188
- /* c8 ignore start -- cleanup hooks are only present for transient install sources */
1189
- if (resolvedSource.cleanup) {
1190
- await resolvedSource.cleanup();
1191
- }
1192
- /* c8 ignore stop */
1193
- }
1111
+ if (installSource.kind === "local") {
1112
+ return {
1113
+ kind: "local",
1114
+ input: installSource.input,
1115
+ location: installSource.absolute_path,
1116
+ };
1117
+ }
1118
+ if (installSource.kind === "npm") {
1119
+ return {
1120
+ kind: "npm",
1121
+ input: installSource.input,
1122
+ location: resolvedSource.resolved_subpath ?? ".",
1123
+ package: resolvedSource.npm_package,
1124
+ version: resolvedSource.npm_version,
1125
+ };
1126
+ }
1127
+ return {
1128
+ kind: "github",
1129
+ input: installSource.input,
1130
+ location: resolvedSource.resolved_subpath ?? installSource.subpath ?? ".",
1131
+ repository: installSource.repository,
1132
+ owner: installSource.owner,
1133
+ repo: installSource.repo,
1134
+ ref: installSource.ref,
1135
+ subpath: resolvedSource.resolved_subpath ?? installSource.subpath,
1136
+ commit: resolvedSource.commit,
1137
+ };
1138
+ }
1139
+ /* c8 ignore stop */
1140
+ /**
1141
+ * Run the install body while holding the per-destination install lock: read
1142
+ * settings and managed state, copy the validated extension into the scope root
1143
+ * unless it is already installed in place, upsert the managed entry and activation
1144
+ * state, scaffold any contributed item-type folders, runtime-probe the freshly
1145
+ * installed command paths, and return the install result envelope.
1146
+ */
1147
+ async function performExtensionInstallUnderLock(ctx, input) {
1148
+ const { scope, resolvedRoots, warnings, global, withResult } = ctx;
1149
+ const { validated, destinationDirectoryName, bundledAliasName, installSource, resolvedSource } = input;
1150
+ const settings = await readSettings(resolvedRoots.settings_root);
1151
+ const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1152
+ warnings.push(...managedStateRead.warnings);
1153
+ const destinationDirectory = path.join(resolvedRoots.selected_root, destinationDirectoryName);
1154
+ const destinationExists = await pathExists(destinationDirectory);
1155
+ const installInPlace = await areDirectoriesEquivalent(validated.directory, destinationDirectory);
1156
+ await fs.mkdir(resolvedRoots.selected_root, { recursive: true });
1157
+ if (!installInPlace) {
1158
+ await copyExtensionDirectoryForInstall(validated.directory, destinationDirectory);
1159
+ }
1160
+ const sourceRecord = buildInstallManagedSource(bundledAliasName, installSource, resolvedSource);
1161
+ const now = nowIso();
1162
+ const existingManagedEntry = managedStateRead.state.entries.find((entry) => normalizeExtensionNameForMatch(entry.name) === normalizeExtensionNameForMatch(validated.manifest.name));
1163
+ const sourceUnchanged = existingManagedEntry !== undefined &&
1164
+ existingManagedEntry.manifest_version === validated.manifest.version &&
1165
+ managedExtensionSourcesEquivalent(existingManagedEntry.source, sourceRecord);
1166
+ const managedState = upsertManagedEntry(managedStateRead.state, {
1167
+ name: validated.manifest.name,
1168
+ directory: destinationDirectoryName,
1169
+ scope,
1170
+ manifest_version: validated.manifest.version,
1171
+ manifest_entry: validated.manifest.entry,
1172
+ capabilities: [...validated.manifest.capabilities],
1173
+ installed_at: existingManagedEntry?.installed_at ?? now,
1174
+ updated_at: sourceUnchanged ? existingManagedEntry.updated_at : now,
1175
+ source: sourceRecord,
1176
+ });
1177
+ await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
1178
+ const activationChanged = ensureActivated(settings, validated.manifest.name);
1179
+ if (activationChanged) {
1180
+ await writeSettings(resolvedRoots.settings_root, settings, "settings:write");
1194
1181
  }
1195
- if (action === "adopt-all") {
1196
- if (normalizedTarget !== undefined) {
1197
- throw new PmCliError('Action "adopt-all" does not accept a target argument.', EXIT_CODE.USAGE);
1182
+ const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
1183
+ warnings.push(...refreshedInstalled.warnings);
1184
+ const runtimeProbe = await probeRuntimeCommandPathsForInstall(resolvedRoots.pm_root, settings, refreshedInstalled.extensions, global);
1185
+ warnings.push(...runtimeProbe.warnings);
1186
+ // Scaffold the folders for any item types the installed package contributes
1187
+ // so the tracker is immediately healthy — matching `pm schema add-type` and
1188
+ // `pm profile apply`, the other paths that register a type. Without this a
1189
+ // freshly-installed schema package leaves a `missing_directory` health
1190
+ // warning until the first item of its type is created. Scoped to project
1191
+ // installs, where `pm_root` is unambiguously the tracker the type folders
1192
+ // belong to; a global install is not tied to one tracker, so its folders are
1193
+ // created lazily on first use in each project.
1194
+ const installedItemTypeDefinitions = runtimeProbe.item_type_registrations
1195
+ .filter((entry) => normalizeExtensionNameForMatch(entry.name) === normalizeExtensionNameForMatch(validated.manifest.name))
1196
+ .flatMap((entry) => entry.types.map((type) => ({ name: type.name, folder: type.folder })));
1197
+ if (scope === "project" && installedItemTypeDefinitions.length > 0) {
1198
+ await ensureTypeFolderScaffold(resolvedRoots.pm_root, installedItemTypeDefinitions, warnings, "install:type-folder");
1199
+ }
1200
+ const commandSummary = summarizeRuntimeCommandPathsForExtension(validated.manifest.name, runtimeProbe.installed);
1201
+ const installActivationFailure = findActivationFailureByName(validated.manifest.name, runtimeProbe.activation_failures, scope);
1202
+ const runtimeActivationStatus = resolveInstallRuntimeActivationStatus(validated.manifest.name, scope, runtimeProbe.installed, installActivationFailure);
1203
+ return withResult({
1204
+ extension: {
1205
+ name: validated.manifest.name,
1206
+ version: validated.manifest.version,
1207
+ entry: validated.manifest.entry,
1208
+ capabilities: validated.manifest.capabilities,
1209
+ directory: destinationDirectoryName,
1210
+ },
1211
+ source: sourceRecord,
1212
+ destination_path: destinationDirectory,
1213
+ overwritten: destinationExists && !installInPlace,
1214
+ installed_in_place: installInPlace,
1215
+ activated: true,
1216
+ settings_changed: activationChanged,
1217
+ runtime_activation_status: runtimeActivationStatus,
1218
+ command_paths: commandSummary.command_paths,
1219
+ action_paths: commandSummary.action_paths,
1220
+ command_discovery: buildInstallCommandDiscovery(validated.manifest.name, sourceRecord, commandSummary),
1221
+ activation_diagnostics: {
1222
+ failed_count: runtimeProbe.activation_failures.length,
1223
+ failed: runtimeProbe.activation_failures,
1224
+ installed_extension_failed: installActivationFailure ?? null,
1225
+ },
1226
+ });
1227
+ }
1228
+ async function runExtensionInstallAction(ctx) {
1229
+ const { action, normalizedTarget, resolvedRoots, warnings, options, global, withResult } = ctx;
1230
+ const githubOption = resolveGithubOption(options);
1231
+ const explicitSourceInput = githubOption ?? requireTarget(normalizedTarget, action, options);
1232
+ if (typeof githubOption !== "string" && isBundledPackageInstallAllTarget(explicitSourceInput)) {
1233
+ if (typeof options.ref === "string" && options.ref.trim().length > 0) {
1234
+ throw new PmCliError('Action "install all" does not accept --ref.', EXIT_CODE.USAGE);
1235
+ }
1236
+ const aliases = await listBundledPackageAliases();
1237
+ const packages = [];
1238
+ for (const alias of aliases) {
1239
+ packages.push({
1240
+ alias,
1241
+ result: await runExtension(alias, { ...options, install: true }, global),
1242
+ });
1198
1243
  }
1199
- const githubOption = resolveGithubOption(options);
1200
- if (githubOption !== undefined || (typeof options.ref === "string" && options.ref.trim().length > 0)) {
1201
- throw new PmCliError('Action "adopt-all" does not accept --gh/--github/--ref options.', EXIT_CODE.USAGE);
1244
+ for (const entry of packages) {
1245
+ warnings.push(...entry.result.warnings);
1202
1246
  }
1203
- const settings = await readSettings(resolvedRoots.settings_root);
1204
- const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1205
- warnings.push(...managedStateRead.warnings);
1206
- const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1207
- warnings.push(...installed.warnings);
1208
- const adoption = await adoptUnmanagedExtensions(resolvedRoots.selected_root, scope, installed.extensions, managedStateRead.state);
1209
- const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, adoption.state);
1210
- warnings.push(...refreshedInstalled.warnings);
1211
- const triage = buildExtensionTriageSummary(scope, warnings, refreshedInstalled.extensions, options);
1212
- warnings.push(...triage.warnings);
1213
- /* c8 ignore start -- refresh-entry optional metadata is display-only and exercised indirectly */
1214
- const adoptedDetails = adoption.adopted_entries.map((entry) => {
1215
- const refreshedEntry = refreshedInstalled.extensions.find((candidate) => normalizeExtensionNameForMatch(candidate.name) === normalizeExtensionNameForMatch(entry.name) &&
1216
- normalizeExtensionNameForMatch(candidate.directory) === normalizeExtensionNameForMatch(entry.directory)) ??
1217
- /* c8 ignore next 3 -- fallback only matters if a manifest renames between adopt and refresh */
1218
- refreshedInstalled.extensions.find((candidate) => normalizeExtensionNameForMatch(candidate.directory) === normalizeExtensionNameForMatch(entry.directory));
1219
- return {
1220
- ...entry,
1221
- update_check_status: refreshedEntry?.update_check_status ?? null,
1222
- update_check_reason: refreshedEntry?.update_check_reason ?? null,
1223
- };
1224
- });
1225
- /* c8 ignore stop */
1226
- /* c8 ignore start -- adopt-all summary booleans are deterministic mirrors of adoptedDetails length */
1227
1247
  return withResult({
1228
- adopted_all: adoptedDetails.length > 0,
1229
- adopted_count: adoptedDetails.length,
1230
- already_managed_count: adoption.already_managed_count,
1231
- extensions: adoptedDetails,
1232
- triage,
1233
- warning_codes: triage.warning_codes,
1234
- update_health_partial: triage.update_health_partial,
1235
- update_health_coverage: triage.update_health_coverage,
1248
+ installed_all: true,
1249
+ installed_count: packages.length,
1250
+ packages: packages.map((entry) => ({
1251
+ alias: entry.alias,
1252
+ ok: entry.result.ok,
1253
+ extension: entry.result.details.extension,
1254
+ source: entry.result.details.source,
1255
+ destination_path: entry.result.details.destination_path,
1256
+ activated: entry.result.details.activated,
1257
+ settings_changed: entry.result.details.settings_changed,
1258
+ command_paths: entry.result.details.command_paths,
1259
+ action_paths: entry.result.details.action_paths,
1260
+ command_discovery: entry.result.details.command_discovery,
1261
+ warnings: entry.result.warnings,
1262
+ })),
1236
1263
  });
1237
- /* c8 ignore stop */
1238
1264
  }
1239
- if (action === "adopt") {
1240
- const extensionTarget = requireTarget(normalizedTarget, action, options);
1241
- const githubOption = resolveGithubOption(options);
1242
- const settings = await readSettings(resolvedRoots.settings_root);
1243
- const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1244
- warnings.push(...managedStateRead.warnings);
1245
- const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1246
- warnings.push(...installed.warnings);
1247
- const candidate = await resolveInstalledExtensionCandidate(installed.extensions, extensionTarget);
1248
- if (!candidate) {
1249
- throw new PmCliError(`Installed extension "${extensionTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
1250
- }
1251
- if (candidate.managed) {
1252
- return withResult({
1253
- adopted: false,
1254
- already_managed: true,
1255
- extension: {
1256
- name: candidate.name,
1257
- directory: candidate.directory,
1258
- },
1259
- });
1265
+ /* c8 ignore start -- github/local alias-source split is exercised in install-action integration tests */
1266
+ const bundledAliasSource = typeof githubOption === "string" ? null : await resolveBundledExtensionAliasSource(explicitSourceInput);
1267
+ /* c8 ignore stop */
1268
+ const bundledAliasName = bundledAliasSource === null ? null : explicitSourceInput.trim().toLowerCase();
1269
+ const sourceInput = bundledAliasSource ?? explicitSourceInput;
1270
+ /* c8 ignore start -- install-source branch combinations are covered in install-sources focused tests */
1271
+ const installSource = parseExtensionInstallSource(sourceInput, {
1272
+ forceGithub: typeof githubOption === "string",
1273
+ ref: options.ref,
1274
+ });
1275
+ /* c8 ignore stop */
1276
+ const resolvedSource = await resolveInstallSource(installSource);
1277
+ try {
1278
+ const validated = await validateExtensionDirectory(resolvedSource.directory);
1279
+ const destinationDirectoryName = normalizeManagedDirectoryName(validated.manifest.name);
1280
+ return await withExtensionInstallLock(resolvedRoots.settings_root, destinationDirectoryName, () => performExtensionInstallUnderLock(ctx, {
1281
+ validated,
1282
+ destinationDirectoryName,
1283
+ bundledAliasName,
1284
+ installSource,
1285
+ resolvedSource,
1286
+ }));
1287
+ }
1288
+ finally {
1289
+ /* c8 ignore start -- cleanup hooks are only present for transient install sources */
1290
+ if (resolvedSource.cleanup) {
1291
+ await resolvedSource.cleanup();
1260
1292
  }
1261
- const extensionDirectory = path.join(resolvedRoots.selected_root, candidate.directory);
1262
- const validated = await validateExtensionDirectory(extensionDirectory);
1263
- const now = nowIso();
1264
- const sourceRecord = githubOption === undefined
1265
- ? {
1266
- kind: "local",
1267
- input: extensionTarget,
1268
- location: extensionDirectory,
1269
- }
1270
- : (() => {
1271
- const parsed = parseExtensionInstallSource(githubOption, {
1272
- forceGithub: true,
1273
- ref: options.ref,
1274
- });
1275
- /* c8 ignore start -- forceGithub guarantees a github-kind install source */
1276
- if (parsed.kind !== "github") {
1277
- throw new PmCliError(`Invalid GitHub shorthand "${githubOption}".`, EXIT_CODE.USAGE);
1278
- }
1279
- /* c8 ignore stop */
1280
- /* c8 ignore start -- github subpath defaults are validated in install-source parser tests */
1281
- return {
1282
- kind: "github",
1283
- input: parsed.input,
1284
- location: parsed.subpath ?? ".",
1285
- repository: parsed.repository,
1286
- owner: parsed.owner,
1287
- repo: parsed.repo,
1288
- ref: parsed.ref,
1289
- subpath: parsed.subpath,
1290
- };
1291
- /* c8 ignore stop */
1292
- })();
1293
- const managedState = upsertManagedEntry(managedStateRead.state, {
1294
- name: validated.manifest.name,
1295
- directory: candidate.directory,
1296
- scope,
1297
- manifest_version: validated.manifest.version,
1298
- manifest_entry: validated.manifest.entry,
1299
- capabilities: [...validated.manifest.capabilities],
1300
- installed_at: now,
1301
- updated_at: now,
1302
- source: sourceRecord,
1303
- });
1304
- await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
1305
- const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
1306
- warnings.push(...refreshedInstalled.warnings);
1307
- /* c8 ignore start -- fallback only matters if a manifest renames between adopt and refresh */
1308
- const refreshedEntry = refreshedInstalled.extensions.find((entry) => normalizeExtensionNameForMatch(entry.name) === normalizeExtensionNameForMatch(validated.manifest.name)) ??
1309
- refreshedInstalled.extensions.find((entry) => normalizeExtensionNameForMatch(entry.directory) === normalizeExtensionNameForMatch(candidate.directory));
1310
1293
  /* c8 ignore stop */
1311
- /* c8 ignore start -- adopt result mirrors refreshedEntry optionals for display only */
1312
- return withResult({
1313
- adopted: true,
1314
- extension: {
1315
- name: validated.manifest.name,
1316
- directory: candidate.directory,
1317
- version: validated.manifest.version,
1318
- entry: validated.manifest.entry,
1319
- },
1320
- source: sourceRecord,
1294
+ }
1295
+ }
1296
+ async function runExtensionAdoptAllAction(ctx) {
1297
+ const { normalizedTarget, scope, resolvedRoots, warnings, options, withResult } = ctx;
1298
+ if (normalizedTarget !== undefined) {
1299
+ throw new PmCliError('Action "adopt-all" does not accept a target argument.', EXIT_CODE.USAGE);
1300
+ }
1301
+ const githubOption = resolveGithubOption(options);
1302
+ if (githubOption !== undefined || (typeof options.ref === "string" && options.ref.trim().length > 0)) {
1303
+ throw new PmCliError('Action "adopt-all" does not accept --gh/--github/--ref options.', EXIT_CODE.USAGE);
1304
+ }
1305
+ const settings = await readSettings(resolvedRoots.settings_root);
1306
+ const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1307
+ warnings.push(...managedStateRead.warnings);
1308
+ const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1309
+ warnings.push(...installed.warnings);
1310
+ const adoption = await adoptUnmanagedExtensions(resolvedRoots.selected_root, scope, installed.extensions, managedStateRead.state);
1311
+ const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, adoption.state);
1312
+ warnings.push(...refreshedInstalled.warnings);
1313
+ const triage = buildExtensionTriageSummary(scope, warnings, refreshedInstalled.extensions, options);
1314
+ warnings.push(...triage.warnings);
1315
+ /* c8 ignore start -- refresh-entry optional metadata is display-only and exercised indirectly */
1316
+ const adoptedDetails = adoption.adopted_entries.map((entry) => {
1317
+ const refreshedEntry = refreshedInstalled.extensions.find((candidate) => normalizeExtensionNameForMatch(candidate.name) === normalizeExtensionNameForMatch(entry.name) &&
1318
+ normalizeExtensionNameForMatch(candidate.directory) === normalizeExtensionNameForMatch(entry.directory)) ??
1319
+ /* c8 ignore next 3 -- fallback only matters if a manifest renames between adopt and refresh */
1320
+ refreshedInstalled.extensions.find((candidate) => normalizeExtensionNameForMatch(candidate.directory) === normalizeExtensionNameForMatch(entry.directory));
1321
+ return {
1322
+ ...entry,
1321
1323
  update_check_status: refreshedEntry?.update_check_status ?? null,
1322
1324
  update_check_reason: refreshedEntry?.update_check_reason ?? null,
1323
- });
1324
- /* c8 ignore stop */
1325
- }
1326
- if (action === "uninstall") {
1327
- const extensionTarget = requireTarget(normalizedTarget, action, options);
1328
- const settings = await readSettings(resolvedRoots.settings_root);
1329
- const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1330
- warnings.push(...managedStateRead.warnings);
1331
- const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1332
- warnings.push(...installed.warnings);
1333
- const candidate = await resolveInstalledExtensionCandidate(installed.extensions, extensionTarget);
1334
- if (!candidate) {
1335
- throw new PmCliError(`Installed extension "${extensionTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
1336
- }
1337
- const destinationDirectory = path.join(resolvedRoots.selected_root, candidate.directory);
1338
- await fs.rm(destinationDirectory, { recursive: true, force: true });
1339
- const updatedState = {
1340
- ...managedStateRead.state,
1341
- updated_at: nowIso(),
1342
- /* c8 ignore start -- uninstall filter keeps both name+directory guards for legacy managed-state migrations */
1343
- entries: managedStateRead.state.entries.filter((entry) => normalizeExtensionNameForMatch(entry.name) !== normalizeExtensionNameForMatch(candidate.name) &&
1344
- normalizeExtensionNameForMatch(entry.directory) !== normalizeExtensionNameForMatch(candidate.directory)),
1345
- /* c8 ignore stop */
1346
1325
  };
1347
- await writeManagedExtensionState(resolvedRoots.selected_root, updatedState);
1348
- const stateChanged = clearExtensionState(settings, candidate.name);
1349
- if (stateChanged) {
1350
- await writeSettings(resolvedRoots.settings_root, settings, "settings:write");
1351
- }
1326
+ });
1327
+ /* c8 ignore stop */
1328
+ /* c8 ignore start -- adopt-all summary booleans are deterministic mirrors of adoptedDetails length */
1329
+ return withResult({
1330
+ adopted_all: adoptedDetails.length > 0,
1331
+ adopted_count: adoptedDetails.length,
1332
+ already_managed_count: adoption.already_managed_count,
1333
+ extensions: adoptedDetails,
1334
+ triage,
1335
+ warning_codes: triage.warning_codes,
1336
+ update_health_partial: triage.update_health_partial,
1337
+ update_health_coverage: triage.update_health_coverage,
1338
+ });
1339
+ /* c8 ignore stop */
1340
+ }
1341
+ async function runExtensionAdoptAction(ctx) {
1342
+ const { action, normalizedTarget, scope, resolvedRoots, warnings, options, withResult } = ctx;
1343
+ const extensionTarget = requireTarget(normalizedTarget, action, options);
1344
+ const githubOption = resolveGithubOption(options);
1345
+ const settings = await readSettings(resolvedRoots.settings_root);
1346
+ const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1347
+ warnings.push(...managedStateRead.warnings);
1348
+ const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1349
+ warnings.push(...installed.warnings);
1350
+ const candidate = await resolveInstalledExtensionCandidate(installed.extensions, extensionTarget);
1351
+ if (!candidate) {
1352
+ throw new PmCliError(`Installed extension "${extensionTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
1353
+ }
1354
+ if (candidate.managed) {
1352
1355
  return withResult({
1353
- removed: true,
1356
+ adopted: false,
1357
+ already_managed: true,
1354
1358
  extension: {
1355
1359
  name: candidate.name,
1356
1360
  directory: candidate.directory,
1357
1361
  },
1358
- destination_path: destinationDirectory,
1359
- settings_changed: stateChanged,
1360
1362
  });
1361
1363
  }
1362
- if (action === "activate" || action === "deactivate") {
1363
- const extensionTarget = requireTarget(normalizedTarget, action, options);
1364
- const settings = await readSettings(resolvedRoots.settings_root);
1365
- const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1366
- warnings.push(...managedStateRead.warnings);
1367
- const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1368
- warnings.push(...installed.warnings);
1369
- const candidate = await resolveInstalledExtensionCandidate(installed.extensions, extensionTarget);
1370
- if (!candidate) {
1371
- throw new PmCliError(`Installed extension "${extensionTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
1372
- }
1373
- const settingsChanged = action === "activate" ? ensureActivated(settings, candidate.name) : ensureDeactivated(settings, candidate.name);
1374
- if (settingsChanged) {
1375
- await writeSettings(resolvedRoots.settings_root, settings, "settings:write");
1364
+ const extensionDirectory = path.join(resolvedRoots.selected_root, candidate.directory);
1365
+ const validated = await validateExtensionDirectory(extensionDirectory);
1366
+ const now = nowIso();
1367
+ const sourceRecord = githubOption === undefined
1368
+ ? {
1369
+ kind: "local",
1370
+ input: extensionTarget,
1371
+ location: extensionDirectory,
1376
1372
  }
1377
- return withResult({
1378
- extension: {
1379
- name: candidate.name,
1380
- directory: candidate.directory,
1373
+ : (() => {
1374
+ const parsed = parseExtensionInstallSource(githubOption, {
1375
+ forceGithub: true,
1376
+ ref: options.ref,
1377
+ });
1378
+ /* c8 ignore start -- forceGithub guarantees a github-kind install source */
1379
+ if (parsed.kind !== "github") {
1380
+ throw new PmCliError(`Invalid GitHub shorthand "${githubOption}".`, EXIT_CODE.USAGE);
1381
+ }
1382
+ /* c8 ignore stop */
1383
+ /* c8 ignore start -- github subpath defaults are validated in install-source parser tests */
1384
+ return {
1385
+ kind: "github",
1386
+ input: parsed.input,
1387
+ location: parsed.subpath ?? ".",
1388
+ repository: parsed.repository,
1389
+ owner: parsed.owner,
1390
+ repo: parsed.repo,
1391
+ ref: parsed.ref,
1392
+ subpath: parsed.subpath,
1393
+ };
1394
+ /* c8 ignore stop */
1395
+ })();
1396
+ const managedState = upsertManagedEntry(managedStateRead.state, {
1397
+ name: validated.manifest.name,
1398
+ directory: candidate.directory,
1399
+ scope,
1400
+ manifest_version: validated.manifest.version,
1401
+ manifest_entry: validated.manifest.entry,
1402
+ capabilities: [...validated.manifest.capabilities],
1403
+ installed_at: now,
1404
+ updated_at: now,
1405
+ source: sourceRecord,
1406
+ });
1407
+ await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
1408
+ const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
1409
+ warnings.push(...refreshedInstalled.warnings);
1410
+ /* c8 ignore start -- fallback only matters if a manifest renames between adopt and refresh */
1411
+ const refreshedEntry = refreshedInstalled.extensions.find((entry) => normalizeExtensionNameForMatch(entry.name) === normalizeExtensionNameForMatch(validated.manifest.name)) ??
1412
+ refreshedInstalled.extensions.find((entry) => normalizeExtensionNameForMatch(entry.directory) === normalizeExtensionNameForMatch(candidate.directory));
1413
+ /* c8 ignore stop */
1414
+ /* c8 ignore start -- adopt result mirrors refreshedEntry optionals for display only */
1415
+ return withResult({
1416
+ adopted: true,
1417
+ extension: {
1418
+ name: validated.manifest.name,
1419
+ directory: candidate.directory,
1420
+ version: validated.manifest.version,
1421
+ entry: validated.manifest.entry,
1422
+ },
1423
+ source: sourceRecord,
1424
+ update_check_status: refreshedEntry?.update_check_status ?? null,
1425
+ update_check_reason: refreshedEntry?.update_check_reason ?? null,
1426
+ });
1427
+ /* c8 ignore stop */
1428
+ }
1429
+ async function runExtensionUninstallAction(ctx) {
1430
+ const { action, normalizedTarget, scope, resolvedRoots, warnings, options, withResult } = ctx;
1431
+ const extensionTarget = requireTarget(normalizedTarget, action, options);
1432
+ const settings = await readSettings(resolvedRoots.settings_root);
1433
+ const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1434
+ warnings.push(...managedStateRead.warnings);
1435
+ const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1436
+ warnings.push(...installed.warnings);
1437
+ const candidate = await resolveInstalledExtensionCandidate(installed.extensions, extensionTarget);
1438
+ if (!candidate) {
1439
+ throw new PmCliError(`Installed extension "${extensionTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
1440
+ }
1441
+ const destinationDirectory = path.join(resolvedRoots.selected_root, candidate.directory);
1442
+ await fs.rm(destinationDirectory, { recursive: true, force: true });
1443
+ const updatedState = {
1444
+ ...managedStateRead.state,
1445
+ updated_at: nowIso(),
1446
+ /* c8 ignore start -- uninstall filter keeps both name+directory guards for legacy managed-state migrations */
1447
+ entries: managedStateRead.state.entries.filter((entry) => normalizeExtensionNameForMatch(entry.name) !== normalizeExtensionNameForMatch(candidate.name) &&
1448
+ normalizeExtensionNameForMatch(entry.directory) !== normalizeExtensionNameForMatch(candidate.directory)),
1449
+ /* c8 ignore stop */
1450
+ };
1451
+ await writeManagedExtensionState(resolvedRoots.selected_root, updatedState);
1452
+ const stateChanged = clearExtensionState(settings, candidate.name);
1453
+ if (stateChanged) {
1454
+ await writeSettings(resolvedRoots.settings_root, settings, "settings:write");
1455
+ }
1456
+ return withResult({
1457
+ removed: true,
1458
+ extension: {
1459
+ name: candidate.name,
1460
+ directory: candidate.directory,
1461
+ },
1462
+ destination_path: destinationDirectory,
1463
+ settings_changed: stateChanged,
1464
+ });
1465
+ }
1466
+ async function runExtensionActivateDeactivateAction(ctx) {
1467
+ const { action, normalizedTarget, scope, resolvedRoots, warnings, options, withResult } = ctx;
1468
+ const extensionTarget = requireTarget(normalizedTarget, action, options);
1469
+ const settings = await readSettings(resolvedRoots.settings_root);
1470
+ const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1471
+ warnings.push(...managedStateRead.warnings);
1472
+ const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1473
+ warnings.push(...installed.warnings);
1474
+ const candidate = await resolveInstalledExtensionCandidate(installed.extensions, extensionTarget);
1475
+ if (!candidate) {
1476
+ throw new PmCliError(`Installed extension "${extensionTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
1477
+ }
1478
+ const settingsChanged = action === "activate" ? ensureActivated(settings, candidate.name) : ensureDeactivated(settings, candidate.name);
1479
+ if (settingsChanged) {
1480
+ await writeSettings(resolvedRoots.settings_root, settings, "settings:write");
1481
+ }
1482
+ return withResult({
1483
+ extension: {
1484
+ name: candidate.name,
1485
+ directory: candidate.directory,
1486
+ },
1487
+ active: action === "activate",
1488
+ settings_changed: settingsChanged,
1489
+ settings: {
1490
+ enabled: [...settings.extensions.enabled],
1491
+ disabled: [...settings.extensions.disabled],
1492
+ },
1493
+ });
1494
+ }
1495
+ /**
1496
+ * Assemble the doctor remediation hints: the triage remediations, vocabulary-aware
1497
+ * advice to inspect load failures and activation failures, and a note when a
1498
+ * managed-state fix adopted entries. Blank entries are trimmed and the list is
1499
+ * de-duplicated.
1500
+ */
1501
+ function buildDoctorRemediation(baseRemediation, loadFailureCount, activationFailureCount, vocabulary, managedStateFix) {
1502
+ return [
1503
+ ...new Set([
1504
+ ...baseRemediation,
1505
+ /* c8 ignore start -- vocabulary-specific remediation branches are copy-only variants */
1506
+ ...(loadFailureCount > 0
1507
+ ? [
1508
+ vocabulary === "package"
1509
+ ? "Run pm package explore --project and pm package explore --global to inspect load failures."
1510
+ : "Run pm extension --explore --project and pm extension --explore --global to inspect load failures.",
1511
+ ]
1512
+ : []),
1513
+ ...(activationFailureCount > 0
1514
+ ? [
1515
+ vocabulary === "package"
1516
+ ? "Review activation failures in pm package doctor --detail deep output."
1517
+ : "Review activation failures in pm extension --doctor --detail deep output.",
1518
+ ]
1519
+ : []),
1520
+ /* c8 ignore stop */
1521
+ ...(managedStateFix && managedStateFix.adopted_entries.length > 0
1522
+ ? [`Managed-state fix adopted ${managedStateFix.adopted_entries.length} extension(s).`]
1523
+ : []),
1524
+ ].map((entry) => entry.trim()).filter((entry) => entry.length > 0)),
1525
+ ];
1526
+ }
1527
+ async function runExtensionDoctorAction(ctx) {
1528
+ const { normalizedTarget, scope, resolvedRoots, warnings, options, global, withResult } = ctx;
1529
+ if (normalizedTarget && normalizedTarget.trim().length > 0) {
1530
+ throw new PmCliError('Action "doctor" does not accept a target argument.', EXIT_CODE.USAGE);
1531
+ }
1532
+ const detailMode = parseDoctorDetailMode(options.detail);
1533
+ const includeTrace = options.trace === true;
1534
+ if (includeTrace && detailMode !== "deep") {
1535
+ throw new PmCliError("--trace requires --detail deep with --doctor.", EXIT_CODE.USAGE);
1536
+ }
1537
+ const settings = await readSettings(resolvedRoots.settings_root);
1538
+ const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1539
+ warnings.push(...managedStateRead.warnings);
1540
+ const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1541
+ warnings.push(...installed.warnings);
1542
+ let managedState = managedStateRead.state;
1543
+ const managedStateFix = options.fixManagedState === true
1544
+ ? await adoptUnmanagedExtensions(resolvedRoots.selected_root, scope, installed.extensions, managedStateRead.state)
1545
+ : null;
1546
+ if (managedStateFix) {
1547
+ managedState = managedStateFix.state;
1548
+ }
1549
+ const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
1550
+ warnings.push(...refreshedInstalled.warnings);
1551
+ const loadResult = await loadExtensions({
1552
+ pmRoot: resolvedRoots.pm_root,
1553
+ settings,
1554
+ cwd: process.cwd(),
1555
+ noExtensions: global.noExtensions === true,
1556
+ });
1557
+ const activationResult = await activateExtensions({
1558
+ ...loadResult,
1559
+ loaded: loadResult.loaded,
1560
+ });
1561
+ warnings.push(...loadResult.warnings);
1562
+ warnings.push(...classifyDoctorLoadFailureWarnings(loadResult.failed));
1563
+ warnings.push(...activationResult.warnings);
1564
+ warnings.push(...classifyDoctorActivationFailureWarnings(activationResult.failed));
1565
+ warnings.push(...classifyUnusedCapabilityWarnings(loadResult, activationResult));
1566
+ warnings.push(...collectGlobalOutputOverrideDoctorWarnings(activationResult));
1567
+ warnings.push(...collectSchemaNarrowActivationDoctorWarnings(loadResult, activationResult));
1568
+ const runtimeInstalledExtensions = applyDoctorRuntimeActivationState(refreshedInstalled.extensions, loadResult, activationResult);
1569
+ const doctorConsistency = buildDoctorConsistencySummary(scope, runtimeInstalledExtensions, loadResult.loaded.map((entry) => ({ layer: entry.layer, name: entry.name })), loadResult.failed.map((entry) => ({ name: entry.name })), loadResult.disabled_by_flag);
1570
+ warnings.push(...doctorConsistency.warnings);
1571
+ const updateCheckWarnings = runtimeInstalledExtensions
1572
+ .filter((entry) => entry.update_check_status === "failed")
1573
+ .map((entry) => `extension_update_check_failed:${entry.name}`);
1574
+ warnings.push(...updateCheckWarnings);
1575
+ const triage = buildExtensionTriageSummary(scope, warnings, runtimeInstalledExtensions, options);
1576
+ warnings.push(...triage.warnings);
1577
+ const normalizedWarnings = [...triage.warnings];
1578
+ const policySummary = {
1579
+ mode: loadResult.policy.mode,
1580
+ trust_mode: loadResult.policy.trust_mode,
1581
+ require_provenance: loadResult.policy.require_provenance,
1582
+ default_sandbox_profile: loadResult.policy.default_sandbox_profile,
1583
+ // Honest trust model (ADR pm-6ef3): keep this caveat to one concise line.
1584
+ sandbox_enforcement: "advisory: sandbox_profile/permissions are declaration-based load gates, not runtime isolation (ADR pm-6ef3)",
1585
+ trusted_extensions_count: loadResult.policy.trusted_extensions.length,
1586
+ allowed_extensions_count: loadResult.policy.allowed_extensions.length,
1587
+ blocked_extensions_count: loadResult.policy.blocked_extensions.length,
1588
+ allowed_capabilities_count: loadResult.policy.allowed_capabilities.length,
1589
+ blocked_capabilities_count: loadResult.policy.blocked_capabilities.length,
1590
+ allowed_surfaces_count: loadResult.policy.allowed_surfaces.length,
1591
+ blocked_surfaces_count: loadResult.policy.blocked_surfaces.length,
1592
+ allowed_commands_count: loadResult.policy.allowed_commands.length,
1593
+ blocked_commands_count: loadResult.policy.blocked_commands.length,
1594
+ allowed_actions_count: loadResult.policy.allowed_actions.length,
1595
+ blocked_actions_count: loadResult.policy.blocked_actions.length,
1596
+ allowed_services_count: loadResult.policy.allowed_services.length,
1597
+ blocked_services_count: loadResult.policy.blocked_services.length,
1598
+ extension_override_count: loadResult.policy.extension_overrides.length,
1599
+ };
1600
+ const capabilityGuidance = collectUnknownCapabilityGuidance(normalizedWarnings);
1601
+ const capabilityContract = buildCapabilityContractMetadata();
1602
+ const warningCodes = triage.warning_codes;
1603
+ const remediation = buildDoctorRemediation(triage.remediation, loadResult.failed.length, activationResult.failed.length, options.vocabulary, managedStateFix);
1604
+ const summary = {
1605
+ status: triage.status,
1606
+ scope,
1607
+ warning_count: triage.warning_count,
1608
+ warning_codes: warningCodes,
1609
+ total_extensions: runtimeInstalledExtensions.length,
1610
+ managed_total: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
1611
+ enabled_total: runtimeInstalledExtensions.filter((entry) => entry.enabled).length,
1612
+ active_total: runtimeInstalledExtensions.filter((entry) => entry.active).length,
1613
+ unmanaged_loaded_extension_count: triage.unmanaged_loaded_extension_count,
1614
+ unmanaged_action_required_extension_count: triage.unmanaged_action_required_extension_count,
1615
+ unmanaged_expected_extension_count: triage.unmanaged_expected_extension_count,
1616
+ runtime_active_total: runtimeInstalledExtensions.filter((entry) => entry.runtime_active === true).length,
1617
+ activation_status_totals: {
1618
+ ok: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "ok").length,
1619
+ failed: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "failed").length,
1620
+ not_loaded: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "not_loaded").length,
1621
+ unknown: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "unknown").length,
1622
+ },
1623
+ unknown_capability_count: capabilityGuidance.length,
1624
+ capability_contract_version: capabilityContract.version,
1625
+ update_available_total: runtimeInstalledExtensions.filter((entry) => entry.update_available === true).length,
1626
+ update_health_coverage: triage.update_health_coverage,
1627
+ update_health_partial: triage.update_health_partial,
1628
+ update_check_failed_total: runtimeInstalledExtensions.filter((entry) => entry.update_check_status === "failed").length,
1629
+ load_failure_count: loadResult.failed.length,
1630
+ activation_failure_count: activationResult.failed.length,
1631
+ blocking_failure_count: loadResult.failed.length + activationResult.failed.length,
1632
+ has_blocking_failures: loadResult.failed.length + activationResult.failed.length > 0,
1633
+ consistency_warning_count: doctorConsistency.warnings.length,
1634
+ trace_enabled: includeTrace,
1635
+ policy: policySummary,
1636
+ remediation,
1637
+ };
1638
+ const managedStateFixSummary = managedStateFix
1639
+ ? {
1640
+ requested: true,
1641
+ applied: managedStateFix.adopted_entries.length > 0,
1642
+ adopted_count: managedStateFix.adopted_entries.length,
1643
+ already_managed_count: managedStateFix.already_managed_count,
1644
+ adopted_extensions: managedStateFix.adopted_entries.map((entry) => entry.name),
1645
+ }
1646
+ : {
1647
+ requested: false,
1648
+ applied: false,
1649
+ adopted_count: 0,
1650
+ already_managed_count: refreshedInstalled.extensions.filter((entry) => entry.managed).length,
1651
+ adopted_extensions: [],
1652
+ };
1653
+ const details = {
1654
+ mode: detailMode,
1655
+ summary,
1656
+ triage,
1657
+ trace_enabled: includeTrace,
1658
+ capability_contract: capabilityContract,
1659
+ capability_guidance: capabilityGuidance,
1660
+ managed_state_fix: managedStateFixSummary,
1661
+ policy: loadResult.policy,
1662
+ };
1663
+ if (detailMode === "deep") {
1664
+ const activationFailedDetails = includeTrace
1665
+ ? activationResult.failed
1666
+ : activationResult.failed.map((entry) => {
1667
+ const { trace: _trace, ...rest } = entry;
1668
+ return rest;
1669
+ });
1670
+ details.deep = {
1671
+ warnings: normalizedWarnings,
1672
+ warning_codes: warningCodes,
1673
+ capability_contract: capabilityContract,
1674
+ capability_guidance: capabilityGuidance,
1675
+ trace_enabled: includeTrace,
1676
+ managed_state: {
1677
+ path: managedStateRead.path,
1678
+ count: managedState.entries.length,
1679
+ entries: managedState.entries,
1381
1680
  },
1382
- active: action === "activate",
1383
- settings_changed: settingsChanged,
1384
- settings: {
1385
- enabled: [...settings.extensions.enabled],
1386
- disabled: [...settings.extensions.disabled],
1681
+ installed_extensions: runtimeInstalledExtensions,
1682
+ load: {
1683
+ roots: loadResult.roots,
1684
+ policy: loadResult.policy,
1685
+ warnings: loadResult.warnings,
1686
+ failed: loadResult.failed,
1687
+ loaded: loadResult.loaded.map((entry) => ({
1688
+ layer: entry.layer,
1689
+ directory: entry.directory,
1690
+ name: entry.name,
1691
+ version: entry.version,
1692
+ entry: entry.entry,
1693
+ priority: entry.priority,
1694
+ })),
1387
1695
  },
1388
- });
1389
- }
1390
- if (action === "doctor") {
1391
- if (normalizedTarget && normalizedTarget.trim().length > 0) {
1392
- throw new PmCliError('Action "doctor" does not accept a target argument.', EXIT_CODE.USAGE);
1393
- }
1394
- const detailMode = parseDoctorDetailMode(options.detail);
1395
- const includeTrace = options.trace === true;
1396
- if (includeTrace && detailMode !== "deep") {
1397
- throw new PmCliError("--trace requires --detail deep with --doctor.", EXIT_CODE.USAGE);
1398
- }
1399
- const settings = await readSettings(resolvedRoots.settings_root);
1400
- const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1401
- warnings.push(...managedStateRead.warnings);
1402
- const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1403
- warnings.push(...installed.warnings);
1404
- let managedState = managedStateRead.state;
1405
- const managedStateFix = options.fixManagedState === true
1406
- ? await adoptUnmanagedExtensions(resolvedRoots.selected_root, scope, installed.extensions, managedStateRead.state)
1407
- : null;
1408
- if (managedStateFix) {
1409
- managedState = managedStateFix.state;
1696
+ activation: {
1697
+ failed: activationFailedDetails,
1698
+ warnings: activationResult.warnings,
1699
+ hook_counts: activationResult.hook_counts,
1700
+ registration_counts: activationResult.registration_counts,
1701
+ parser_override_count: activationResult.parser_override_count,
1702
+ preflight_override_count: activationResult.preflight_override_count,
1703
+ service_override_count: activationResult.service_override_count,
1704
+ renderer_override_count: activationResult.renderer_override_count,
1705
+ },
1706
+ consistency: doctorConsistency.summary,
1707
+ };
1708
+ if (includeTrace) {
1709
+ details.deep.trace = {
1710
+ activation_failures: activationResult.failed
1711
+ .filter((entry) => entry.trace !== undefined)
1712
+ .map((entry) => ({
1713
+ layer: entry.layer,
1714
+ name: entry.name,
1715
+ entry_path: entry.entry_path,
1716
+ error: entry.error,
1717
+ method: entry.trace?.method,
1718
+ command: entry.trace?.command,
1719
+ capability: entry.trace?.capability,
1720
+ missing_capability: entry.trace?.missing_capability,
1721
+ registration_index: entry.trace?.registration_index,
1722
+ expected_schema: entry.trace?.expected_schema,
1723
+ hint: entry.trace?.hint,
1724
+ received: entry.trace?.received,
1725
+ })),
1726
+ };
1410
1727
  }
1411
- const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
1412
- warnings.push(...refreshedInstalled.warnings);
1728
+ }
1729
+ return withResult(details);
1730
+ }
1731
+ async function runExtensionDescribeAction(ctx) {
1732
+ const { normalizedTarget, scope, resolvedRoots, warnings, options, global, withResult } = ctx;
1733
+ const settings = await readSettings(resolvedRoots.settings_root);
1734
+ const loadResult = await loadExtensions({
1735
+ pmRoot: resolvedRoots.pm_root,
1736
+ settings,
1737
+ cwd: process.cwd(),
1738
+ noExtensions: global.noExtensions === true,
1739
+ });
1740
+ const activationResult = await activateExtensions(loadResult);
1741
+ warnings.push(...loadResult.warnings);
1742
+ warnings.push(...activationResult.warnings);
1743
+ const describeResult = buildExtensionDescribeResult(normalizedTarget, loadResult, activationResult);
1744
+ if (normalizedTarget !== undefined && describeResult.extensions.length === 0) {
1745
+ const noun = options.vocabulary === "package" ? "package" : "extension";
1746
+ throw new PmCliError(`No loaded ${noun} named "${normalizedTarget}" was found in ${scope} scope. Run pm ${noun} explore to list discovered ${noun}s.`, EXIT_CODE.NOT_FOUND);
1747
+ }
1748
+ return withResult({
1749
+ target: describeResult.target,
1750
+ total: describeResult.total,
1751
+ extensions: describeResult.extensions,
1752
+ union: describeResult.union,
1753
+ });
1754
+ }
1755
+ /* c8 ignore start -- explore/manage action split is validated by dedicated command-action tests */
1756
+ async function runExtensionExploreManageAction(ctx) {
1757
+ const { action, scope, resolvedRoots, warnings, options, global, withResult } = ctx;
1758
+ const settings = await readSettings(resolvedRoots.settings_root);
1759
+ const configuredPolicy = buildExtensionPolicyDetails(settings.extensions.policy);
1760
+ const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1761
+ warnings.push(...managedStateRead.warnings);
1762
+ const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1763
+ warnings.push(...installed.warnings);
1764
+ let managedState = managedStateRead.state;
1765
+ const managedStateFix = action === "manage" && options.fixManagedState === true
1766
+ ? await adoptUnmanagedExtensions(resolvedRoots.selected_root, scope, installed.extensions, managedStateRead.state)
1767
+ : null;
1768
+ if (managedStateFix) {
1769
+ managedState = managedStateFix.state;
1770
+ }
1771
+ if (action === "manage") {
1772
+ const updates = await Promise.all(managedState.entries.map(async (entry) => {
1773
+ if (entry.source.kind !== "github") {
1774
+ return entry;
1775
+ }
1776
+ const updateStatus = await checkGithubUpdate(entry.source);
1777
+ return {
1778
+ ...entry,
1779
+ last_update_check_at: updateStatus.checked_at,
1780
+ last_update_remote_commit: updateStatus.remote_commit,
1781
+ update_available: updateStatus.available,
1782
+ update_error: updateStatus.error,
1783
+ };
1784
+ }));
1785
+ managedState = {
1786
+ ...managedState,
1787
+ updated_at: nowIso(),
1788
+ entries: sortManagedEntries(updates),
1789
+ };
1790
+ await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
1791
+ }
1792
+ const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
1793
+ warnings.push(...refreshedInstalled.warnings);
1794
+ if (action === "manage") {
1795
+ const updateWarnings = refreshedInstalled.extensions
1796
+ .filter((entry) => entry.update_check_status === "failed")
1797
+ .map((entry) => `extension_update_check_failed:${entry.name}`);
1798
+ warnings.push(...updateWarnings);
1799
+ }
1800
+ let runtimeProbeSummary;
1801
+ let runtimeInstalledExtensions = refreshedInstalled.extensions;
1802
+ let runtimeActivationFailures;
1803
+ if (action === "explore" || options.runtimeProbe === true) {
1413
1804
  const loadResult = await loadExtensions({
1414
1805
  pmRoot: resolvedRoots.pm_root,
1415
1806
  settings,
@@ -1421,345 +1812,86 @@ export async function runExtension(target, options, global) {
1421
1812
  loaded: loadResult.loaded,
1422
1813
  });
1423
1814
  warnings.push(...loadResult.warnings);
1424
- warnings.push(...classifyDoctorLoadFailureWarnings(loadResult.failed));
1425
1815
  warnings.push(...activationResult.warnings);
1426
- warnings.push(...classifyDoctorActivationFailureWarnings(activationResult.failed));
1427
- warnings.push(...classifyUnusedCapabilityWarnings(loadResult, activationResult));
1428
- warnings.push(...collectGlobalOutputOverrideDoctorWarnings(activationResult));
1429
- warnings.push(...collectSchemaNarrowActivationDoctorWarnings(loadResult, activationResult));
1430
- const runtimeInstalledExtensions = applyDoctorRuntimeActivationState(refreshedInstalled.extensions, loadResult, activationResult);
1431
- const doctorConsistency = buildDoctorConsistencySummary(scope, runtimeInstalledExtensions, loadResult.loaded.map((entry) => ({ layer: entry.layer, name: entry.name })), loadResult.failed.map((entry) => ({ name: entry.name })), loadResult.disabled_by_flag);
1432
- warnings.push(...doctorConsistency.warnings);
1433
- const updateCheckWarnings = runtimeInstalledExtensions
1434
- .filter((entry) => entry.update_check_status === "failed")
1435
- .map((entry) => `extension_update_check_failed:${entry.name}`);
1436
- warnings.push(...updateCheckWarnings);
1437
- const triage = buildExtensionTriageSummary(scope, warnings, runtimeInstalledExtensions, options);
1438
- warnings.push(...triage.warnings);
1439
- const normalizedWarnings = [...triage.warnings];
1440
- const policySummary = {
1441
- mode: loadResult.policy.mode,
1442
- trust_mode: loadResult.policy.trust_mode,
1443
- require_provenance: loadResult.policy.require_provenance,
1444
- default_sandbox_profile: loadResult.policy.default_sandbox_profile,
1445
- // Honest trust model (ADR pm-6ef3): keep this caveat to one concise line.
1446
- sandbox_enforcement: "advisory: sandbox_profile/permissions are declaration-based load gates, not runtime isolation (ADR pm-6ef3)",
1447
- trusted_extensions_count: loadResult.policy.trusted_extensions.length,
1448
- allowed_extensions_count: loadResult.policy.allowed_extensions.length,
1449
- blocked_extensions_count: loadResult.policy.blocked_extensions.length,
1450
- allowed_capabilities_count: loadResult.policy.allowed_capabilities.length,
1451
- blocked_capabilities_count: loadResult.policy.blocked_capabilities.length,
1452
- allowed_surfaces_count: loadResult.policy.allowed_surfaces.length,
1453
- blocked_surfaces_count: loadResult.policy.blocked_surfaces.length,
1454
- allowed_commands_count: loadResult.policy.allowed_commands.length,
1455
- blocked_commands_count: loadResult.policy.blocked_commands.length,
1456
- allowed_actions_count: loadResult.policy.allowed_actions.length,
1457
- blocked_actions_count: loadResult.policy.blocked_actions.length,
1458
- allowed_services_count: loadResult.policy.allowed_services.length,
1459
- blocked_services_count: loadResult.policy.blocked_services.length,
1460
- extension_override_count: loadResult.policy.extension_overrides.length,
1461
- };
1462
- const capabilityGuidance = collectUnknownCapabilityGuidance(normalizedWarnings);
1463
- const capabilityContract = buildCapabilityContractMetadata();
1464
- const warningCodes = triage.warning_codes;
1465
- const remediation = [
1466
- ...new Set([
1467
- ...triage.remediation,
1468
- /* c8 ignore start -- vocabulary-specific remediation branches are copy-only variants */
1469
- ...(loadResult.failed.length > 0
1470
- ? [
1471
- options.vocabulary === "package"
1472
- ? "Run pm package explore --project and pm package explore --global to inspect load failures."
1473
- : "Run pm extension --explore --project and pm extension --explore --global to inspect load failures.",
1474
- ]
1475
- : []),
1476
- ...(activationResult.failed.length > 0
1477
- ? [
1478
- options.vocabulary === "package"
1479
- ? "Review activation failures in pm package doctor --detail deep output."
1480
- : "Review activation failures in pm extension --doctor --detail deep output.",
1481
- ]
1482
- : []),
1483
- /* c8 ignore stop */
1484
- ...(managedStateFix && managedStateFix.adopted_entries.length > 0
1485
- ? [`Managed-state fix adopted ${managedStateFix.adopted_entries.length} extension(s).`]
1486
- : []),
1487
- ].map((entry) => entry.trim()).filter((entry) => entry.length > 0)),
1488
- ];
1489
- const summary = {
1490
- status: triage.status,
1491
- scope,
1492
- warning_count: triage.warning_count,
1493
- warning_codes: warningCodes,
1494
- total_extensions: runtimeInstalledExtensions.length,
1495
- managed_total: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
1496
- enabled_total: runtimeInstalledExtensions.filter((entry) => entry.enabled).length,
1497
- active_total: runtimeInstalledExtensions.filter((entry) => entry.active).length,
1498
- unmanaged_loaded_extension_count: triage.unmanaged_loaded_extension_count,
1499
- unmanaged_action_required_extension_count: triage.unmanaged_action_required_extension_count,
1500
- unmanaged_expected_extension_count: triage.unmanaged_expected_extension_count,
1501
- runtime_active_total: runtimeInstalledExtensions.filter((entry) => entry.runtime_active === true).length,
1502
- activation_status_totals: {
1503
- ok: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "ok").length,
1504
- failed: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "failed").length,
1505
- not_loaded: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "not_loaded").length,
1506
- unknown: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "unknown").length,
1507
- },
1508
- unknown_capability_count: capabilityGuidance.length,
1509
- capability_contract_version: capabilityContract.version,
1510
- update_available_total: runtimeInstalledExtensions.filter((entry) => entry.update_available === true).length,
1511
- update_health_coverage: triage.update_health_coverage,
1512
- update_health_partial: triage.update_health_partial,
1513
- update_check_failed_total: runtimeInstalledExtensions.filter((entry) => entry.update_check_status === "failed").length,
1816
+ runtimeInstalledExtensions = applyDoctorRuntimeActivationState(refreshedInstalled.extensions, loadResult, activationResult);
1817
+ runtimeActivationFailures = collectActivationFailureDiagnostics(activationResult.failed);
1818
+ runtimeProbeSummary = {
1819
+ requested: true,
1820
+ executed: true,
1821
+ reason: action === "explore" ? "explore_defaults_to_runtime_probe" : "runtime_probe_requested",
1514
1822
  load_failure_count: loadResult.failed.length,
1515
1823
  activation_failure_count: activationResult.failed.length,
1516
- blocking_failure_count: loadResult.failed.length + activationResult.failed.length,
1517
- has_blocking_failures: loadResult.failed.length + activationResult.failed.length > 0,
1518
- consistency_warning_count: doctorConsistency.warnings.length,
1519
- trace_enabled: includeTrace,
1520
- policy: policySummary,
1521
- remediation,
1522
- };
1523
- const managedStateFixSummary = managedStateFix
1524
- ? {
1525
- requested: true,
1526
- applied: managedStateFix.adopted_entries.length > 0,
1527
- adopted_count: managedStateFix.adopted_entries.length,
1528
- already_managed_count: managedStateFix.already_managed_count,
1529
- adopted_extensions: managedStateFix.adopted_entries.map((entry) => entry.name),
1530
- }
1531
- : {
1532
- requested: false,
1533
- applied: false,
1534
- adopted_count: 0,
1535
- already_managed_count: refreshedInstalled.extensions.filter((entry) => entry.managed).length,
1536
- adopted_extensions: [],
1537
- };
1538
- const details = {
1539
- mode: detailMode,
1540
- summary,
1541
- triage,
1542
- trace_enabled: includeTrace,
1543
- capability_contract: capabilityContract,
1544
- capability_guidance: capabilityGuidance,
1545
- managed_state_fix: managedStateFixSummary,
1824
+ warning_count: [...new Set([...loadResult.warnings, ...activationResult.warnings])].length,
1546
1825
  policy: loadResult.policy,
1547
1826
  };
1548
- if (detailMode === "deep") {
1549
- const activationFailedDetails = includeTrace
1550
- ? activationResult.failed
1551
- : activationResult.failed.map((entry) => {
1552
- const { trace: _trace, ...rest } = entry;
1553
- return rest;
1554
- });
1555
- details.deep = {
1556
- warnings: normalizedWarnings,
1557
- warning_codes: warningCodes,
1558
- capability_contract: capabilityContract,
1559
- capability_guidance: capabilityGuidance,
1560
- trace_enabled: includeTrace,
1561
- managed_state: {
1562
- path: managedStateRead.path,
1563
- count: managedState.entries.length,
1564
- entries: managedState.entries,
1565
- },
1566
- installed_extensions: runtimeInstalledExtensions,
1567
- load: {
1568
- roots: loadResult.roots,
1569
- policy: loadResult.policy,
1570
- warnings: loadResult.warnings,
1571
- failed: loadResult.failed,
1572
- loaded: loadResult.loaded.map((entry) => ({
1573
- layer: entry.layer,
1574
- directory: entry.directory,
1575
- name: entry.name,
1576
- version: entry.version,
1577
- entry: entry.entry,
1578
- priority: entry.priority,
1579
- })),
1580
- },
1581
- activation: {
1582
- failed: activationFailedDetails,
1583
- warnings: activationResult.warnings,
1584
- hook_counts: activationResult.hook_counts,
1585
- registration_counts: activationResult.registration_counts,
1586
- parser_override_count: activationResult.parser_override_count,
1587
- preflight_override_count: activationResult.preflight_override_count,
1588
- service_override_count: activationResult.service_override_count,
1589
- renderer_override_count: activationResult.renderer_override_count,
1590
- },
1591
- consistency: doctorConsistency.summary,
1592
- };
1593
- if (includeTrace) {
1594
- details.deep.trace = {
1595
- activation_failures: activationResult.failed
1596
- .filter((entry) => entry.trace !== undefined)
1597
- .map((entry) => ({
1598
- layer: entry.layer,
1599
- name: entry.name,
1600
- entry_path: entry.entry_path,
1601
- error: entry.error,
1602
- method: entry.trace?.method,
1603
- command: entry.trace?.command,
1604
- capability: entry.trace?.capability,
1605
- missing_capability: entry.trace?.missing_capability,
1606
- registration_index: entry.trace?.registration_index,
1607
- expected_schema: entry.trace?.expected_schema,
1608
- hint: entry.trace?.hint,
1609
- received: entry.trace?.received,
1610
- })),
1611
- };
1612
- }
1613
- }
1614
- return withResult(details);
1615
1827
  }
1616
- if (action === "describe") {
1617
- const settings = await readSettings(resolvedRoots.settings_root);
1618
- const loadResult = await loadExtensions({
1619
- pmRoot: resolvedRoots.pm_root,
1620
- settings,
1621
- cwd: process.cwd(),
1622
- noExtensions: global.noExtensions === true,
1623
- });
1624
- const activationResult = await activateExtensions(loadResult);
1625
- warnings.push(...loadResult.warnings);
1626
- warnings.push(...activationResult.warnings);
1627
- const describeResult = buildExtensionDescribeResult(normalizedTarget, loadResult, activationResult);
1628
- if (normalizedTarget !== undefined && describeResult.extensions.length === 0) {
1629
- const noun = options.vocabulary === "package" ? "package" : "extension";
1630
- throw new PmCliError(`No loaded ${noun} named "${normalizedTarget}" was found in ${scope} scope. Run pm ${noun} explore to list discovered ${noun}s.`, EXIT_CODE.NOT_FOUND);
1631
- }
1632
- return withResult({
1633
- target: describeResult.target,
1634
- total: describeResult.total,
1635
- extensions: describeResult.extensions,
1636
- union: describeResult.union,
1637
- });
1828
+ else if (action === "manage") {
1829
+ runtimeProbeSummary = {
1830
+ requested: false,
1831
+ executed: false,
1832
+ };
1638
1833
  }
1639
- /* c8 ignore start -- explore/manage action split is validated by dedicated command-action tests */
1640
- if (action === "explore" || action === "manage") {
1641
- const settings = await readSettings(resolvedRoots.settings_root);
1642
- const configuredPolicy = buildExtensionPolicyDetails(settings.extensions.policy);
1643
- const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
1644
- warnings.push(...managedStateRead.warnings);
1645
- const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
1646
- warnings.push(...installed.warnings);
1647
- let managedState = managedStateRead.state;
1648
- const managedStateFix = action === "manage" && options.fixManagedState === true
1649
- ? await adoptUnmanagedExtensions(resolvedRoots.selected_root, scope, installed.extensions, managedStateRead.state)
1650
- : null;
1651
- if (managedStateFix) {
1652
- managedState = managedStateFix.state;
1653
- }
1654
- if (action === "manage") {
1655
- const updates = await Promise.all(managedState.entries.map(async (entry) => {
1656
- if (entry.source.kind !== "github") {
1657
- return entry;
1834
+ const triage = buildExtensionTriageSummary(scope, warnings, runtimeInstalledExtensions, options);
1835
+ warnings.push(...triage.warnings);
1836
+ const details = {
1837
+ total: runtimeInstalledExtensions.length,
1838
+ managed_total: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
1839
+ enabled_total: runtimeInstalledExtensions.filter((entry) => entry.enabled).length,
1840
+ active_total: runtimeInstalledExtensions.filter((entry) => entry.active).length,
1841
+ extensions: runtimeInstalledExtensions,
1842
+ triage,
1843
+ policy: configuredPolicy,
1844
+ };
1845
+ if (runtimeActivationFailures !== undefined) {
1846
+ details.activation_diagnostics = {
1847
+ failed_count: runtimeActivationFailures.length,
1848
+ failed: runtimeActivationFailures,
1849
+ };
1850
+ }
1851
+ if (action === "explore") {
1852
+ details.runtime_probe = runtimeProbeSummary;
1853
+ }
1854
+ if (action === "manage") {
1855
+ details.runtime_probe = runtimeProbeSummary;
1856
+ details.managed_state_fix =
1857
+ managedStateFix !== null
1858
+ ? {
1859
+ requested: true,
1860
+ applied: managedStateFix.adopted_entries.length > 0,
1861
+ adopted_count: managedStateFix.adopted_entries.length,
1862
+ adopted_extensions: managedStateFix.adopted_entries.map((entry) => entry.name),
1863
+ already_managed_count: managedStateFix.already_managed_count,
1658
1864
  }
1659
- const updateStatus = await checkGithubUpdate(entry.source);
1660
- return {
1661
- ...entry,
1662
- last_update_check_at: updateStatus.checked_at,
1663
- last_update_remote_commit: updateStatus.remote_commit,
1664
- update_available: updateStatus.available,
1665
- update_error: updateStatus.error,
1865
+ : {
1866
+ requested: false,
1867
+ applied: false,
1868
+ adopted_count: 0,
1869
+ adopted_extensions: [],
1870
+ already_managed_count: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
1666
1871
  };
1667
- }));
1668
- managedState = {
1669
- ...managedState,
1670
- updated_at: nowIso(),
1671
- entries: sortManagedEntries(updates),
1672
- };
1673
- await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
1674
- }
1675
- const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
1676
- warnings.push(...refreshedInstalled.warnings);
1677
- if (action === "manage") {
1678
- const updateWarnings = refreshedInstalled.extensions
1679
- .filter((entry) => entry.update_check_status === "failed")
1680
- .map((entry) => `extension_update_check_failed:${entry.name}`);
1681
- warnings.push(...updateWarnings);
1682
- }
1683
- let runtimeProbeSummary;
1684
- let runtimeInstalledExtensions = refreshedInstalled.extensions;
1685
- let runtimeActivationFailures;
1686
- if (action === "explore" || options.runtimeProbe === true) {
1687
- const loadResult = await loadExtensions({
1688
- pmRoot: resolvedRoots.pm_root,
1689
- settings,
1690
- cwd: process.cwd(),
1691
- noExtensions: global.noExtensions === true,
1692
- });
1693
- const activationResult = await activateExtensions({
1694
- ...loadResult,
1695
- loaded: loadResult.loaded,
1696
- });
1697
- warnings.push(...loadResult.warnings);
1698
- warnings.push(...activationResult.warnings);
1699
- runtimeInstalledExtensions = applyDoctorRuntimeActivationState(refreshedInstalled.extensions, loadResult, activationResult);
1700
- runtimeActivationFailures = collectActivationFailureDiagnostics(activationResult.failed);
1701
- runtimeProbeSummary = {
1702
- requested: true,
1703
- executed: true,
1704
- reason: action === "explore" ? "explore_defaults_to_runtime_probe" : "runtime_probe_requested",
1705
- load_failure_count: loadResult.failed.length,
1706
- activation_failure_count: activationResult.failed.length,
1707
- warning_count: [...new Set([...loadResult.warnings, ...activationResult.warnings])].length,
1708
- policy: loadResult.policy,
1709
- };
1710
- }
1711
- else if (action === "manage") {
1712
- runtimeProbeSummary = {
1713
- requested: false,
1714
- executed: false,
1715
- };
1716
- }
1717
- const triage = buildExtensionTriageSummary(scope, warnings, runtimeInstalledExtensions, options);
1718
- warnings.push(...triage.warnings);
1719
- const details = {
1720
- total: runtimeInstalledExtensions.length,
1721
- managed_total: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
1722
- enabled_total: runtimeInstalledExtensions.filter((entry) => entry.enabled).length,
1723
- active_total: runtimeInstalledExtensions.filter((entry) => entry.active).length,
1724
- extensions: runtimeInstalledExtensions,
1725
- triage,
1726
- policy: configuredPolicy,
1727
- };
1728
- if (runtimeActivationFailures !== undefined) {
1729
- details.activation_diagnostics = {
1730
- failed_count: runtimeActivationFailures.length,
1731
- failed: runtimeActivationFailures,
1732
- };
1733
- }
1734
- if (action === "explore") {
1735
- details.runtime_probe = runtimeProbeSummary;
1736
- }
1737
- if (action === "manage") {
1738
- details.runtime_probe = runtimeProbeSummary;
1739
- details.managed_state_fix =
1740
- managedStateFix !== null
1741
- ? {
1742
- requested: true,
1743
- applied: managedStateFix.adopted_entries.length > 0,
1744
- adopted_count: managedStateFix.adopted_entries.length,
1745
- adopted_extensions: managedStateFix.adopted_entries.map((entry) => entry.name),
1746
- already_managed_count: managedStateFix.already_managed_count,
1747
- }
1748
- : {
1749
- requested: false,
1750
- applied: false,
1751
- adopted_count: 0,
1752
- adopted_extensions: [],
1753
- already_managed_count: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
1754
- };
1755
- }
1756
- return withResult(details);
1757
1872
  }
1758
- /* c8 ignore stop */
1759
- /* c8 ignore start -- resolveAction returns a closed ExtensionCommandAction union */
1760
- throw new PmCliError(`Unsupported extension action "${action}".`, EXIT_CODE.USAGE);
1761
- /* c8 ignore stop */
1873
+ return withResult(details);
1762
1874
  }
1875
+ /* c8 ignore stop */
1876
+ // Dispatch table from lifecycle action to its handler. `explore`/`manage` and
1877
+ // `activate`/`deactivate` share a handler that branches on `ctx.action`; the
1878
+ // closed ExtensionCommandAction union guarantees every action has an entry, so
1879
+ // runExtension needs no unsupported-action fallthrough.
1880
+ const EXTENSION_ACTION_HANDLERS = {
1881
+ init: runExtensionInitAction,
1882
+ install: runExtensionInstallAction,
1883
+ uninstall: runExtensionUninstallAction,
1884
+ explore: runExtensionExploreManageAction,
1885
+ manage: runExtensionExploreManageAction,
1886
+ describe: runExtensionDescribeAction,
1887
+ reload: runExtensionReloadAction,
1888
+ doctor: runExtensionDoctorAction,
1889
+ catalog: runExtensionCatalogAction,
1890
+ adopt: runExtensionAdoptAction,
1891
+ "adopt-all": runExtensionAdoptAllAction,
1892
+ activate: runExtensionActivateDeactivateAction,
1893
+ deactivate: runExtensionActivateDeactivateAction,
1894
+ };
1763
1895
  export const _testOnly = {
1764
1896
  adoptUnmanagedExtensions,
1765
1897
  buildExtensionPolicyDetails,
@@ -1785,4 +1917,4 @@ export const _testOnly = {
1785
1917
  withExtensionInstallLock,
1786
1918
  };
1787
1919
  //# sourceMappingURL=extension.js.map
1788
- //# debugId=e112e059-bf75-55f5-a0ec-652b037fe54b
1920
+ //# debugId=0e9a5528-9595-5a89-89b7-5a5acce477a8