@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.
- package/AGENTS.md +2 -0
- package/CHANGELOG.md +20 -0
- package/dist/cli/bootstrap-args.js +89 -79
- package/dist/cli/bootstrap-args.js.map +1 -1
- package/dist/cli/commands/calendar.js +63 -62
- package/dist/cli/commands/calendar.js.map +1 -1
- package/dist/cli/commands/create.js +483 -434
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/extension/bundled-catalog.js +59 -46
- package/dist/cli/commands/extension/bundled-catalog.js.map +1 -1
- package/dist/cli/commands/extension/doctor.js +129 -78
- package/dist/cli/commands/extension/doctor.js.map +1 -1
- package/dist/cli/commands/extension/managed-state.js +101 -57
- package/dist/cli/commands/extension/managed-state.js.map +1 -1
- package/dist/cli/commands/extension/scaffold.d.ts +7 -0
- package/dist/cli/commands/extension/scaffold.js +214 -186
- package/dist/cli/commands/extension/scaffold.js.map +1 -1
- package/dist/cli/commands/extension.d.ts +6 -1
- package/dist/cli/commands/extension.js +1034 -902
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/list-filter-shared.js +55 -48
- package/dist/cli/commands/list-filter-shared.js.map +1 -1
- package/dist/cli/commands/search.js +94 -68
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/test.js +108 -122
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update.js +27 -77
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/extension-command-options.js +48 -21
- package/dist/cli/extension-command-options.js.map +1 -1
- package/dist/cli/registration-helpers.js +117 -122
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli-bundle/chunks/activity-AW6XVFH6.js +16 -0
- package/dist/cli-bundle/chunks/{activity-MVSEND6D.js → activity-DBLQVIP6.js} +9 -9
- package/dist/cli-bundle/chunks/{aggregate-MOC4TR2G.js → aggregate-JTEF4BP7.js} +9 -9
- package/dist/cli-bundle/chunks/{aggregate-XJHLZQ5X.js → aggregate-SDF7DUOD.js} +9 -9
- package/dist/cli-bundle/chunks/{append-LEDBAM3K.js → append-LOVPGVPT.js} +6 -6
- package/dist/cli-bundle/chunks/{append-KDHT4GHI.js → append-QCFJSDFL.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-FBZ5XAAF.js → chunk-22WKIL3H.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-EVWYAG46.js → chunk-2466X6E4.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-3JWQCLR5.js → chunk-27BXPBAY.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-WTRUDJ3R.js → chunk-2D4HATP2.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-DORJSBGJ.js → chunk-3J6JRJ3I.js} +127 -125
- package/dist/cli-bundle/chunks/chunk-3J6JRJ3I.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-LBH7UYKY.js → chunk-3K2M5OYU.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-KTMMTOIP.js → chunk-3S2KT7NG.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-FDEVKXC4.js → chunk-3VGN2UWE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-K46GQ265.js → chunk-3XZCOZ5J.js} +107 -117
- package/dist/cli-bundle/chunks/chunk-3XZCOZ5J.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-4A3BJ675.js +799 -0
- package/dist/cli-bundle/chunks/chunk-4A3BJ675.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-4BU75MF4.js +87 -0
- package/dist/cli-bundle/chunks/chunk-4BU75MF4.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-KYDYQMNW.js → chunk-4DSGXSBL.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-7L6TXOOC.js → chunk-4DUVCVLZ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-UB3V5WUI.js → chunk-4XOIEKSD.js} +351 -330
- package/dist/cli-bundle/chunks/chunk-4XOIEKSD.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-DJDXAU74.js → chunk-55SNVXRQ.js} +68 -69
- package/dist/cli-bundle/chunks/chunk-55SNVXRQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-ZIE6WXJ2.js → chunk-5CGRF3L5.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-7WDETKGP.js → chunk-5QFDBI4F.js} +1105 -965
- package/dist/cli-bundle/chunks/chunk-5QFDBI4F.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-IBU2LLWM.js → chunk-64HNBBFQ.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-T7ZMQI4J.js → chunk-6AQZPVHQ.js} +198 -189
- package/dist/cli-bundle/chunks/chunk-6AQZPVHQ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-CY5IJMUM.js → chunk-7R4QEMZZ.js} +361 -322
- package/dist/cli-bundle/chunks/chunk-7R4QEMZZ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-WFJZDUM7.js → chunk-A7FPBAQS.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-74PUWBGN.js → chunk-AVEE5EHK.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-KRASIL6M.js → chunk-AXIDKKAT.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-CHRNYKNI.js → chunk-BDTISOSD.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZFIEEDTJ.js → chunk-BHO33VBQ.js} +509 -363
- package/dist/cli-bundle/chunks/chunk-BHO33VBQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-RM6MHL6A.js → chunk-BZCEN4JA.js} +98 -74
- package/dist/cli-bundle/chunks/chunk-BZCEN4JA.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-RPRW26NG.js → chunk-CF7RL6FR.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-NIBP3I7A.js → chunk-CWFNTKQJ.js} +128 -126
- package/dist/cli-bundle/chunks/chunk-CWFNTKQJ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-BN3CWK6G.js → chunk-DDPTYJIM.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4YIMPANT.js → chunk-EJUDVUYZ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-73PTKMAE.js → chunk-EVMTBV6V.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-6YRAMXRS.js → chunk-FFMQB7WR.js} +99 -75
- package/dist/cli-bundle/chunks/chunk-FFMQB7WR.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-E2Q2ULMR.js → chunk-G7I7DEZA.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-IDYCAK35.js → chunk-GJ326ZKX.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-JJ4SG243.js → chunk-HPPFYYOV.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5IRVSKPS.js → chunk-HXTQJXWT.js} +150 -224
- package/dist/cli-bundle/chunks/chunk-HXTQJXWT.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-JIP67N2K.js → chunk-HYTGA6GI.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-7RIJGN4R.js → chunk-HZZEHPRG.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4TXTVZL3.js → chunk-IJYK2T43.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-GF7EAR22.js → chunk-IPYBJWTE.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-AWN4PPH5.js → chunk-IZBR4NRW.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-IF4ERU6A.js → chunk-JLM7BHI7.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-DU66JUGT.js → chunk-JMP4E6D7.js} +106 -116
- package/dist/cli-bundle/chunks/chunk-JMP4E6D7.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-HUYYMTGW.js → chunk-JPECA746.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-KGQ3W65B.js → chunk-JSU5P7VS.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-HIBK6H4S.js → chunk-JWXRETDF.js} +69 -70
- package/dist/cli-bundle/chunks/chunk-JWXRETDF.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-Z5BM2FKQ.js → chunk-KNPEF7QG.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-DLDCPF5X.js → chunk-L5OEFZQG.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-DRPF274X.js → chunk-LB6TP6MC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-YEDFE4DC.js → chunk-MAUKX7JC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-6T5ZIWBS.js → chunk-MDPEOIGN.js} +150 -224
- package/dist/cli-bundle/chunks/chunk-MDPEOIGN.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-OB3RJV5F.js → chunk-N74UMG5H.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZEATCVAC.js → chunk-NFDPYAIP.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OUQ5JEFM.js → chunk-NKZAN7BD.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-5ABGFWR4.js → chunk-NOLPZMSV.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JZG5ADVE.js → chunk-NU2UEROZ.js} +1103 -963
- package/dist/cli-bundle/chunks/chunk-NU2UEROZ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-A3UNLXNJ.js → chunk-NUHHPVVS.js} +36 -86
- package/dist/cli-bundle/chunks/chunk-NUHHPVVS.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-QE5UFCCO.js → chunk-NWMZWYYB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-VMY7MZEM.js → chunk-OGXLACHC.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-IHXXUIXS.js → chunk-OTUHB4HS.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-V3KLX7U7.js → chunk-QCWF6IYD.js} +510 -364
- package/dist/cli-bundle/chunks/chunk-QCWF6IYD.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-UFKNF23C.js → chunk-RGEMWD6Q.js} +5 -5
- package/dist/cli-bundle/chunks/chunk-RH5ZBYFD.js +809 -0
- package/dist/cli-bundle/chunks/chunk-RH5ZBYFD.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-Z55WX4IQ.js → chunk-RLDHZHQS.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-NO6Y6FB2.js → chunk-RMMQ74TG.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-SNUK7H5J.js → chunk-RVUALSJF.js} +361 -322
- package/dist/cli-bundle/chunks/chunk-RVUALSJF.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-IZQOJR2B.js → chunk-SDR5J34Q.js} +198 -189
- package/dist/cli-bundle/chunks/chunk-SDR5J34Q.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-SJZTPVFT.js → chunk-SLMUGTK3.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-BOWQWXLI.js → chunk-TP5Q5ZD3.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-D5LYZVGB.js → chunk-UYUYDGIB.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-JVQ7UOYC.js → chunk-UZIWVBE6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-JTRKME24.js → chunk-V3NOKJF2.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-5T6WPLRO.js → chunk-VARHOHYV.js} +350 -329
- package/dist/cli-bundle/chunks/chunk-VARHOHYV.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-F7G53BOA.js → chunk-VICZWYGZ.js} +4 -4
- package/dist/cli-bundle/chunks/chunk-VY3VQ22F.js +84 -0
- package/dist/cli-bundle/chunks/chunk-VY3VQ22F.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-TQ6E76BE.js → chunk-W4ULYO7Z.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-MLHX6DN5.js → chunk-WYDHYJPO.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-53ARXF2O.js → chunk-YITK2PJ6.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-VD3LKZFX.js → chunk-ZETXE4SE.js} +37 -87
- package/dist/cli-bundle/chunks/chunk-ZETXE4SE.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-D6USKAMA.js → chunk-ZRP4VG5U.js} +2 -2
- package/dist/cli-bundle/chunks/{claim-6NINZYB3.js → claim-EMQLYPRW.js} +8 -8
- package/dist/cli-bundle/chunks/{claim-HMCLSLUE.js → claim-T3GCKV7C.js} +8 -8
- package/dist/cli-bundle/chunks/close-E6ZZGCJY.js +14 -0
- package/dist/cli-bundle/chunks/{close-OP3LK7Z2.js → close-TQYAAFJP.js} +7 -7
- package/dist/cli-bundle/chunks/{close-many-BFMP6HHK.js → close-many-BG5QQIDQ.js} +15 -15
- package/dist/cli-bundle/chunks/{close-many-CXJBOWWY.js → close-many-LDRVEQY2.js} +15 -15
- package/dist/cli-bundle/chunks/{comments-MU2WMBUY.js → comments-QCKR2YY2.js} +8 -8
- package/dist/cli-bundle/chunks/{comments-ETHABIY6.js → comments-YUXJRZPQ.js} +8 -8
- package/dist/cli-bundle/chunks/{config-FIXJZEQK.js → config-DMSU64QO.js} +7 -7
- package/dist/cli-bundle/chunks/{config-X3ZVCUUG.js → config-QH2DICD6.js} +7 -7
- package/dist/cli-bundle/chunks/{context-XDI4DKKT.js → context-B6275WPX.js} +12 -12
- package/dist/cli-bundle/chunks/{context-7ZEZV3BV.js → context-OCZ3FJ4Z.js} +12 -12
- package/dist/cli-bundle/chunks/{contracts-SMOAN5NF.js → contracts-HN7ABKLP.js} +3 -3
- package/dist/cli-bundle/chunks/{contracts-KP4QAGVW.js → contracts-W4FZVVD6.js} +3 -3
- package/dist/cli-bundle/chunks/{copy-CWM6SBY6.js → copy-BTJOSKKT.js} +5 -5
- package/dist/cli-bundle/chunks/{copy-JJ3KOQW2.js → copy-DEM4DATS.js} +5 -5
- package/dist/cli-bundle/chunks/create-OH3BDGBB.js +28 -0
- package/dist/cli-bundle/chunks/{create-J5Q2ELZT.js → create-RLRJMRTM.js} +12 -12
- package/dist/cli-bundle/chunks/{delete-OOQS4KVD.js → delete-BHK7VB2Z.js} +5 -5
- package/dist/cli-bundle/chunks/{delete-2GZLQEUQ.js → delete-LSVHAB4Y.js} +5 -5
- package/dist/cli-bundle/chunks/{deps-ZVGGCRR6.js → deps-4UDFJRUA.js} +5 -5
- package/dist/cli-bundle/chunks/{deps-IF4IGL4R.js → deps-XHYXWEPT.js} +5 -5
- package/dist/cli-bundle/chunks/{docs-2TIFR62T.js → docs-26S44RXU.js} +7 -7
- package/dist/cli-bundle/chunks/{docs-NFTBCQQC.js → docs-GYZNVS26.js} +7 -7
- package/dist/cli-bundle/chunks/{eval-2F6EH4XN.js → eval-PGRVIJQU.js} +10 -10
- package/dist/cli-bundle/chunks/{eval-PFKXQR3B.js → eval-UYF3ZPVO.js} +10 -10
- package/dist/cli-bundle/chunks/{extension-GMVOIP4O.js → extension-CPSLJQVE.js} +11 -10
- package/dist/cli-bundle/chunks/{extension-3LRYX7SW.js → extension-CXJ6RELI.js} +11 -10
- package/dist/cli-bundle/chunks/{files-T5ODMETM.js → files-MBNICQFM.js} +7 -7
- package/dist/cli-bundle/chunks/{files-DF3HO6XK.js → files-NQHEXUZD.js} +7 -7
- package/dist/cli-bundle/chunks/{focus-DLXKK4AH.js → focus-DWYIG7GU.js} +6 -6
- package/dist/cli-bundle/chunks/{focus-MY5ARIEK.js → focus-XZW5423D.js} +6 -6
- package/dist/cli-bundle/chunks/{gc-FULIVYR4.js → gc-7GQYOS2G.js} +3 -3
- package/dist/cli-bundle/chunks/{gc-MDGRR2SU.js → gc-LPVMKJQJ.js} +3 -3
- package/dist/cli-bundle/chunks/{get-AWK324RS.js → get-A7MAOHCU.js} +9 -9
- package/dist/cli-bundle/chunks/{get-VYPIICPC.js → get-DSDEKJ3L.js} +9 -9
- package/dist/cli-bundle/chunks/{health-Q66C43GN.js → health-3IPFLKXB.js} +17 -16
- package/dist/cli-bundle/chunks/{health-Q66C43GN.js.map → health-3IPFLKXB.js.map} +1 -1
- package/dist/cli-bundle/chunks/{health-FBCVZGSX.js → health-GZXGBZ36.js} +15 -14
- package/dist/cli-bundle/chunks/{health-FBCVZGSX.js.map → health-GZXGBZ36.js.map} +1 -1
- package/dist/cli-bundle/chunks/{history-X4OSES6K.js → history-NERDJNUB.js} +8 -8
- package/dist/cli-bundle/chunks/history-WSZHY3PN.js +18 -0
- package/dist/cli-bundle/chunks/{history-compact-WLCQEKXS.js → history-compact-2WRZ2WK4.js} +10 -10
- package/dist/cli-bundle/chunks/{history-compact-2GHT32UX.js → history-compact-HR7BB4LR.js} +10 -10
- package/dist/cli-bundle/chunks/history-redact-MP6CH7U5.js +19 -0
- package/dist/cli-bundle/chunks/{history-redact-45YW65BK.js → history-redact-O3NBCNWC.js} +9 -9
- package/dist/cli-bundle/chunks/{history-repair-GABSDSVD.js → history-repair-LCMOS45X.js} +10 -10
- package/dist/cli-bundle/chunks/{history-repair-FY75IC26.js → history-repair-XA3LC4GA.js} +10 -10
- package/dist/cli-bundle/chunks/{init-KO7CGIRQ.js → init-64XDLQJB.js} +12 -11
- package/dist/cli-bundle/chunks/init-PAX32BJA.js +22 -0
- package/dist/cli-bundle/chunks/{learnings-3F7YLI45.js → learnings-JR6MA5TI.js} +8 -8
- package/dist/cli-bundle/chunks/{learnings-LHZT5BHW.js → learnings-LPKCSJX7.js} +8 -8
- package/dist/cli-bundle/chunks/{list-ROT7JF62.js → list-DNBJVO3E.js} +8 -8
- package/dist/cli-bundle/chunks/{list-Y6AU5BJS.js → list-G5Y65VF6.js} +8 -8
- package/dist/cli-bundle/chunks/{next-66BJB4N2.js → next-BCERKDUR.js} +13 -13
- package/dist/cli-bundle/chunks/{next-N5MWJTBY.js → next-FYTQF6HG.js} +13 -13
- package/dist/cli-bundle/chunks/{notes-FW6YFLND.js → notes-2BMU3VVQ.js} +8 -8
- package/dist/cli-bundle/chunks/{notes-EVJZ3VAB.js → notes-6KTGO2OJ.js} +8 -8
- package/dist/cli-bundle/chunks/{plan-DQ7G4EDC.js → plan-4WXEQCTN.js} +12 -12
- package/dist/cli-bundle/chunks/{plan-ZHKZ7JVF.js → plan-RKZHQVXR.js} +12 -12
- package/dist/cli-bundle/chunks/{profile-UPZGCDOG.js → profile-4OMM32CD.js} +8 -8
- package/dist/cli-bundle/chunks/{profile-CHAW6SEA.js → profile-QLER5ENE.js} +8 -8
- package/dist/cli-bundle/chunks/{register-list-query-Y2VRHPCL.js → register-list-query-7LV46VAU.js} +18 -18
- package/dist/cli-bundle/chunks/{register-list-query-KY6Z6WV7.js → register-list-query-SNG5PGA4.js} +18 -18
- package/dist/cli-bundle/chunks/{register-mutation-PCARIGZS.js → register-mutation-ENNDUAZG.js} +35 -35
- package/dist/cli-bundle/chunks/{register-mutation-N6AYSKPM.js → register-mutation-KK7PHYYU.js} +35 -35
- package/dist/cli-bundle/chunks/{register-operations-YAT6FUUB.js → register-operations-C6OWLDSH.js} +30 -30
- package/dist/cli-bundle/chunks/{register-operations-L6CYTOIH.js → register-operations-HZ6XERQG.js} +30 -30
- package/dist/cli-bundle/chunks/{register-setup-N7UGXYJC.js → register-setup-P67EMBDJ.js} +15 -15
- package/dist/cli-bundle/chunks/{register-setup-MPANILQF.js → register-setup-ZKJ53RS7.js} +15 -15
- package/dist/cli-bundle/chunks/{restore-DKMCLPI5.js → restore-4MHZFJ2E.js} +9 -9
- package/dist/cli-bundle/chunks/restore-YALDGTQR.js +17 -0
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-3F4QUEDH.js → scheduling-shortcuts-LB6DOLRL.js} +12 -12
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-BNZLQK36.js → scheduling-shortcuts-UTOYKLXQ.js} +12 -12
- package/dist/cli-bundle/chunks/{schema-OLT6LVKH.js → schema-73HR2OJW.js} +7 -7
- package/dist/cli-bundle/chunks/{schema-XJXKJQF5.js → schema-U6LJKSIR.js} +7 -7
- package/dist/cli-bundle/chunks/{search-CX5UMV4H.js → search-AXPXKZER.js} +10 -10
- package/dist/cli-bundle/chunks/{search-KP6H7COV.js → search-KILGT37L.js} +10 -10
- package/dist/cli-bundle/chunks/{stats-QZUG6MX5.js → stats-PSYVVTNZ.js} +6 -6
- package/dist/cli-bundle/chunks/{stats-7XW4OEMK.js → stats-W5KNVJWQ.js} +6 -6
- package/dist/cli-bundle/chunks/{telemetry-WTYFUPRL.js → telemetry-BZUF6H7G.js} +4 -4
- package/dist/cli-bundle/chunks/{telemetry-DIFPXCAT.js → telemetry-GAHHQTOS.js} +4 -4
- package/dist/cli-bundle/chunks/{test-QNDXZQCW.js → test-ACD52Z3S.js} +15 -14
- package/dist/cli-bundle/chunks/{test-HU2BS7EY.js → test-PWDIZ255.js} +15 -14
- package/dist/cli-bundle/chunks/{test-all-XLPI4USF.js → test-all-L2MDDUCA.js} +17 -16
- package/dist/cli-bundle/chunks/{test-all-XLPI4USF.js.map → test-all-L2MDDUCA.js.map} +1 -1
- package/dist/cli-bundle/chunks/{test-all-PZTBLLQ6.js → test-all-RBZ6DLU2.js} +15 -14
- package/dist/cli-bundle/chunks/{test-all-PZTBLLQ6.js.map → test-all-RBZ6DLU2.js.map} +1 -1
- package/dist/cli-bundle/chunks/{test-runs-LANLLPVO.js → test-runs-PLRAZEFW.js} +4 -4
- package/dist/cli-bundle/chunks/{test-runs-CA6K32RD.js → test-runs-UXIXPDKU.js} +4 -4
- package/dist/cli-bundle/chunks/update-AMRSOIWP.js +24 -0
- package/dist/cli-bundle/chunks/{update-DJKWLBWJ.js → update-KFX2SIAC.js} +15 -15
- package/dist/cli-bundle/chunks/{update-many-VW5DGF3S.js → update-many-RNSBX2TA.js} +23 -23
- package/dist/cli-bundle/chunks/{update-many-LU3SCNK5.js → update-many-Z5GJS5LC.js} +23 -23
- package/dist/cli-bundle/chunks/{upgrade-77FRUAXN.js → upgrade-BRL6KCOJ.js} +13 -12
- package/dist/cli-bundle/chunks/{upgrade-77FRUAXN.js.map → upgrade-BRL6KCOJ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{upgrade-ICXY244R.js → upgrade-HAK6JG2O.js} +11 -10
- package/dist/cli-bundle/chunks/{upgrade-ICXY244R.js.map → upgrade-HAK6JG2O.js.map} +1 -1
- package/dist/cli-bundle/chunks/{validate-2G566PKQ.js → validate-MTUVL5VC.js} +20 -19
- package/dist/cli-bundle/chunks/{validate-2G566PKQ.js.map → validate-MTUVL5VC.js.map} +1 -1
- package/dist/cli-bundle/chunks/{validate-BDPVXHHH.js → validate-X5W76YJL.js} +22 -21
- package/dist/cli-bundle/chunks/{validate-BDPVXHHH.js.map → validate-X5W76YJL.js.map} +1 -1
- package/dist/cli-bundle/main.js +55 -702
- package/dist/cli-bundle/main.js.map +4 -4
- package/dist/core/extensions/activation-summary-markdown.js +23 -12
- package/dist/core/extensions/activation-summary-markdown.js.map +1 -1
- package/dist/core/extensions/extension-policy.d.ts +18 -3
- package/dist/core/extensions/extension-policy.js +116 -106
- package/dist/core/extensions/extension-policy.js.map +1 -1
- package/dist/core/extensions/loader.js +310 -232
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/item/item-format.js +523 -410
- package/dist/core/item/item-format.js.map +1 -1
- package/dist/mcp/server.js +387 -367
- package/dist/mcp/server.js.map +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.js +111 -180
- package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +76 -45
- package/dist/sdk/cli-contracts/tool-schema.js.map +1 -1
- package/dist/sdk/compose.d.ts +4 -1
- package/dist/sdk/compose.js +181 -115
- package/dist/sdk/compose.js.map +1 -1
- package/docs/RELEASING.md +2 -3
- package/package.json +1 -1
- package/dist/cli-bundle/chunks/activity-EJBMXUBH.js +0 -16
- package/dist/cli-bundle/chunks/chunk-5IRVSKPS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-5T6WPLRO.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-6T5ZIWBS.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-6YRAMXRS.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-7WDETKGP.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-A3UNLXNJ.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-C2KCIZKZ.js +0 -115
- package/dist/cli-bundle/chunks/chunk-C2KCIZKZ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-CY5IJMUM.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-DJDXAU74.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-DORJSBGJ.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-DU66JUGT.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-F6VH3LFC.js +0 -118
- package/dist/cli-bundle/chunks/chunk-F6VH3LFC.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-HIBK6H4S.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-ISEKN64V.js +0 -35
- package/dist/cli-bundle/chunks/chunk-ISEKN64V.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-IZQOJR2B.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-JZG5ADVE.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-K46GQ265.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-NIBP3I7A.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-RM6MHL6A.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-SNUK7H5J.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-T7ZMQI4J.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-UB3V5WUI.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-V3KLX7U7.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-VD3LKZFX.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-W2VMLL5S.js +0 -32
- package/dist/cli-bundle/chunks/chunk-W2VMLL5S.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-ZFIEEDTJ.js.map +0 -7
- package/dist/cli-bundle/chunks/close-37KEHLYM.js +0 -14
- package/dist/cli-bundle/chunks/create-DFMNBKBS.js +0 -28
- package/dist/cli-bundle/chunks/history-5XUSLAJA.js +0 -18
- package/dist/cli-bundle/chunks/history-redact-BVHWDXPR.js +0 -19
- package/dist/cli-bundle/chunks/init-TRYJELH4.js +0 -21
- package/dist/cli-bundle/chunks/restore-IRAKSWIW.js +0 -17
- package/dist/cli-bundle/chunks/update-UXDLTEOZ.js +0 -24
- /package/dist/cli-bundle/chunks/{activity-EJBMXUBH.js.map → activity-AW6XVFH6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{activity-MVSEND6D.js.map → activity-DBLQVIP6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{aggregate-MOC4TR2G.js.map → aggregate-JTEF4BP7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{aggregate-XJHLZQ5X.js.map → aggregate-SDF7DUOD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-LEDBAM3K.js.map → append-LOVPGVPT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-KDHT4GHI.js.map → append-QCFJSDFL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FBZ5XAAF.js.map → chunk-22WKIL3H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-EVWYAG46.js.map → chunk-2466X6E4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-3JWQCLR5.js.map → chunk-27BXPBAY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WTRUDJ3R.js.map → chunk-2D4HATP2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-LBH7UYKY.js.map → chunk-3K2M5OYU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KTMMTOIP.js.map → chunk-3S2KT7NG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FDEVKXC4.js.map → chunk-3VGN2UWE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KYDYQMNW.js.map → chunk-4DSGXSBL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7L6TXOOC.js.map → chunk-4DUVCVLZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZIE6WXJ2.js.map → chunk-5CGRF3L5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IBU2LLWM.js.map → chunk-64HNBBFQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WFJZDUM7.js.map → chunk-A7FPBAQS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-74PUWBGN.js.map → chunk-AVEE5EHK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KRASIL6M.js.map → chunk-AXIDKKAT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CHRNYKNI.js.map → chunk-BDTISOSD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RPRW26NG.js.map → chunk-CF7RL6FR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BN3CWK6G.js.map → chunk-DDPTYJIM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4YIMPANT.js.map → chunk-EJUDVUYZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-73PTKMAE.js.map → chunk-EVMTBV6V.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-E2Q2ULMR.js.map → chunk-G7I7DEZA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IDYCAK35.js.map → chunk-GJ326ZKX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JJ4SG243.js.map → chunk-HPPFYYOV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JIP67N2K.js.map → chunk-HYTGA6GI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7RIJGN4R.js.map → chunk-HZZEHPRG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4TXTVZL3.js.map → chunk-IJYK2T43.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GF7EAR22.js.map → chunk-IPYBJWTE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AWN4PPH5.js.map → chunk-IZBR4NRW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IF4ERU6A.js.map → chunk-JLM7BHI7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HUYYMTGW.js.map → chunk-JPECA746.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KGQ3W65B.js.map → chunk-JSU5P7VS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-Z5BM2FKQ.js.map → chunk-KNPEF7QG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DLDCPF5X.js.map → chunk-L5OEFZQG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DRPF274X.js.map → chunk-LB6TP6MC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-YEDFE4DC.js.map → chunk-MAUKX7JC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OB3RJV5F.js.map → chunk-N74UMG5H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZEATCVAC.js.map → chunk-NFDPYAIP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OUQ5JEFM.js.map → chunk-NKZAN7BD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5ABGFWR4.js.map → chunk-NOLPZMSV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QE5UFCCO.js.map → chunk-NWMZWYYB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VMY7MZEM.js.map → chunk-OGXLACHC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IHXXUIXS.js.map → chunk-OTUHB4HS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UFKNF23C.js.map → chunk-RGEMWD6Q.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-Z55WX4IQ.js.map → chunk-RLDHZHQS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NO6Y6FB2.js.map → chunk-RMMQ74TG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-SJZTPVFT.js.map → chunk-SLMUGTK3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BOWQWXLI.js.map → chunk-TP5Q5ZD3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-D5LYZVGB.js.map → chunk-UYUYDGIB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JVQ7UOYC.js.map → chunk-UZIWVBE6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JTRKME24.js.map → chunk-V3NOKJF2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-F7G53BOA.js.map → chunk-VICZWYGZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TQ6E76BE.js.map → chunk-W4ULYO7Z.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-MLHX6DN5.js.map → chunk-WYDHYJPO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-53ARXF2O.js.map → chunk-YITK2PJ6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-D6USKAMA.js.map → chunk-ZRP4VG5U.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{claim-6NINZYB3.js.map → claim-EMQLYPRW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{claim-HMCLSLUE.js.map → claim-T3GCKV7C.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-37KEHLYM.js.map → close-E6ZZGCJY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-OP3LK7Z2.js.map → close-TQYAAFJP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-BFMP6HHK.js.map → close-many-BG5QQIDQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-CXJBOWWY.js.map → close-many-LDRVEQY2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-MU2WMBUY.js.map → comments-QCKR2YY2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-ETHABIY6.js.map → comments-YUXJRZPQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{config-FIXJZEQK.js.map → config-DMSU64QO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{config-X3ZVCUUG.js.map → config-QH2DICD6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{context-XDI4DKKT.js.map → context-B6275WPX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{context-7ZEZV3BV.js.map → context-OCZ3FJ4Z.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{contracts-SMOAN5NF.js.map → contracts-HN7ABKLP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{contracts-KP4QAGVW.js.map → contracts-W4FZVVD6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-CWM6SBY6.js.map → copy-BTJOSKKT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-JJ3KOQW2.js.map → copy-DEM4DATS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-DFMNBKBS.js.map → create-OH3BDGBB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-J5Q2ELZT.js.map → create-RLRJMRTM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-OOQS4KVD.js.map → delete-BHK7VB2Z.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-2GZLQEUQ.js.map → delete-LSVHAB4Y.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-ZVGGCRR6.js.map → deps-4UDFJRUA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-IF4IGL4R.js.map → deps-XHYXWEPT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-2TIFR62T.js.map → docs-26S44RXU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-NFTBCQQC.js.map → docs-GYZNVS26.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{eval-2F6EH4XN.js.map → eval-PGRVIJQU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{eval-PFKXQR3B.js.map → eval-UYF3ZPVO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-GMVOIP4O.js.map → extension-CPSLJQVE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-3LRYX7SW.js.map → extension-CXJ6RELI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-T5ODMETM.js.map → files-MBNICQFM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-DF3HO6XK.js.map → files-NQHEXUZD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-DLXKK4AH.js.map → focus-DWYIG7GU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-MY5ARIEK.js.map → focus-XZW5423D.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{gc-FULIVYR4.js.map → gc-7GQYOS2G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{gc-MDGRR2SU.js.map → gc-LPVMKJQJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{get-AWK324RS.js.map → get-A7MAOHCU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{get-VYPIICPC.js.map → get-DSDEKJ3L.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-X4OSES6K.js.map → history-NERDJNUB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-5XUSLAJA.js.map → history-WSZHY3PN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-WLCQEKXS.js.map → history-compact-2WRZ2WK4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-2GHT32UX.js.map → history-compact-HR7BB4LR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-BVHWDXPR.js.map → history-redact-MP6CH7U5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-45YW65BK.js.map → history-redact-O3NBCNWC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-GABSDSVD.js.map → history-repair-LCMOS45X.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-FY75IC26.js.map → history-repair-XA3LC4GA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-KO7CGIRQ.js.map → init-64XDLQJB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-TRYJELH4.js.map → init-PAX32BJA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-3F7YLI45.js.map → learnings-JR6MA5TI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-LHZT5BHW.js.map → learnings-LPKCSJX7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-ROT7JF62.js.map → list-DNBJVO3E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-Y6AU5BJS.js.map → list-G5Y65VF6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{next-66BJB4N2.js.map → next-BCERKDUR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{next-N5MWJTBY.js.map → next-FYTQF6HG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-FW6YFLND.js.map → notes-2BMU3VVQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-EVJZ3VAB.js.map → notes-6KTGO2OJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-DQ7G4EDC.js.map → plan-4WXEQCTN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-ZHKZ7JVF.js.map → plan-RKZHQVXR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-UPZGCDOG.js.map → profile-4OMM32CD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-CHAW6SEA.js.map → profile-QLER5ENE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-list-query-Y2VRHPCL.js.map → register-list-query-7LV46VAU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-list-query-KY6Z6WV7.js.map → register-list-query-SNG5PGA4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-mutation-PCARIGZS.js.map → register-mutation-ENNDUAZG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-mutation-N6AYSKPM.js.map → register-mutation-KK7PHYYU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-operations-YAT6FUUB.js.map → register-operations-C6OWLDSH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-operations-L6CYTOIH.js.map → register-operations-HZ6XERQG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-setup-N7UGXYJC.js.map → register-setup-P67EMBDJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-setup-MPANILQF.js.map → register-setup-ZKJ53RS7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-DKMCLPI5.js.map → restore-4MHZFJ2E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-IRAKSWIW.js.map → restore-YALDGTQR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{scheduling-shortcuts-3F4QUEDH.js.map → scheduling-shortcuts-LB6DOLRL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{scheduling-shortcuts-BNZLQK36.js.map → scheduling-shortcuts-UTOYKLXQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-OLT6LVKH.js.map → schema-73HR2OJW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-XJXKJQF5.js.map → schema-U6LJKSIR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{search-CX5UMV4H.js.map → search-AXPXKZER.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{search-KP6H7COV.js.map → search-KILGT37L.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{stats-QZUG6MX5.js.map → stats-PSYVVTNZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{stats-7XW4OEMK.js.map → stats-W5KNVJWQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{telemetry-WTYFUPRL.js.map → telemetry-BZUF6H7G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{telemetry-DIFPXCAT.js.map → telemetry-GAHHQTOS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-QNDXZQCW.js.map → test-ACD52Z3S.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-HU2BS7EY.js.map → test-PWDIZ255.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-runs-LANLLPVO.js.map → test-runs-PLRAZEFW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-runs-CA6K32RD.js.map → test-runs-UXIXPDKU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-UXDLTEOZ.js.map → update-AMRSOIWP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-DJKWLBWJ.js.map → update-KFX2SIAC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-VW5DGF3S.js.map → update-many-RNSBX2TA.js.map} +0 -0
- /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]="
|
|
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 = [
|
|
357
|
-
|
|
358
|
-
|
|
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
|
-
|
|
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
|
-
|
|
489
|
-
|
|
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
|
-
|
|
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
|
-
|
|
527
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
850
|
-
const
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
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
|
-
|
|
861
|
-
|
|
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 (
|
|
864
|
-
|
|
923
|
+
if (action === "reload" && normalizedInput === "reload") {
|
|
924
|
+
return undefined;
|
|
865
925
|
}
|
|
866
|
-
if (
|
|
867
|
-
|
|
926
|
+
if (action === "catalog" && normalizedInput === "catalog") {
|
|
927
|
+
return undefined;
|
|
868
928
|
}
|
|
869
|
-
|
|
870
|
-
|
|
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
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
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
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
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
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
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
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
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 (
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
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
|
|
1200
|
-
|
|
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
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
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
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
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
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
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
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
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
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
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
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
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
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
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
|
-
|
|
1412
|
-
|
|
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
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
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
|
-
|
|
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 === "
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
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
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
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
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
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
|
-
|
|
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=
|
|
1920
|
+
//# debugId=0e9a5528-9595-5a89-89b7-5a5acce477a8
|