@unbrained/pm-cli 2026.6.24 → 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 +113 -1
- package/CONTRIBUTING.md +30 -0
- package/README.md +16 -3
- package/dist/cli/bootstrap-args.js +89 -79
- package/dist/cli/bootstrap-args.js.map +1 -1
- package/dist/cli/commander-usage.js +3 -3
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/aggregate.js +8 -7
- package/dist/cli/commands/aggregate.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/close.d.ts +2 -4
- package/dist/cli/commands/close.js +5 -17
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/completion.js +158 -9
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/config.d.ts +1 -1
- package/dist/cli/commands/config.js +2 -2
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/context.d.ts +31 -4
- package/dist/cli/commands/context.js +33 -10
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/contracts.js +48 -8
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/create.d.ts +1 -6
- package/dist/cli/commands/create.js +491 -587
- 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/describe.d.ts +15 -0
- package/dist/cli/commands/extension/describe.js +48 -2
- package/dist/cli/commands/extension/describe.js.map +1 -1
- package/dist/cli/commands/extension/doctor.js +129 -75
- package/dist/cli/commands/extension/doctor.js.map +1 -1
- package/dist/cli/commands/extension/install-sources.js +37 -7
- package/dist/cli/commands/extension/install-sources.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 +38 -8
- package/dist/cli/commands/extension/scaffold.js +1956 -242
- package/dist/cli/commands/extension/scaffold.js.map +1 -1
- package/dist/cli/commands/extension.d.ts +28 -3
- package/dist/cli/commands/extension.js +1181 -880
- package/dist/cli/commands/extension.js.map +1 -1
- package/dist/cli/commands/index.d.ts +3 -1
- package/dist/cli/commands/index.js +5 -3
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/item-filter-options.d.ts +63 -0
- package/dist/cli/commands/item-filter-options.js +10 -0
- package/dist/cli/commands/item-filter-options.js.map +1 -0
- package/dist/cli/commands/legacy-none-tokens.d.ts +14 -0
- package/dist/cli/commands/legacy-none-tokens.js +31 -2
- package/dist/cli/commands/legacy-none-tokens.js.map +1 -1
- package/dist/cli/commands/linked-artifacts.d.ts +7 -0
- package/dist/cli/commands/linked-artifacts.js +12 -2
- package/dist/cli/commands/linked-artifacts.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/list.d.ts +16 -39
- package/dist/cli/commands/list.js +127 -118
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/next.d.ts +98 -0
- package/dist/cli/commands/next.js +304 -0
- package/dist/cli/commands/next.js.map +1 -0
- package/dist/cli/commands/profile.d.ts +208 -0
- package/dist/cli/commands/profile.js +418 -0
- package/dist/cli/commands/profile.js.map +1 -0
- package/dist/cli/commands/repeatable-metadata-parsers.js +12 -13
- package/dist/cli/commands/repeatable-metadata-parsers.js.map +1 -1
- package/dist/cli/commands/schema.d.ts +7 -0
- package/dist/cli/commands/schema.js +9 -3
- package/dist/cli/commands/schema.js.map +1 -1
- package/dist/cli/commands/search.d.ts +2 -39
- package/dist/cli/commands/search.js +196 -172
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/shared-unset-fields.d.ts +30 -0
- package/dist/cli/commands/shared-unset-fields.js +161 -0
- package/dist/cli/commands/shared-unset-fields.js.map +1 -0
- package/dist/cli/commands/stats.js +15 -3
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/test.js +115 -125
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update.d.ts +1 -6
- package/dist/cli/commands/update.js +37 -232
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/validate.js +20 -5
- package/dist/cli/commands/validate.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/help-content.js +26 -2
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/help-json-payload.js +3 -3
- package/dist/cli/help-json-payload.js.map +1 -1
- package/dist/cli/main.js +27 -12
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.js +42 -3
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-mutation.js +86 -2
- package/dist/cli/register-mutation.js.map +1 -1
- package/dist/cli/register-setup.js +67 -6
- package/dist/cli/register-setup.js.map +1 -1
- package/dist/cli/registration-helpers.d.ts +9 -1
- package/dist/cli/registration-helpers.js +149 -123
- 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-N7RVTLBQ.js → activity-DBLQVIP6.js} +9 -11
- package/dist/cli-bundle/chunks/{aggregate-63NWNIBR.js → aggregate-JTEF4BP7.js} +17 -18
- package/dist/cli-bundle/chunks/aggregate-JTEF4BP7.js.map +1 -0
- package/dist/cli-bundle/chunks/{aggregate-YHCYX2EV.js → aggregate-SDF7DUOD.js} +16 -17
- package/dist/cli-bundle/chunks/aggregate-SDF7DUOD.js.map +7 -0
- package/dist/cli-bundle/chunks/{append-VLQQDHMJ.js → append-LOVPGVPT.js} +8 -10
- package/dist/cli-bundle/chunks/{append-VLQQDHMJ.js.map → append-LOVPGVPT.js.map} +1 -1
- package/dist/cli-bundle/chunks/{append-PUKREFV5.js → append-QCFJSDFL.js} +10 -12
- package/dist/cli-bundle/chunks/{append-PUKREFV5.js.map → append-QCFJSDFL.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-ABYCA5VX.js → chunk-22WKIL3H.js} +9 -11
- package/dist/cli-bundle/chunks/{chunk-ABYCA5VX.js.map → chunk-22WKIL3H.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-A66VYUOV.js → chunk-2466X6E4.js} +9 -11
- package/dist/cli-bundle/chunks/{chunk-A66VYUOV.js.map → chunk-2466X6E4.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-F32L4HR6.js → chunk-27BXPBAY.js} +3 -3
- package/dist/cli-bundle/chunks/{schema-QO5I4FBL.js → chunk-2D4HATP2.js} +136 -66
- package/dist/cli-bundle/chunks/chunk-2D4HATP2.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-J7I4C5ZB.js → chunk-3J6JRJ3I.js} +153 -125
- package/dist/cli-bundle/chunks/chunk-3J6JRJ3I.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-OHDQNKJB.js → chunk-3K2M5OYU.js} +106 -34
- package/dist/cli-bundle/chunks/chunk-3K2M5OYU.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-XVYKWZNL.js → chunk-3S2KT7NG.js} +127 -127
- package/dist/cli-bundle/chunks/chunk-3S2KT7NG.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-5BBEWX6C.js → chunk-3VGN2UWE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-N5B6WZC5.js → chunk-3XZCOZ5J.js} +115 -123
- 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-HZF5RLKX.js → chunk-4DSGXSBL.js} +5 -7
- package/dist/cli-bundle/chunks/{chunk-HZF5RLKX.js.map → chunk-4DSGXSBL.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-JV27C7OZ.js → chunk-4DUVCVLZ.js} +4 -6
- package/dist/cli-bundle/chunks/{chunk-JV27C7OZ.js.map → chunk-4DUVCVLZ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-IAP5KYBQ.js → chunk-4XOIEKSD.js} +563 -506
- package/dist/cli-bundle/chunks/chunk-4XOIEKSD.js.map +1 -0
- package/dist/cli-bundle/chunks/{context-5LB7UGKE.js → chunk-55SNVXRQ.js} +79 -82
- package/dist/cli-bundle/chunks/chunk-55SNVXRQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-BFFO3AIB.js → chunk-5CGRF3L5.js} +128 -128
- package/dist/cli-bundle/chunks/chunk-5CGRF3L5.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-JKL6HRMV.js → chunk-5QFDBI4F.js} +1260 -1046
- package/dist/cli-bundle/chunks/chunk-5QFDBI4F.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-LU36E6GU.js → chunk-64HNBBFQ.js} +8 -12
- package/dist/cli-bundle/chunks/{chunk-LU36E6GU.js.map → chunk-64HNBBFQ.js.map} +1 -1
- package/dist/cli-bundle/chunks/chunk-6AQZPVHQ.js +2444 -0
- package/dist/cli-bundle/chunks/chunk-6AQZPVHQ.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-7M2HAZEB.js +17 -0
- package/dist/cli-bundle/chunks/chunk-7M2HAZEB.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-VSAABFGQ.js → chunk-7R4QEMZZ.js} +1490 -734
- package/dist/cli-bundle/chunks/chunk-7R4QEMZZ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-M6TUBOGW.js → chunk-A7FPBAQS.js} +19 -12
- package/dist/cli-bundle/chunks/chunk-A7FPBAQS.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-GQYJEEFX.js → chunk-AVEE5EHK.js} +53 -54
- package/dist/cli-bundle/chunks/chunk-AVEE5EHK.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-FMWW2JDU.js → chunk-AXIDKKAT.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TIM4OD74.js → chunk-BDTISOSD.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-C4C3EJCJ.js → chunk-BHO33VBQ.js} +509 -363
- package/dist/cli-bundle/chunks/chunk-BHO33VBQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-6W3Y65PL.js → chunk-BZCEN4JA.js} +198 -177
- package/dist/cli-bundle/chunks/chunk-BZCEN4JA.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-RRP6D345.js → chunk-CF7RL6FR.js} +12 -16
- package/dist/cli-bundle/chunks/{chunk-RRP6D345.js.map → chunk-CF7RL6FR.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-HC2S36NB.js → chunk-CWFNTKQJ.js} +154 -126
- package/dist/cli-bundle/chunks/chunk-CWFNTKQJ.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-CZVISY5A.js +87 -0
- package/dist/cli-bundle/chunks/chunk-CZVISY5A.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-CZIFFMZI.js → chunk-DDPTYJIM.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-AYPQUFCX.js → chunk-EJUDVUYZ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-EOGBMLCE.js → chunk-EVMTBV6V.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-RAWA3Y7O.js → chunk-FFMQB7WR.js} +199 -178
- package/dist/cli-bundle/chunks/chunk-FFMQB7WR.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-CG3KP6I5.js → chunk-G7I7DEZA.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-MEXZ5XUM.js → chunk-GJ326ZKX.js} +53 -54
- package/dist/cli-bundle/chunks/chunk-GJ326ZKX.js.map +7 -0
- package/dist/cli-bundle/chunks/chunk-HPPFYYOV.js +119 -0
- package/dist/cli-bundle/chunks/chunk-HPPFYYOV.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-OF7V47P3.js → chunk-HXTQJXWT.js} +2172 -2146
- package/dist/cli-bundle/chunks/chunk-HXTQJXWT.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-F4BNR2IN.js → chunk-HYTGA6GI.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-2WCYE3IF.js → chunk-HZZEHPRG.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-IBMFIKVS.js +14 -0
- package/dist/cli-bundle/chunks/chunk-IBMFIKVS.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-YV2OSAMS.js → chunk-IJYK2T43.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4XDGYFHL.js → chunk-IPYBJWTE.js} +10 -14
- package/dist/cli-bundle/chunks/{chunk-4XDGYFHL.js.map → chunk-IPYBJWTE.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-6EBNFQOR.js → chunk-IZBR4NRW.js} +10 -14
- package/dist/cli-bundle/chunks/{chunk-6EBNFQOR.js.map → chunk-IZBR4NRW.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-VFJYVXHL.js → chunk-JLM7BHI7.js} +7 -9
- package/dist/cli-bundle/chunks/{chunk-VFJYVXHL.js.map → chunk-JLM7BHI7.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-6EL7SW5C.js → chunk-JMP4E6D7.js} +114 -122
- package/dist/cli-bundle/chunks/chunk-JMP4E6D7.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-QOUOMPHO.js → chunk-JPECA746.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-KJZOSF7J.js → chunk-JSU5P7VS.js} +100 -35
- package/dist/cli-bundle/chunks/chunk-JSU5P7VS.js.map +1 -0
- package/dist/cli-bundle/chunks/{context-55VEOYI3.js → chunk-JWXRETDF.js} +79 -82
- package/dist/cli-bundle/chunks/chunk-JWXRETDF.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-OQ2E64FH.js → chunk-KNPEF7QG.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-3BKH2CL3.js → chunk-L5OEFZQG.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-DTABLLVE.js → chunk-LB6TP6MC.js} +5 -7
- package/dist/cli-bundle/chunks/{chunk-DTABLLVE.js.map → chunk-LB6TP6MC.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TSI32UEL.js → chunk-MAUKX7JC.js} +6 -8
- package/dist/cli-bundle/chunks/{chunk-TSI32UEL.js.map → chunk-MAUKX7JC.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-SMXSDY7J.js → chunk-MDPEOIGN.js} +2221 -2172
- package/dist/cli-bundle/chunks/chunk-MDPEOIGN.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-5S4ZGDB2.js → chunk-N74UMG5H.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-IXAZI443.js → chunk-NFDPYAIP.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-SKC4UTRP.js → chunk-NKZAN7BD.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-NOLPZMSV.js +116 -0
- package/dist/cli-bundle/chunks/chunk-NOLPZMSV.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-L7UXKP2I.js → chunk-NU2UEROZ.js} +1257 -1029
- package/dist/cli-bundle/chunks/chunk-NU2UEROZ.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-HBAEFWX3.js → chunk-NUHHPVVS.js} +65 -335
- package/dist/cli-bundle/chunks/chunk-NUHHPVVS.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-JPJDP4VU.js → chunk-NWMZWYYB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-MWMHZOZZ.js → chunk-OGXLACHC.js} +10 -14
- package/dist/cli-bundle/chunks/{chunk-MWMHZOZZ.js.map → chunk-OGXLACHC.js.map} +1 -1
- package/dist/cli-bundle/chunks/chunk-OKQ22KTH.js +379 -0
- package/dist/cli-bundle/chunks/chunk-OKQ22KTH.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-KKX4Z2SE.js → chunk-OTUHB4HS.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-ZLWRPBOW.js → chunk-QCWF6IYD.js} +510 -364
- package/dist/cli-bundle/chunks/chunk-QCWF6IYD.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-PRVTGX64.js → chunk-RGEMWD6Q.js} +11 -23
- package/dist/cli-bundle/chunks/chunk-RGEMWD6Q.js.map +7 -0
- 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-ALQKV6U7.js → chunk-RLDHZHQS.js} +12 -16
- package/dist/cli-bundle/chunks/{chunk-ALQKV6U7.js.map → chunk-RLDHZHQS.js.map} +1 -1
- package/dist/cli-bundle/chunks/{schema-C6QA367T.js → chunk-RMMQ74TG.js} +144 -67
- package/dist/cli-bundle/chunks/chunk-RMMQ74TG.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-EYPINTFR.js → chunk-RVUALSJF.js} +1516 -753
- package/dist/cli-bundle/chunks/chunk-RVUALSJF.js.map +7 -0
- package/dist/cli-bundle/chunks/chunk-SDR5J34Q.js +2468 -0
- package/dist/cli-bundle/chunks/chunk-SDR5J34Q.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-WB5BYQMF.js → chunk-SLMUGTK3.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-SUREE24M.js → chunk-TP5Q5ZD3.js} +12 -24
- package/dist/cli-bundle/chunks/chunk-TP5Q5ZD3.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-UACWNBL2.js → chunk-UYUYDGIB.js} +7 -9
- package/dist/cli-bundle/chunks/{chunk-UACWNBL2.js.map → chunk-UYUYDGIB.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-V4UYNSEM.js → chunk-UZIWVBE6.js} +6 -8
- package/dist/cli-bundle/chunks/{chunk-V4UYNSEM.js.map → chunk-UZIWVBE6.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-EWRSXOIZ.js → chunk-V3NOKJF2.js} +11 -13
- package/dist/cli-bundle/chunks/{chunk-EWRSXOIZ.js.map → chunk-V3NOKJF2.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-XXKV4UWE.js → chunk-VARHOHYV.js} +571 -507
- package/dist/cli-bundle/chunks/chunk-VARHOHYV.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-AEACLRVH.js → chunk-VICZWYGZ.js} +18 -11
- package/dist/cli-bundle/chunks/chunk-VICZWYGZ.js.map +7 -0
- 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-VZDBVEZR.js +382 -0
- package/dist/cli-bundle/chunks/chunk-VZDBVEZR.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-GDUMGZK3.js → chunk-W4ULYO7Z.js} +11 -13
- package/dist/cli-bundle/chunks/{chunk-GDUMGZK3.js.map → chunk-W4ULYO7Z.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-I6QMJ2XT.js → chunk-WYDHYJPO.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ALKFCIIB.js → chunk-YITK2PJ6.js} +9 -11
- package/dist/cli-bundle/chunks/{chunk-ALKFCIIB.js.map → chunk-YITK2PJ6.js.map} +1 -1
- package/dist/cli-bundle/chunks/chunk-YJIEJRZB.js +84 -0
- package/dist/cli-bundle/chunks/chunk-YJIEJRZB.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-LNEDHJNQ.js → chunk-ZETXE4SE.js} +66 -329
- package/dist/cli-bundle/chunks/chunk-ZETXE4SE.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-KIEAK7YE.js → chunk-ZRP4VG5U.js} +2 -2
- package/dist/cli-bundle/chunks/{claim-FZZZCAY6.js → claim-EMQLYPRW.js} +10 -12
- package/dist/cli-bundle/chunks/{claim-FZZZCAY6.js.map → claim-EMQLYPRW.js.map} +1 -1
- package/dist/cli-bundle/chunks/{claim-XK5QBZE3.js → claim-T3GCKV7C.js} +8 -10
- package/dist/cli-bundle/chunks/{claim-XK5QBZE3.js.map → claim-T3GCKV7C.js.map} +1 -1
- package/dist/cli-bundle/chunks/close-E6ZZGCJY.js +14 -0
- package/dist/cli-bundle/chunks/{close-QHMVWM7M.js → close-TQYAAFJP.js} +7 -8
- package/dist/cli-bundle/chunks/{close-many-OIXJE2JZ.js → close-many-BG5QQIDQ.js} +16 -18
- package/dist/cli-bundle/chunks/{close-many-OIXJE2JZ.js.map → close-many-BG5QQIDQ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{close-many-SUU5BS2C.js → close-many-LDRVEQY2.js} +18 -20
- package/dist/cli-bundle/chunks/{close-many-SUU5BS2C.js.map → close-many-LDRVEQY2.js.map} +1 -1
- package/dist/cli-bundle/chunks/{comments-5YM62D75.js → comments-QCKR2YY2.js} +11 -13
- package/dist/cli-bundle/chunks/{comments-5YM62D75.js.map → comments-QCKR2YY2.js.map} +1 -1
- package/dist/cli-bundle/chunks/{comments-RH3IBIRH.js → comments-YUXJRZPQ.js} +9 -11
- package/dist/cli-bundle/chunks/{comments-RH3IBIRH.js.map → comments-YUXJRZPQ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{config-NCNNWF6R.js → config-DMSU64QO.js} +18 -387
- package/dist/cli-bundle/chunks/config-DMSU64QO.js.map +7 -0
- package/dist/cli-bundle/chunks/{config-SW3U7XP2.js → config-QH2DICD6.js} +18 -380
- package/dist/cli-bundle/chunks/config-QH2DICD6.js.map +1 -0
- package/dist/cli-bundle/chunks/context-B6275WPX.js +46 -0
- package/dist/cli-bundle/chunks/context-OCZ3FJ4Z.js +42 -0
- package/dist/cli-bundle/chunks/{contracts-SY6PDFIK.js → contracts-HN7ABKLP.js} +72 -15
- package/dist/cli-bundle/chunks/contracts-HN7ABKLP.js.map +7 -0
- package/dist/cli-bundle/chunks/{contracts-JXFGBOYT.js → contracts-W4FZVVD6.js} +72 -15
- package/dist/cli-bundle/chunks/contracts-W4FZVVD6.js.map +1 -0
- package/dist/cli-bundle/chunks/{copy-N3GE6FYS.js → copy-BTJOSKKT.js} +7 -11
- package/dist/cli-bundle/chunks/{copy-N3GE6FYS.js.map → copy-BTJOSKKT.js.map} +1 -1
- package/dist/cli-bundle/chunks/{copy-IEDBJOOX.js → copy-DEM4DATS.js} +9 -13
- package/dist/cli-bundle/chunks/{copy-IEDBJOOX.js.map → copy-DEM4DATS.js.map} +1 -1
- package/dist/cli-bundle/chunks/create-OH3BDGBB.js +28 -0
- package/dist/cli-bundle/chunks/{create-O4VONGPG.js → create-RLRJMRTM.js} +12 -14
- package/dist/cli-bundle/chunks/{delete-LPEIF7RU.js → delete-BHK7VB2Z.js} +5 -7
- package/dist/cli-bundle/chunks/{delete-LPEIF7RU.js.map → delete-BHK7VB2Z.js.map} +1 -1
- package/dist/cli-bundle/chunks/{delete-724EQ6OS.js → delete-LSVHAB4Y.js} +7 -9
- package/dist/cli-bundle/chunks/{delete-724EQ6OS.js.map → delete-LSVHAB4Y.js.map} +1 -1
- package/dist/cli-bundle/chunks/{deps-RSBU4SIU.js → deps-4UDFJRUA.js} +8 -11
- package/dist/cli-bundle/chunks/{deps-RSBU4SIU.js.map → deps-4UDFJRUA.js.map} +1 -1
- package/dist/cli-bundle/chunks/{deps-T3Y6Y7RT.js → deps-XHYXWEPT.js} +6 -9
- package/dist/cli-bundle/chunks/{deps-T3Y6Y7RT.js.map → deps-XHYXWEPT.js.map} +1 -1
- package/dist/cli-bundle/chunks/{docs-IFS7HZPP.js → docs-26S44RXU.js} +8 -9
- package/dist/cli-bundle/chunks/{docs-IFS7HZPP.js.map → docs-26S44RXU.js.map} +1 -1
- package/dist/cli-bundle/chunks/{docs-75ZLCO3G.js → docs-GYZNVS26.js} +10 -11
- package/dist/cli-bundle/chunks/{docs-75ZLCO3G.js.map → docs-GYZNVS26.js.map} +1 -1
- package/dist/cli-bundle/chunks/{eval-L2KD7W3M.js → eval-PGRVIJQU.js} +12 -14
- package/dist/cli-bundle/chunks/{eval-L2KD7W3M.js.map → eval-PGRVIJQU.js.map} +1 -1
- package/dist/cli-bundle/chunks/{eval-QGR7JCQO.js → eval-UYF3ZPVO.js} +10 -12
- package/dist/cli-bundle/chunks/{eval-QGR7JCQO.js.map → eval-UYF3ZPVO.js.map} +1 -1
- package/dist/cli-bundle/chunks/{extension-YQF4CPIR.js → extension-CPSLJQVE.js} +12 -7
- package/dist/cli-bundle/chunks/{extension-3JYWJ5K2.js → extension-CXJ6RELI.js} +12 -7
- package/dist/cli-bundle/chunks/{files-EPEJMJHQ.js → files-MBNICQFM.js} +9 -11
- package/dist/cli-bundle/chunks/{files-EPEJMJHQ.js.map → files-MBNICQFM.js.map} +1 -1
- package/dist/cli-bundle/chunks/{files-5BQWDRDT.js → files-NQHEXUZD.js} +11 -13
- package/dist/cli-bundle/chunks/{files-5BQWDRDT.js.map → files-NQHEXUZD.js.map} +1 -1
- package/dist/cli-bundle/chunks/{focus-RWGKD76E.js → focus-DWYIG7GU.js} +10 -14
- package/dist/cli-bundle/chunks/{focus-RWGKD76E.js.map → focus-DWYIG7GU.js.map} +1 -1
- package/dist/cli-bundle/chunks/{focus-DQVJAPOE.js → focus-XZW5423D.js} +8 -12
- package/dist/cli-bundle/chunks/{focus-DQVJAPOE.js.map → focus-XZW5423D.js.map} +1 -1
- package/dist/cli-bundle/chunks/{gc-BEJMQT64.js → gc-7GQYOS2G.js} +3 -3
- package/dist/cli-bundle/chunks/{gc-JEFQDJPA.js → gc-LPVMKJQJ.js} +3 -3
- package/dist/cli-bundle/chunks/{get-LQG6PEVG.js → get-A7MAOHCU.js} +10 -13
- package/dist/cli-bundle/chunks/{get-LQG6PEVG.js.map → get-A7MAOHCU.js.map} +1 -1
- package/dist/cli-bundle/chunks/{get-WVN75H42.js → get-DSDEKJ3L.js} +12 -15
- package/dist/cli-bundle/chunks/{get-WVN75H42.js.map → get-DSDEKJ3L.js.map} +1 -1
- package/dist/cli-bundle/chunks/{health-JJJOY7DJ.js → health-3IPFLKXB.js} +17 -17
- package/dist/cli-bundle/chunks/{health-P67NZ6TT.js → health-GZXGBZ36.js} +17 -17
- package/dist/cli-bundle/chunks/{history-RUKPKNY7.js → history-NERDJNUB.js} +8 -10
- package/dist/cli-bundle/chunks/history-WSZHY3PN.js +18 -0
- package/dist/cli-bundle/chunks/{history-compact-NQ7VPRVT.js → history-compact-2WRZ2WK4.js} +11 -14
- package/dist/cli-bundle/chunks/{history-compact-NQ7VPRVT.js.map → history-compact-2WRZ2WK4.js.map} +1 -1
- package/dist/cli-bundle/chunks/{history-compact-ZAOWR7GD.js → history-compact-HR7BB4LR.js} +13 -16
- package/dist/cli-bundle/chunks/{history-compact-ZAOWR7GD.js.map → history-compact-HR7BB4LR.js.map} +1 -1
- package/dist/cli-bundle/chunks/history-redact-MP6CH7U5.js +19 -0
- package/dist/cli-bundle/chunks/{history-redact-YY4XYVEP.js → history-redact-O3NBCNWC.js} +9 -11
- package/dist/cli-bundle/chunks/{history-repair-EHL4ODQY.js → history-repair-LCMOS45X.js} +11 -14
- package/dist/cli-bundle/chunks/{history-repair-EHL4ODQY.js.map → history-repair-LCMOS45X.js.map} +1 -1
- package/dist/cli-bundle/chunks/{history-repair-YSQH6SY6.js → history-repair-XA3LC4GA.js} +13 -16
- package/dist/cli-bundle/chunks/{history-repair-YSQH6SY6.js.map → history-repair-XA3LC4GA.js.map} +1 -1
- package/dist/cli-bundle/chunks/{init-HBFGYS66.js → init-64XDLQJB.js} +12 -11
- package/dist/cli-bundle/chunks/init-PAX32BJA.js +22 -0
- package/dist/cli-bundle/chunks/{learnings-KFQO7GEZ.js → learnings-JR6MA5TI.js} +9 -11
- package/dist/cli-bundle/chunks/{learnings-KFQO7GEZ.js.map → learnings-JR6MA5TI.js.map} +1 -1
- package/dist/cli-bundle/chunks/{learnings-J555ZFPD.js → learnings-LPKCSJX7.js} +11 -13
- package/dist/cli-bundle/chunks/{learnings-J555ZFPD.js.map → learnings-LPKCSJX7.js.map} +1 -1
- package/dist/cli-bundle/chunks/{list-C7R33MD5.js → list-DNBJVO3E.js} +10 -10
- package/dist/cli-bundle/chunks/{list-DSN6UNFB.js → list-G5Y65VF6.js} +10 -10
- package/dist/cli-bundle/chunks/next-BCERKDUR.js +277 -0
- package/dist/cli-bundle/chunks/next-BCERKDUR.js.map +7 -0
- package/dist/cli-bundle/chunks/next-FYTQF6HG.js +274 -0
- package/dist/cli-bundle/chunks/next-FYTQF6HG.js.map +1 -0
- package/dist/cli-bundle/chunks/{notes-V4VNIQL4.js → notes-2BMU3VVQ.js} +9 -11
- package/dist/cli-bundle/chunks/{notes-V4VNIQL4.js.map → notes-2BMU3VVQ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{notes-VYJFN2A3.js → notes-6KTGO2OJ.js} +11 -13
- package/dist/cli-bundle/chunks/{notes-VYJFN2A3.js.map → notes-6KTGO2OJ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{plan-RBHQ5PO7.js → plan-4WXEQCTN.js} +15 -18
- package/dist/cli-bundle/chunks/{plan-RBHQ5PO7.js.map → plan-4WXEQCTN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{plan-DHRSVSHR.js → plan-RKZHQVXR.js} +17 -20
- package/dist/cli-bundle/chunks/{plan-DHRSVSHR.js.map → plan-RKZHQVXR.js.map} +1 -1
- package/dist/cli-bundle/chunks/profile-4OMM32CD.js +1235 -0
- package/dist/cli-bundle/chunks/profile-4OMM32CD.js.map +7 -0
- package/dist/cli-bundle/chunks/profile-QLER5ENE.js +1197 -0
- package/dist/cli-bundle/chunks/profile-QLER5ENE.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-list-query-OM3E2KMY.js → register-list-query-7LV46VAU.js} +45 -21
- package/dist/cli-bundle/chunks/register-list-query-7LV46VAU.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-list-query-CCMHGZTF.js → register-list-query-SNG5PGA4.js} +44 -20
- package/dist/cli-bundle/chunks/register-list-query-SNG5PGA4.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-mutation-N3CDEGZU.js → register-mutation-ENNDUAZG.js} +106 -40
- package/dist/cli-bundle/chunks/register-mutation-ENNDUAZG.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-mutation-UXTTWL6N.js → register-mutation-KK7PHYYU.js} +105 -39
- package/dist/cli-bundle/chunks/register-mutation-KK7PHYYU.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-operations-UDIFMQKD.js → register-operations-C6OWLDSH.js} +32 -34
- package/dist/cli-bundle/chunks/{register-operations-UDIFMQKD.js.map → register-operations-C6OWLDSH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-operations-R2FLOCRI.js → register-operations-HZ6XERQG.js} +30 -32
- package/dist/cli-bundle/chunks/{register-operations-R2FLOCRI.js.map → register-operations-HZ6XERQG.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-G5LTSFYK.js → register-setup-P67EMBDJ.js} +68 -25
- package/dist/cli-bundle/chunks/register-setup-P67EMBDJ.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-setup-TWHKICM2.js → register-setup-ZKJ53RS7.js} +67 -24
- package/dist/cli-bundle/chunks/register-setup-ZKJ53RS7.js.map +7 -0
- package/dist/cli-bundle/chunks/{restore-LL2WLEDG.js → restore-4MHZFJ2E.js} +9 -11
- package/dist/cli-bundle/chunks/restore-YALDGTQR.js +17 -0
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-M4H2ZI64.js → scheduling-shortcuts-LB6DOLRL.js} +14 -16
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-M4H2ZI64.js.map → scheduling-shortcuts-LB6DOLRL.js.map} +1 -1
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-255GI3BU.js → scheduling-shortcuts-UTOYKLXQ.js} +12 -14
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-255GI3BU.js.map → scheduling-shortcuts-UTOYKLXQ.js.map} +1 -1
- package/dist/cli-bundle/chunks/schema-73HR2OJW.js +75 -0
- package/dist/cli-bundle/chunks/schema-U6LJKSIR.js +71 -0
- package/dist/cli-bundle/chunks/{search-2EI6EAXH.js → search-AXPXKZER.js} +10 -12
- package/dist/cli-bundle/chunks/{search-QBFBLQRO.js → search-KILGT37L.js} +10 -12
- package/dist/cli-bundle/chunks/{stats-TKC6CAKB.js → stats-PSYVVTNZ.js} +21 -13
- package/dist/cli-bundle/chunks/stats-PSYVVTNZ.js.map +1 -0
- package/dist/cli-bundle/chunks/{stats-TCW2SZQG.js → stats-W5KNVJWQ.js} +20 -12
- package/dist/cli-bundle/chunks/stats-W5KNVJWQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{telemetry-BT2VSWU2.js → telemetry-BZUF6H7G.js} +4 -4
- package/dist/cli-bundle/chunks/{telemetry-LQ6FRTUT.js → telemetry-GAHHQTOS.js} +4 -4
- package/dist/cli-bundle/chunks/test-ACD52Z3S.js +35 -0
- package/dist/cli-bundle/chunks/test-ACD52Z3S.js.map +7 -0
- package/dist/cli-bundle/chunks/{test-NV2DRPUS.js → test-PWDIZ255.js} +15 -16
- package/dist/cli-bundle/chunks/test-PWDIZ255.js.map +1 -0
- package/dist/cli-bundle/chunks/{test-all-DZ76VTPQ.js → test-all-L2MDDUCA.js} +20 -22
- package/dist/cli-bundle/chunks/{test-all-DZ76VTPQ.js.map → test-all-L2MDDUCA.js.map} +1 -1
- package/dist/cli-bundle/chunks/{test-all-REW67LXT.js → test-all-RBZ6DLU2.js} +18 -20
- package/dist/cli-bundle/chunks/{test-all-REW67LXT.js.map → test-all-RBZ6DLU2.js.map} +1 -1
- package/dist/cli-bundle/chunks/{test-runs-PX73DMMI.js → test-runs-PLRAZEFW.js} +5 -6
- package/dist/cli-bundle/chunks/test-runs-PLRAZEFW.js.map +7 -0
- package/dist/cli-bundle/chunks/{test-runs-FQ5WNQLP.js → test-runs-UXIXPDKU.js} +6 -7
- package/dist/cli-bundle/chunks/test-runs-UXIXPDKU.js.map +1 -0
- package/dist/cli-bundle/chunks/update-AMRSOIWP.js +24 -0
- package/dist/cli-bundle/chunks/update-AMRSOIWP.js.map +7 -0
- package/dist/cli-bundle/chunks/update-KFX2SIAC.js +28 -0
- package/dist/cli-bundle/chunks/update-KFX2SIAC.js.map +1 -0
- package/dist/cli-bundle/chunks/{update-many-Q5ZEI64S.js → update-many-RNSBX2TA.js} +35 -36
- package/dist/cli-bundle/chunks/{update-many-Q5ZEI64S.js.map → update-many-RNSBX2TA.js.map} +1 -1
- package/dist/cli-bundle/chunks/{update-many-2ILP6E4Y.js → update-many-Z5GJS5LC.js} +33 -34
- package/dist/cli-bundle/chunks/{update-many-2ILP6E4Y.js.map → update-many-Z5GJS5LC.js.map} +1 -1
- package/dist/cli-bundle/chunks/{upgrade-FOZKQTQF.js → upgrade-BRL6KCOJ.js} +13 -8
- package/dist/cli-bundle/chunks/{upgrade-FOZKQTQF.js.map → upgrade-BRL6KCOJ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{upgrade-DHL74PQH.js → upgrade-HAK6JG2O.js} +11 -6
- package/dist/cli-bundle/chunks/{upgrade-DHL74PQH.js.map → upgrade-HAK6JG2O.js.map} +1 -1
- package/dist/cli-bundle/chunks/{validate-HYZNIB6W.js → validate-MTUVL5VC.js} +38 -28
- package/dist/cli-bundle/chunks/validate-MTUVL5VC.js.map +7 -0
- package/dist/cli-bundle/chunks/{validate-54SYJ7QW.js → validate-X5W76YJL.js} +39 -29
- package/dist/cli-bundle/chunks/validate-X5W76YJL.js.map +1 -0
- package/dist/cli-bundle/main.js +95 -724
- package/dist/cli-bundle/main.js.map +4 -4
- package/dist/core/config/positional-value.d.ts +2 -0
- package/dist/core/config/positional-value.js +2 -2
- package/dist/core/config/positional-value.js.map +1 -1
- package/dist/core/extensions/activation-summary-markdown.d.ts +71 -0
- package/dist/core/extensions/activation-summary-markdown.js +151 -0
- package/dist/core/extensions/activation-summary-markdown.js.map +1 -0
- package/dist/core/extensions/activation-summary.d.ts +2 -0
- package/dist/core/extensions/activation-summary.js +3 -2
- package/dist/core/extensions/activation-summary.js.map +1 -1
- package/dist/core/extensions/capability-usage.d.ts +1 -1
- package/dist/core/extensions/capability-usage.js +4 -3
- package/dist/core/extensions/capability-usage.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/extension-registries.js +3 -2
- package/dist/core/extensions/extension-registries.js.map +1 -1
- package/dist/core/extensions/extension-types.d.ts +21 -1
- package/dist/core/extensions/extension-types.js +3 -2
- package/dist/core/extensions/extension-types.js.map +1 -1
- package/dist/core/extensions/loader.js +439 -232
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/fs/fs-utils.js +27 -2
- package/dist/core/fs/fs-utils.js.map +1 -1
- package/dist/core/item/actionability.d.ts +57 -0
- package/dist/core/item/actionability.js +178 -0
- package/dist/core/item/actionability.js.map +1 -0
- package/dist/core/item/item-format.js +523 -410
- package/dist/core/item/item-format.js.map +1 -1
- package/dist/core/item/type-registry.js +18 -45
- package/dist/core/item/type-registry.js.map +1 -1
- package/dist/core/profile/profile-describe.d.ts +64 -0
- package/dist/core/profile/profile-describe.js +83 -0
- package/dist/core/profile/profile-describe.js.map +1 -0
- package/dist/core/profile/profile-lint.d.ts +53 -0
- package/dist/core/profile/profile-lint.js +422 -0
- package/dist/core/profile/profile-lint.js.map +1 -0
- package/dist/core/profile/profile-plan.d.ts +145 -0
- package/dist/core/profile/profile-plan.js +0 -0
- package/dist/core/profile/profile-plan.js.map +1 -0
- package/dist/core/profile/profile-presets.d.ts +218 -0
- package/dist/core/profile/profile-presets.js +325 -0
- package/dist/core/profile/profile-presets.js.map +1 -0
- package/dist/core/schema/fields-file.js +25 -25
- package/dist/core/schema/fields-file.js.map +1 -1
- package/dist/core/schema/item-types-file.js +3 -3
- package/dist/core/schema/item-types-file.js.map +1 -1
- package/dist/core/schema/runtime-schema.js +4 -4
- package/dist/core/schema/runtime-schema.js.map +1 -1
- package/dist/core/schema/status-defs-file.js +3 -3
- package/dist/core/schema/status-defs-file.js.map +1 -1
- package/dist/core/shared/serialization.js +83 -62
- package/dist/core/shared/serialization.js.map +1 -1
- package/dist/core/store/item-store.d.ts +1 -0
- package/dist/core/store/item-store.js +16 -8
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/core/store/paths.js +4 -32
- package/dist/core/store/paths.js.map +1 -1
- package/dist/core/store/settings.js +14 -14
- package/dist/core/store/settings.js.map +1 -1
- package/dist/core/telemetry/observability.js +50 -54
- package/dist/core/telemetry/observability.js.map +1 -1
- package/dist/core/telemetry/runtime.js +11 -2
- package/dist/core/telemetry/runtime.js.map +1 -1
- package/dist/core/test/background-runs.js +3 -2
- package/dist/core/test/background-runs.js.map +1 -1
- package/dist/core/validate/linked-artifact-reference.d.ts +24 -0
- package/dist/core/validate/linked-artifact-reference.js +41 -0
- package/dist/core/validate/linked-artifact-reference.js.map +1 -0
- package/dist/mcp/server.js +540 -420
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tool-definitions.js +33 -2
- package/dist/mcp/tool-definitions.js.map +1 -1
- package/dist/sdk/cli-contracts/commander-types.d.ts +1 -0
- package/dist/sdk/cli-contracts/commander-types.js +15 -2
- package/dist/sdk/cli-contracts/commander-types.js.map +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +3 -3
- package/dist/sdk/cli-contracts/enum-contracts.js +6 -2
- package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.d.ts +149 -0
- package/dist/sdk/cli-contracts/flag-contracts.js +1514 -0
- package/dist/sdk/cli-contracts/flag-contracts.js.map +1 -0
- package/dist/sdk/cli-contracts/string-lists.d.ts +14 -0
- package/dist/sdk/cli-contracts/string-lists.js +20 -0
- package/dist/sdk/cli-contracts/string-lists.js.map +1 -0
- package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/tool-option-contracts.js +51 -109
- package/dist/sdk/cli-contracts/tool-option-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.d.ts +17 -0
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +54 -5
- package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-schema.d.ts +74 -0
- package/dist/sdk/cli-contracts/tool-schema.js +871 -0
- package/dist/sdk/cli-contracts/tool-schema.js.map +1 -0
- package/dist/sdk/cli-contracts.d.ts +13 -193
- package/dist/sdk/cli-contracts.js +5 -2277
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/sdk/compose.d.ts +11 -5
- package/dist/sdk/compose.js +240 -124
- package/dist/sdk/compose.js.map +1 -1
- package/dist/sdk/define.d.ts +14 -0
- package/dist/sdk/define.js +17 -2
- package/dist/sdk/define.js.map +1 -1
- package/dist/sdk/index.d.ts +14 -3
- package/dist/sdk/index.js +14 -3
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/testing.d.ts +82 -2
- package/dist/sdk/testing.js +74 -3
- package/dist/sdk/testing.js.map +1 -1
- package/docs/AGENT_GUIDE.md +2 -0
- package/docs/CLAUDE_CODE_PLUGIN.md +2 -2
- package/docs/COMMANDS.md +37 -0
- package/docs/EXTENSIONS.md +12 -13
- package/docs/RELEASING.md +8 -4
- package/docs/SDK.md +184 -17
- package/docs/TESTING.md +12 -0
- package/docs/examples/policy-restricted-extension/README.md +6 -0
- package/docs/examples/policy-restricted-extension/index.ts +40 -0
- package/docs/examples/policy-restricted-extension/manifest.json +2 -2
- package/docs/examples/starter-extension/README.md +14 -2
- package/docs/examples/starter-extension/{index.js → index.ts} +51 -6
- package/docs/examples/starter-extension/manifest.json +2 -2
- package/package.json +20 -7
- package/packages/pm-beads/extensions/beads/index.ts +3 -3
- package/packages/pm-beads/extensions/beads/manifest.json +2 -2
- package/packages/pm-beads/extensions/beads/runtime-loader.ts +19 -7
- package/packages/pm-beads/extensions/beads/runtime.ts +155 -37
- package/packages/pm-calendar/extensions/calendar/index.ts +3 -3
- package/packages/pm-calendar/extensions/calendar/manifest.json +2 -2
- package/packages/pm-calendar/extensions/calendar/runtime.ts +2 -2
- package/packages/pm-command-kit/extensions/command-kit/index.ts +1 -1
- package/packages/pm-command-kit/extensions/command-kit/manifest.json +2 -2
- package/packages/pm-governance-audit/extensions/governance-audit/index.ts +2 -2
- package/packages/pm-governance-audit/extensions/governance-audit/manifest.json +2 -2
- package/packages/pm-governance-audit/extensions/governance-audit/runtime.ts +1 -1
- package/packages/pm-guide-shell/extensions/guide-shell/index.ts +2 -2
- package/packages/pm-guide-shell/extensions/guide-shell/manifest.json +2 -2
- package/packages/pm-guide-shell/extensions/guide-shell/runtime.ts +1 -1
- package/packages/pm-kanban/README.md +97 -0
- package/packages/pm-kanban/extensions/kanban/index.ts +191 -0
- package/packages/pm-kanban/extensions/kanban/manifest.json +19 -0
- package/packages/pm-kanban/package.json +57 -0
- package/packages/pm-lifecycle-hooks/extensions/lifecycle-hooks/index.ts +1 -1
- package/packages/pm-lifecycle-hooks/extensions/lifecycle-hooks/manifest.json +2 -2
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/index.ts +2 -2
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/manifest.json +2 -2
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.ts +1 -1
- package/packages/pm-search-advanced/extensions/search-advanced/index.ts +2 -2
- package/packages/pm-search-advanced/extensions/search-advanced/manifest.json +2 -2
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +1 -1
- package/packages/pm-templates/extensions/templates/index.ts +2 -2
- package/packages/pm-templates/extensions/templates/manifest.json +2 -2
- package/packages/pm-templates/extensions/templates/runtime.ts +1 -1
- package/packages/pm-todos/extensions/todos/index.ts +3 -3
- package/packages/pm-todos/extensions/todos/manifest.json +2 -2
- package/packages/pm-todos/extensions/todos/runtime-loader.ts +19 -7
- package/packages/pm-todos/extensions/todos/runtime.ts +177 -43
- package/plugins/pm-claude/scripts/pm-mcp-server.mjs +2 -2
- package/plugins/pm-codex/scripts/pm-mcp-server.mjs +2 -2
- package/scripts/bundle-cli.mjs +1 -1
- package/dist/cli-bundle/chunks/activity-54TXGJ2T.js +0 -18
- package/dist/cli-bundle/chunks/aggregate-63NWNIBR.js.map +0 -1
- package/dist/cli-bundle/chunks/aggregate-YHCYX2EV.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-6EL7SW5C.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-6W3Y65PL.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-AEACLRVH.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-B74BP6IS.js +0 -78
- package/dist/cli-bundle/chunks/chunk-B74BP6IS.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-BFFO3AIB.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-C4C3EJCJ.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-EYPINTFR.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-FBLT6WGK.js +0 -75
- package/dist/cli-bundle/chunks/chunk-FBLT6WGK.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-GQYJEEFX.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-HBAEFWX3.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-HC2S36NB.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-IAP5KYBQ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-INPHFO33.js +0 -764
- package/dist/cli-bundle/chunks/chunk-INPHFO33.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-IOT6WRL5.js +0 -86
- package/dist/cli-bundle/chunks/chunk-IOT6WRL5.js.map +0 -7
- 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-J3NMWFIN.js +0 -115
- package/dist/cli-bundle/chunks/chunk-J3NMWFIN.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-J7I4C5ZB.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-JKL6HRMV.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-KJZOSF7J.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-L7UXKP2I.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-LNEDHJNQ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-M6TUBOGW.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-MEXZ5XUM.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-N5B6WZC5.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-NJ73ALW2.js +0 -761
- package/dist/cli-bundle/chunks/chunk-NJ73ALW2.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-NVXGVEFD.js +0 -83
- package/dist/cli-bundle/chunks/chunk-NVXGVEFD.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-OF7V47P3.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-OHDQNKJB.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-PEL2NLQE.js +0 -118
- package/dist/cli-bundle/chunks/chunk-PEL2NLQE.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-PRVTGX64.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-RAWA3Y7O.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-SMXSDY7J.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-SUREE24M.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-TKPP4GOO.js +0 -654
- package/dist/cli-bundle/chunks/chunk-TKPP4GOO.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-VSAABFGQ.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-XVYKWZNL.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-XXKV4UWE.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-ZLWRPBOW.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-ZV7IQ23N.js +0 -657
- package/dist/cli-bundle/chunks/chunk-ZV7IQ23N.js.map +0 -7
- package/dist/cli-bundle/chunks/close-JEBZXONN.js +0 -15
- package/dist/cli-bundle/chunks/config-NCNNWF6R.js.map +0 -7
- package/dist/cli-bundle/chunks/config-SW3U7XP2.js.map +0 -1
- package/dist/cli-bundle/chunks/context-55VEOYI3.js.map +0 -1
- package/dist/cli-bundle/chunks/context-5LB7UGKE.js.map +0 -7
- package/dist/cli-bundle/chunks/contracts-JXFGBOYT.js.map +0 -1
- package/dist/cli-bundle/chunks/contracts-SY6PDFIK.js.map +0 -7
- package/dist/cli-bundle/chunks/create-CLSCHGJJ.js +0 -30
- package/dist/cli-bundle/chunks/history-ALTM2RRP.js +0 -20
- package/dist/cli-bundle/chunks/history-redact-5YGLWUDH.js +0 -21
- package/dist/cli-bundle/chunks/init-C4CRHW22.js +0 -21
- package/dist/cli-bundle/chunks/register-list-query-CCMHGZTF.js.map +0 -7
- package/dist/cli-bundle/chunks/register-list-query-OM3E2KMY.js.map +0 -1
- package/dist/cli-bundle/chunks/register-mutation-N3CDEGZU.js.map +0 -1
- package/dist/cli-bundle/chunks/register-mutation-UXTTWL6N.js.map +0 -7
- package/dist/cli-bundle/chunks/register-setup-G5LTSFYK.js.map +0 -1
- package/dist/cli-bundle/chunks/register-setup-TWHKICM2.js.map +0 -7
- package/dist/cli-bundle/chunks/restore-LQHXBAY5.js +0 -19
- package/dist/cli-bundle/chunks/schema-C6QA367T.js.map +0 -7
- package/dist/cli-bundle/chunks/schema-QO5I4FBL.js.map +0 -1
- package/dist/cli-bundle/chunks/stats-TCW2SZQG.js.map +0 -7
- package/dist/cli-bundle/chunks/stats-TKC6CAKB.js.map +0 -1
- package/dist/cli-bundle/chunks/test-WA6RZGM2.js +0 -36
- package/dist/cli-bundle/chunks/test-runs-FQ5WNQLP.js.map +0 -1
- package/dist/cli-bundle/chunks/test-runs-PX73DMMI.js.map +0 -7
- package/dist/cli-bundle/chunks/update-BSKMQOYH.js +0 -28
- package/dist/cli-bundle/chunks/update-FIGYNQ2I.js +0 -24
- package/dist/cli-bundle/chunks/validate-54SYJ7QW.js.map +0 -1
- package/dist/cli-bundle/chunks/validate-HYZNIB6W.js.map +0 -7
- package/docs/examples/policy-restricted-extension/index.js +0 -21
- package/packages/pm-beads/extensions/beads/index.js +0 -64
- package/packages/pm-beads/extensions/beads/runtime-loader.js +0 -86
- package/packages/pm-beads/extensions/beads/runtime.js +0 -482
- package/packages/pm-calendar/extensions/calendar/index.js +0 -150
- package/packages/pm-calendar/extensions/calendar/runtime.js +0 -126
- package/packages/pm-command-kit/extensions/command-kit/index.js +0 -181
- package/packages/pm-governance-audit/extensions/governance-audit/index.js +0 -177
- package/packages/pm-governance-audit/extensions/governance-audit/runtime.js +0 -153
- package/packages/pm-guide-shell/extensions/guide-shell/index.js +0 -98
- package/packages/pm-guide-shell/extensions/guide-shell/runtime.js +0 -294
- package/packages/pm-lifecycle-hooks/extensions/lifecycle-hooks/index.js +0 -18
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/index.js +0 -124
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/runtime.js +0 -110
- package/packages/pm-search-advanced/extensions/search-advanced/index.js +0 -258
- package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +0 -361
- package/packages/pm-templates/extensions/templates/index.js +0 -132
- package/packages/pm-templates/extensions/templates/runtime.js +0 -35
- package/packages/pm-todos/extensions/todos/index.js +0 -81
- package/packages/pm-todos/extensions/todos/runtime-loader.js +0 -86
- package/packages/pm-todos/extensions/todos/runtime.js +0 -545
- /package/dist/cli-bundle/chunks/{activity-54TXGJ2T.js.map → activity-AW6XVFH6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{activity-N7RVTLBQ.js.map → activity-DBLQVIP6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-F32L4HR6.js.map → chunk-27BXPBAY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5BBEWX6C.js.map → chunk-3VGN2UWE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FMWW2JDU.js.map → chunk-AXIDKKAT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TIM4OD74.js.map → chunk-BDTISOSD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CZIFFMZI.js.map → chunk-DDPTYJIM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AYPQUFCX.js.map → chunk-EJUDVUYZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-EOGBMLCE.js.map → chunk-EVMTBV6V.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CG3KP6I5.js.map → chunk-G7I7DEZA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-F4BNR2IN.js.map → chunk-HYTGA6GI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2WCYE3IF.js.map → chunk-HZZEHPRG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-YV2OSAMS.js.map → chunk-IJYK2T43.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QOUOMPHO.js.map → chunk-JPECA746.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OQ2E64FH.js.map → chunk-KNPEF7QG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-3BKH2CL3.js.map → chunk-L5OEFZQG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5S4ZGDB2.js.map → chunk-N74UMG5H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IXAZI443.js.map → chunk-NFDPYAIP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-SKC4UTRP.js.map → chunk-NKZAN7BD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-JPJDP4VU.js.map → chunk-NWMZWYYB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KKX4Z2SE.js.map → chunk-OTUHB4HS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WB5BYQMF.js.map → chunk-SLMUGTK3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-I6QMJ2XT.js.map → chunk-WYDHYJPO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KIEAK7YE.js.map → chunk-ZRP4VG5U.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-JEBZXONN.js.map → close-E6ZZGCJY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-QHMVWM7M.js.map → close-TQYAAFJP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-O4VONGPG.js.map → context-B6275WPX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-CLSCHGJJ.js.map → context-OCZ3FJ4Z.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-YQF4CPIR.js.map → create-OH3BDGBB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-3JYWJ5K2.js.map → create-RLRJMRTM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-ALTM2RRP.js.map → extension-CPSLJQVE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-RUKPKNY7.js.map → extension-CXJ6RELI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{gc-BEJMQT64.js.map → gc-7GQYOS2G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{gc-JEFQDJPA.js.map → gc-LPVMKJQJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{health-JJJOY7DJ.js.map → health-3IPFLKXB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{health-P67NZ6TT.js.map → health-GZXGBZ36.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-YY4XYVEP.js.map → history-NERDJNUB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-5YGLWUDH.js.map → history-WSZHY3PN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-C4CRHW22.js.map → history-redact-MP6CH7U5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-HBFGYS66.js.map → history-redact-O3NBCNWC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-C7R33MD5.js.map → init-64XDLQJB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-DSN6UNFB.js.map → init-PAX32BJA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-LL2WLEDG.js.map → list-DNBJVO3E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-LQHXBAY5.js.map → list-G5Y65VF6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{search-2EI6EAXH.js.map → restore-4MHZFJ2E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{search-QBFBLQRO.js.map → restore-YALDGTQR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-NV2DRPUS.js.map → schema-73HR2OJW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-WA6RZGM2.js.map → schema-U6LJKSIR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-BSKMQOYH.js.map → search-AXPXKZER.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-FIGYNQ2I.js.map → search-KILGT37L.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{telemetry-BT2VSWU2.js.map → telemetry-BZUF6H7G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{telemetry-LQ6FRTUT.js.map → telemetry-GAHHQTOS.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";
|
|
@@ -16,9 +16,11 @@ import { pathExists } from "../../core/fs/fs-utils.js";
|
|
|
16
16
|
import { isPathWithinDirectory } from "../../core/fs/path-utils.js";
|
|
17
17
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
18
18
|
import { PmCliError } from "../../core/shared/errors.js";
|
|
19
|
+
import { levenshteinDistanceWithinLimit } from "../../core/shared/levenshtein.js";
|
|
19
20
|
import { nowIso } from "../../core/shared/time.js";
|
|
20
21
|
import { resolveGlobalPmRoot, resolvePmRoot } from "../../core/store/paths.js";
|
|
21
22
|
import { readSettings, writeSettings } from "../../core/store/settings.js";
|
|
23
|
+
import { ensureTypeFolderScaffold } from "./schema.js";
|
|
22
24
|
// Cohesive helper groups now live in ./extension/* sibling modules. They are
|
|
23
25
|
// imported for the command wiring that stays here and re-exported below so
|
|
24
26
|
// existing import sites (sdk barrels, upgrade.ts, tests) keep importing the
|
|
@@ -39,6 +41,41 @@ const EXTENSION_INSTALL_COPY_ATTEMPTS = 3;
|
|
|
39
41
|
const EXTENSION_INSTALL_LOCK_ATTEMPTS = 120;
|
|
40
42
|
const EXTENSION_INSTALL_LOCK_DELAY_MS = 250;
|
|
41
43
|
const EXTENSION_INSTALL_LOCK_STALE_MS = 120_000;
|
|
44
|
+
const LIFECYCLE_ACTION_TARGETS = [
|
|
45
|
+
["install", "install", "--install"],
|
|
46
|
+
["uninstall", "uninstall", "--uninstall"],
|
|
47
|
+
["explore", "explore", "--explore"],
|
|
48
|
+
["list", "explore", "--explore"],
|
|
49
|
+
["manage", "manage", "--manage"],
|
|
50
|
+
["describe", "describe", "--describe"],
|
|
51
|
+
["reload", "reload", "--reload"],
|
|
52
|
+
["doctor", "doctor", "--doctor"],
|
|
53
|
+
["catalog", "catalog", "--catalog"],
|
|
54
|
+
["init", "init", "--init"],
|
|
55
|
+
["scaffold", "init", "--scaffold"],
|
|
56
|
+
["adopt", "adopt", "--adopt"],
|
|
57
|
+
["adopt-all", "adopt-all", "--adopt-all"],
|
|
58
|
+
["activate", "activate", "--activate"],
|
|
59
|
+
["deactivate", "deactivate", "--deactivate"],
|
|
60
|
+
];
|
|
61
|
+
const LIFECYCLE_ACTION_FLAG_HINT = LIFECYCLE_ACTION_TARGETS.map(([, , flag]) => flag)
|
|
62
|
+
.filter((flag, index, flags) => flags.indexOf(flag) === index)
|
|
63
|
+
.join(", ");
|
|
64
|
+
const LIFECYCLE_ACTION_FLAGS = {
|
|
65
|
+
install: "--install",
|
|
66
|
+
uninstall: "--uninstall",
|
|
67
|
+
explore: "--explore",
|
|
68
|
+
manage: "--manage",
|
|
69
|
+
describe: "--describe",
|
|
70
|
+
reload: "--reload",
|
|
71
|
+
doctor: "--doctor",
|
|
72
|
+
catalog: "--catalog",
|
|
73
|
+
adopt: "--adopt",
|
|
74
|
+
"adopt-all": "--adopt-all",
|
|
75
|
+
activate: "--activate",
|
|
76
|
+
deactivate: "--deactivate",
|
|
77
|
+
init: "--init",
|
|
78
|
+
};
|
|
42
79
|
const NATIVE_OUTPUT_MARKER = "__pm_native_output";
|
|
43
80
|
function buildExtensionPolicyDetails(policy) {
|
|
44
81
|
const overrides = (policy.extension_overrides ?? [])
|
|
@@ -268,49 +305,116 @@ function clearExtensionState(settings, name) {
|
|
|
268
305
|
return (settings.extensions.enabled.join("\u0000") !== previousEnabled.join("\u0000") ||
|
|
269
306
|
settings.extensions.disabled.join("\u0000") !== previousDisabled.join("\u0000"));
|
|
270
307
|
}
|
|
271
|
-
function
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
options.adopt ? "adopt" : null,
|
|
284
|
-
options.adoptAll ? "adopt-all" : null,
|
|
285
|
-
options.activate ? "activate" : null,
|
|
286
|
-
options.deactivate ? "deactivate" : null,
|
|
287
|
-
].filter((value) => value !== null))];
|
|
288
|
-
if (selected.length === 0) {
|
|
289
|
-
if (typeof target === "string" && target.trim().toLowerCase() === "doctor") {
|
|
290
|
-
return "doctor";
|
|
291
|
-
}
|
|
292
|
-
if (typeof target === "string" && target.trim().toLowerCase() === "reload") {
|
|
293
|
-
return "reload";
|
|
294
|
-
}
|
|
295
|
-
if (typeof target === "string" && target.trim().toLowerCase() === "catalog") {
|
|
296
|
-
return "catalog";
|
|
297
|
-
}
|
|
298
|
-
if (typeof target === "string" && (target.trim().toLowerCase() === "init" || target.trim().toLowerCase() === "scaffold")) {
|
|
299
|
-
return "init";
|
|
300
|
-
}
|
|
301
|
-
if (typeof target === "string" && target.trim().toLowerCase() === "explore") {
|
|
302
|
-
return "explore";
|
|
308
|
+
function suggestLifecycleActionTarget(target) {
|
|
309
|
+
const normalizedTarget = target.trim().toLowerCase();
|
|
310
|
+
const exactMatch = LIFECYCLE_ACTION_TARGETS.find(([candidate]) => candidate === normalizedTarget);
|
|
311
|
+
if (exactMatch) {
|
|
312
|
+
return { action: exactMatch[1], flag: exactMatch[2] };
|
|
313
|
+
}
|
|
314
|
+
const maxDistance = normalizedTarget.length <= 4 ? 1 : 2;
|
|
315
|
+
let nearest = null;
|
|
316
|
+
for (const [candidate, action, flag] of LIFECYCLE_ACTION_TARGETS) {
|
|
317
|
+
const distance = levenshteinDistanceWithinLimit(normalizedTarget, candidate, maxDistance);
|
|
318
|
+
if (distance === null) {
|
|
319
|
+
continue;
|
|
303
320
|
}
|
|
304
|
-
if (
|
|
305
|
-
|
|
321
|
+
if (nearest === null) {
|
|
322
|
+
nearest = { action, flag, distance };
|
|
323
|
+
continue;
|
|
306
324
|
}
|
|
307
|
-
if (
|
|
308
|
-
|
|
325
|
+
if (distance < nearest.distance) {
|
|
326
|
+
nearest = { action, flag, distance };
|
|
309
327
|
}
|
|
328
|
+
}
|
|
329
|
+
return nearest === null ? null : { action: nearest.action, flag: nearest.flag };
|
|
330
|
+
}
|
|
331
|
+
function buildUnknownLifecycleActionError(target, options) {
|
|
332
|
+
const noun = options.vocabulary === "package" ? "package" : "extension";
|
|
333
|
+
const suggestion = suggestLifecycleActionTarget(target);
|
|
334
|
+
if (!suggestion) {
|
|
335
|
+
return new PmCliError(`One action flag is required. Use one of: ${LIFECYCLE_ACTION_FLAG_HINT}. Bare \`pm package\` and \`pm extension\` default to --explore.`, EXIT_CODE.USAGE);
|
|
336
|
+
}
|
|
337
|
+
const command = `pm ${noun} ${suggestion.flag}`;
|
|
338
|
+
return new PmCliError(`Unknown ${noun} lifecycle action "${target}". Did you mean "${suggestion.flag}"?`, EXIT_CODE.USAGE, {
|
|
339
|
+
code: "unknown_lifecycle_action",
|
|
340
|
+
required: `Use one of: ${LIFECYCLE_ACTION_FLAG_HINT}.`,
|
|
341
|
+
examples: [command, `pm ${noun} --help`],
|
|
342
|
+
recovery: {
|
|
343
|
+
attempted_command: `pm ${noun} ${target}`,
|
|
344
|
+
suggested_retry: command,
|
|
345
|
+
fallback_candidates: [
|
|
346
|
+
{
|
|
347
|
+
source: "lifecycle_action",
|
|
348
|
+
command,
|
|
349
|
+
reason: `nearest lifecycle action for "${target}"`,
|
|
350
|
+
},
|
|
351
|
+
],
|
|
352
|
+
},
|
|
353
|
+
});
|
|
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
|
+
}
|
|
405
|
+
function resolveAction(target, options) {
|
|
406
|
+
const selected = [
|
|
407
|
+
...new Set(EXTENSION_ACTION_FLAG_SELECTORS.filter(([flag]) => options[flag] === true).map(([, mappedAction]) => mappedAction)),
|
|
408
|
+
];
|
|
409
|
+
if (selected.length === 0) {
|
|
310
410
|
if (target === undefined) {
|
|
311
411
|
return "explore";
|
|
312
412
|
}
|
|
313
|
-
|
|
413
|
+
const implicitAction = resolveImplicitActionFromTarget(target.trim().toLowerCase());
|
|
414
|
+
if (implicitAction) {
|
|
415
|
+
return implicitAction;
|
|
416
|
+
}
|
|
417
|
+
throw buildUnknownLifecycleActionError(target, options);
|
|
314
418
|
}
|
|
315
419
|
if (selected.length > 1) {
|
|
316
420
|
throw new PmCliError("Extension action flags are mutually exclusive.", EXIT_CODE.USAGE);
|
|
@@ -368,6 +472,34 @@ function resolveUpdateCheckResolution(managedEntry) {
|
|
|
368
472
|
reason: "no_update_check_recorded",
|
|
369
473
|
};
|
|
370
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
|
+
}
|
|
371
503
|
async function listInstalledExtensions(extensionsRoot, scope, settings, state) {
|
|
372
504
|
if (!(await pathExists(extensionsRoot))) {
|
|
373
505
|
return {
|
|
@@ -394,27 +526,13 @@ async function listInstalledExtensions(extensionsRoot, scope, settings, state) {
|
|
|
394
526
|
if (!(await pathExists(manifestPath))) {
|
|
395
527
|
warnings.push(`extension_manifest_missing:${scope}:${directoryName}`);
|
|
396
528
|
const managedEntry = managedByDirectory.get(normalizeExtensionNameForMatch(directoryName));
|
|
397
|
-
|
|
398
|
-
const enabled = managedEntry ? isExtensionEnabled(settings, managedEntry.name) : false;
|
|
399
|
-
summaries.push({
|
|
529
|
+
summaries.push(buildInstalledExtensionSummary({
|
|
400
530
|
name: managedEntry?.name ?? directoryName,
|
|
401
531
|
directory: directoryName,
|
|
402
532
|
version: managedEntry?.manifest_version ?? "unknown",
|
|
403
533
|
entry: managedEntry?.manifest_entry ?? "unknown",
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
enabled,
|
|
407
|
-
runtime_active: null,
|
|
408
|
-
activation_status: "unknown",
|
|
409
|
-
managed: Boolean(managedEntry),
|
|
410
|
-
source: managedEntry?.source,
|
|
411
|
-
update_available: managedEntry?.update_available,
|
|
412
|
-
last_update_check_at: managedEntry?.last_update_check_at,
|
|
413
|
-
last_update_remote_commit: managedEntry?.last_update_remote_commit,
|
|
414
|
-
update_error: managedEntry?.update_error,
|
|
415
|
-
update_check_status: updateCheck.status,
|
|
416
|
-
update_check_reason: updateCheck.reason,
|
|
417
|
-
});
|
|
534
|
+
enabled: managedEntry ? isExtensionEnabled(settings, managedEntry.name) : false,
|
|
535
|
+
}, scope, managedEntry, resolveUpdateCheckResolution(managedEntry)));
|
|
418
536
|
continue;
|
|
419
537
|
}
|
|
420
538
|
let rawManifest;
|
|
@@ -432,27 +550,13 @@ async function listInstalledExtensions(extensionsRoot, scope, settings, state) {
|
|
|
432
550
|
}
|
|
433
551
|
const managedEntry = managedByName.get(normalizeExtensionNameForMatch(manifest.name)) ??
|
|
434
552
|
managedByDirectory.get(normalizeExtensionNameForMatch(directoryName));
|
|
435
|
-
|
|
436
|
-
const enabled = isExtensionEnabled(settings, manifest.name);
|
|
437
|
-
summaries.push({
|
|
553
|
+
summaries.push(buildInstalledExtensionSummary({
|
|
438
554
|
name: manifest.name,
|
|
439
555
|
directory: directoryName,
|
|
440
556
|
version: manifest.version,
|
|
441
557
|
entry: manifest.entry,
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
enabled,
|
|
445
|
-
runtime_active: null,
|
|
446
|
-
activation_status: "unknown",
|
|
447
|
-
managed: Boolean(managedEntry),
|
|
448
|
-
source: managedEntry?.source,
|
|
449
|
-
update_available: managedEntry?.update_available,
|
|
450
|
-
last_update_check_at: managedEntry?.last_update_check_at,
|
|
451
|
-
last_update_remote_commit: managedEntry?.last_update_remote_commit,
|
|
452
|
-
update_error: managedEntry?.update_error,
|
|
453
|
-
update_check_status: updateCheck.status,
|
|
454
|
-
update_check_reason: updateCheck.reason,
|
|
455
|
-
});
|
|
558
|
+
enabled: isExtensionEnabled(settings, manifest.name),
|
|
559
|
+
}, scope, managedEntry, resolveUpdateCheckResolution(managedEntry)));
|
|
456
560
|
}
|
|
457
561
|
return {
|
|
458
562
|
extensions: summaries.sort((left, right) => left.name.localeCompare(right.name)),
|
|
@@ -542,6 +646,7 @@ async function probeRuntimeCommandPathsForInstall(pmRoot, settings, refreshedIns
|
|
|
542
646
|
installed: applyDoctorRuntimeActivationState(refreshedInstalled, loadResult, activationResult),
|
|
543
647
|
warnings: [...loadResult.warnings, ...activationResult.warnings],
|
|
544
648
|
activation_failures: collectActivationFailureDiagnostics(activationResult.failed),
|
|
649
|
+
item_type_registrations: activationResult.registrations.item_types,
|
|
545
650
|
};
|
|
546
651
|
}
|
|
547
652
|
async function checkGithubUpdate(source, gitCommandRunner = runGitCommand) {
|
|
@@ -673,13 +778,37 @@ function resolveGithubOption(options) {
|
|
|
673
778
|
}
|
|
674
779
|
return undefined;
|
|
675
780
|
}
|
|
676
|
-
function
|
|
781
|
+
function getLifecycleActionFlag(action) {
|
|
782
|
+
return LIFECYCLE_ACTION_FLAGS[action];
|
|
783
|
+
}
|
|
784
|
+
function requireTarget(target, action, options = {}) {
|
|
677
785
|
const normalized = target?.trim();
|
|
678
786
|
if (!normalized) {
|
|
679
787
|
if (action === "init") {
|
|
680
788
|
throw new PmCliError('Action "init" requires a scaffold target path (for example: pm package init ./my-package or pm extension init ./my-extension).', EXIT_CODE.USAGE);
|
|
681
789
|
}
|
|
682
|
-
|
|
790
|
+
const noun = options.vocabulary === "package" ? "package" : "extension";
|
|
791
|
+
const targetName = action === "install" ? "source" : "name";
|
|
792
|
+
const targetLabel = `${noun} ${targetName}`;
|
|
793
|
+
const actionFlag = getLifecycleActionFlag(action);
|
|
794
|
+
const commandTarget = `<${targetName}>`;
|
|
795
|
+
const command = `pm ${noun} ${actionFlag} ${commandTarget}`;
|
|
796
|
+
throw new PmCliError(`Action "${action}" requires ${targetLabel} input.`, EXIT_CODE.USAGE, {
|
|
797
|
+
code: "missing_lifecycle_target",
|
|
798
|
+
required: `Provide a ${targetName} target for ${action}.`,
|
|
799
|
+
examples: [`pm ${noun} ${action} ${commandTarget}`, command, `pm ${noun} --help`],
|
|
800
|
+
recovery: {
|
|
801
|
+
attempted_command: `pm ${noun} ${action}`,
|
|
802
|
+
suggested_retry: command,
|
|
803
|
+
fallback_candidates: [
|
|
804
|
+
{
|
|
805
|
+
source: "lifecycle_action",
|
|
806
|
+
command,
|
|
807
|
+
reason: `flag-form ${action} command with required ${targetName} target`,
|
|
808
|
+
},
|
|
809
|
+
],
|
|
810
|
+
},
|
|
811
|
+
});
|
|
683
812
|
}
|
|
684
813
|
return normalized;
|
|
685
814
|
}
|
|
@@ -697,50 +826,128 @@ function collectGlobalOutputOverrideDoctorWarnings(activationResult) {
|
|
|
697
826
|
return [...new Set(warnings)].sort((left, right) => left.localeCompare(right));
|
|
698
827
|
}
|
|
699
828
|
/**
|
|
700
|
-
*
|
|
829
|
+
* Doctor advisory: flag loaded extensions that contribute GLOBAL schema (custom
|
|
830
|
+
* item types or fields) yet also declare narrow `activation.commands`.
|
|
831
|
+
*
|
|
832
|
+
* Custom item types and fields must be present for the built-in commands the
|
|
833
|
+
* extension does not own and cannot enumerate (`pm create <type>`,
|
|
834
|
+
* `pm list --type <type>`, `pm validate`). Declaring `activation.commands` gates
|
|
835
|
+
* lazy activation to only the listed command paths, so the package never
|
|
836
|
+
* activates for those built-ins and its custom type silently fails to register —
|
|
837
|
+
* a quiet footgun (decision pm-halx). The `schema` scaffold deliberately omits
|
|
838
|
+
* the field; this advisory catches hand-authored packages that do not. It is
|
|
839
|
+
* doctor-only and non-blocking — `pm health` does not surface it — so the author
|
|
840
|
+
* can either drop `activation.commands` or, when the schema is intentionally
|
|
841
|
+
* command-scoped, knowingly ignore the hint.
|
|
701
842
|
*/
|
|
702
|
-
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
843
|
+
function collectSchemaNarrowActivationDoctorWarnings(loadResult, activationResult) {
|
|
844
|
+
const schemaContributors = new Set();
|
|
845
|
+
for (const entry of activationResult.registrations.item_types) {
|
|
846
|
+
if (entry.types.length > 0) {
|
|
847
|
+
schemaContributors.add(`${entry.layer}:${normalizeExtensionNameForMatch(entry.name)}`);
|
|
848
|
+
}
|
|
706
849
|
}
|
|
707
|
-
|
|
708
|
-
|
|
850
|
+
for (const entry of activationResult.registrations.item_fields) {
|
|
851
|
+
if (entry.fields.length > 0) {
|
|
852
|
+
schemaContributors.add(`${entry.layer}:${normalizeExtensionNameForMatch(entry.name)}`);
|
|
853
|
+
}
|
|
709
854
|
}
|
|
710
|
-
|
|
711
|
-
|
|
855
|
+
const warnings = [];
|
|
856
|
+
for (const extension of loadResult.loaded) {
|
|
857
|
+
if ((extension.activation?.commands ?? []).length === 0) {
|
|
858
|
+
continue;
|
|
859
|
+
}
|
|
860
|
+
if (schemaContributors.has(`${extension.layer}:${normalizeExtensionNameForMatch(extension.name)}`)) {
|
|
861
|
+
warnings.push(`extension_schema_narrow_activation:${extension.layer}:${extension.name}`);
|
|
862
|
+
}
|
|
712
863
|
}
|
|
713
|
-
|
|
714
|
-
|
|
864
|
+
return [...new Set(warnings)].sort((left, right) => left.localeCompare(right));
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
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.
|
|
874
|
+
*/
|
|
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
|
+
}
|
|
715
909
|
}
|
|
716
|
-
|
|
717
|
-
|
|
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;
|
|
718
922
|
}
|
|
719
|
-
if (
|
|
720
|
-
|
|
923
|
+
if (action === "reload" && normalizedInput === "reload") {
|
|
924
|
+
return undefined;
|
|
721
925
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
926
|
+
if (action === "catalog" && normalizedInput === "catalog") {
|
|
927
|
+
return undefined;
|
|
928
|
+
}
|
|
929
|
+
const inferredInitAlias = action === "init" &&
|
|
930
|
+
options.init !== true &&
|
|
931
|
+
options.scaffold !== true &&
|
|
932
|
+
(normalizedInput === "init" || normalizedInput === "scaffold");
|
|
933
|
+
if (inferredInitAlias) {
|
|
934
|
+
return undefined;
|
|
935
|
+
}
|
|
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);
|
|
744
951
|
const scope = resolveScope(options);
|
|
745
952
|
const resolvedRoots = resolveExtensionRootsForScope(scope, global);
|
|
746
953
|
const warnings = [];
|
|
@@ -774,475 +981,826 @@ export async function runExtension(target, options, global) {
|
|
|
774
981
|
}
|
|
775
982
|
return result;
|
|
776
983
|
};
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
},
|
|
795
|
-
capability: scaffold.capability,
|
|
796
|
-
target_path: scaffold.target_path,
|
|
797
|
-
created_directory: scaffold.created_directory,
|
|
798
|
-
files: scaffold.files,
|
|
799
|
-
next_steps: [
|
|
800
|
-
// The scaffold is authored in TypeScript (ADR pm-2c28); the manifest's
|
|
801
|
-
// ./index.js entry only exists after a compile, so building comes first.
|
|
802
|
-
...(options.vocabulary === "package"
|
|
803
|
-
? [`Build the package: cd ${quotedShellTargetPath}, then run "npm install" and "npm run build"`]
|
|
804
|
-
: [
|
|
805
|
-
`Build the extension: cd ${quotedShellTargetPath}, then run "npm install -D typescript @types/node @unbrained/pm-cli" and "npx tsc"`,
|
|
806
|
-
]),
|
|
807
|
-
`Install the scaffold: ${options.vocabulary === "package" ? "pm install --project" : "pm extension --install --project"} ${quotedTargetPath}`,
|
|
808
|
-
`Smoke-test command path: pm ${scaffold.command_name}`,
|
|
809
|
-
...(options.vocabulary === "package"
|
|
810
|
-
? [`Validate the sample test: cd ${quotedShellTargetPath}, then run "npm test"`]
|
|
811
|
-
: []),
|
|
812
|
-
`Run diagnostics: ${options.vocabulary === "package" ? "pm package doctor" : "pm extension --doctor"} --project --detail summary`,
|
|
813
|
-
],
|
|
814
|
-
});
|
|
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);
|
|
815
1001
|
}
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
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,
|
|
828
1060
|
cache_bust: true,
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
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,
|
|
858
1109
|
};
|
|
859
|
-
if (options.watch === true) {
|
|
860
|
-
warnings.push("extension_reload_watch_hint:watch_mode_requested_non_interactive_single_pass_only");
|
|
861
|
-
}
|
|
862
|
-
return withResult(details);
|
|
863
1110
|
}
|
|
864
|
-
if (
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
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");
|
|
1181
|
+
}
|
|
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);
|
|
905
1235
|
}
|
|
906
|
-
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
const installSource = parseExtensionInstallSource(sourceInput, {
|
|
913
|
-
forceGithub: typeof githubOption === "string",
|
|
914
|
-
ref: options.ref,
|
|
915
|
-
});
|
|
916
|
-
/* c8 ignore stop */
|
|
917
|
-
const resolvedSource = await resolveInstallSource(installSource);
|
|
918
|
-
try {
|
|
919
|
-
const validated = await validateExtensionDirectory(resolvedSource.directory);
|
|
920
|
-
const destinationDirectoryName = normalizeManagedDirectoryName(validated.manifest.name);
|
|
921
|
-
return await withExtensionInstallLock(resolvedRoots.settings_root, destinationDirectoryName, async () => {
|
|
922
|
-
const settings = await readSettings(resolvedRoots.settings_root);
|
|
923
|
-
const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
|
|
924
|
-
warnings.push(...managedStateRead.warnings);
|
|
925
|
-
const destinationDirectory = path.join(resolvedRoots.selected_root, destinationDirectoryName);
|
|
926
|
-
const destinationExists = await pathExists(destinationDirectory);
|
|
927
|
-
const installInPlace = await areDirectoriesEquivalent(validated.directory, destinationDirectory);
|
|
928
|
-
await fs.mkdir(resolvedRoots.selected_root, { recursive: true });
|
|
929
|
-
if (!installInPlace) {
|
|
930
|
-
await copyExtensionDirectoryForInstall(validated.directory, destinationDirectory);
|
|
931
|
-
}
|
|
932
|
-
/* c8 ignore start -- source-shape branch combinations are exercised in install-source focused tests */
|
|
933
|
-
const sourceRecord = bundledAliasName
|
|
934
|
-
? {
|
|
935
|
-
kind: "builtin",
|
|
936
|
-
input: bundledAliasName,
|
|
937
|
-
location: bundledAliasName,
|
|
938
|
-
name: bundledAliasName,
|
|
939
|
-
}
|
|
940
|
-
: installSource.kind === "local"
|
|
941
|
-
? {
|
|
942
|
-
kind: "local",
|
|
943
|
-
input: installSource.input,
|
|
944
|
-
location: installSource.absolute_path,
|
|
945
|
-
}
|
|
946
|
-
: installSource.kind === "npm"
|
|
947
|
-
? {
|
|
948
|
-
kind: "npm",
|
|
949
|
-
input: installSource.input,
|
|
950
|
-
location: resolvedSource.resolved_subpath ?? ".",
|
|
951
|
-
package: resolvedSource.npm_package,
|
|
952
|
-
version: resolvedSource.npm_version,
|
|
953
|
-
}
|
|
954
|
-
: {
|
|
955
|
-
kind: "github",
|
|
956
|
-
input: installSource.input,
|
|
957
|
-
location: resolvedSource.resolved_subpath ?? installSource.subpath ?? ".",
|
|
958
|
-
repository: installSource.repository,
|
|
959
|
-
owner: installSource.owner,
|
|
960
|
-
repo: installSource.repo,
|
|
961
|
-
ref: installSource.ref,
|
|
962
|
-
subpath: resolvedSource.resolved_subpath ?? installSource.subpath,
|
|
963
|
-
commit: resolvedSource.commit,
|
|
964
|
-
};
|
|
965
|
-
/* c8 ignore stop */
|
|
966
|
-
const now = nowIso();
|
|
967
|
-
const existingManagedEntry = managedStateRead.state.entries.find((entry) => normalizeExtensionNameForMatch(entry.name) === normalizeExtensionNameForMatch(validated.manifest.name));
|
|
968
|
-
const sourceUnchanged = existingManagedEntry !== undefined &&
|
|
969
|
-
existingManagedEntry.manifest_version === validated.manifest.version &&
|
|
970
|
-
managedExtensionSourcesEquivalent(existingManagedEntry.source, sourceRecord);
|
|
971
|
-
const managedState = upsertManagedEntry(managedStateRead.state, {
|
|
972
|
-
name: validated.manifest.name,
|
|
973
|
-
directory: destinationDirectoryName,
|
|
974
|
-
scope,
|
|
975
|
-
manifest_version: validated.manifest.version,
|
|
976
|
-
manifest_entry: validated.manifest.entry,
|
|
977
|
-
capabilities: [...validated.manifest.capabilities],
|
|
978
|
-
installed_at: existingManagedEntry?.installed_at ?? now,
|
|
979
|
-
updated_at: sourceUnchanged ? existingManagedEntry.updated_at : now,
|
|
980
|
-
source: sourceRecord,
|
|
981
|
-
});
|
|
982
|
-
await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
|
|
983
|
-
const activationChanged = ensureActivated(settings, validated.manifest.name);
|
|
984
|
-
if (activationChanged) {
|
|
985
|
-
await writeSettings(resolvedRoots.settings_root, settings, "settings:write");
|
|
986
|
-
}
|
|
987
|
-
const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
|
|
988
|
-
warnings.push(...refreshedInstalled.warnings);
|
|
989
|
-
const runtimeProbe = await probeRuntimeCommandPathsForInstall(resolvedRoots.pm_root, settings, refreshedInstalled.extensions, global);
|
|
990
|
-
warnings.push(...runtimeProbe.warnings);
|
|
991
|
-
const commandSummary = summarizeRuntimeCommandPathsForExtension(validated.manifest.name, runtimeProbe.installed);
|
|
992
|
-
const installActivationFailure = findActivationFailureByName(validated.manifest.name, runtimeProbe.activation_failures, scope);
|
|
993
|
-
const runtimeActivationStatus = resolveInstallRuntimeActivationStatus(validated.manifest.name, scope, runtimeProbe.installed, installActivationFailure);
|
|
994
|
-
return withResult({
|
|
995
|
-
extension: {
|
|
996
|
-
name: validated.manifest.name,
|
|
997
|
-
version: validated.manifest.version,
|
|
998
|
-
entry: validated.manifest.entry,
|
|
999
|
-
capabilities: validated.manifest.capabilities,
|
|
1000
|
-
directory: destinationDirectoryName,
|
|
1001
|
-
},
|
|
1002
|
-
source: sourceRecord,
|
|
1003
|
-
destination_path: destinationDirectory,
|
|
1004
|
-
overwritten: destinationExists && !installInPlace,
|
|
1005
|
-
installed_in_place: installInPlace,
|
|
1006
|
-
activated: true,
|
|
1007
|
-
settings_changed: activationChanged,
|
|
1008
|
-
runtime_activation_status: runtimeActivationStatus,
|
|
1009
|
-
command_paths: commandSummary.command_paths,
|
|
1010
|
-
action_paths: commandSummary.action_paths,
|
|
1011
|
-
command_discovery: buildInstallCommandDiscovery(validated.manifest.name, sourceRecord, commandSummary),
|
|
1012
|
-
activation_diagnostics: {
|
|
1013
|
-
failed_count: runtimeProbe.activation_failures.length,
|
|
1014
|
-
failed: runtimeProbe.activation_failures,
|
|
1015
|
-
installed_extension_failed: installActivationFailure ?? null,
|
|
1016
|
-
},
|
|
1017
|
-
});
|
|
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),
|
|
1018
1242
|
});
|
|
1019
1243
|
}
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
if (resolvedSource.cleanup) {
|
|
1023
|
-
await resolvedSource.cleanup();
|
|
1024
|
-
}
|
|
1025
|
-
/* c8 ignore stop */
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
if (action === "adopt-all") {
|
|
1029
|
-
if (normalizedTarget !== undefined) {
|
|
1030
|
-
throw new PmCliError('Action "adopt-all" does not accept a target argument.', EXIT_CODE.USAGE);
|
|
1031
|
-
}
|
|
1032
|
-
const githubOption = resolveGithubOption(options);
|
|
1033
|
-
if (githubOption !== undefined || (typeof options.ref === "string" && options.ref.trim().length > 0)) {
|
|
1034
|
-
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);
|
|
1035
1246
|
}
|
|
1036
|
-
const settings = await readSettings(resolvedRoots.settings_root);
|
|
1037
|
-
const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
|
|
1038
|
-
warnings.push(...managedStateRead.warnings);
|
|
1039
|
-
const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
|
|
1040
|
-
warnings.push(...installed.warnings);
|
|
1041
|
-
const adoption = await adoptUnmanagedExtensions(resolvedRoots.selected_root, scope, installed.extensions, managedStateRead.state);
|
|
1042
|
-
const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, adoption.state);
|
|
1043
|
-
warnings.push(...refreshedInstalled.warnings);
|
|
1044
|
-
const triage = buildExtensionTriageSummary(scope, warnings, refreshedInstalled.extensions, options);
|
|
1045
|
-
warnings.push(...triage.warnings);
|
|
1046
|
-
/* c8 ignore start -- refresh-entry optional metadata is display-only and exercised indirectly */
|
|
1047
|
-
const adoptedDetails = adoption.adopted_entries.map((entry) => {
|
|
1048
|
-
const refreshedEntry = refreshedInstalled.extensions.find((candidate) => normalizeExtensionNameForMatch(candidate.name) === normalizeExtensionNameForMatch(entry.name) &&
|
|
1049
|
-
normalizeExtensionNameForMatch(candidate.directory) === normalizeExtensionNameForMatch(entry.directory)) ??
|
|
1050
|
-
/* c8 ignore next 3 -- fallback only matters if a manifest renames between adopt and refresh */
|
|
1051
|
-
refreshedInstalled.extensions.find((candidate) => normalizeExtensionNameForMatch(candidate.directory) === normalizeExtensionNameForMatch(entry.directory));
|
|
1052
|
-
return {
|
|
1053
|
-
...entry,
|
|
1054
|
-
update_check_status: refreshedEntry?.update_check_status ?? null,
|
|
1055
|
-
update_check_reason: refreshedEntry?.update_check_reason ?? null,
|
|
1056
|
-
};
|
|
1057
|
-
});
|
|
1058
|
-
/* c8 ignore stop */
|
|
1059
|
-
/* c8 ignore start -- adopt-all summary booleans are deterministic mirrors of adoptedDetails length */
|
|
1060
1247
|
return withResult({
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
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
|
+
})),
|
|
1069
1263
|
});
|
|
1070
|
-
/* c8 ignore stop */
|
|
1071
1264
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
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();
|
|
1093
1292
|
}
|
|
1094
|
-
const extensionDirectory = path.join(resolvedRoots.selected_root, candidate.directory);
|
|
1095
|
-
const validated = await validateExtensionDirectory(extensionDirectory);
|
|
1096
|
-
const now = nowIso();
|
|
1097
|
-
const sourceRecord = githubOption === undefined
|
|
1098
|
-
? {
|
|
1099
|
-
kind: "local",
|
|
1100
|
-
input: extensionTarget,
|
|
1101
|
-
location: extensionDirectory,
|
|
1102
|
-
}
|
|
1103
|
-
: (() => {
|
|
1104
|
-
const parsed = parseExtensionInstallSource(githubOption, {
|
|
1105
|
-
forceGithub: true,
|
|
1106
|
-
ref: options.ref,
|
|
1107
|
-
});
|
|
1108
|
-
/* c8 ignore start -- forceGithub guarantees a github-kind install source */
|
|
1109
|
-
if (parsed.kind !== "github") {
|
|
1110
|
-
throw new PmCliError(`Invalid GitHub shorthand "${githubOption}".`, EXIT_CODE.USAGE);
|
|
1111
|
-
}
|
|
1112
|
-
/* c8 ignore stop */
|
|
1113
|
-
/* c8 ignore start -- github subpath defaults are validated in install-source parser tests */
|
|
1114
|
-
return {
|
|
1115
|
-
kind: "github",
|
|
1116
|
-
input: parsed.input,
|
|
1117
|
-
location: parsed.subpath ?? ".",
|
|
1118
|
-
repository: parsed.repository,
|
|
1119
|
-
owner: parsed.owner,
|
|
1120
|
-
repo: parsed.repo,
|
|
1121
|
-
ref: parsed.ref,
|
|
1122
|
-
subpath: parsed.subpath,
|
|
1123
|
-
};
|
|
1124
|
-
/* c8 ignore stop */
|
|
1125
|
-
})();
|
|
1126
|
-
const managedState = upsertManagedEntry(managedStateRead.state, {
|
|
1127
|
-
name: validated.manifest.name,
|
|
1128
|
-
directory: candidate.directory,
|
|
1129
|
-
scope,
|
|
1130
|
-
manifest_version: validated.manifest.version,
|
|
1131
|
-
manifest_entry: validated.manifest.entry,
|
|
1132
|
-
capabilities: [...validated.manifest.capabilities],
|
|
1133
|
-
installed_at: now,
|
|
1134
|
-
updated_at: now,
|
|
1135
|
-
source: sourceRecord,
|
|
1136
|
-
});
|
|
1137
|
-
await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
|
|
1138
|
-
const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
|
|
1139
|
-
warnings.push(...refreshedInstalled.warnings);
|
|
1140
|
-
/* c8 ignore start -- fallback only matters if a manifest renames between adopt and refresh */
|
|
1141
|
-
const refreshedEntry = refreshedInstalled.extensions.find((entry) => normalizeExtensionNameForMatch(entry.name) === normalizeExtensionNameForMatch(validated.manifest.name)) ??
|
|
1142
|
-
refreshedInstalled.extensions.find((entry) => normalizeExtensionNameForMatch(entry.directory) === normalizeExtensionNameForMatch(candidate.directory));
|
|
1143
1293
|
/* c8 ignore stop */
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
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,
|
|
1154
1323
|
update_check_status: refreshedEntry?.update_check_status ?? null,
|
|
1155
1324
|
update_check_reason: refreshedEntry?.update_check_reason ?? null,
|
|
1156
|
-
});
|
|
1157
|
-
/* c8 ignore stop */
|
|
1158
|
-
}
|
|
1159
|
-
if (action === "uninstall") {
|
|
1160
|
-
const extensionTarget = requireTarget(normalizedTarget, action);
|
|
1161
|
-
const settings = await readSettings(resolvedRoots.settings_root);
|
|
1162
|
-
const managedStateRead = await readManagedExtensionState(resolvedRoots.selected_root);
|
|
1163
|
-
warnings.push(...managedStateRead.warnings);
|
|
1164
|
-
const installed = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedStateRead.state);
|
|
1165
|
-
warnings.push(...installed.warnings);
|
|
1166
|
-
const candidate = await resolveInstalledExtensionCandidate(installed.extensions, extensionTarget);
|
|
1167
|
-
if (!candidate) {
|
|
1168
|
-
throw new PmCliError(`Installed extension "${extensionTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
|
|
1169
|
-
}
|
|
1170
|
-
const destinationDirectory = path.join(resolvedRoots.selected_root, candidate.directory);
|
|
1171
|
-
await fs.rm(destinationDirectory, { recursive: true, force: true });
|
|
1172
|
-
const updatedState = {
|
|
1173
|
-
...managedStateRead.state,
|
|
1174
|
-
updated_at: nowIso(),
|
|
1175
|
-
/* c8 ignore start -- uninstall filter keeps both name+directory guards for legacy managed-state migrations */
|
|
1176
|
-
entries: managedStateRead.state.entries.filter((entry) => normalizeExtensionNameForMatch(entry.name) !== normalizeExtensionNameForMatch(candidate.name) &&
|
|
1177
|
-
normalizeExtensionNameForMatch(entry.directory) !== normalizeExtensionNameForMatch(candidate.directory)),
|
|
1178
|
-
/* c8 ignore stop */
|
|
1179
1325
|
};
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
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) {
|
|
1185
1355
|
return withResult({
|
|
1186
|
-
|
|
1356
|
+
adopted: false,
|
|
1357
|
+
already_managed: true,
|
|
1187
1358
|
extension: {
|
|
1188
1359
|
name: candidate.name,
|
|
1189
1360
|
directory: candidate.directory,
|
|
1190
1361
|
},
|
|
1191
|
-
destination_path: destinationDirectory,
|
|
1192
|
-
settings_changed: stateChanged,
|
|
1193
1362
|
});
|
|
1194
1363
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
if (!candidate) {
|
|
1204
|
-
throw new PmCliError(`Installed extension "${extensionTarget}" was not found in ${scope} scope.`, EXIT_CODE.NOT_FOUND);
|
|
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,
|
|
1205
1372
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
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),
|
|
1209
1645
|
}
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
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,
|
|
1214
1680
|
},
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
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
|
+
})),
|
|
1220
1695
|
},
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
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
|
+
};
|
|
1243
1727
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
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) {
|
|
1246
1804
|
const loadResult = await loadExtensions({
|
|
1247
1805
|
pmRoot: resolvedRoots.pm_root,
|
|
1248
1806
|
settings,
|
|
@@ -1254,344 +1812,86 @@ export async function runExtension(target, options, global) {
|
|
|
1254
1812
|
loaded: loadResult.loaded,
|
|
1255
1813
|
});
|
|
1256
1814
|
warnings.push(...loadResult.warnings);
|
|
1257
|
-
warnings.push(...classifyDoctorLoadFailureWarnings(loadResult.failed));
|
|
1258
1815
|
warnings.push(...activationResult.warnings);
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
const updateCheckWarnings = runtimeInstalledExtensions
|
|
1266
|
-
.filter((entry) => entry.update_check_status === "failed")
|
|
1267
|
-
.map((entry) => `extension_update_check_failed:${entry.name}`);
|
|
1268
|
-
warnings.push(...updateCheckWarnings);
|
|
1269
|
-
const triage = buildExtensionTriageSummary(scope, warnings, runtimeInstalledExtensions, options);
|
|
1270
|
-
warnings.push(...triage.warnings);
|
|
1271
|
-
const normalizedWarnings = [...triage.warnings];
|
|
1272
|
-
const policySummary = {
|
|
1273
|
-
mode: loadResult.policy.mode,
|
|
1274
|
-
trust_mode: loadResult.policy.trust_mode,
|
|
1275
|
-
require_provenance: loadResult.policy.require_provenance,
|
|
1276
|
-
default_sandbox_profile: loadResult.policy.default_sandbox_profile,
|
|
1277
|
-
// Honest trust model (ADR pm-6ef3): keep this caveat to one concise line.
|
|
1278
|
-
sandbox_enforcement: "advisory: sandbox_profile/permissions are declaration-based load gates, not runtime isolation (ADR pm-6ef3)",
|
|
1279
|
-
trusted_extensions_count: loadResult.policy.trusted_extensions.length,
|
|
1280
|
-
allowed_extensions_count: loadResult.policy.allowed_extensions.length,
|
|
1281
|
-
blocked_extensions_count: loadResult.policy.blocked_extensions.length,
|
|
1282
|
-
allowed_capabilities_count: loadResult.policy.allowed_capabilities.length,
|
|
1283
|
-
blocked_capabilities_count: loadResult.policy.blocked_capabilities.length,
|
|
1284
|
-
allowed_surfaces_count: loadResult.policy.allowed_surfaces.length,
|
|
1285
|
-
blocked_surfaces_count: loadResult.policy.blocked_surfaces.length,
|
|
1286
|
-
allowed_commands_count: loadResult.policy.allowed_commands.length,
|
|
1287
|
-
blocked_commands_count: loadResult.policy.blocked_commands.length,
|
|
1288
|
-
allowed_actions_count: loadResult.policy.allowed_actions.length,
|
|
1289
|
-
blocked_actions_count: loadResult.policy.blocked_actions.length,
|
|
1290
|
-
allowed_services_count: loadResult.policy.allowed_services.length,
|
|
1291
|
-
blocked_services_count: loadResult.policy.blocked_services.length,
|
|
1292
|
-
extension_override_count: loadResult.policy.extension_overrides.length,
|
|
1293
|
-
};
|
|
1294
|
-
const capabilityGuidance = collectUnknownCapabilityGuidance(normalizedWarnings);
|
|
1295
|
-
const capabilityContract = buildCapabilityContractMetadata();
|
|
1296
|
-
const warningCodes = triage.warning_codes;
|
|
1297
|
-
const remediation = [
|
|
1298
|
-
...new Set([
|
|
1299
|
-
...triage.remediation,
|
|
1300
|
-
/* c8 ignore start -- vocabulary-specific remediation branches are copy-only variants */
|
|
1301
|
-
...(loadResult.failed.length > 0
|
|
1302
|
-
? [
|
|
1303
|
-
options.vocabulary === "package"
|
|
1304
|
-
? "Run pm package explore --project and pm package explore --global to inspect load failures."
|
|
1305
|
-
: "Run pm extension --explore --project and pm extension --explore --global to inspect load failures.",
|
|
1306
|
-
]
|
|
1307
|
-
: []),
|
|
1308
|
-
...(activationResult.failed.length > 0
|
|
1309
|
-
? [
|
|
1310
|
-
options.vocabulary === "package"
|
|
1311
|
-
? "Review activation failures in pm package doctor --detail deep output."
|
|
1312
|
-
: "Review activation failures in pm extension --doctor --detail deep output.",
|
|
1313
|
-
]
|
|
1314
|
-
: []),
|
|
1315
|
-
/* c8 ignore stop */
|
|
1316
|
-
...(managedStateFix && managedStateFix.adopted_entries.length > 0
|
|
1317
|
-
? [`Managed-state fix adopted ${managedStateFix.adopted_entries.length} extension(s).`]
|
|
1318
|
-
: []),
|
|
1319
|
-
].map((entry) => entry.trim()).filter((entry) => entry.length > 0)),
|
|
1320
|
-
];
|
|
1321
|
-
const summary = {
|
|
1322
|
-
status: triage.status,
|
|
1323
|
-
scope,
|
|
1324
|
-
warning_count: triage.warning_count,
|
|
1325
|
-
warning_codes: warningCodes,
|
|
1326
|
-
total_extensions: runtimeInstalledExtensions.length,
|
|
1327
|
-
managed_total: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
|
|
1328
|
-
enabled_total: runtimeInstalledExtensions.filter((entry) => entry.enabled).length,
|
|
1329
|
-
active_total: runtimeInstalledExtensions.filter((entry) => entry.active).length,
|
|
1330
|
-
unmanaged_loaded_extension_count: triage.unmanaged_loaded_extension_count,
|
|
1331
|
-
unmanaged_action_required_extension_count: triage.unmanaged_action_required_extension_count,
|
|
1332
|
-
unmanaged_expected_extension_count: triage.unmanaged_expected_extension_count,
|
|
1333
|
-
runtime_active_total: runtimeInstalledExtensions.filter((entry) => entry.runtime_active === true).length,
|
|
1334
|
-
activation_status_totals: {
|
|
1335
|
-
ok: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "ok").length,
|
|
1336
|
-
failed: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "failed").length,
|
|
1337
|
-
not_loaded: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "not_loaded").length,
|
|
1338
|
-
unknown: runtimeInstalledExtensions.filter((entry) => entry.activation_status === "unknown").length,
|
|
1339
|
-
},
|
|
1340
|
-
unknown_capability_count: capabilityGuidance.length,
|
|
1341
|
-
capability_contract_version: capabilityContract.version,
|
|
1342
|
-
update_available_total: runtimeInstalledExtensions.filter((entry) => entry.update_available === true).length,
|
|
1343
|
-
update_health_coverage: triage.update_health_coverage,
|
|
1344
|
-
update_health_partial: triage.update_health_partial,
|
|
1345
|
-
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",
|
|
1346
1822
|
load_failure_count: loadResult.failed.length,
|
|
1347
1823
|
activation_failure_count: activationResult.failed.length,
|
|
1348
|
-
|
|
1349
|
-
has_blocking_failures: loadResult.failed.length + activationResult.failed.length > 0,
|
|
1350
|
-
consistency_warning_count: doctorConsistency.warnings.length,
|
|
1351
|
-
trace_enabled: includeTrace,
|
|
1352
|
-
policy: policySummary,
|
|
1353
|
-
remediation,
|
|
1354
|
-
};
|
|
1355
|
-
const managedStateFixSummary = managedStateFix
|
|
1356
|
-
? {
|
|
1357
|
-
requested: true,
|
|
1358
|
-
applied: managedStateFix.adopted_entries.length > 0,
|
|
1359
|
-
adopted_count: managedStateFix.adopted_entries.length,
|
|
1360
|
-
already_managed_count: managedStateFix.already_managed_count,
|
|
1361
|
-
adopted_extensions: managedStateFix.adopted_entries.map((entry) => entry.name),
|
|
1362
|
-
}
|
|
1363
|
-
: {
|
|
1364
|
-
requested: false,
|
|
1365
|
-
applied: false,
|
|
1366
|
-
adopted_count: 0,
|
|
1367
|
-
already_managed_count: refreshedInstalled.extensions.filter((entry) => entry.managed).length,
|
|
1368
|
-
adopted_extensions: [],
|
|
1369
|
-
};
|
|
1370
|
-
const details = {
|
|
1371
|
-
mode: detailMode,
|
|
1372
|
-
summary,
|
|
1373
|
-
triage,
|
|
1374
|
-
trace_enabled: includeTrace,
|
|
1375
|
-
capability_contract: capabilityContract,
|
|
1376
|
-
capability_guidance: capabilityGuidance,
|
|
1377
|
-
managed_state_fix: managedStateFixSummary,
|
|
1824
|
+
warning_count: [...new Set([...loadResult.warnings, ...activationResult.warnings])].length,
|
|
1378
1825
|
policy: loadResult.policy,
|
|
1379
1826
|
};
|
|
1380
|
-
if (detailMode === "deep") {
|
|
1381
|
-
const activationFailedDetails = includeTrace
|
|
1382
|
-
? activationResult.failed
|
|
1383
|
-
: activationResult.failed.map((entry) => {
|
|
1384
|
-
const { trace: _trace, ...rest } = entry;
|
|
1385
|
-
return rest;
|
|
1386
|
-
});
|
|
1387
|
-
details.deep = {
|
|
1388
|
-
warnings: normalizedWarnings,
|
|
1389
|
-
warning_codes: warningCodes,
|
|
1390
|
-
capability_contract: capabilityContract,
|
|
1391
|
-
capability_guidance: capabilityGuidance,
|
|
1392
|
-
trace_enabled: includeTrace,
|
|
1393
|
-
managed_state: {
|
|
1394
|
-
path: managedStateRead.path,
|
|
1395
|
-
count: managedState.entries.length,
|
|
1396
|
-
entries: managedState.entries,
|
|
1397
|
-
},
|
|
1398
|
-
installed_extensions: runtimeInstalledExtensions,
|
|
1399
|
-
load: {
|
|
1400
|
-
roots: loadResult.roots,
|
|
1401
|
-
policy: loadResult.policy,
|
|
1402
|
-
warnings: loadResult.warnings,
|
|
1403
|
-
failed: loadResult.failed,
|
|
1404
|
-
loaded: loadResult.loaded.map((entry) => ({
|
|
1405
|
-
layer: entry.layer,
|
|
1406
|
-
directory: entry.directory,
|
|
1407
|
-
name: entry.name,
|
|
1408
|
-
version: entry.version,
|
|
1409
|
-
entry: entry.entry,
|
|
1410
|
-
priority: entry.priority,
|
|
1411
|
-
})),
|
|
1412
|
-
},
|
|
1413
|
-
activation: {
|
|
1414
|
-
failed: activationFailedDetails,
|
|
1415
|
-
warnings: activationResult.warnings,
|
|
1416
|
-
hook_counts: activationResult.hook_counts,
|
|
1417
|
-
registration_counts: activationResult.registration_counts,
|
|
1418
|
-
parser_override_count: activationResult.parser_override_count,
|
|
1419
|
-
preflight_override_count: activationResult.preflight_override_count,
|
|
1420
|
-
service_override_count: activationResult.service_override_count,
|
|
1421
|
-
renderer_override_count: activationResult.renderer_override_count,
|
|
1422
|
-
},
|
|
1423
|
-
consistency: doctorConsistency.summary,
|
|
1424
|
-
};
|
|
1425
|
-
if (includeTrace) {
|
|
1426
|
-
details.deep.trace = {
|
|
1427
|
-
activation_failures: activationResult.failed
|
|
1428
|
-
.filter((entry) => entry.trace !== undefined)
|
|
1429
|
-
.map((entry) => ({
|
|
1430
|
-
layer: entry.layer,
|
|
1431
|
-
name: entry.name,
|
|
1432
|
-
entry_path: entry.entry_path,
|
|
1433
|
-
error: entry.error,
|
|
1434
|
-
method: entry.trace?.method,
|
|
1435
|
-
command: entry.trace?.command,
|
|
1436
|
-
capability: entry.trace?.capability,
|
|
1437
|
-
missing_capability: entry.trace?.missing_capability,
|
|
1438
|
-
registration_index: entry.trace?.registration_index,
|
|
1439
|
-
expected_schema: entry.trace?.expected_schema,
|
|
1440
|
-
hint: entry.trace?.hint,
|
|
1441
|
-
received: entry.trace?.received,
|
|
1442
|
-
})),
|
|
1443
|
-
};
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
return withResult(details);
|
|
1447
1827
|
}
|
|
1448
|
-
if (action === "
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
cwd: process.cwd(),
|
|
1454
|
-
noExtensions: global.noExtensions === true,
|
|
1455
|
-
});
|
|
1456
|
-
const activationResult = await activateExtensions(loadResult);
|
|
1457
|
-
warnings.push(...loadResult.warnings);
|
|
1458
|
-
warnings.push(...activationResult.warnings);
|
|
1459
|
-
const describeResult = buildExtensionDescribeResult(normalizedTarget, loadResult, activationResult);
|
|
1460
|
-
if (normalizedTarget !== undefined && describeResult.extensions.length === 0) {
|
|
1461
|
-
const noun = options.vocabulary === "package" ? "package" : "extension";
|
|
1462
|
-
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);
|
|
1463
|
-
}
|
|
1464
|
-
return withResult({
|
|
1465
|
-
target: describeResult.target,
|
|
1466
|
-
total: describeResult.total,
|
|
1467
|
-
extensions: describeResult.extensions,
|
|
1468
|
-
union: describeResult.union,
|
|
1469
|
-
});
|
|
1828
|
+
else if (action === "manage") {
|
|
1829
|
+
runtimeProbeSummary = {
|
|
1830
|
+
requested: false,
|
|
1831
|
+
executed: false,
|
|
1832
|
+
};
|
|
1470
1833
|
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
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,
|
|
1490
1864
|
}
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
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,
|
|
1498
1871
|
};
|
|
1499
|
-
}));
|
|
1500
|
-
managedState = {
|
|
1501
|
-
...managedState,
|
|
1502
|
-
updated_at: nowIso(),
|
|
1503
|
-
entries: sortManagedEntries(updates),
|
|
1504
|
-
};
|
|
1505
|
-
await writeManagedExtensionState(resolvedRoots.selected_root, managedState);
|
|
1506
|
-
}
|
|
1507
|
-
const refreshedInstalled = await listInstalledExtensions(resolvedRoots.selected_root, scope, settings, managedState);
|
|
1508
|
-
warnings.push(...refreshedInstalled.warnings);
|
|
1509
|
-
if (action === "manage") {
|
|
1510
|
-
const updateWarnings = refreshedInstalled.extensions
|
|
1511
|
-
.filter((entry) => entry.update_check_status === "failed")
|
|
1512
|
-
.map((entry) => `extension_update_check_failed:${entry.name}`);
|
|
1513
|
-
warnings.push(...updateWarnings);
|
|
1514
|
-
}
|
|
1515
|
-
let runtimeProbeSummary;
|
|
1516
|
-
let runtimeInstalledExtensions = refreshedInstalled.extensions;
|
|
1517
|
-
let runtimeActivationFailures;
|
|
1518
|
-
if (action === "explore" || options.runtimeProbe === true) {
|
|
1519
|
-
const loadResult = await loadExtensions({
|
|
1520
|
-
pmRoot: resolvedRoots.pm_root,
|
|
1521
|
-
settings,
|
|
1522
|
-
cwd: process.cwd(),
|
|
1523
|
-
noExtensions: global.noExtensions === true,
|
|
1524
|
-
});
|
|
1525
|
-
const activationResult = await activateExtensions({
|
|
1526
|
-
...loadResult,
|
|
1527
|
-
loaded: loadResult.loaded,
|
|
1528
|
-
});
|
|
1529
|
-
warnings.push(...loadResult.warnings);
|
|
1530
|
-
warnings.push(...activationResult.warnings);
|
|
1531
|
-
runtimeInstalledExtensions = applyDoctorRuntimeActivationState(refreshedInstalled.extensions, loadResult, activationResult);
|
|
1532
|
-
runtimeActivationFailures = collectActivationFailureDiagnostics(activationResult.failed);
|
|
1533
|
-
runtimeProbeSummary = {
|
|
1534
|
-
requested: true,
|
|
1535
|
-
executed: true,
|
|
1536
|
-
reason: action === "explore" ? "explore_defaults_to_runtime_probe" : "runtime_probe_requested",
|
|
1537
|
-
load_failure_count: loadResult.failed.length,
|
|
1538
|
-
activation_failure_count: activationResult.failed.length,
|
|
1539
|
-
warning_count: [...new Set([...loadResult.warnings, ...activationResult.warnings])].length,
|
|
1540
|
-
policy: loadResult.policy,
|
|
1541
|
-
};
|
|
1542
|
-
}
|
|
1543
|
-
else if (action === "manage") {
|
|
1544
|
-
runtimeProbeSummary = {
|
|
1545
|
-
requested: false,
|
|
1546
|
-
executed: false,
|
|
1547
|
-
};
|
|
1548
|
-
}
|
|
1549
|
-
const triage = buildExtensionTriageSummary(scope, warnings, runtimeInstalledExtensions, options);
|
|
1550
|
-
warnings.push(...triage.warnings);
|
|
1551
|
-
const details = {
|
|
1552
|
-
total: runtimeInstalledExtensions.length,
|
|
1553
|
-
managed_total: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
|
|
1554
|
-
enabled_total: runtimeInstalledExtensions.filter((entry) => entry.enabled).length,
|
|
1555
|
-
active_total: runtimeInstalledExtensions.filter((entry) => entry.active).length,
|
|
1556
|
-
extensions: runtimeInstalledExtensions,
|
|
1557
|
-
triage,
|
|
1558
|
-
policy: configuredPolicy,
|
|
1559
|
-
};
|
|
1560
|
-
if (runtimeActivationFailures !== undefined) {
|
|
1561
|
-
details.activation_diagnostics = {
|
|
1562
|
-
failed_count: runtimeActivationFailures.length,
|
|
1563
|
-
failed: runtimeActivationFailures,
|
|
1564
|
-
};
|
|
1565
|
-
}
|
|
1566
|
-
if (action === "explore") {
|
|
1567
|
-
details.runtime_probe = runtimeProbeSummary;
|
|
1568
|
-
}
|
|
1569
|
-
if (action === "manage") {
|
|
1570
|
-
details.runtime_probe = runtimeProbeSummary;
|
|
1571
|
-
details.managed_state_fix =
|
|
1572
|
-
managedStateFix !== null
|
|
1573
|
-
? {
|
|
1574
|
-
requested: true,
|
|
1575
|
-
applied: managedStateFix.adopted_entries.length > 0,
|
|
1576
|
-
adopted_count: managedStateFix.adopted_entries.length,
|
|
1577
|
-
adopted_extensions: managedStateFix.adopted_entries.map((entry) => entry.name),
|
|
1578
|
-
already_managed_count: managedStateFix.already_managed_count,
|
|
1579
|
-
}
|
|
1580
|
-
: {
|
|
1581
|
-
requested: false,
|
|
1582
|
-
applied: false,
|
|
1583
|
-
adopted_count: 0,
|
|
1584
|
-
adopted_extensions: [],
|
|
1585
|
-
already_managed_count: runtimeInstalledExtensions.filter((entry) => entry.managed).length,
|
|
1586
|
-
};
|
|
1587
|
-
}
|
|
1588
|
-
return withResult(details);
|
|
1589
1872
|
}
|
|
1590
|
-
|
|
1591
|
-
/* c8 ignore start -- resolveAction returns a closed ExtensionCommandAction union */
|
|
1592
|
-
throw new PmCliError(`Unsupported extension action "${action}".`, EXIT_CODE.USAGE);
|
|
1593
|
-
/* c8 ignore stop */
|
|
1873
|
+
return withResult(details);
|
|
1594
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
|
+
};
|
|
1595
1895
|
export const _testOnly = {
|
|
1596
1896
|
adoptUnmanagedExtensions,
|
|
1597
1897
|
buildExtensionPolicyDetails,
|
|
@@ -1602,6 +1902,7 @@ export const _testOnly = {
|
|
|
1602
1902
|
findActivationFailureByName,
|
|
1603
1903
|
resolveInstallRuntimeActivationStatus,
|
|
1604
1904
|
collectGlobalOutputOverrideDoctorWarnings,
|
|
1905
|
+
collectSchemaNarrowActivationDoctorWarnings,
|
|
1605
1906
|
copyExtensionDirectoryWithoutSelfNesting,
|
|
1606
1907
|
isErrnoCode,
|
|
1607
1908
|
isRetriableExtensionInstallCopyError,
|
|
@@ -1616,4 +1917,4 @@ export const _testOnly = {
|
|
|
1616
1917
|
withExtensionInstallLock,
|
|
1617
1918
|
};
|
|
1618
1919
|
//# sourceMappingURL=extension.js.map
|
|
1619
|
-
//# debugId=
|
|
1920
|
+
//# debugId=0e9a5528-9595-5a89-89b7-5a5acce477a8
|