@unbrained/pm-cli 2026.6.23 → 2026.6.30
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/CHANGELOG.md +120 -0
- package/CONTRIBUTING.md +30 -0
- package/README.md +16 -3
- 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/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 +10 -155
- package/dist/cli/commands/create.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 +5 -2
- 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/scaffold.d.ts +31 -8
- package/dist/cli/commands/extension/scaffold.js +1956 -182
- package/dist/cli/commands/extension/scaffold.js.map +1 -1
- package/dist/cli/commands/extension.d.ts +22 -2
- package/dist/cli/commands/extension.js +189 -13
- 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.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 +104 -106
- 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 +9 -5
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/commands/update.d.ts +1 -6
- package/dist/cli/commands/update.js +12 -157
- 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/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 +34 -3
- package/dist/cli/registration-helpers.js.map +1 -1
- package/dist/cli-bundle/chunks/activity-EJBMXUBH.js +16 -0
- package/dist/cli-bundle/chunks/{activity-H2LMOSSW.js → activity-MVSEND6D.js} +9 -11
- package/dist/cli-bundle/chunks/{aggregate-R725FC3S.js → aggregate-MOC4TR2G.js} +16 -17
- package/dist/cli-bundle/chunks/aggregate-MOC4TR2G.js.map +1 -0
- package/dist/cli-bundle/chunks/{aggregate-EGJLZQBI.js → aggregate-XJHLZQ5X.js} +15 -16
- package/dist/cli-bundle/chunks/aggregate-XJHLZQ5X.js.map +7 -0
- package/dist/cli-bundle/chunks/{append-5J345QGU.js → append-KDHT4GHI.js} +10 -12
- package/dist/cli-bundle/chunks/{append-5J345QGU.js.map → append-KDHT4GHI.js.map} +1 -1
- package/dist/cli-bundle/chunks/{append-O5HPBMRN.js → append-LEDBAM3K.js} +8 -10
- package/dist/cli-bundle/chunks/{append-O5HPBMRN.js.map → append-LEDBAM3K.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-IB3GYLQE.js → chunk-3JWQCLR5.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-2A34E3BA.js → chunk-4TXTVZL3.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-G6N5VEOK.js → chunk-4YIMPANT.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-7AUB5HNA.js → chunk-53ARXF2O.js} +9 -11
- package/dist/cli-bundle/chunks/{chunk-7AUB5HNA.js.map → chunk-53ARXF2O.js.map} +1 -1
- package/dist/cli-bundle/chunks/chunk-5ABGFWR4.js +116 -0
- package/dist/cli-bundle/chunks/chunk-5ABGFWR4.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-2BFPAUAF.js → chunk-5IRVSKPS.js} +2990 -2890
- package/dist/cli-bundle/chunks/chunk-5IRVSKPS.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-JR2LV3M4.js → chunk-5T6WPLRO.js} +233 -190
- package/dist/cli-bundle/chunks/chunk-5T6WPLRO.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-CKGNPJAG.js → chunk-6T5ZIWBS.js} +3011 -2888
- package/dist/cli-bundle/chunks/chunk-6T5ZIWBS.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-QH3PJYON.js → chunk-6YRAMXRS.js} +111 -114
- package/dist/cli-bundle/chunks/chunk-6YRAMXRS.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-7XGQXHFB.js → chunk-73PTKMAE.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-Y4SUQQYH.js → chunk-74PUWBGN.js} +53 -54
- package/dist/cli-bundle/chunks/chunk-74PUWBGN.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-T5472OMV.js → chunk-7L6TXOOC.js} +4 -6
- package/dist/cli-bundle/chunks/{chunk-T5472OMV.js.map → chunk-7L6TXOOC.js.map} +1 -1
- 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-3VY3YQO6.js → chunk-7RIJGN4R.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-G6PYHBBR.js → chunk-7WDETKGP.js} +192 -113
- package/dist/cli-bundle/chunks/chunk-7WDETKGP.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-AONIHR2C.js → chunk-A3UNLXNJ.js} +40 -260
- package/dist/cli-bundle/chunks/chunk-A3UNLXNJ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-4KD54S3Z.js → chunk-AWN4PPH5.js} +10 -14
- package/dist/cli-bundle/chunks/{chunk-4KD54S3Z.js.map → chunk-AWN4PPH5.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-FXR67XVQ.js → chunk-BN3CWK6G.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-KFWBJPSG.js → chunk-BOWQWXLI.js} +12 -24
- package/dist/cli-bundle/chunks/chunk-BOWQWXLI.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-4BHT5VDC.js → chunk-C2KCIZKZ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-O6LLO73I.js → chunk-CHRNYKNI.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-UELRKQQU.js → chunk-CY5IJMUM.js} +1239 -495
- package/dist/cli-bundle/chunks/chunk-CY5IJMUM.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-7K2XXO4I.js → chunk-D5LYZVGB.js} +7 -9
- package/dist/cli-bundle/chunks/{chunk-7K2XXO4I.js.map → chunk-D5LYZVGB.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-ZQ3ZVXX2.js → chunk-D6USKAMA.js} +2 -2
- package/dist/cli-bundle/chunks/{context-BLBD3PUB.js → chunk-DJDXAU74.js} +19 -21
- package/dist/cli-bundle/chunks/chunk-DJDXAU74.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-WZQWHN4R.js → chunk-DLDCPF5X.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-HFFUQR73.js → chunk-DORJSBGJ.js} +35 -9
- package/dist/cli-bundle/chunks/chunk-DORJSBGJ.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-XVF4YARA.js → chunk-DRPF274X.js} +5 -7
- package/dist/cli-bundle/chunks/{chunk-XVF4YARA.js.map → chunk-DRPF274X.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-QL5RVYOA.js → chunk-DU66JUGT.js} +16 -14
- package/dist/cli-bundle/chunks/chunk-DU66JUGT.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-UVC5LOR7.js → chunk-E2Q2ULMR.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-U2Z5YUSO.js → chunk-EVWYAG46.js} +9 -11
- package/dist/cli-bundle/chunks/{chunk-U2Z5YUSO.js.map → chunk-EVWYAG46.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-5VOINNKT.js → chunk-F6VH3LFC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-VFAQ4LMN.js → chunk-F7G53BOA.js} +18 -11
- package/dist/cli-bundle/chunks/chunk-F7G53BOA.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-Q2KNGP7C.js → chunk-FBZ5XAAF.js} +9 -11
- package/dist/cli-bundle/chunks/{chunk-Q2KNGP7C.js.map → chunk-FBZ5XAAF.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-H4IIJDE4.js → chunk-FDEVKXC4.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-7UGEAPRY.js → chunk-GF7EAR22.js} +10 -14
- package/dist/cli-bundle/chunks/{chunk-7UGEAPRY.js.map → chunk-GF7EAR22.js.map} +1 -1
- package/dist/cli-bundle/chunks/{context-DHLVPXN3.js → chunk-HIBK6H4S.js} +20 -22
- package/dist/cli-bundle/chunks/chunk-HIBK6H4S.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-34EONI5F.js → chunk-HUYYMTGW.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-BB6MDVNQ.js → chunk-IBU2LLWM.js} +8 -12
- package/dist/cli-bundle/chunks/{chunk-BB6MDVNQ.js.map → chunk-IBU2LLWM.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-55ISXAQH.js → chunk-IDYCAK35.js} +53 -54
- package/dist/cli-bundle/chunks/chunk-IDYCAK35.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-M4T5DXD5.js → chunk-IF4ERU6A.js} +7 -9
- package/dist/cli-bundle/chunks/{chunk-M4T5DXD5.js.map → chunk-IF4ERU6A.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-CIIK67GW.js → chunk-IHXXUIXS.js} +4 -4
- package/dist/cli-bundle/chunks/chunk-IZQOJR2B.js +2459 -0
- package/dist/cli-bundle/chunks/chunk-IZQOJR2B.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-SBQTAVJZ.js → chunk-JIP67N2K.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-JJ4SG243.js +119 -0
- package/dist/cli-bundle/chunks/chunk-JJ4SG243.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-TQZH6OD6.js → chunk-JTRKME24.js} +11 -13
- package/dist/cli-bundle/chunks/{chunk-TQZH6OD6.js.map → chunk-JTRKME24.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-WBRKK5QR.js → chunk-JVQ7UOYC.js} +6 -8
- package/dist/cli-bundle/chunks/{chunk-WBRKK5QR.js.map → chunk-JVQ7UOYC.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-KQMUV6LX.js → chunk-JZG5ADVE.js} +191 -98
- package/dist/cli-bundle/chunks/chunk-JZG5ADVE.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-46G6RSB6.js → chunk-K46GQ265.js} +17 -15
- package/dist/cli-bundle/chunks/chunk-K46GQ265.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-5UVVASSA.js → chunk-KGQ3W65B.js} +100 -35
- package/dist/cli-bundle/chunks/chunk-KGQ3W65B.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-2T3JG6V4.js → chunk-KRASIL6M.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-SR3EKWZG.js → chunk-KTMMTOIP.js} +127 -127
- package/dist/cli-bundle/chunks/chunk-KTMMTOIP.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-DT5LPYOD.js → chunk-KYDYQMNW.js} +5 -7
- package/dist/cli-bundle/chunks/{chunk-DT5LPYOD.js.map → chunk-KYDYQMNW.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-IPKJ6B36.js → chunk-LBH7UYKY.js} +106 -34
- package/dist/cli-bundle/chunks/chunk-LBH7UYKY.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-P77P2ILI.js → chunk-MLHX6DN5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-YUDJD3XO.js → chunk-NIBP3I7A.js} +36 -10
- package/dist/cli-bundle/chunks/chunk-NIBP3I7A.js.map +1 -0
- package/dist/cli-bundle/chunks/{schema-RBTJ2YXW.js → chunk-NO6Y6FB2.js} +144 -67
- package/dist/cli-bundle/chunks/chunk-NO6Y6FB2.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-2CKH2LMV.js → chunk-OB3RJV5F.js} +2 -2
- 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-FIGAZ4Y7.js → chunk-OUQ5JEFM.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-NK3UPBVG.js → chunk-QE5UFCCO.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-MJTINN54.js → chunk-RM6MHL6A.js} +110 -113
- package/dist/cli-bundle/chunks/chunk-RM6MHL6A.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-LRKKONT2.js → chunk-RPRW26NG.js} +12 -16
- package/dist/cli-bundle/chunks/{chunk-LRKKONT2.js.map → chunk-RPRW26NG.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-WM5ZVBPE.js → chunk-SJZTPVFT.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-MJTSZKK5.js → chunk-SNUK7H5J.js} +1363 -605
- package/dist/cli-bundle/chunks/chunk-SNUK7H5J.js.map +7 -0
- package/dist/cli-bundle/chunks/chunk-T7ZMQI4J.js +2435 -0
- package/dist/cli-bundle/chunks/chunk-T7ZMQI4J.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-W72GHSJE.js → chunk-TQ6E76BE.js} +11 -13
- package/dist/cli-bundle/chunks/{chunk-W72GHSJE.js.map → chunk-TQ6E76BE.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-ZRK4O56R.js → chunk-UB3V5WUI.js} +225 -189
- package/dist/cli-bundle/chunks/chunk-UB3V5WUI.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-SKN7LC5W.js → chunk-UFKNF23C.js} +11 -23
- package/dist/cli-bundle/chunks/chunk-UFKNF23C.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-VAYA4XFX.js → chunk-V3KLX7U7.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-GAJVRGGA.js → chunk-VD3LKZFX.js} +41 -254
- package/dist/cli-bundle/chunks/chunk-VD3LKZFX.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-AD3A7ZD6.js → chunk-VMY7MZEM.js} +10 -14
- package/dist/cli-bundle/chunks/{chunk-AD3A7ZD6.js.map → chunk-VMY7MZEM.js.map} +1 -1
- 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-CE5P2NQR.js → chunk-WFJZDUM7.js} +19 -12
- package/dist/cli-bundle/chunks/chunk-WFJZDUM7.js.map +1 -0
- package/dist/cli-bundle/chunks/{schema-MNTAVQCY.js → chunk-WTRUDJ3R.js} +136 -66
- package/dist/cli-bundle/chunks/chunk-WTRUDJ3R.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-T72AZDBA.js → chunk-YEDFE4DC.js} +6 -8
- package/dist/cli-bundle/chunks/{chunk-T72AZDBA.js.map → chunk-YEDFE4DC.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-H2IP4QLJ.js → chunk-Z55WX4IQ.js} +12 -16
- package/dist/cli-bundle/chunks/{chunk-H2IP4QLJ.js.map → chunk-Z55WX4IQ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-2RDVQEWV.js → chunk-Z5BM2FKQ.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-66MEDTUD.js → chunk-ZEATCVAC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-NCVCO3NZ.js → chunk-ZFIEEDTJ.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-7SV63ZHD.js → chunk-ZIE6WXJ2.js} +128 -128
- package/dist/cli-bundle/chunks/chunk-ZIE6WXJ2.js.map +1 -0
- package/dist/cli-bundle/chunks/{claim-4KHAA2RN.js → claim-6NINZYB3.js} +10 -12
- package/dist/cli-bundle/chunks/{claim-4KHAA2RN.js.map → claim-6NINZYB3.js.map} +1 -1
- package/dist/cli-bundle/chunks/{claim-CSPJFLNH.js → claim-HMCLSLUE.js} +8 -10
- package/dist/cli-bundle/chunks/{claim-CSPJFLNH.js.map → claim-HMCLSLUE.js.map} +1 -1
- package/dist/cli-bundle/chunks/close-37KEHLYM.js +14 -0
- package/dist/cli-bundle/chunks/{close-W56IOGYG.js → close-OP3LK7Z2.js} +7 -8
- package/dist/cli-bundle/chunks/{close-many-BX5DCSVV.js → close-many-BFMP6HHK.js} +15 -17
- package/dist/cli-bundle/chunks/{close-many-BX5DCSVV.js.map → close-many-BFMP6HHK.js.map} +1 -1
- package/dist/cli-bundle/chunks/{close-many-TQU5F4E4.js → close-many-CXJBOWWY.js} +17 -19
- package/dist/cli-bundle/chunks/{close-many-TQU5F4E4.js.map → close-many-CXJBOWWY.js.map} +1 -1
- package/dist/cli-bundle/chunks/{comments-VRECH75R.js → comments-ETHABIY6.js} +9 -11
- package/dist/cli-bundle/chunks/{comments-VRECH75R.js.map → comments-ETHABIY6.js.map} +1 -1
- package/dist/cli-bundle/chunks/{comments-U5KUC4EU.js → comments-MU2WMBUY.js} +11 -13
- package/dist/cli-bundle/chunks/{comments-U5KUC4EU.js.map → comments-MU2WMBUY.js.map} +1 -1
- package/dist/cli-bundle/chunks/{config-D3OKQO52.js → config-FIXJZEQK.js} +18 -387
- package/dist/cli-bundle/chunks/config-FIXJZEQK.js.map +7 -0
- package/dist/cli-bundle/chunks/{config-MMJA4LLK.js → config-X3ZVCUUG.js} +18 -380
- package/dist/cli-bundle/chunks/config-X3ZVCUUG.js.map +1 -0
- package/dist/cli-bundle/chunks/context-7ZEZV3BV.js +42 -0
- package/dist/cli-bundle/chunks/context-XDI4DKKT.js +46 -0
- package/dist/cli-bundle/chunks/{contracts-XGVMMPC5.js → contracts-KP4QAGVW.js} +72 -15
- package/dist/cli-bundle/chunks/contracts-KP4QAGVW.js.map +1 -0
- package/dist/cli-bundle/chunks/{contracts-C3SZCXXG.js → contracts-SMOAN5NF.js} +72 -15
- package/dist/cli-bundle/chunks/contracts-SMOAN5NF.js.map +7 -0
- package/dist/cli-bundle/chunks/{copy-HHL3K4QP.js → copy-CWM6SBY6.js} +7 -11
- package/dist/cli-bundle/chunks/{copy-HHL3K4QP.js.map → copy-CWM6SBY6.js.map} +1 -1
- package/dist/cli-bundle/chunks/{copy-5D5DX3VK.js → copy-JJ3KOQW2.js} +9 -13
- package/dist/cli-bundle/chunks/{copy-5D5DX3VK.js.map → copy-JJ3KOQW2.js.map} +1 -1
- package/dist/cli-bundle/chunks/create-DFMNBKBS.js +28 -0
- package/dist/cli-bundle/chunks/{create-IXY43O4H.js → create-J5Q2ELZT.js} +12 -14
- package/dist/cli-bundle/chunks/{delete-IBUR3M42.js → delete-2GZLQEUQ.js} +7 -9
- package/dist/cli-bundle/chunks/{delete-IBUR3M42.js.map → delete-2GZLQEUQ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{delete-QQC2FGUH.js → delete-OOQS4KVD.js} +5 -7
- package/dist/cli-bundle/chunks/{delete-QQC2FGUH.js.map → delete-OOQS4KVD.js.map} +1 -1
- package/dist/cli-bundle/chunks/{deps-KWKRHXIN.js → deps-IF4IGL4R.js} +6 -9
- package/dist/cli-bundle/chunks/{deps-KWKRHXIN.js.map → deps-IF4IGL4R.js.map} +1 -1
- package/dist/cli-bundle/chunks/{deps-VTPO4BSE.js → deps-ZVGGCRR6.js} +8 -11
- package/dist/cli-bundle/chunks/{deps-VTPO4BSE.js.map → deps-ZVGGCRR6.js.map} +1 -1
- package/dist/cli-bundle/chunks/{docs-IIO3FEUO.js → docs-2TIFR62T.js} +8 -9
- package/dist/cli-bundle/chunks/{docs-IIO3FEUO.js.map → docs-2TIFR62T.js.map} +1 -1
- package/dist/cli-bundle/chunks/{docs-7CHFHXLN.js → docs-NFTBCQQC.js} +10 -11
- package/dist/cli-bundle/chunks/{docs-7CHFHXLN.js.map → docs-NFTBCQQC.js.map} +1 -1
- package/dist/cli-bundle/chunks/{eval-IO7LREOL.js → eval-2F6EH4XN.js} +12 -14
- package/dist/cli-bundle/chunks/{eval-IO7LREOL.js.map → eval-2F6EH4XN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{eval-CEYYEPSX.js → eval-PFKXQR3B.js} +10 -12
- package/dist/cli-bundle/chunks/{eval-CEYYEPSX.js.map → eval-PFKXQR3B.js.map} +1 -1
- package/dist/cli-bundle/chunks/{extension-KCPUWSY2.js → extension-3LRYX7SW.js} +11 -7
- package/dist/cli-bundle/chunks/{extension-UTTQDUYI.js → extension-GMVOIP4O.js} +11 -7
- package/dist/cli-bundle/chunks/{files-Z2HHEFGP.js → files-DF3HO6XK.js} +11 -13
- package/dist/cli-bundle/chunks/{files-Z2HHEFGP.js.map → files-DF3HO6XK.js.map} +1 -1
- package/dist/cli-bundle/chunks/{files-TPUL6KWB.js → files-T5ODMETM.js} +9 -11
- package/dist/cli-bundle/chunks/{files-TPUL6KWB.js.map → files-T5ODMETM.js.map} +1 -1
- package/dist/cli-bundle/chunks/{focus-YRNNH7IP.js → focus-DLXKK4AH.js} +10 -14
- package/dist/cli-bundle/chunks/{focus-YRNNH7IP.js.map → focus-DLXKK4AH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{focus-JVJCGC2D.js → focus-MY5ARIEK.js} +8 -12
- package/dist/cli-bundle/chunks/{focus-JVJCGC2D.js.map → focus-MY5ARIEK.js.map} +1 -1
- package/dist/cli-bundle/chunks/{gc-O5GUO3SU.js → gc-FULIVYR4.js} +3 -3
- package/dist/cli-bundle/chunks/{gc-PYVVEELM.js → gc-MDGRR2SU.js} +3 -3
- package/dist/cli-bundle/chunks/{get-X4O3HBEY.js → get-AWK324RS.js} +10 -13
- package/dist/cli-bundle/chunks/{get-X4O3HBEY.js.map → get-AWK324RS.js.map} +1 -1
- package/dist/cli-bundle/chunks/{get-ENLTEGTX.js → get-VYPIICPC.js} +12 -15
- package/dist/cli-bundle/chunks/{get-ENLTEGTX.js.map → get-VYPIICPC.js.map} +1 -1
- package/dist/cli-bundle/chunks/{health-5EXTY44Q.js → health-FBCVZGSX.js} +16 -17
- package/dist/cli-bundle/chunks/{health-5EXTY44Q.js.map → health-FBCVZGSX.js.map} +1 -1
- package/dist/cli-bundle/chunks/{health-BOTB7YSU.js → health-Q66C43GN.js} +18 -19
- package/dist/cli-bundle/chunks/{health-BOTB7YSU.js.map → health-Q66C43GN.js.map} +1 -1
- package/dist/cli-bundle/chunks/history-5XUSLAJA.js +18 -0
- package/dist/cli-bundle/chunks/{history-AJTXLT6S.js → history-X4OSES6K.js} +8 -10
- package/dist/cli-bundle/chunks/{history-compact-46MRHW3I.js → history-compact-2GHT32UX.js} +13 -16
- package/dist/cli-bundle/chunks/{history-compact-46MRHW3I.js.map → history-compact-2GHT32UX.js.map} +1 -1
- package/dist/cli-bundle/chunks/{history-compact-43OOUAWD.js → history-compact-WLCQEKXS.js} +11 -14
- package/dist/cli-bundle/chunks/{history-compact-43OOUAWD.js.map → history-compact-WLCQEKXS.js.map} +1 -1
- package/dist/cli-bundle/chunks/{history-redact-KUUUVUFM.js → history-redact-45YW65BK.js} +9 -11
- package/dist/cli-bundle/chunks/history-redact-BVHWDXPR.js +19 -0
- package/dist/cli-bundle/chunks/{history-repair-B5PZBOPU.js → history-repair-FY75IC26.js} +13 -16
- package/dist/cli-bundle/chunks/{history-repair-B5PZBOPU.js.map → history-repair-FY75IC26.js.map} +1 -1
- package/dist/cli-bundle/chunks/{history-repair-VQTYOSRS.js → history-repair-GABSDSVD.js} +11 -14
- package/dist/cli-bundle/chunks/{history-repair-VQTYOSRS.js.map → history-repair-GABSDSVD.js.map} +1 -1
- package/dist/cli-bundle/chunks/{init-BNLVFPRG.js → init-KO7CGIRQ.js} +11 -11
- package/dist/cli-bundle/chunks/init-TRYJELH4.js +21 -0
- package/dist/cli-bundle/chunks/{learnings-MUUU5KMC.js → learnings-3F7YLI45.js} +9 -11
- package/dist/cli-bundle/chunks/{learnings-MUUU5KMC.js.map → learnings-3F7YLI45.js.map} +1 -1
- package/dist/cli-bundle/chunks/{learnings-XSGX52S7.js → learnings-LHZT5BHW.js} +11 -13
- package/dist/cli-bundle/chunks/{learnings-XSGX52S7.js.map → learnings-LHZT5BHW.js.map} +1 -1
- package/dist/cli-bundle/chunks/{list-32U7BSKE.js → list-ROT7JF62.js} +10 -10
- package/dist/cli-bundle/chunks/{list-ZEEOHLTQ.js → list-Y6AU5BJS.js} +10 -10
- package/dist/cli-bundle/chunks/next-66BJB4N2.js +277 -0
- package/dist/cli-bundle/chunks/next-66BJB4N2.js.map +7 -0
- package/dist/cli-bundle/chunks/next-N5MWJTBY.js +274 -0
- package/dist/cli-bundle/chunks/next-N5MWJTBY.js.map +1 -0
- package/dist/cli-bundle/chunks/{notes-OHU25L3M.js → notes-EVJZ3VAB.js} +11 -13
- package/dist/cli-bundle/chunks/{notes-OHU25L3M.js.map → notes-EVJZ3VAB.js.map} +1 -1
- package/dist/cli-bundle/chunks/{notes-NJ45OZGF.js → notes-FW6YFLND.js} +9 -11
- package/dist/cli-bundle/chunks/{notes-NJ45OZGF.js.map → notes-FW6YFLND.js.map} +1 -1
- package/dist/cli-bundle/chunks/{plan-LWWAEV5Y.js → plan-DQ7G4EDC.js} +15 -18
- package/dist/cli-bundle/chunks/{plan-LWWAEV5Y.js.map → plan-DQ7G4EDC.js.map} +1 -1
- package/dist/cli-bundle/chunks/{plan-KQA7CAKI.js → plan-ZHKZ7JVF.js} +17 -20
- package/dist/cli-bundle/chunks/{plan-KQA7CAKI.js.map → plan-ZHKZ7JVF.js.map} +1 -1
- package/dist/cli-bundle/chunks/profile-CHAW6SEA.js +1197 -0
- package/dist/cli-bundle/chunks/profile-CHAW6SEA.js.map +1 -0
- package/dist/cli-bundle/chunks/profile-UPZGCDOG.js +1235 -0
- package/dist/cli-bundle/chunks/profile-UPZGCDOG.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-list-query-DDCHPONM.js → register-list-query-KY6Z6WV7.js} +44 -20
- package/dist/cli-bundle/chunks/register-list-query-KY6Z6WV7.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-list-query-YNPBVIKM.js → register-list-query-Y2VRHPCL.js} +45 -21
- package/dist/cli-bundle/chunks/register-list-query-Y2VRHPCL.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-mutation-LAVKYY63.js → register-mutation-N6AYSKPM.js} +103 -37
- package/dist/cli-bundle/chunks/register-mutation-N6AYSKPM.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-mutation-7ALWDDAX.js → register-mutation-PCARIGZS.js} +104 -38
- package/dist/cli-bundle/chunks/register-mutation-PCARIGZS.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-operations-U5JAW3WE.js → register-operations-L6CYTOIH.js} +30 -32
- package/dist/cli-bundle/chunks/{register-operations-U5JAW3WE.js.map → register-operations-L6CYTOIH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-operations-R4VOQ6EF.js → register-operations-YAT6FUUB.js} +32 -34
- package/dist/cli-bundle/chunks/{register-operations-R4VOQ6EF.js.map → register-operations-YAT6FUUB.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-KBXQDCXE.js → register-setup-MPANILQF.js} +67 -24
- package/dist/cli-bundle/chunks/register-setup-MPANILQF.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-setup-RCRUHMSZ.js → register-setup-N7UGXYJC.js} +68 -25
- package/dist/cli-bundle/chunks/register-setup-N7UGXYJC.js.map +1 -0
- package/dist/cli-bundle/chunks/{restore-6K53WOWO.js → restore-DKMCLPI5.js} +9 -11
- package/dist/cli-bundle/chunks/restore-IRAKSWIW.js +17 -0
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-NJ5UVJFB.js → scheduling-shortcuts-3F4QUEDH.js} +14 -16
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-NJ5UVJFB.js.map → scheduling-shortcuts-3F4QUEDH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-OQVJXG3M.js → scheduling-shortcuts-BNZLQK36.js} +12 -14
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-OQVJXG3M.js.map → scheduling-shortcuts-BNZLQK36.js.map} +1 -1
- package/dist/cli-bundle/chunks/schema-OLT6LVKH.js +75 -0
- package/dist/cli-bundle/chunks/schema-XJXKJQF5.js +71 -0
- package/dist/cli-bundle/chunks/{search-6HOIVZDU.js → search-CX5UMV4H.js} +10 -12
- package/dist/cli-bundle/chunks/{search-ZWYEMASC.js → search-KP6H7COV.js} +10 -12
- package/dist/cli-bundle/chunks/{stats-R5OAJVZK.js → stats-7XW4OEMK.js} +20 -12
- package/dist/cli-bundle/chunks/stats-7XW4OEMK.js.map +7 -0
- package/dist/cli-bundle/chunks/{stats-FS742AMA.js → stats-QZUG6MX5.js} +21 -13
- package/dist/cli-bundle/chunks/stats-QZUG6MX5.js.map +1 -0
- package/dist/cli-bundle/chunks/{telemetry-7DIGDQUO.js → telemetry-DIFPXCAT.js} +4 -4
- package/dist/cli-bundle/chunks/{telemetry-FWEXSJLQ.js → telemetry-WTYFUPRL.js} +4 -4
- package/dist/cli-bundle/chunks/{test-NZF7OT2F.js → test-HU2BS7EY.js} +14 -16
- package/dist/cli-bundle/chunks/test-HU2BS7EY.js.map +1 -0
- package/dist/cli-bundle/chunks/test-QNDXZQCW.js +34 -0
- package/dist/cli-bundle/chunks/test-QNDXZQCW.js.map +7 -0
- package/dist/cli-bundle/chunks/{test-all-DPN62TX7.js → test-all-PZTBLLQ6.js} +17 -20
- package/dist/cli-bundle/chunks/{test-all-DPN62TX7.js.map → test-all-PZTBLLQ6.js.map} +1 -1
- package/dist/cli-bundle/chunks/{test-all-KL7TLMJF.js → test-all-XLPI4USF.js} +19 -22
- package/dist/cli-bundle/chunks/{test-all-KL7TLMJF.js.map → test-all-XLPI4USF.js.map} +1 -1
- package/dist/cli-bundle/chunks/{test-runs-C6CFIVOS.js → test-runs-CA6K32RD.js} +6 -7
- package/dist/cli-bundle/chunks/test-runs-CA6K32RD.js.map +1 -0
- package/dist/cli-bundle/chunks/{test-runs-IAJDL6CA.js → test-runs-LANLLPVO.js} +5 -6
- package/dist/cli-bundle/chunks/test-runs-LANLLPVO.js.map +7 -0
- package/dist/cli-bundle/chunks/update-DJKWLBWJ.js +28 -0
- package/dist/cli-bundle/chunks/update-DJKWLBWJ.js.map +1 -0
- package/dist/cli-bundle/chunks/update-UXDLTEOZ.js +24 -0
- package/dist/cli-bundle/chunks/update-UXDLTEOZ.js.map +7 -0
- package/dist/cli-bundle/chunks/{update-many-YEH2DQL6.js → update-many-LU3SCNK5.js} +32 -33
- package/dist/cli-bundle/chunks/{update-many-YEH2DQL6.js.map → update-many-LU3SCNK5.js.map} +1 -1
- package/dist/cli-bundle/chunks/{update-many-MUTIOAP3.js → update-many-VW5DGF3S.js} +34 -35
- package/dist/cli-bundle/chunks/{update-many-MUTIOAP3.js.map → update-many-VW5DGF3S.js.map} +1 -1
- package/dist/cli-bundle/chunks/{upgrade-HYJ3SWWU.js → upgrade-77FRUAXN.js} +12 -8
- package/dist/cli-bundle/chunks/{upgrade-HYJ3SWWU.js.map → upgrade-77FRUAXN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{upgrade-UBNLBZNR.js → upgrade-ICXY244R.js} +10 -6
- package/dist/cli-bundle/chunks/{upgrade-UBNLBZNR.js.map → upgrade-ICXY244R.js.map} +1 -1
- package/dist/cli-bundle/chunks/{validate-6QWQVCX2.js → validate-2G566PKQ.js} +37 -28
- package/dist/cli-bundle/chunks/validate-2G566PKQ.js.map +7 -0
- package/dist/cli-bundle/chunks/{validate-W5V5ZGQX.js → validate-BDPVXHHH.js} +38 -29
- package/dist/cli-bundle/chunks/validate-BDPVXHHH.js.map +1 -0
- package/dist/cli-bundle/main.js +56 -38
- package/dist/cli-bundle/main.js.map +2 -2
- 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 +140 -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-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.d.ts +1 -2
- package/dist/core/extensions/loader.js +169 -103
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/version-compat.d.ts +107 -0
- package/dist/core/extensions/version-compat.js +130 -0
- package/dist/core/extensions/version-compat.js.map +1 -0
- 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/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 +183 -83
- 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 +1583 -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 +840 -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 +346 -4
- package/dist/sdk/compose.js +486 -15
- package/dist/sdk/compose.js.map +1 -1
- package/dist/sdk/define.d.ts +29 -14
- package/dist/sdk/define.js +21 -7
- 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 +156 -3
- package/dist/sdk/testing.js +172 -4
- 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 +20 -20
- package/docs/RELEASING.md +6 -1
- package/docs/SDK.md +387 -20
- 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-XUZ2AHCW.js +0 -18
- package/dist/cli-bundle/chunks/aggregate-EGJLZQBI.js.map +0 -7
- package/dist/cli-bundle/chunks/aggregate-R725FC3S.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-2BFPAUAF.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-46G6RSB6.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-55ISXAQH.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-5UVVASSA.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-7MRQ4HMK.js +0 -78
- package/dist/cli-bundle/chunks/chunk-7MRQ4HMK.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-7SV63ZHD.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-AONIHR2C.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-C5AOG6D2.js +0 -691
- package/dist/cli-bundle/chunks/chunk-C5AOG6D2.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-CE5P2NQR.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-CKGNPJAG.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-G6PYHBBR.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-GAJVRGGA.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-HFFUQR73.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-IPKJ6B36.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-JR2LV3M4.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-KFWBJPSG.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-KQMUV6LX.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-MJTINN54.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-MJTSZKK5.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-MVKFOLLM.js +0 -694
- package/dist/cli-bundle/chunks/chunk-MVKFOLLM.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-QH3PJYON.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-QL5RVYOA.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-S26C36QC.js +0 -83
- package/dist/cli-bundle/chunks/chunk-S26C36QC.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-S2RUQSX2.js +0 -75
- package/dist/cli-bundle/chunks/chunk-S2RUQSX2.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-SKH7OGE5.js +0 -86
- package/dist/cli-bundle/chunks/chunk-SKH7OGE5.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-SKN7LC5W.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-SR3EKWZG.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-UELRKQQU.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-VFAQ4LMN.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-Y4SUQQYH.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-YDEXO24S.js +0 -654
- package/dist/cli-bundle/chunks/chunk-YDEXO24S.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-YJ3SUEPD.js +0 -657
- package/dist/cli-bundle/chunks/chunk-YJ3SUEPD.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-YUDJD3XO.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-ZRK4O56R.js.map +0 -1
- package/dist/cli-bundle/chunks/close-A3EMKBBY.js +0 -15
- package/dist/cli-bundle/chunks/config-D3OKQO52.js.map +0 -7
- package/dist/cli-bundle/chunks/config-MMJA4LLK.js.map +0 -1
- package/dist/cli-bundle/chunks/context-BLBD3PUB.js.map +0 -7
- package/dist/cli-bundle/chunks/context-DHLVPXN3.js.map +0 -1
- package/dist/cli-bundle/chunks/contracts-C3SZCXXG.js.map +0 -7
- package/dist/cli-bundle/chunks/contracts-XGVMMPC5.js.map +0 -1
- package/dist/cli-bundle/chunks/create-QVGFYA2X.js +0 -30
- package/dist/cli-bundle/chunks/history-AK3E5Z3C.js +0 -20
- package/dist/cli-bundle/chunks/history-redact-TWIYQV5J.js +0 -21
- package/dist/cli-bundle/chunks/init-RCRKW5PL.js +0 -21
- package/dist/cli-bundle/chunks/register-list-query-DDCHPONM.js.map +0 -7
- package/dist/cli-bundle/chunks/register-list-query-YNPBVIKM.js.map +0 -1
- package/dist/cli-bundle/chunks/register-mutation-7ALWDDAX.js.map +0 -1
- package/dist/cli-bundle/chunks/register-mutation-LAVKYY63.js.map +0 -7
- package/dist/cli-bundle/chunks/register-setup-KBXQDCXE.js.map +0 -7
- package/dist/cli-bundle/chunks/register-setup-RCRUHMSZ.js.map +0 -1
- package/dist/cli-bundle/chunks/restore-2ZKT6UDC.js +0 -19
- package/dist/cli-bundle/chunks/schema-MNTAVQCY.js.map +0 -1
- package/dist/cli-bundle/chunks/schema-RBTJ2YXW.js.map +0 -7
- package/dist/cli-bundle/chunks/stats-FS742AMA.js.map +0 -1
- package/dist/cli-bundle/chunks/stats-R5OAJVZK.js.map +0 -7
- package/dist/cli-bundle/chunks/test-QJXLKV26.js +0 -36
- package/dist/cli-bundle/chunks/test-runs-C6CFIVOS.js.map +0 -1
- package/dist/cli-bundle/chunks/test-runs-IAJDL6CA.js.map +0 -7
- package/dist/cli-bundle/chunks/update-2XCQNOD6.js +0 -28
- package/dist/cli-bundle/chunks/update-IWUCXVH2.js +0 -24
- package/dist/cli-bundle/chunks/validate-6QWQVCX2.js.map +0 -7
- package/dist/cli-bundle/chunks/validate-W5V5ZGQX.js.map +0 -1
- 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-XUZ2AHCW.js.map → activity-EJBMXUBH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{activity-H2LMOSSW.js.map → activity-MVSEND6D.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IB3GYLQE.js.map → chunk-3JWQCLR5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2A34E3BA.js.map → chunk-4TXTVZL3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-G6N5VEOK.js.map → chunk-4YIMPANT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7XGQXHFB.js.map → chunk-73PTKMAE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-3VY3YQO6.js.map → chunk-7RIJGN4R.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FXR67XVQ.js.map → chunk-BN3CWK6G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4BHT5VDC.js.map → chunk-C2KCIZKZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-O6LLO73I.js.map → chunk-CHRNYKNI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZQ3ZVXX2.js.map → chunk-D6USKAMA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WZQWHN4R.js.map → chunk-DLDCPF5X.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UVC5LOR7.js.map → chunk-E2Q2ULMR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5VOINNKT.js.map → chunk-F6VH3LFC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-H4IIJDE4.js.map → chunk-FDEVKXC4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-34EONI5F.js.map → chunk-HUYYMTGW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CIIK67GW.js.map → chunk-IHXXUIXS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-SBQTAVJZ.js.map → chunk-JIP67N2K.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2T3JG6V4.js.map → chunk-KRASIL6M.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-P77P2ILI.js.map → chunk-MLHX6DN5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2CKH2LMV.js.map → chunk-OB3RJV5F.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FIGAZ4Y7.js.map → chunk-OUQ5JEFM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NK3UPBVG.js.map → chunk-QE5UFCCO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WM5ZVBPE.js.map → chunk-SJZTPVFT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VAYA4XFX.js.map → chunk-V3KLX7U7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2RDVQEWV.js.map → chunk-Z5BM2FKQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-66MEDTUD.js.map → chunk-ZEATCVAC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NCVCO3NZ.js.map → chunk-ZFIEEDTJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-A3EMKBBY.js.map → close-37KEHLYM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-W56IOGYG.js.map → close-OP3LK7Z2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-QVGFYA2X.js.map → context-7ZEZV3BV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-IXY43O4H.js.map → context-XDI4DKKT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-UTTQDUYI.js.map → create-DFMNBKBS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-KCPUWSY2.js.map → create-J5Q2ELZT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-AJTXLT6S.js.map → extension-3LRYX7SW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-AK3E5Z3C.js.map → extension-GMVOIP4O.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{gc-O5GUO3SU.js.map → gc-FULIVYR4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{gc-PYVVEELM.js.map → gc-MDGRR2SU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-TWIYQV5J.js.map → history-5XUSLAJA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-KUUUVUFM.js.map → history-X4OSES6K.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-BNLVFPRG.js.map → history-redact-45YW65BK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-RCRKW5PL.js.map → history-redact-BVHWDXPR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-32U7BSKE.js.map → init-KO7CGIRQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-ZEEOHLTQ.js.map → init-TRYJELH4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-6K53WOWO.js.map → list-ROT7JF62.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-2ZKT6UDC.js.map → list-Y6AU5BJS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{search-6HOIVZDU.js.map → restore-DKMCLPI5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{search-ZWYEMASC.js.map → restore-IRAKSWIW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-NZF7OT2F.js.map → schema-OLT6LVKH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-QJXLKV26.js.map → schema-XJXKJQF5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-2XCQNOD6.js.map → search-CX5UMV4H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-IWUCXVH2.js.map → search-KP6H7COV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{telemetry-7DIGDQUO.js.map → telemetry-DIFPXCAT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{telemetry-FWEXSJLQ.js.map → telemetry-WTYFUPRL.js.map} +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/extensions/version-compat
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for extension-manifest version-bound compatibility.
|
|
5
|
+
*
|
|
6
|
+
* An extension manifest may declare an inclusive `pm_min_version` lower bound and
|
|
7
|
+
* an inclusive `pm_max_version` upper bound. At load time the
|
|
8
|
+
* {@link ../extensions/loader.js | loader} compares them against the running pm
|
|
9
|
+
* CLI version and skips (or warns about) an extension that falls outside the
|
|
10
|
+
* supported window. The comparison and the per-bound status semantics live here
|
|
11
|
+
* so the runtime loader and the author-time SDK helper
|
|
12
|
+
* (`checkExtensionManifestCompatibility`) share one implementation and can never
|
|
13
|
+
* drift — the same "agrees with the loader by construction" guarantee the
|
|
14
|
+
* declarative authoring helpers (`describeExtensionBlueprint`,
|
|
15
|
+
* `deriveExtensionCapabilities`) already provide.
|
|
16
|
+
*
|
|
17
|
+
* The functions here are pure: they take an already-resolved current version
|
|
18
|
+
* (the loader resolves it from `package.json`; the SDK caller supplies a target
|
|
19
|
+
* version) and return structured outcomes. Warning-string formatting and
|
|
20
|
+
* version resolution stay with the loader; finding/message presentation stays
|
|
21
|
+
* with the SDK.
|
|
22
|
+
*/
|
|
23
|
+
import type { PmMaxVersionExceededMode } from "./extension-types.js";
|
|
24
|
+
/** The two inclusive manifest version bounds pm evaluates at load time. */
|
|
25
|
+
export type PmVersionBoundKind = "pm_min_version" | "pm_max_version";
|
|
26
|
+
/**
|
|
27
|
+
* The outcome of evaluating a single manifest version bound against a pm version.
|
|
28
|
+
*
|
|
29
|
+
* - `absent`: the bound is not declared — nothing to enforce.
|
|
30
|
+
* - `ok`: the bound is declared and satisfied by the current version.
|
|
31
|
+
* - `invalid`: the declared bound is malformed (unparseable, or a range prefix on
|
|
32
|
+
* `pm_max_version`); the loader treats the extension as incompatible and skips it.
|
|
33
|
+
* - `unchecked`: the bound is well-formed but cannot be compared against the
|
|
34
|
+
* current version (the current version is unknown or not comparable); the
|
|
35
|
+
* extension still loads, with an advisory warning.
|
|
36
|
+
* - `unmet`: the current version is older than the inclusive `pm_min_version`
|
|
37
|
+
* lower bound; the loader skips the extension (only emitted for `pm_min_version`).
|
|
38
|
+
* - `exceeded`: the current version is newer than the inclusive `pm_max_version`
|
|
39
|
+
* upper bound and the exceeded mode is `block`; the loader skips the extension
|
|
40
|
+
* (only emitted for `pm_max_version`).
|
|
41
|
+
* - `exceeded_warn`: the current version is newer than `pm_max_version` but the
|
|
42
|
+
* exceeded mode is `warn`, so the extension loads with an advisory warning
|
|
43
|
+
* (only emitted for `pm_max_version`).
|
|
44
|
+
*/
|
|
45
|
+
export type PmVersionBoundStatus = "absent" | "ok" | "invalid" | "unchecked" | "unmet" | "exceeded" | "exceeded_warn";
|
|
46
|
+
/**
|
|
47
|
+
* The structured result of evaluating one manifest version bound, consumed by the
|
|
48
|
+
* loader (to format its `extension_pm_*_version_*` warning strings) and the SDK
|
|
49
|
+
* (to build author-time compatibility findings).
|
|
50
|
+
*/
|
|
51
|
+
export interface PmVersionBoundEvaluation {
|
|
52
|
+
/** Which bound this evaluation describes. */
|
|
53
|
+
kind: PmVersionBoundKind;
|
|
54
|
+
/** The classified outcome of comparing the bound against the current version. */
|
|
55
|
+
status: PmVersionBoundStatus;
|
|
56
|
+
/** Whether the bound permits the extension to load (`false` only for `invalid`/`unmet`/`exceeded`). */
|
|
57
|
+
allowed: boolean;
|
|
58
|
+
/** The declared bound value, verbatim; the empty string when the bound is absent. */
|
|
59
|
+
required: string;
|
|
60
|
+
/** The current version compared against, or `null` when it could not be resolved. */
|
|
61
|
+
current: string | null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Parse a comparable release string into numeric segments, or `null` when it is
|
|
65
|
+
* not an interpretable dotted-numeric version.
|
|
66
|
+
*
|
|
67
|
+
* Leniently strips a leading inclusive-minimum `>=` and an optional `v` prefix
|
|
68
|
+
* (so `engines.pm`-style `">=2026.5.31"` and `"v1.2.3"` both parse), then drops
|
|
69
|
+
* any build/pre-release suffix and keeps the leading dotted-numeric release.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseComparableVersion(value: string): number[] | null;
|
|
72
|
+
/**
|
|
73
|
+
* Compare two comparable version strings segment by segment.
|
|
74
|
+
*
|
|
75
|
+
* Returns `1` when `currentVersion` is greater, `-1` when it is smaller, `0` when
|
|
76
|
+
* equal, and `null` when either side is not an interpretable version (so callers
|
|
77
|
+
* can classify the comparison as `unchecked`). Missing trailing segments are
|
|
78
|
+
* treated as `0`, so `1.2` and `1.2.0` compare equal.
|
|
79
|
+
*/
|
|
80
|
+
export declare function compareComparableVersions(currentVersion: string, otherVersion: string): number | null;
|
|
81
|
+
/**
|
|
82
|
+
* Evaluate a manifest `pm_min_version` inclusive lower bound against the current
|
|
83
|
+
* pm version.
|
|
84
|
+
*
|
|
85
|
+
* An omitted bound is `absent`; a blank, non-string, or unparseable bound is
|
|
86
|
+
* `invalid`; an unknown or incomparable current version is `unchecked`; a current
|
|
87
|
+
* version below the bound is `unmet`; otherwise the bound is satisfied (`ok`).
|
|
88
|
+
* `currentVersion` is `null` when the loader could not resolve the running CLI
|
|
89
|
+
* version.
|
|
90
|
+
*/
|
|
91
|
+
export declare function evaluatePmMinVersionBound(required: unknown, currentVersion: string | null): PmVersionBoundEvaluation;
|
|
92
|
+
/**
|
|
93
|
+
* Evaluate a manifest `pm_max_version` inclusive upper bound against the current
|
|
94
|
+
* pm version.
|
|
95
|
+
*
|
|
96
|
+
* An omitted bound is `absent`. A blank or non-string bound is `invalid`. The
|
|
97
|
+
* upper bound must be an exact version: a range prefix (`<`/`>`/`=`/`~`/`^`) is
|
|
98
|
+
* rejected as `invalid`, because
|
|
99
|
+
* {@link parseComparableVersion} leniently strips a leading `>=` for
|
|
100
|
+
* `engines.pm` min-version compatibility and would otherwise turn a range-like
|
|
101
|
+
* `">=2026.6.1"` into an inclusive max and wrongly block newer CLIs. An
|
|
102
|
+
* unparseable bound is `invalid`; an unknown or incomparable current version is
|
|
103
|
+
* `unchecked`; a current version above the bound is `exceeded` (or
|
|
104
|
+
* `exceeded_warn` when `exceededMode` is `warn`, so the extension still loads
|
|
105
|
+
* during a controlled upgrade window); otherwise the bound is satisfied (`ok`).
|
|
106
|
+
*/
|
|
107
|
+
export declare function evaluatePmMaxVersionBound(required: unknown, currentVersion: string | null, exceededMode: PmMaxVersionExceededMode): PmVersionBoundEvaluation;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
|
|
2
|
+
!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]="9675b93b-da90-574d-a6cf-ea7448b40600")}catch(e){}}();
|
|
3
|
+
function formatVersionBoundValue(value) {
|
|
4
|
+
return typeof value === "string" ? value : String(value);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Parse a comparable release string into numeric segments, or `null` when it is
|
|
8
|
+
* not an interpretable dotted-numeric version.
|
|
9
|
+
*
|
|
10
|
+
* Leniently strips a leading inclusive-minimum `>=` and an optional `v` prefix
|
|
11
|
+
* (so `engines.pm`-style `">=2026.5.31"` and `"v1.2.3"` both parse), then drops
|
|
12
|
+
* any build/pre-release suffix and keeps the leading dotted-numeric release.
|
|
13
|
+
*/
|
|
14
|
+
export function parseComparableVersion(value) {
|
|
15
|
+
const normalized = value.trim().replace(/^>=\s*/, "").replace(/^v/i, "");
|
|
16
|
+
const release = normalized.split(/[+-]/, 1)[0];
|
|
17
|
+
if (!/^\d+(?:[.-]\d+)*$/.test(release)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return release.split(/[.-]/).map((part) => Number(part));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Compare two comparable version strings segment by segment.
|
|
24
|
+
*
|
|
25
|
+
* Returns `1` when `currentVersion` is greater, `-1` when it is smaller, `0` when
|
|
26
|
+
* equal, and `null` when either side is not an interpretable version (so callers
|
|
27
|
+
* can classify the comparison as `unchecked`). Missing trailing segments are
|
|
28
|
+
* treated as `0`, so `1.2` and `1.2.0` compare equal.
|
|
29
|
+
*/
|
|
30
|
+
export function compareComparableVersions(currentVersion, otherVersion) {
|
|
31
|
+
const currentParts = parseComparableVersion(currentVersion);
|
|
32
|
+
const otherParts = parseComparableVersion(otherVersion);
|
|
33
|
+
if (!currentParts || !otherParts) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const width = Math.max(currentParts.length, otherParts.length);
|
|
37
|
+
for (let index = 0; index < width; index += 1) {
|
|
38
|
+
const current = currentParts[index] ?? 0;
|
|
39
|
+
const other = otherParts[index] ?? 0;
|
|
40
|
+
if (current > other) {
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
if (current < other) {
|
|
44
|
+
return -1;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Evaluate a manifest `pm_min_version` inclusive lower bound against the current
|
|
51
|
+
* pm version.
|
|
52
|
+
*
|
|
53
|
+
* An omitted bound is `absent`; a blank, non-string, or unparseable bound is
|
|
54
|
+
* `invalid`; an unknown or incomparable current version is `unchecked`; a current
|
|
55
|
+
* version below the bound is `unmet`; otherwise the bound is satisfied (`ok`).
|
|
56
|
+
* `currentVersion` is `null` when the loader could not resolve the running CLI
|
|
57
|
+
* version.
|
|
58
|
+
*/
|
|
59
|
+
export function evaluatePmMinVersionBound(required, currentVersion) {
|
|
60
|
+
if (required === undefined || required === null) {
|
|
61
|
+
return { kind: "pm_min_version", status: "absent", allowed: true, required: "", current: currentVersion };
|
|
62
|
+
}
|
|
63
|
+
const declared = formatVersionBoundValue(required);
|
|
64
|
+
if (typeof required !== "string" || declared.trim().length === 0) {
|
|
65
|
+
return { kind: "pm_min_version", status: "invalid", allowed: false, required: declared, current: currentVersion };
|
|
66
|
+
}
|
|
67
|
+
if (!parseComparableVersion(declared)) {
|
|
68
|
+
return { kind: "pm_min_version", status: "invalid", allowed: false, required: declared, current: currentVersion };
|
|
69
|
+
}
|
|
70
|
+
if (currentVersion === null) {
|
|
71
|
+
return { kind: "pm_min_version", status: "unchecked", allowed: true, required: declared, current: null };
|
|
72
|
+
}
|
|
73
|
+
const comparison = compareComparableVersions(currentVersion, declared);
|
|
74
|
+
if (comparison === null) {
|
|
75
|
+
return { kind: "pm_min_version", status: "unchecked", allowed: true, required: declared, current: currentVersion };
|
|
76
|
+
}
|
|
77
|
+
if (comparison < 0) {
|
|
78
|
+
return { kind: "pm_min_version", status: "unmet", allowed: false, required: declared, current: currentVersion };
|
|
79
|
+
}
|
|
80
|
+
return { kind: "pm_min_version", status: "ok", allowed: true, required: declared, current: currentVersion };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Evaluate a manifest `pm_max_version` inclusive upper bound against the current
|
|
84
|
+
* pm version.
|
|
85
|
+
*
|
|
86
|
+
* An omitted bound is `absent`. A blank or non-string bound is `invalid`. The
|
|
87
|
+
* upper bound must be an exact version: a range prefix (`<`/`>`/`=`/`~`/`^`) is
|
|
88
|
+
* rejected as `invalid`, because
|
|
89
|
+
* {@link parseComparableVersion} leniently strips a leading `>=` for
|
|
90
|
+
* `engines.pm` min-version compatibility and would otherwise turn a range-like
|
|
91
|
+
* `">=2026.6.1"` into an inclusive max and wrongly block newer CLIs. An
|
|
92
|
+
* unparseable bound is `invalid`; an unknown or incomparable current version is
|
|
93
|
+
* `unchecked`; a current version above the bound is `exceeded` (or
|
|
94
|
+
* `exceeded_warn` when `exceededMode` is `warn`, so the extension still loads
|
|
95
|
+
* during a controlled upgrade window); otherwise the bound is satisfied (`ok`).
|
|
96
|
+
*/
|
|
97
|
+
export function evaluatePmMaxVersionBound(required, currentVersion, exceededMode) {
|
|
98
|
+
if (required === undefined || required === null) {
|
|
99
|
+
return { kind: "pm_max_version", status: "absent", allowed: true, required: "", current: currentVersion };
|
|
100
|
+
}
|
|
101
|
+
const declared = formatVersionBoundValue(required);
|
|
102
|
+
if (typeof required !== "string" || declared.trim().length === 0) {
|
|
103
|
+
return { kind: "pm_max_version", status: "invalid", allowed: false, required: declared, current: currentVersion };
|
|
104
|
+
}
|
|
105
|
+
if (/^[<>=~^]/.test(declared.trim()) || !parseComparableVersion(declared)) {
|
|
106
|
+
return { kind: "pm_max_version", status: "invalid", allowed: false, required: declared, current: currentVersion };
|
|
107
|
+
}
|
|
108
|
+
if (currentVersion === null) {
|
|
109
|
+
return { kind: "pm_max_version", status: "unchecked", allowed: true, required: declared, current: null };
|
|
110
|
+
}
|
|
111
|
+
const comparison = compareComparableVersions(currentVersion, declared);
|
|
112
|
+
if (comparison === null) {
|
|
113
|
+
return { kind: "pm_max_version", status: "unchecked", allowed: true, required: declared, current: currentVersion };
|
|
114
|
+
}
|
|
115
|
+
if (comparison > 0) {
|
|
116
|
+
if (exceededMode === "warn") {
|
|
117
|
+
return {
|
|
118
|
+
kind: "pm_max_version",
|
|
119
|
+
status: "exceeded_warn",
|
|
120
|
+
allowed: true,
|
|
121
|
+
required: declared,
|
|
122
|
+
current: currentVersion,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return { kind: "pm_max_version", status: "exceeded", allowed: false, required: declared, current: currentVersion };
|
|
126
|
+
}
|
|
127
|
+
return { kind: "pm_max_version", status: "ok", allowed: true, required: declared, current: currentVersion };
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=version-compat.js.map
|
|
130
|
+
//# debugId=9675b93b-da90-574d-a6cf-ea7448b40600
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-compat.js","sources":["core/extensions/version-compat.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/extensions/version-compat\n *\n * Single source of truth for extension-manifest version-bound compatibility.\n *\n * An extension manifest may declare an inclusive `pm_min_version` lower bound and\n * an inclusive `pm_max_version` upper bound. At load time the\n * {@link ../extensions/loader.js | loader} compares them against the running pm\n * CLI version and skips (or warns about) an extension that falls outside the\n * supported window. The comparison and the per-bound status semantics live here\n * so the runtime loader and the author-time SDK helper\n * (`checkExtensionManifestCompatibility`) share one implementation and can never\n * drift — the same \"agrees with the loader by construction\" guarantee the\n * declarative authoring helpers (`describeExtensionBlueprint`,\n * `deriveExtensionCapabilities`) already provide.\n *\n * The functions here are pure: they take an already-resolved current version\n * (the loader resolves it from `package.json`; the SDK caller supplies a target\n * version) and return structured outcomes. Warning-string formatting and\n * version resolution stay with the loader; finding/message presentation stays\n * with the SDK.\n */\nimport type { PmMaxVersionExceededMode } from \"./extension-types.js\";\n\n/** The two inclusive manifest version bounds pm evaluates at load time. */\nexport type PmVersionBoundKind = \"pm_min_version\" | \"pm_max_version\";\n\n/**\n * The outcome of evaluating a single manifest version bound against a pm version.\n *\n * - `absent`: the bound is not declared — nothing to enforce.\n * - `ok`: the bound is declared and satisfied by the current version.\n * - `invalid`: the declared bound is malformed (unparseable, or a range prefix on\n * `pm_max_version`); the loader treats the extension as incompatible and skips it.\n * - `unchecked`: the bound is well-formed but cannot be compared against the\n * current version (the current version is unknown or not comparable); the\n * extension still loads, with an advisory warning.\n * - `unmet`: the current version is older than the inclusive `pm_min_version`\n * lower bound; the loader skips the extension (only emitted for `pm_min_version`).\n * - `exceeded`: the current version is newer than the inclusive `pm_max_version`\n * upper bound and the exceeded mode is `block`; the loader skips the extension\n * (only emitted for `pm_max_version`).\n * - `exceeded_warn`: the current version is newer than `pm_max_version` but the\n * exceeded mode is `warn`, so the extension loads with an advisory warning\n * (only emitted for `pm_max_version`).\n */\nexport type PmVersionBoundStatus =\n | \"absent\"\n | \"ok\"\n | \"invalid\"\n | \"unchecked\"\n | \"unmet\"\n | \"exceeded\"\n | \"exceeded_warn\";\n\n/**\n * The structured result of evaluating one manifest version bound, consumed by the\n * loader (to format its `extension_pm_*_version_*` warning strings) and the SDK\n * (to build author-time compatibility findings).\n */\nexport interface PmVersionBoundEvaluation {\n /** Which bound this evaluation describes. */\n kind: PmVersionBoundKind;\n /** The classified outcome of comparing the bound against the current version. */\n status: PmVersionBoundStatus;\n /** Whether the bound permits the extension to load (`false` only for `invalid`/`unmet`/`exceeded`). */\n allowed: boolean;\n /** The declared bound value, verbatim; the empty string when the bound is absent. */\n required: string;\n /** The current version compared against, or `null` when it could not be resolved. */\n current: string | null;\n}\n\nfunction formatVersionBoundValue(value: unknown): string {\n return typeof value === \"string\" ? value : String(value);\n}\n\n/**\n * Parse a comparable release string into numeric segments, or `null` when it is\n * not an interpretable dotted-numeric version.\n *\n * Leniently strips a leading inclusive-minimum `>=` and an optional `v` prefix\n * (so `engines.pm`-style `\">=2026.5.31\"` and `\"v1.2.3\"` both parse), then drops\n * any build/pre-release suffix and keeps the leading dotted-numeric release.\n */\nexport function parseComparableVersion(value: string): number[] | null {\n const normalized = value.trim().replace(/^>=\\s*/, \"\").replace(/^v/i, \"\");\n const release = normalized.split(/[+-]/, 1)[0];\n if (!/^\\d+(?:[.-]\\d+)*$/.test(release)) {\n return null;\n }\n return release.split(/[.-]/).map((part) => Number(part));\n}\n\n/**\n * Compare two comparable version strings segment by segment.\n *\n * Returns `1` when `currentVersion` is greater, `-1` when it is smaller, `0` when\n * equal, and `null` when either side is not an interpretable version (so callers\n * can classify the comparison as `unchecked`). Missing trailing segments are\n * treated as `0`, so `1.2` and `1.2.0` compare equal.\n */\nexport function compareComparableVersions(currentVersion: string, otherVersion: string): number | null {\n const currentParts = parseComparableVersion(currentVersion);\n const otherParts = parseComparableVersion(otherVersion);\n if (!currentParts || !otherParts) {\n return null;\n }\n const width = Math.max(currentParts.length, otherParts.length);\n for (let index = 0; index < width; index += 1) {\n const current = currentParts[index] ?? 0;\n const other = otherParts[index] ?? 0;\n if (current > other) {\n return 1;\n }\n if (current < other) {\n return -1;\n }\n }\n return 0;\n}\n\n/**\n * Evaluate a manifest `pm_min_version` inclusive lower bound against the current\n * pm version.\n *\n * An omitted bound is `absent`; a blank, non-string, or unparseable bound is\n * `invalid`; an unknown or incomparable current version is `unchecked`; a current\n * version below the bound is `unmet`; otherwise the bound is satisfied (`ok`).\n * `currentVersion` is `null` when the loader could not resolve the running CLI\n * version.\n */\nexport function evaluatePmMinVersionBound(\n required: unknown,\n currentVersion: string | null,\n): PmVersionBoundEvaluation {\n if (required === undefined || required === null) {\n return { kind: \"pm_min_version\", status: \"absent\", allowed: true, required: \"\", current: currentVersion };\n }\n const declared = formatVersionBoundValue(required);\n if (typeof required !== \"string\" || declared.trim().length === 0) {\n return { kind: \"pm_min_version\", status: \"invalid\", allowed: false, required: declared, current: currentVersion };\n }\n if (!parseComparableVersion(declared)) {\n return { kind: \"pm_min_version\", status: \"invalid\", allowed: false, required: declared, current: currentVersion };\n }\n if (currentVersion === null) {\n return { kind: \"pm_min_version\", status: \"unchecked\", allowed: true, required: declared, current: null };\n }\n const comparison = compareComparableVersions(currentVersion, declared);\n if (comparison === null) {\n return { kind: \"pm_min_version\", status: \"unchecked\", allowed: true, required: declared, current: currentVersion };\n }\n if (comparison < 0) {\n return { kind: \"pm_min_version\", status: \"unmet\", allowed: false, required: declared, current: currentVersion };\n }\n return { kind: \"pm_min_version\", status: \"ok\", allowed: true, required: declared, current: currentVersion };\n}\n\n/**\n * Evaluate a manifest `pm_max_version` inclusive upper bound against the current\n * pm version.\n *\n * An omitted bound is `absent`. A blank or non-string bound is `invalid`. The\n * upper bound must be an exact version: a range prefix (`<`/`>`/`=`/`~`/`^`) is\n * rejected as `invalid`, because\n * {@link parseComparableVersion} leniently strips a leading `>=` for\n * `engines.pm` min-version compatibility and would otherwise turn a range-like\n * `\">=2026.6.1\"` into an inclusive max and wrongly block newer CLIs. An\n * unparseable bound is `invalid`; an unknown or incomparable current version is\n * `unchecked`; a current version above the bound is `exceeded` (or\n * `exceeded_warn` when `exceededMode` is `warn`, so the extension still loads\n * during a controlled upgrade window); otherwise the bound is satisfied (`ok`).\n */\nexport function evaluatePmMaxVersionBound(\n required: unknown,\n currentVersion: string | null,\n exceededMode: PmMaxVersionExceededMode,\n): PmVersionBoundEvaluation {\n if (required === undefined || required === null) {\n return { kind: \"pm_max_version\", status: \"absent\", allowed: true, required: \"\", current: currentVersion };\n }\n const declared = formatVersionBoundValue(required);\n if (typeof required !== \"string\" || declared.trim().length === 0) {\n return { kind: \"pm_max_version\", status: \"invalid\", allowed: false, required: declared, current: currentVersion };\n }\n if (/^[<>=~^]/.test(declared.trim()) || !parseComparableVersion(declared)) {\n return { kind: \"pm_max_version\", status: \"invalid\", allowed: false, required: declared, current: currentVersion };\n }\n if (currentVersion === null) {\n return { kind: \"pm_max_version\", status: \"unchecked\", allowed: true, required: declared, current: null };\n }\n const comparison = compareComparableVersions(currentVersion, declared);\n if (comparison === null) {\n return { kind: \"pm_max_version\", status: \"unchecked\", allowed: true, required: declared, current: currentVersion };\n }\n if (comparison > 0) {\n if (exceededMode === \"warn\") {\n return {\n kind: \"pm_max_version\",\n status: \"exceeded_warn\",\n allowed: true,\n required: declared,\n current: currentVersion,\n };\n }\n return { kind: \"pm_max_version\", status: \"exceeded\", allowed: false, required: declared, current: currentVersion };\n }\n return { kind: \"pm_max_version\", status: \"ok\", allowed: true, required: declared, current: currentVersion };\n}\n"],"names":[],"mappings":"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","debugId":"9675b93b-da90-574d-a6cf-ea7448b40600"}
|
package/dist/core/fs/fs-utils.js
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* Provides filesystem helpers for Fs Utils.
|
|
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]="4ba3885b-85fc-5941-bf52-6c70b2bb5c2a")}catch(e){}}();
|
|
8
8
|
import * as fs from "node:fs/promises";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import crypto from "node:crypto";
|
|
11
|
+
const WINDOWS_RENAME_RETRY_DELAYS_MS = [10, 25, 50, 100];
|
|
11
12
|
/**
|
|
12
13
|
* Implements ensure dir for the public runtime surface of this module.
|
|
13
14
|
*/
|
|
@@ -52,6 +53,30 @@ export async function writeFileAtomic(targetPath, contents) {
|
|
|
52
53
|
await fs.rename(tempPath, targetPath);
|
|
53
54
|
}
|
|
54
55
|
catch (error) {
|
|
56
|
+
if (process.platform === "win32" &&
|
|
57
|
+
(isErrno(error, "EPERM") || isErrno(error, "EBUSY"))) {
|
|
58
|
+
let lastError = error;
|
|
59
|
+
for (const delayMs of WINDOWS_RENAME_RETRY_DELAYS_MS) {
|
|
60
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
61
|
+
try {
|
|
62
|
+
await fs.rename(tempPath, targetPath);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
catch (retryError) {
|
|
66
|
+
lastError = retryError;
|
|
67
|
+
if (!isErrno(retryError, "EPERM") && !isErrno(retryError, "EBUSY")) {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
await fs.unlink(tempPath);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Best-effort cleanup only.
|
|
77
|
+
}
|
|
78
|
+
throw lastError;
|
|
79
|
+
}
|
|
55
80
|
if (isErrno(error, "EXDEV")) {
|
|
56
81
|
try {
|
|
57
82
|
await fs.copyFile(tempPath, targetPath);
|
|
@@ -122,4 +147,4 @@ function isErrno(error, code) {
|
|
|
122
147
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
123
148
|
}
|
|
124
149
|
//# sourceMappingURL=fs-utils.js.map
|
|
125
|
-
//# debugId=
|
|
150
|
+
//# debugId=4ba3885b-85fc-5941-bf52-6c70b2bb5c2a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-utils.js","sources":["core/fs/fs-utils.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/fs/fs-utils\n *\n * Provides filesystem helpers for Fs Utils.\n */\nimport * as fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\n/**\n * Implements ensure dir for the public runtime surface of this module.\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\n/**\n * Implements path exists for the public runtime surface of this module.\n */\nexport async function pathExists(targetPath: string): Promise<boolean> {\n try {\n await fs.access(targetPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Implements read file if exists for the public runtime surface of this module.\n */\nexport async function readFileIfExists(targetPath: string): Promise<string | null> {\n try {\n return await fs.readFile(targetPath, \"utf8\");\n } catch (error: unknown) {\n if (isErrno(error, \"ENOENT\")) {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Implements write file atomic for the public runtime surface of this module.\n */\nexport async function writeFileAtomic(targetPath: string, contents: string): Promise<void> {\n const dirPath = path.dirname(targetPath);\n await ensureDir(dirPath);\n const tempPath = path.join(\n dirPath,\n `.${path.basename(targetPath)}.${process.pid}.${Date.now()}.${crypto.randomBytes(4).toString(\"hex\")}.tmp`,\n );\n await fs.writeFile(tempPath, contents, \"utf8\");\n try {\n await fs.rename(tempPath, targetPath);\n } catch (error: unknown) {\n if (isErrno(error, \"EXDEV\")) {\n try {\n await fs.copyFile(tempPath, targetPath);\n } finally {\n try {\n await fs.unlink(tempPath);\n } catch {\n // Best-effort cleanup only.\n }\n }\n return;\n }\n try {\n await fs.unlink(tempPath);\n } catch {\n // Best-effort cleanup only.\n }\n throw error;\n }\n}\n\n/**\n * Append a single newline-terminated line to a file, opened with `O_APPEND`.\n *\n * Concurrency contract: `O_APPEND` makes the seek-to-EOF that precedes each\n * `write(2)` atomic, so independent appenders never overwrite each other's\n * bytes. For the common case the whole `${line}\\n` buffer is handed to the\n * kernel in one `write(2)`, which mainstream filesystems (ext4/xfs/apfs) commit\n * atomically under the inode lock — concurrent multi-process appends of small\n * records (e.g. the telemetry and OTLP-span queues) therefore stay\n * line-coherent without an external lock.\n *\n * The guarantee weakens only for a single record large enough that the OS\n * splits it across multiple `write(2)` calls (multi-KiB lines), where another\n * process's append could interleave between fragments. History JSONL — the only\n * caller that can produce large lines — is always written while the per-item\n * store lock is held (see core/store/item-store.ts), so those appends are\n * serialized regardless. Callers writing large records concurrently from\n * multiple processes must hold an equivalent lock.\n */\nexport async function appendLineAtomic(targetPath: string, line: string): Promise<void> {\n const dirPath = path.dirname(targetPath);\n await ensureDir(dirPath);\n const handle = await fs.open(targetPath, \"a\");\n try {\n await handle.writeFile(`${line}\\n`, \"utf8\");\n } finally {\n await handle.close();\n }\n}\n\n/**\n * Implements remove file if exists for the public runtime surface of this module.\n */\nexport async function removeFileIfExists(targetPath: string): Promise<void> {\n try {\n await fs.unlink(targetPath);\n } catch (error: unknown) {\n if (!isErrno(error, \"ENOENT\")) {\n throw error;\n }\n }\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: string }).code === code;\n}\n"],"names":[],"mappings":"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","debugId":"
|
|
1
|
+
{"version":3,"file":"fs-utils.js","sources":["core/fs/fs-utils.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/fs/fs-utils\n *\n * Provides filesystem helpers for Fs Utils.\n */\nimport * as fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\nconst WINDOWS_RENAME_RETRY_DELAYS_MS = [10, 25, 50, 100];\n\n/**\n * Implements ensure dir for the public runtime surface of this module.\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\n/**\n * Implements path exists for the public runtime surface of this module.\n */\nexport async function pathExists(targetPath: string): Promise<boolean> {\n try {\n await fs.access(targetPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Implements read file if exists for the public runtime surface of this module.\n */\nexport async function readFileIfExists(targetPath: string): Promise<string | null> {\n try {\n return await fs.readFile(targetPath, \"utf8\");\n } catch (error: unknown) {\n if (isErrno(error, \"ENOENT\")) {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Implements write file atomic for the public runtime surface of this module.\n */\nexport async function writeFileAtomic(targetPath: string, contents: string): Promise<void> {\n const dirPath = path.dirname(targetPath);\n await ensureDir(dirPath);\n const tempPath = path.join(\n dirPath,\n `.${path.basename(targetPath)}.${process.pid}.${Date.now()}.${crypto.randomBytes(4).toString(\"hex\")}.tmp`,\n );\n await fs.writeFile(tempPath, contents, \"utf8\");\n try {\n await fs.rename(tempPath, targetPath);\n } catch (error: unknown) {\n if (\n process.platform === \"win32\" &&\n (isErrno(error, \"EPERM\") || isErrno(error, \"EBUSY\"))\n ) {\n let lastError = error;\n for (const delayMs of WINDOWS_RENAME_RETRY_DELAYS_MS) {\n await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n try {\n await fs.rename(tempPath, targetPath);\n return;\n } catch (retryError: unknown) {\n lastError = retryError;\n if (!isErrno(retryError, \"EPERM\") && !isErrno(retryError, \"EBUSY\")) {\n break;\n }\n }\n }\n try {\n await fs.unlink(tempPath);\n } catch {\n // Best-effort cleanup only.\n }\n throw lastError;\n }\n if (isErrno(error, \"EXDEV\")) {\n try {\n await fs.copyFile(tempPath, targetPath);\n } finally {\n try {\n await fs.unlink(tempPath);\n } catch {\n // Best-effort cleanup only.\n }\n }\n return;\n }\n try {\n await fs.unlink(tempPath);\n } catch {\n // Best-effort cleanup only.\n }\n throw error;\n }\n}\n\n/**\n * Append a single newline-terminated line to a file, opened with `O_APPEND`.\n *\n * Concurrency contract: `O_APPEND` makes the seek-to-EOF that precedes each\n * `write(2)` atomic, so independent appenders never overwrite each other's\n * bytes. For the common case the whole `${line}\\n` buffer is handed to the\n * kernel in one `write(2)`, which mainstream filesystems (ext4/xfs/apfs) commit\n * atomically under the inode lock — concurrent multi-process appends of small\n * records (e.g. the telemetry and OTLP-span queues) therefore stay\n * line-coherent without an external lock.\n *\n * The guarantee weakens only for a single record large enough that the OS\n * splits it across multiple `write(2)` calls (multi-KiB lines), where another\n * process's append could interleave between fragments. History JSONL — the only\n * caller that can produce large lines — is always written while the per-item\n * store lock is held (see core/store/item-store.ts), so those appends are\n * serialized regardless. Callers writing large records concurrently from\n * multiple processes must hold an equivalent lock.\n */\nexport async function appendLineAtomic(targetPath: string, line: string): Promise<void> {\n const dirPath = path.dirname(targetPath);\n await ensureDir(dirPath);\n const handle = await fs.open(targetPath, \"a\");\n try {\n await handle.writeFile(`${line}\\n`, \"utf8\");\n } finally {\n await handle.close();\n }\n}\n\n/**\n * Implements remove file if exists for the public runtime surface of this module.\n */\nexport async function removeFileIfExists(targetPath: string): Promise<void> {\n try {\n await fs.unlink(targetPath);\n } catch (error: unknown) {\n if (!isErrno(error, \"ENOENT\")) {\n throw error;\n }\n }\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: string }).code === code;\n}\n"],"names":[],"mappings":"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","debugId":"4ba3885b-85fc-5941-bf52-6c70b2bb5c2a"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { RuntimeStatusRegistry } from "../schema/runtime-schema.js";
|
|
2
|
+
import type { ItemFrontMatter, ItemStatus } from "../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Collects the blocker item ids declared by an item: the legacy scalar
|
|
5
|
+
* `blocked_by` field plus every `blocked_by` dependency edge. Ids are trimmed,
|
|
6
|
+
* de-duplicated, and returned in stable lexicographic order. This is the single
|
|
7
|
+
* source of truth for "what must close before this item can proceed", shared by
|
|
8
|
+
* `pm next` readiness classification and the close-time auto-unblock sweep.
|
|
9
|
+
*/
|
|
10
|
+
export declare function collectBlockedByIds(item: Pick<ItemFrontMatter, "blocked_by" | "dependencies">): string[];
|
|
11
|
+
/** A blocker reference resolved against the corpus and annotated with its state. */
|
|
12
|
+
export interface ResolvedBlocker {
|
|
13
|
+
id: string;
|
|
14
|
+
title: string | null;
|
|
15
|
+
status: ItemStatus | null;
|
|
16
|
+
/** True when the blocker no longer gates work: its id is unknown or terminal. */
|
|
17
|
+
resolved: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolves an item's declared blockers against a corpus index, annotating each
|
|
21
|
+
* with the blocker's title/status and whether it still gates work. A blocker is
|
|
22
|
+
* treated as resolved when its id is unknown (a dangling reference cannot be
|
|
23
|
+
* waited on) or the referenced item is terminal — mirroring the close-time
|
|
24
|
+
* auto-unblock rule, which only clears a dependent once its blocker is terminal.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveItemBlockers(item: Pick<ItemFrontMatter, "blocked_by" | "dependencies">, itemsById: Map<string, ItemFrontMatter>, statusRegistry: RuntimeStatusRegistry): ResolvedBlocker[];
|
|
27
|
+
/** A classified actionable item plus the context an agent needs to act on it. */
|
|
28
|
+
export interface ActionableEntry {
|
|
29
|
+
item: ItemFrontMatter;
|
|
30
|
+
/** Blockers that still gate the item (resolved blockers are filtered out). */
|
|
31
|
+
open_blockers: ResolvedBlocker[];
|
|
32
|
+
/** Ids of non-terminal items whose `blocked_by` points at this item. */
|
|
33
|
+
unblocks: string[];
|
|
34
|
+
}
|
|
35
|
+
/** Result of partitioning a candidate set into ready vs blocked leaf work. */
|
|
36
|
+
export interface ActionabilityReport {
|
|
37
|
+
/** Active leaves with no open blockers — ready to work on now. */
|
|
38
|
+
ready: ActionableEntry[];
|
|
39
|
+
/** Active leaves with at least one open blocker — waiting to become ready. */
|
|
40
|
+
blocked: ActionableEntry[];
|
|
41
|
+
/** Active candidates considered before the leaf/blocker split. */
|
|
42
|
+
active_count: number;
|
|
43
|
+
/** Active candidates skipped because they still have open descendants. */
|
|
44
|
+
container_count: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Partitions a candidate set into ready vs blocked leaf work using the corpus to
|
|
48
|
+
* resolve blockers, descendants, and downstream dependents.
|
|
49
|
+
*
|
|
50
|
+
* An item qualifies when its status is active. Containers — items with at least
|
|
51
|
+
* one non-terminal descendant — are excluded from both lists because the real
|
|
52
|
+
* work is the leaf beneath them. A leaf with no open blockers is READY; a leaf
|
|
53
|
+
* with one or more open blockers is BLOCKED, annotated with the unresolved
|
|
54
|
+
* blockers and the non-terminal items it would unblock. Returned lists preserve
|
|
55
|
+
* the candidate order so the caller can apply its own ranking.
|
|
56
|
+
*/
|
|
57
|
+
export declare function computeActionabilityReport(candidates: ItemFrontMatter[], corpus: ItemFrontMatter[], statusRegistry: RuntimeStatusRegistry): ActionabilityReport;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/item/actionability
|
|
3
|
+
*
|
|
4
|
+
* Pure, dependency-aware actionability model shared by the `pm next` command and
|
|
5
|
+
* the close-time auto-unblock sweep. It answers "what is ready to work on now?"
|
|
6
|
+
* without any I/O: given a candidate set and the surrounding corpus it partitions
|
|
7
|
+
* work into READY items (active, leaf, no open blockers) and BLOCKED items (active
|
|
8
|
+
* leaf waiting on at least one open blocker). Keeping the logic here — rather than
|
|
9
|
+
* inside a CLI command — makes it trivially testable and reusable, and gives the
|
|
10
|
+
* `blocked_by` resolution a single source of truth.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
!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]="b38f538c-6772-5336-bea4-8c72447c236f")}catch(e){}}();
|
|
14
|
+
import { isTerminalStatus, normalizeStatusForRegistry } from "./status.js";
|
|
15
|
+
/** Dependency kind that marks "this item is blocked by the referenced item". */
|
|
16
|
+
const BLOCKED_BY_DEPENDENCY_KIND = "blocked_by";
|
|
17
|
+
/**
|
|
18
|
+
* Normalizes an item id / parent reference / blocker id to its canonical
|
|
19
|
+
* comparison key (trimmed, lowercased). pm ids are canonically lowercase, but
|
|
20
|
+
* resolving case-insensitively — as {@link collectSubtreeIds} does — keeps a
|
|
21
|
+
* hand-edited mixed-case reference from being silently treated as missing.
|
|
22
|
+
*/
|
|
23
|
+
function normalizeItemId(id) {
|
|
24
|
+
return id.trim().toLowerCase();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Collects the blocker item ids declared by an item: the legacy scalar
|
|
28
|
+
* `blocked_by` field plus every `blocked_by` dependency edge. Ids are trimmed,
|
|
29
|
+
* de-duplicated, and returned in stable lexicographic order. This is the single
|
|
30
|
+
* source of truth for "what must close before this item can proceed", shared by
|
|
31
|
+
* `pm next` readiness classification and the close-time auto-unblock sweep.
|
|
32
|
+
*/
|
|
33
|
+
export function collectBlockedByIds(item) {
|
|
34
|
+
const ids = new Set();
|
|
35
|
+
const scalar = typeof item.blocked_by === "string" ? item.blocked_by.trim() : "";
|
|
36
|
+
if (scalar.length > 0) {
|
|
37
|
+
ids.add(scalar);
|
|
38
|
+
}
|
|
39
|
+
for (const dependency of item.dependencies ?? []) {
|
|
40
|
+
if (dependency.kind === BLOCKED_BY_DEPENDENCY_KIND &&
|
|
41
|
+
typeof dependency.id === "string" &&
|
|
42
|
+
dependency.id.trim().length > 0) {
|
|
43
|
+
ids.add(dependency.id.trim());
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return [...ids].sort((left, right) => left.localeCompare(right));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolves an item's declared blockers against a corpus index, annotating each
|
|
50
|
+
* with the blocker's title/status and whether it still gates work. A blocker is
|
|
51
|
+
* treated as resolved when its id is unknown (a dangling reference cannot be
|
|
52
|
+
* waited on) or the referenced item is terminal — mirroring the close-time
|
|
53
|
+
* auto-unblock rule, which only clears a dependent once its blocker is terminal.
|
|
54
|
+
*/
|
|
55
|
+
export function resolveItemBlockers(item, itemsById, statusRegistry) {
|
|
56
|
+
return collectBlockedByIds(item).map((id) => {
|
|
57
|
+
const blocker = itemsById.get(normalizeItemId(id));
|
|
58
|
+
if (!blocker) {
|
|
59
|
+
return { id, title: null, status: null, resolved: true };
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
id,
|
|
63
|
+
title: blocker.title,
|
|
64
|
+
status: blocker.status,
|
|
65
|
+
resolved: isTerminalStatus(blocker.status, statusRegistry),
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resolves the registry's active status set, falling back to just the canonical
|
|
71
|
+
* open status when a custom schema declares none — the same safety net `pm
|
|
72
|
+
* context` applies so the report never misclassifies every item as inactive.
|
|
73
|
+
*/
|
|
74
|
+
function resolveActiveStatusSet(statusRegistry) {
|
|
75
|
+
/* c8 ignore start -- fallback applies only to custom schemas that intentionally define zero active statuses */
|
|
76
|
+
return statusRegistry.active_statuses.size > 0 ? statusRegistry.active_statuses : new Set([statusRegistry.open_status]);
|
|
77
|
+
/* c8 ignore stop */
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns whether an item has any non-terminal descendant by walking the
|
|
81
|
+
* parent→children index depth-first, short-circuiting on the first one found.
|
|
82
|
+
* Such an item is a container (its real work lives in its children), so `pm next`
|
|
83
|
+
* skips it and recommends a leaf instead. Cycle-safe via a visited set.
|
|
84
|
+
*/
|
|
85
|
+
function hasOpenDescendant(rootId, childrenByParent, statusRegistry) {
|
|
86
|
+
const stack = [normalizeItemId(rootId)];
|
|
87
|
+
const visited = new Set();
|
|
88
|
+
while (stack.length > 0) {
|
|
89
|
+
const current = stack.pop();
|
|
90
|
+
/* c8 ignore start -- defensive cycle-guard: unreachable for active roots (an open child returns before any node is revisited, and single-parent graphs cannot form a root-reachable cycle excluding the root), retained for safety */
|
|
91
|
+
if (visited.has(current))
|
|
92
|
+
continue;
|
|
93
|
+
/* c8 ignore stop */
|
|
94
|
+
visited.add(current);
|
|
95
|
+
for (const child of childrenByParent.get(current) ?? []) {
|
|
96
|
+
if (!isTerminalStatus(child.status, statusRegistry)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
stack.push(normalizeItemId(child.id));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Indexes the corpus into a by-id map, a parent→children map, and a reverse
|
|
106
|
+
* blocker map (blocker id → ids of items it blocks). Built once per report so
|
|
107
|
+
* blocker resolution, descendant counting, and downstream "unblocks" lookups
|
|
108
|
+
* share the same passes over the corpus.
|
|
109
|
+
*/
|
|
110
|
+
function indexCorpus(corpus) {
|
|
111
|
+
const itemsById = new Map();
|
|
112
|
+
const childrenByParent = new Map();
|
|
113
|
+
const blockedByReverse = new Map();
|
|
114
|
+
for (const item of corpus) {
|
|
115
|
+
// Index keys are normalized (lowercased) for case-insensitive resolution;
|
|
116
|
+
// stored values keep the item's original-case id for display.
|
|
117
|
+
itemsById.set(normalizeItemId(item.id), item);
|
|
118
|
+
const parent = typeof item.parent === "string" ? item.parent.trim() : "";
|
|
119
|
+
if (parent.length > 0) {
|
|
120
|
+
const parentKey = normalizeItemId(parent);
|
|
121
|
+
const siblings = childrenByParent.get(parentKey) ?? [];
|
|
122
|
+
siblings.push(item);
|
|
123
|
+
childrenByParent.set(parentKey, siblings);
|
|
124
|
+
}
|
|
125
|
+
for (const blockerId of collectBlockedByIds(item)) {
|
|
126
|
+
const blockerKey = normalizeItemId(blockerId);
|
|
127
|
+
const dependents = blockedByReverse.get(blockerKey) ?? [];
|
|
128
|
+
dependents.push(item.id);
|
|
129
|
+
blockedByReverse.set(blockerKey, dependents);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { itemsById, childrenByParent, blockedByReverse };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Partitions a candidate set into ready vs blocked leaf work using the corpus to
|
|
136
|
+
* resolve blockers, descendants, and downstream dependents.
|
|
137
|
+
*
|
|
138
|
+
* An item qualifies when its status is active. Containers — items with at least
|
|
139
|
+
* one non-terminal descendant — are excluded from both lists because the real
|
|
140
|
+
* work is the leaf beneath them. A leaf with no open blockers is READY; a leaf
|
|
141
|
+
* with one or more open blockers is BLOCKED, annotated with the unresolved
|
|
142
|
+
* blockers and the non-terminal items it would unblock. Returned lists preserve
|
|
143
|
+
* the candidate order so the caller can apply its own ranking.
|
|
144
|
+
*/
|
|
145
|
+
export function computeActionabilityReport(candidates, corpus, statusRegistry) {
|
|
146
|
+
const { itemsById, childrenByParent, blockedByReverse } = indexCorpus(corpus);
|
|
147
|
+
const activeStatuses = resolveActiveStatusSet(statusRegistry);
|
|
148
|
+
// Ids of corpus items still in flight, used to keep only the non-terminal
|
|
149
|
+
// dependents in each item's downstream "unblocks" list.
|
|
150
|
+
const nonTerminalIds = new Set(corpus.filter((entry) => !isTerminalStatus(entry.status, statusRegistry)).map((entry) => normalizeItemId(entry.id)));
|
|
151
|
+
const ready = [];
|
|
152
|
+
const blocked = [];
|
|
153
|
+
let activeCount = 0;
|
|
154
|
+
let containerCount = 0;
|
|
155
|
+
for (const item of candidates) {
|
|
156
|
+
if (!activeStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry)))
|
|
157
|
+
continue;
|
|
158
|
+
activeCount += 1;
|
|
159
|
+
if (hasOpenDescendant(item.id, childrenByParent, statusRegistry)) {
|
|
160
|
+
containerCount += 1;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const openBlockers = resolveItemBlockers(item, itemsById, statusRegistry).filter((blocker) => !blocker.resolved);
|
|
164
|
+
const unblocks = (blockedByReverse.get(normalizeItemId(item.id)) ?? [])
|
|
165
|
+
.filter((dependentId) => nonTerminalIds.has(normalizeItemId(dependentId)))
|
|
166
|
+
.sort((left, right) => left.localeCompare(right));
|
|
167
|
+
const entry = { item, open_blockers: openBlockers, unblocks };
|
|
168
|
+
if (openBlockers.length === 0) {
|
|
169
|
+
ready.push(entry);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
blocked.push(entry);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return { ready, blocked, active_count: activeCount, container_count: containerCount };
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=actionability.js.map
|
|
178
|
+
//# debugId=b38f538c-6772-5336-bea4-8c72447c236f
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actionability.js","sources":["core/item/actionability.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/item/actionability\n *\n * Pure, dependency-aware actionability model shared by the `pm next` command and\n * the close-time auto-unblock sweep. It answers \"what is ready to work on now?\"\n * without any I/O: given a candidate set and the surrounding corpus it partitions\n * work into READY items (active, leaf, no open blockers) and BLOCKED items (active\n * leaf waiting on at least one open blocker). Keeping the logic here — rather than\n * inside a CLI command — makes it trivially testable and reusable, and gives the\n * `blocked_by` resolution a single source of truth.\n */\nimport { isTerminalStatus, normalizeStatusForRegistry } from \"./status.js\";\nimport type { RuntimeStatusRegistry } from \"../schema/runtime-schema.js\";\nimport type { ItemFrontMatter, ItemStatus } from \"../../types/index.js\";\n\n/** Dependency kind that marks \"this item is blocked by the referenced item\". */\nconst BLOCKED_BY_DEPENDENCY_KIND = \"blocked_by\";\n\n/**\n * Normalizes an item id / parent reference / blocker id to its canonical\n * comparison key (trimmed, lowercased). pm ids are canonically lowercase, but\n * resolving case-insensitively — as {@link collectSubtreeIds} does — keeps a\n * hand-edited mixed-case reference from being silently treated as missing.\n */\nfunction normalizeItemId(id: string): string {\n return id.trim().toLowerCase();\n}\n\n/**\n * Collects the blocker item ids declared by an item: the legacy scalar\n * `blocked_by` field plus every `blocked_by` dependency edge. Ids are trimmed,\n * de-duplicated, and returned in stable lexicographic order. This is the single\n * source of truth for \"what must close before this item can proceed\", shared by\n * `pm next` readiness classification and the close-time auto-unblock sweep.\n */\nexport function collectBlockedByIds(item: Pick<ItemFrontMatter, \"blocked_by\" | \"dependencies\">): string[] {\n const ids = new Set<string>();\n const scalar = typeof item.blocked_by === \"string\" ? item.blocked_by.trim() : \"\";\n if (scalar.length > 0) {\n ids.add(scalar);\n }\n for (const dependency of item.dependencies ?? []) {\n if (\n dependency.kind === BLOCKED_BY_DEPENDENCY_KIND &&\n typeof dependency.id === \"string\" &&\n dependency.id.trim().length > 0\n ) {\n ids.add(dependency.id.trim());\n }\n }\n return [...ids].sort((left, right) => left.localeCompare(right));\n}\n\n/** A blocker reference resolved against the corpus and annotated with its state. */\nexport interface ResolvedBlocker {\n id: string;\n title: string | null;\n status: ItemStatus | null;\n /** True when the blocker no longer gates work: its id is unknown or terminal. */\n resolved: boolean;\n}\n\n/**\n * Resolves an item's declared blockers against a corpus index, annotating each\n * with the blocker's title/status and whether it still gates work. A blocker is\n * treated as resolved when its id is unknown (a dangling reference cannot be\n * waited on) or the referenced item is terminal — mirroring the close-time\n * auto-unblock rule, which only clears a dependent once its blocker is terminal.\n */\nexport function resolveItemBlockers(\n item: Pick<ItemFrontMatter, \"blocked_by\" | \"dependencies\">,\n itemsById: Map<string, ItemFrontMatter>,\n statusRegistry: RuntimeStatusRegistry,\n): ResolvedBlocker[] {\n return collectBlockedByIds(item).map((id) => {\n const blocker = itemsById.get(normalizeItemId(id));\n if (!blocker) {\n return { id, title: null, status: null, resolved: true };\n }\n return {\n id,\n title: blocker.title,\n status: blocker.status,\n resolved: isTerminalStatus(blocker.status, statusRegistry),\n };\n });\n}\n\n/** A classified actionable item plus the context an agent needs to act on it. */\nexport interface ActionableEntry {\n item: ItemFrontMatter;\n /** Blockers that still gate the item (resolved blockers are filtered out). */\n open_blockers: ResolvedBlocker[];\n /** Ids of non-terminal items whose `blocked_by` points at this item. */\n unblocks: string[];\n}\n\n/** Result of partitioning a candidate set into ready vs blocked leaf work. */\nexport interface ActionabilityReport {\n /** Active leaves with no open blockers — ready to work on now. */\n ready: ActionableEntry[];\n /** Active leaves with at least one open blocker — waiting to become ready. */\n blocked: ActionableEntry[];\n /** Active candidates considered before the leaf/blocker split. */\n active_count: number;\n /** Active candidates skipped because they still have open descendants. */\n container_count: number;\n}\n\n/**\n * Resolves the registry's active status set, falling back to just the canonical\n * open status when a custom schema declares none — the same safety net `pm\n * context` applies so the report never misclassifies every item as inactive.\n */\nfunction resolveActiveStatusSet(statusRegistry: RuntimeStatusRegistry): Set<string> {\n /* c8 ignore start -- fallback applies only to custom schemas that intentionally define zero active statuses */\n return statusRegistry.active_statuses.size > 0 ? statusRegistry.active_statuses : new Set<string>([statusRegistry.open_status]);\n /* c8 ignore stop */\n}\n\n/**\n * Returns whether an item has any non-terminal descendant by walking the\n * parent→children index depth-first, short-circuiting on the first one found.\n * Such an item is a container (its real work lives in its children), so `pm next`\n * skips it and recommends a leaf instead. Cycle-safe via a visited set.\n */\nfunction hasOpenDescendant(\n rootId: string,\n childrenByParent: Map<string, ItemFrontMatter[]>,\n statusRegistry: RuntimeStatusRegistry,\n): boolean {\n const stack = [normalizeItemId(rootId)];\n const visited = new Set<string>();\n while (stack.length > 0) {\n const current = stack.pop() as string;\n /* c8 ignore start -- defensive cycle-guard: unreachable for active roots (an open child returns before any node is revisited, and single-parent graphs cannot form a root-reachable cycle excluding the root), retained for safety */\n if (visited.has(current)) continue;\n /* c8 ignore stop */\n visited.add(current);\n for (const child of childrenByParent.get(current) ?? []) {\n if (!isTerminalStatus(child.status, statusRegistry)) {\n return true;\n }\n stack.push(normalizeItemId(child.id));\n }\n }\n return false;\n}\n\n/**\n * Indexes the corpus into a by-id map, a parent→children map, and a reverse\n * blocker map (blocker id → ids of items it blocks). Built once per report so\n * blocker resolution, descendant counting, and downstream \"unblocks\" lookups\n * share the same passes over the corpus.\n */\nfunction indexCorpus(corpus: ItemFrontMatter[]): {\n itemsById: Map<string, ItemFrontMatter>;\n childrenByParent: Map<string, ItemFrontMatter[]>;\n blockedByReverse: Map<string, string[]>;\n} {\n const itemsById = new Map<string, ItemFrontMatter>();\n const childrenByParent = new Map<string, ItemFrontMatter[]>();\n const blockedByReverse = new Map<string, string[]>();\n for (const item of corpus) {\n // Index keys are normalized (lowercased) for case-insensitive resolution;\n // stored values keep the item's original-case id for display.\n itemsById.set(normalizeItemId(item.id), item);\n const parent = typeof item.parent === \"string\" ? item.parent.trim() : \"\";\n if (parent.length > 0) {\n const parentKey = normalizeItemId(parent);\n const siblings = childrenByParent.get(parentKey) ?? [];\n siblings.push(item);\n childrenByParent.set(parentKey, siblings);\n }\n for (const blockerId of collectBlockedByIds(item)) {\n const blockerKey = normalizeItemId(blockerId);\n const dependents = blockedByReverse.get(blockerKey) ?? [];\n dependents.push(item.id);\n blockedByReverse.set(blockerKey, dependents);\n }\n }\n return { itemsById, childrenByParent, blockedByReverse };\n}\n\n/**\n * Partitions a candidate set into ready vs blocked leaf work using the corpus to\n * resolve blockers, descendants, and downstream dependents.\n *\n * An item qualifies when its status is active. Containers — items with at least\n * one non-terminal descendant — are excluded from both lists because the real\n * work is the leaf beneath them. A leaf with no open blockers is READY; a leaf\n * with one or more open blockers is BLOCKED, annotated with the unresolved\n * blockers and the non-terminal items it would unblock. Returned lists preserve\n * the candidate order so the caller can apply its own ranking.\n */\nexport function computeActionabilityReport(\n candidates: ItemFrontMatter[],\n corpus: ItemFrontMatter[],\n statusRegistry: RuntimeStatusRegistry,\n): ActionabilityReport {\n const { itemsById, childrenByParent, blockedByReverse } = indexCorpus(corpus);\n const activeStatuses = resolveActiveStatusSet(statusRegistry);\n // Ids of corpus items still in flight, used to keep only the non-terminal\n // dependents in each item's downstream \"unblocks\" list.\n const nonTerminalIds = new Set(\n corpus.filter((entry) => !isTerminalStatus(entry.status, statusRegistry)).map((entry) => normalizeItemId(entry.id)),\n );\n const ready: ActionableEntry[] = [];\n const blocked: ActionableEntry[] = [];\n let activeCount = 0;\n let containerCount = 0;\n for (const item of candidates) {\n if (!activeStatuses.has(normalizeStatusForRegistry(item.status, statusRegistry))) continue;\n activeCount += 1;\n if (hasOpenDescendant(item.id, childrenByParent, statusRegistry)) {\n containerCount += 1;\n continue;\n }\n const openBlockers = resolveItemBlockers(item, itemsById, statusRegistry).filter((blocker) => !blocker.resolved);\n const unblocks = (blockedByReverse.get(normalizeItemId(item.id)) ?? [])\n .filter((dependentId) => nonTerminalIds.has(normalizeItemId(dependentId)))\n .sort((left, right) => left.localeCompare(right));\n const entry: ActionableEntry = { item, open_blockers: openBlockers, unblocks };\n if (openBlockers.length === 0) {\n ready.push(entry);\n } else {\n blocked.push(entry);\n }\n }\n return { ready, blocked, active_count: activeCount, container_count: containerCount };\n}\n"],"names":[],"mappings":"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","debugId":"b38f538c-6772-5336-bea4-8c72447c236f"}
|