@unbrained/pm-cli 2026.6.19 → 2026.6.20
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 +311 -258
- package/README.md +1 -1
- package/dist/cli/bootstrap-args.d.ts +12 -1
- package/dist/cli/bootstrap-args.js +20 -9
- package/dist/cli/bootstrap-args.js.map +1 -1
- package/dist/cli/commander-usage.js +31 -25
- package/dist/cli/commander-usage.js.map +1 -1
- package/dist/cli/commands/completion.js +3 -3
- package/dist/cli/commands/completion.js.map +1 -1
- package/dist/cli/commands/contracts.js +4 -3
- package/dist/cli/commands/contracts.js.map +1 -1
- package/dist/cli/commands/eval.d.ts +62 -0
- package/dist/cli/commands/eval.js +158 -0
- package/dist/cli/commands/eval.js.map +1 -0
- package/dist/cli/commands/extension/install-sources.d.ts +12 -0
- package/dist/cli/commands/extension/install-sources.js +77 -10
- package/dist/cli/commands/extension/install-sources.js.map +1 -1
- package/dist/cli/commands/gc.d.ts +12 -1
- package/dist/cli/commands/gc.js +53 -6
- package/dist/cli/commands/gc.js.map +1 -1
- package/dist/cli/commands/health.js +14 -8
- package/dist/cli/commands/health.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.js +3 -2
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/linked-artifacts.js +13 -3
- package/dist/cli/commands/linked-artifacts.js.map +1 -1
- package/dist/cli/commands/list.js +12 -9
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/plan.js +2 -2
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/restore.js +5 -11
- package/dist/cli/commands/restore.js.map +1 -1
- package/dist/cli/commands/search.d.ts +39 -1
- package/dist/cli/commands/search.js +89 -12
- package/dist/cli/commands/search.js.map +1 -1
- package/dist/cli/commands/update.js +96 -58
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/extension-command-help.d.ts +9 -0
- package/dist/cli/extension-command-help.js +13 -2
- package/dist/cli/extension-command-help.js.map +1 -1
- package/dist/cli/extension-command-options.d.ts +8 -0
- package/dist/cli/extension-command-options.js +27 -2
- package/dist/cli/extension-command-options.js.map +1 -1
- package/dist/cli/help-content.js +15 -2
- package/dist/cli/help-content.js.map +1 -1
- package/dist/cli/main.d.ts +12 -0
- package/dist/cli/main.js +49 -9
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/register-list-query.js +34 -4
- package/dist/cli/register-list-query.js.map +1 -1
- package/dist/cli/register-operations.js +3 -3
- package/dist/cli/register-operations.js.map +1 -1
- package/dist/cli-bundle/chunks/activity-7G7NNNZQ.js +18 -0
- package/dist/cli-bundle/chunks/{activity-XJ7WRNWS.js → activity-KEEITOTB.js} +11 -11
- package/dist/cli-bundle/chunks/{aggregate-OFT4YVB6.js → aggregate-5BTHOHW2.js} +10 -10
- package/dist/cli-bundle/chunks/{aggregate-LBCWF6UJ.js → aggregate-GB2LJNTZ.js} +10 -10
- package/dist/cli-bundle/chunks/{append-BP2ARHOK.js → append-BBM4MNVD.js} +8 -8
- package/dist/cli-bundle/chunks/{append-5U3XR5SD.js → append-BFV5UYWS.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-ZZEM2PH7.js → chunk-26OQTCGH.js} +19 -14
- package/dist/cli-bundle/chunks/chunk-26OQTCGH.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-RVG3WLY3.js → chunk-2LUNPA3U.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-OURX4WVG.js → chunk-2QJLN4KM.js} +7 -7
- package/dist/cli-bundle/chunks/{search-2JX776KX.js → chunk-2ZY5SLNR.js} +184 -23
- package/dist/cli-bundle/chunks/chunk-2ZY5SLNR.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-AVMSP2HH.js → chunk-3KVCMB2M.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-FVZSUIN5.js → chunk-3WAKNI2W.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-H3DP6OUM.js → chunk-4KFL5OYK.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-VG3B2CYD.js → chunk-4PW4C3ZB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-SDUZTZ55.js → chunk-4S4INK3B.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-QCHNPN24.js → chunk-4YMX7XFI.js} +7 -5
- package/dist/cli-bundle/chunks/{chunk-QSH34DSQ.js → chunk-5MWA46UN.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-UIMLAFOE.js → chunk-5XK2RYJR.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-B2NEFANY.js → chunk-6DZO5NN7.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-VP4Z36GO.js → chunk-6FSPWUBI.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-MPEWACTG.js → chunk-6KARQMC6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-N7LDJRB4.js → chunk-6KSFULO6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-XV6N3QND.js → chunk-6LTSLEHD.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-X26ODPU4.js → chunk-6Y7IQ6XN.js} +14 -18
- package/dist/cli-bundle/chunks/chunk-6Y7IQ6XN.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-USKTNI7P.js → chunk-7MMXBIRZ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-UCNEPMPY.js → chunk-ACULWT7G.js} +105 -66
- package/dist/cli-bundle/chunks/chunk-ACULWT7G.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-2K56AWDP.js → chunk-AOCYDQLT.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-ZBVYKWT2.js → chunk-ATRXPXAL.js} +15 -15
- package/dist/cli-bundle/chunks/{chunk-A5JPMD4Q.js → chunk-AW4PYYNF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-I2VJM36R.js → chunk-AZ75OVK4.js} +20 -21
- package/dist/cli-bundle/chunks/chunk-AZ75OVK4.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-MTGMNUMJ.js → chunk-B3LROPTV.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-NPNNW5TU.js → chunk-BBSUVIIT.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-47BYN6CA.js → chunk-BYNJWB5F.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-PSWSQHM7.js → chunk-BZWIDTDE.js} +15 -19
- package/dist/cli-bundle/chunks/chunk-BZWIDTDE.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-S673PVHD.js → chunk-CNPWCUDR.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-TYQBGXH2.js → chunk-DKWIPIJY.js} +2 -2
- package/dist/cli-bundle/chunks/{search-AZR2JITW.js → chunk-DYOJJTCG.js} +190 -22
- package/dist/cli-bundle/chunks/chunk-DYOJJTCG.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-Y4IBSEQ2.js → chunk-E4E7UQBT.js} +20 -8
- package/dist/cli-bundle/chunks/chunk-E4E7UQBT.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-HMQMRHQJ.js → chunk-EKMHDL6Z.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-LIVRA6VG.js → chunk-EOFROIC5.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-NNMBNN6Q.js → chunk-ETJKPURB.js} +7 -5
- package/dist/cli-bundle/chunks/{chunk-2E3KSWFG.js → chunk-F4EYOSNC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-DJ3YYLHG.js → chunk-FA5O2DEG.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-QTWWHFI3.js → chunk-FBBPCSJM.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-EMFDZ7N3.js → chunk-FSOJCFDS.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-M35R7LFX.js → chunk-FXKPUMIR.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-YOGXK3ON.js → chunk-GF44HVZL.js} +18 -13
- package/dist/cli-bundle/chunks/chunk-GF44HVZL.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-UA4ANRJY.js → chunk-H3ZTSYPA.js} +71 -13
- package/dist/cli-bundle/chunks/chunk-H3ZTSYPA.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-II3WDRCM.js → chunk-HWHZ7EY7.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-7R5YKVKO.js → chunk-ICEWMJYH.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-UMTPQMEG.js → chunk-II4BRHKM.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-GDOTTY2S.js → chunk-IWKD7B33.js} +19 -2
- package/dist/cli-bundle/chunks/chunk-IWKD7B33.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-QG6M6XQE.js → chunk-J7VSEFWB.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-22YA6GCA.js → chunk-K2LBDYDC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-BQVESTOG.js → chunk-KCJZREBI.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-YWAYOWDQ.js → chunk-LTUB7ARL.js} +72 -14
- package/dist/cli-bundle/chunks/chunk-LTUB7ARL.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-DVUU3AHP.js → chunk-MFCFHL27.js} +17 -6
- package/dist/cli-bundle/chunks/chunk-MFCFHL27.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-5P2LQV2F.js → chunk-MTQK5ZSB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-LEC57E7K.js → chunk-NCGQ27PK.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-2RI3BDFK.js → chunk-NKTUBA2C.js} +10 -9
- package/dist/cli-bundle/chunks/chunk-NKTUBA2C.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-5LZPDRFW.js → chunk-NMQNXH4U.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-COHNQLB2.js → chunk-OLEP5TJH.js} +20 -3
- package/dist/cli-bundle/chunks/chunk-OLEP5TJH.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-PRUB7RI4.js → chunk-OVSFW4KD.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-4L7Q4OVT.js → chunk-PF5GLFPU.js} +9 -9
- package/dist/cli-bundle/chunks/{chunk-YVYJQR6S.js → chunk-QUTJOHGK.js} +9 -9
- package/dist/cli-bundle/chunks/{chunk-5QLHQK7V.js → chunk-QWAJPGEI.js} +25 -26
- package/dist/cli-bundle/chunks/chunk-QWAJPGEI.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-K5TD74VU.js → chunk-RADIHKJ3.js} +19 -7
- package/dist/cli-bundle/chunks/chunk-RADIHKJ3.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-CSRFOIHG.js → chunk-RICT5QYR.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-OUG4CL4H.js → chunk-RNKUCHUQ.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-X7RKOJXL.js → chunk-SL233DQD.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-USVOBLGB.js → chunk-U3WTMYBX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-DYZKSIVX.js → chunk-VE3BUO3R.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-FPQA4ZMA.js → chunk-VONJSFUW.js} +18 -7
- package/dist/cli-bundle/chunks/chunk-VONJSFUW.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-RNWE2HZR.js → chunk-W2ZESOQE.js} +15 -15
- package/dist/cli-bundle/chunks/{chunk-4BFNWAMQ.js → chunk-WFOITX4A.js} +29 -12
- package/dist/cli-bundle/chunks/chunk-WFOITX4A.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-FP7YLQ52.js → chunk-WMQBNVZL.js} +11 -10
- package/dist/cli-bundle/chunks/chunk-WMQBNVZL.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-5SRID7DV.js → chunk-X3CD2VUI.js} +29 -12
- package/dist/cli-bundle/chunks/chunk-X3CD2VUI.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-GL3QKIET.js → chunk-XKJDCJEH.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-SO2IOH37.js → chunk-XNQ3YH6N.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-ZGEWEO7B.js → chunk-XXGAWTH5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4EOS35RL.js → chunk-YBQF4CAW.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-MTDEEUGV.js → chunk-YT4Z2OVB.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-5NS6TJ2F.js → chunk-ZHCSGIUX.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-MAKOMXVM.js → chunk-ZYG4TR32.js} +106 -67
- package/dist/cli-bundle/chunks/chunk-ZYG4TR32.js.map +1 -0
- package/dist/cli-bundle/chunks/{claim-2BSYPJTJ.js → claim-G57ZJLZ4.js} +10 -10
- package/dist/cli-bundle/chunks/{claim-EZ6JKY5X.js → claim-TRSDQO6L.js} +10 -10
- package/dist/cli-bundle/chunks/{close-3TSX6BYF.js → close-4QMUQMON.js} +8 -8
- package/dist/cli-bundle/chunks/close-NNZZTZ5V.js +15 -0
- package/dist/cli-bundle/chunks/{close-many-B7DBVA46.js → close-many-3UWKJRQK.js} +15 -15
- package/dist/cli-bundle/chunks/{close-many-HB4UFCS3.js → close-many-A7U62CRI.js} +15 -15
- package/dist/cli-bundle/chunks/{comments-M7PAINZT.js → comments-4EM7XR74.js} +10 -10
- package/dist/cli-bundle/chunks/{comments-X7M7XM6I.js → comments-URWDZP2I.js} +10 -10
- package/dist/cli-bundle/chunks/{config-YICACPHA.js → config-GRJYZ2O3.js} +30 -10
- package/dist/cli-bundle/chunks/config-GRJYZ2O3.js.map +1 -0
- package/dist/cli-bundle/chunks/{config-UWF3KRP5.js → config-PSZ5GWAK.js} +29 -9
- package/dist/cli-bundle/chunks/config-PSZ5GWAK.js.map +7 -0
- package/dist/cli-bundle/chunks/{context-EGUGU4K7.js → context-A46YAV2F.js} +13 -13
- package/dist/cli-bundle/chunks/{context-V32ZAPL6.js → context-BCR34RKM.js} +13 -13
- package/dist/cli-bundle/chunks/{contracts-7G553BHP.js → contracts-HPT25X4D.js} +10 -8
- package/dist/cli-bundle/chunks/contracts-HPT25X4D.js.map +1 -0
- package/dist/cli-bundle/chunks/{contracts-B2YWYUV5.js → contracts-JOPCQNDP.js} +10 -8
- package/dist/cli-bundle/chunks/contracts-JOPCQNDP.js.map +7 -0
- package/dist/cli-bundle/chunks/{copy-RMLXLZOL.js → copy-KBTIUW7L.js} +7 -7
- package/dist/cli-bundle/chunks/{copy-NWFFRYWM.js → copy-X7V6AEDB.js} +7 -7
- package/dist/cli-bundle/chunks/create-4KOAQ6ME.js +30 -0
- package/dist/cli-bundle/chunks/{create-GK4MX2LJ.js → create-ZPZKJDFQ.js} +14 -14
- package/dist/cli-bundle/chunks/{delete-EFQLVEAS.js → delete-2ZI6CJZM.js} +7 -7
- package/dist/cli-bundle/chunks/{delete-RMGNIL2S.js → delete-FGKVPUQZ.js} +7 -7
- package/dist/cli-bundle/chunks/{deps-WKHUPVD3.js → deps-IUJOBF2H.js} +7 -7
- package/dist/cli-bundle/chunks/{deps-K2I7QV4Y.js → deps-SJCEFU3C.js} +7 -7
- package/dist/cli-bundle/chunks/{docs-2H2UGIT6.js → docs-2LXF5SVC.js} +12 -11
- package/dist/cli-bundle/chunks/{docs-2H2UGIT6.js.map → docs-2LXF5SVC.js.map} +1 -1
- package/dist/cli-bundle/chunks/{docs-3FXRDYA7.js → docs-UWJ75CKR.js} +10 -9
- package/dist/cli-bundle/chunks/{docs-3FXRDYA7.js.map → docs-UWJ75CKR.js.map} +1 -1
- package/dist/cli-bundle/chunks/eval-FRIDCTM2.js +276 -0
- package/dist/cli-bundle/chunks/eval-FRIDCTM2.js.map +1 -0
- package/dist/cli-bundle/chunks/eval-ZTT3F3SL.js +286 -0
- package/dist/cli-bundle/chunks/eval-ZTT3F3SL.js.map +7 -0
- package/dist/cli-bundle/chunks/{extension-4LPTFTV4.js → extension-VRYTNNSV.js} +5 -5
- package/dist/cli-bundle/chunks/{extension-ASUPTDCC.js → extension-XFQG3BXL.js} +5 -5
- package/dist/cli-bundle/chunks/{files-UAZFB3EA.js → files-AJOGTTAN.js} +10 -9
- package/dist/cli-bundle/chunks/{files-UAZFB3EA.js.map → files-AJOGTTAN.js.map} +1 -1
- package/dist/cli-bundle/chunks/{files-TXEQOA7C.js → files-B2RUCA32.js} +12 -11
- package/dist/cli-bundle/chunks/{files-TXEQOA7C.js.map → files-B2RUCA32.js.map} +1 -1
- package/dist/cli-bundle/chunks/{focus-UGROAMAX.js → focus-7N36RIMT.js} +8 -8
- package/dist/cli-bundle/chunks/{focus-ELOPN2SR.js → focus-CFE33IYC.js} +8 -8
- package/dist/cli-bundle/chunks/gc-OYJK4YBY.js +395 -0
- package/dist/cli-bundle/chunks/gc-OYJK4YBY.js.map +7 -0
- package/dist/cli-bundle/chunks/gc-SBF2FGHK.js +385 -0
- package/dist/cli-bundle/chunks/gc-SBF2FGHK.js.map +1 -0
- package/dist/cli-bundle/chunks/{get-OTXPLWYW.js → get-577VLZZ7.js} +11 -11
- package/dist/cli-bundle/chunks/{get-IWZ7IMPS.js → get-LLFWSPXW.js} +11 -11
- package/dist/cli-bundle/chunks/{health-PPTJ7XKW.js → health-C2PUT6JZ.js} +21 -22
- package/dist/cli-bundle/chunks/{health-PPTJ7XKW.js.map → health-C2PUT6JZ.js.map} +1 -1
- package/dist/cli-bundle/chunks/{health-JEBESKID.js → health-PBJS7W2T.js} +20 -21
- package/dist/cli-bundle/chunks/{health-JEBESKID.js.map → health-PBJS7W2T.js.map} +2 -2
- package/dist/cli-bundle/chunks/{history-HNWBUDMI.js → history-4FJK6Y3O.js} +10 -10
- package/dist/cli-bundle/chunks/history-ZXNWG6H4.js +20 -0
- package/dist/cli-bundle/chunks/{history-compact-EQXVPK3V.js → history-compact-AXR6R6GU.js} +12 -12
- package/dist/cli-bundle/chunks/{history-compact-MMQC7MCW.js → history-compact-HXF3OT7G.js} +12 -12
- package/dist/cli-bundle/chunks/history-redact-GV633Z4H.js +21 -0
- package/dist/cli-bundle/chunks/{history-redact-UBDHBEJE.js → history-redact-UMPD4G3K.js} +11 -11
- package/dist/cli-bundle/chunks/{history-repair-GMMHFAGH.js → history-repair-WHOK2ICG.js} +12 -12
- package/dist/cli-bundle/chunks/{history-repair-7DSDRPMX.js → history-repair-X57HE5EA.js} +12 -12
- package/dist/cli-bundle/chunks/init-KQWZSNBX.js +20 -0
- package/dist/cli-bundle/chunks/{init-QGK4JFF6.js → init-N7MIIYCU.js} +10 -10
- package/dist/cli-bundle/chunks/{learnings-A6DGBMG3.js → learnings-FPG7WAVW.js} +10 -10
- package/dist/cli-bundle/chunks/{learnings-DR53TWRA.js → learnings-GZRBIEAN.js} +10 -10
- package/dist/cli-bundle/chunks/{list-LJ5DBXC3.js → list-MZBCSKLU.js} +10 -10
- package/dist/cli-bundle/chunks/{list-KOJN23UL.js → list-ZDQ2OBSO.js} +10 -10
- package/dist/cli-bundle/chunks/{notes-K5I3TAYR.js → notes-LW53PFLH.js} +10 -10
- package/dist/cli-bundle/chunks/{notes-7VLTHKPW.js → notes-WQAP67EC.js} +10 -10
- package/dist/cli-bundle/chunks/{plan-X3STKLED.js → plan-AVJ4VJQO.js} +15 -15
- package/dist/cli-bundle/chunks/plan-AVJ4VJQO.js.map +7 -0
- package/dist/cli-bundle/chunks/{plan-BK3OMLGP.js → plan-VZKICKIJ.js} +16 -16
- package/dist/cli-bundle/chunks/plan-VZKICKIJ.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-list-query-FUMXPWZ4.js → register-list-query-7BD6ZHU5.js} +42 -21
- package/dist/cli-bundle/chunks/register-list-query-7BD6ZHU5.js.map +7 -0
- package/dist/cli-bundle/chunks/{register-list-query-XDLFESU7.js → register-list-query-CM4SVAQA.js} +43 -22
- package/dist/cli-bundle/chunks/register-list-query-CM4SVAQA.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-mutation-ZAGVKMBQ.js → register-mutation-ANZIWHUF.js} +33 -33
- package/dist/cli-bundle/chunks/{register-mutation-RXRX4P7D.js → register-mutation-PLFHAS4N.js} +33 -33
- package/dist/cli-bundle/chunks/{register-operations-DGSHCS75.js → register-operations-KQPQIFF2.js} +35 -35
- package/dist/cli-bundle/chunks/register-operations-KQPQIFF2.js.map +1 -0
- package/dist/cli-bundle/chunks/{register-operations-6UURPZN5.js → register-operations-VLGCAWIW.js} +34 -34
- package/dist/cli-bundle/chunks/{register-operations-6UURPZN5.js.map → register-operations-VLGCAWIW.js.map} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-2FEGSFLM.js → register-setup-KPTZ36D4.js} +15 -15
- package/dist/cli-bundle/chunks/{register-setup-LTJG52WP.js → register-setup-TMEF6V7O.js} +15 -15
- package/dist/cli-bundle/chunks/{restore-SJUWYOCK.js → restore-64JKQV7G.js} +11 -11
- package/dist/cli-bundle/chunks/restore-GKM26SAW.js +19 -0
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-W4F2LKHW.js → scheduling-shortcuts-4ION7QAX.js} +14 -14
- package/dist/cli-bundle/chunks/{scheduling-shortcuts-VWAMP2S2.js → scheduling-shortcuts-X6D6VSZR.js} +14 -14
- package/dist/cli-bundle/chunks/{schema-N5ETYD4P.js → schema-OA4RSVMI.js} +9 -9
- package/dist/cli-bundle/chunks/{schema-DXQRIEFM.js → schema-TA3NF3RG.js} +9 -9
- package/dist/cli-bundle/chunks/search-INCM5I4J.js +33 -0
- package/dist/cli-bundle/chunks/search-UAIHEQZL.js +37 -0
- package/dist/cli-bundle/chunks/{stats-J563NJBY.js → stats-RHEMG4CE.js} +8 -8
- package/dist/cli-bundle/chunks/{stats-ZFESFVQC.js → stats-WQWTIA5Y.js} +8 -8
- package/dist/cli-bundle/chunks/{telemetry-BNGLIFEM.js → telemetry-G6UKGKJU.js} +4 -4
- package/dist/cli-bundle/chunks/{telemetry-SC7HPRXX.js → telemetry-XA5D2QEO.js} +4 -4
- package/dist/cli-bundle/chunks/{test-55RJCGRU.js → test-XF7BYLMZ.js} +15 -15
- package/dist/cli-bundle/chunks/{test-47UQGEXE.js → test-ZMQF23P3.js} +15 -15
- package/dist/cli-bundle/chunks/{test-all-DN6KG4FX.js → test-all-WUBBJCPU.js} +15 -15
- package/dist/cli-bundle/chunks/{test-all-5SFTTRNL.js → test-all-ZNQBMUOI.js} +15 -15
- package/dist/cli-bundle/chunks/{test-runs-DZEDJ4GH.js → test-runs-N7LI7HLH.js} +5 -5
- package/dist/cli-bundle/chunks/{test-runs-NHRBT7SN.js → test-runs-RFA42EEX.js} +5 -5
- package/dist/cli-bundle/chunks/update-CPNOG73P.js +24 -0
- package/dist/cli-bundle/chunks/update-CPNOG73P.js.map +7 -0
- package/dist/cli-bundle/chunks/update-T5AYT6ZN.js +28 -0
- package/dist/cli-bundle/chunks/update-T5AYT6ZN.js.map +1 -0
- package/dist/cli-bundle/chunks/{update-many-OKYWFCBO.js → update-many-6XFR7TFG.js} +23 -23
- package/dist/cli-bundle/chunks/{update-many-IRNV3OTG.js → update-many-NMRUQZL2.js} +23 -23
- package/dist/cli-bundle/chunks/{upgrade-KP4I45V5.js → upgrade-EJTME2YQ.js} +5 -5
- package/dist/cli-bundle/chunks/{upgrade-3RIAFQIK.js → upgrade-QMCSONWR.js} +5 -5
- package/dist/cli-bundle/chunks/{validate-GVY4VE43.js → validate-3SUCHXXX.js} +21 -21
- package/dist/cli-bundle/chunks/{validate-ADKGN37M.js → validate-KIIJY5RC.js} +21 -21
- package/dist/cli-bundle/main.js +133 -55
- package/dist/cli-bundle/main.js.map +2 -2
- package/dist/core/checkpoint/checkpoint-gc.d.ts +69 -0
- package/dist/core/checkpoint/checkpoint-gc.js +175 -0
- package/dist/core/checkpoint/checkpoint-gc.js.map +1 -0
- package/dist/core/config/nested-settings.js +22 -2
- package/dist/core/config/nested-settings.js.map +1 -1
- package/dist/core/diagnostics/remediation.js +19 -2
- package/dist/core/diagnostics/remediation.js.map +1 -1
- package/dist/core/extensions/extension-types.d.ts +0 -9
- package/dist/core/extensions/extension-types.js +2 -27
- package/dist/core/extensions/extension-types.js.map +1 -1
- package/dist/core/fs/fs-utils.d.ts +17 -1
- package/dist/core/fs/fs-utils.js +19 -3
- package/dist/core/fs/fs-utils.js.map +1 -1
- package/dist/core/history/drift-scan.d.ts +17 -5
- package/dist/core/history/drift-scan.js +22 -14
- package/dist/core/history/drift-scan.js.map +1 -1
- package/dist/core/history/replay.d.ts +7 -0
- package/dist/core/history/replay.js +11 -6
- package/dist/core/history/replay.js.map +1 -1
- package/dist/core/item/status-filter.d.ts +7 -3
- package/dist/core/item/status-filter.js +26 -5
- package/dist/core/item/status-filter.js.map +1 -1
- package/dist/core/search/bm25.d.ts +113 -0
- package/dist/core/search/bm25.js +178 -0
- package/dist/core/search/bm25.js.map +1 -0
- package/dist/core/search/eval.d.ts +114 -0
- package/dist/core/search/eval.js +217 -0
- package/dist/core/search/eval.js.map +1 -0
- package/dist/core/sentry/instrument.d.ts +14 -0
- package/dist/core/sentry/instrument.js +43 -3
- package/dist/core/sentry/instrument.js.map +1 -1
- package/dist/core/shared/constants.js +5 -2
- package/dist/core/shared/constants.js.map +1 -1
- package/dist/core/store/paths.js +4 -3
- package/dist/core/store/paths.js.map +1 -1
- package/dist/core/store/settings-validator.d.ts +7 -0
- package/dist/core/store/settings-validator.js +10 -2
- package/dist/core/store/settings-validator.js.map +1 -1
- package/dist/core/store/settings.js +6 -2
- package/dist/core/store/settings.js.map +1 -1
- package/dist/mcp/tool-definitions.js +4 -3
- package/dist/mcp/tool-definitions.js.map +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.js +3 -2
- package/dist/sdk/cli-contracts/enum-contracts.js.map +1 -1
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +4 -4
- package/dist/sdk/cli-contracts/tool-parameter-tables.js.map +1 -1
- package/dist/sdk/cli-contracts.d.ts +1 -0
- package/dist/sdk/cli-contracts.js +11 -2
- package/dist/sdk/cli-contracts.js.map +1 -1
- package/dist/types.d.ts +19 -0
- package/dist/types.js +2 -2
- package/dist/types.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/ARCHITECTURE.md +124 -11
- package/docs/CLAUDE_CODE_PLUGIN.md +5 -13
- package/docs/COMMANDS.md +55 -5
- package/docs/CONFIGURATION.md +39 -0
- package/docs/EXTENSIONS.md +2 -2
- package/docs/MIGRATION_CLI_SIMPLIFICATION.md +9 -2
- package/docs/QUICKSTART.md +2 -0
- package/docs/README.md +2 -0
- package/docs/RELEASING.md +2 -1
- package/docs/SDK.md +9 -1
- package/docs/TESTING.md +18 -0
- package/package.json +4 -3
- package/packages/pm-todos/extensions/todos/index.js +2 -0
- package/packages/pm-todos/extensions/todos/index.ts +2 -0
- package/packages/pm-todos/extensions/todos/runtime.js +1 -1
- package/packages/pm-todos/extensions/todos/runtime.ts +4 -1
- package/dist/cli-bundle/chunks/activity-62I26XZB.js +0 -18
- package/dist/cli-bundle/chunks/chunk-2RI3BDFK.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-4BFNWAMQ.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-5QLHQK7V.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-5SRID7DV.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-COHNQLB2.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-DVUU3AHP.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-FP7YLQ52.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-FPQA4ZMA.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-GDOTTY2S.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-I2VJM36R.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-K5TD74VU.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-MAKOMXVM.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-PSWSQHM7.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-UA4ANRJY.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-UCNEPMPY.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-X26ODPU4.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-Y4IBSEQ2.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-YOGXK3ON.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-YWAYOWDQ.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-ZZEM2PH7.js.map +0 -1
- package/dist/cli-bundle/chunks/close-TQZK43Z5.js +0 -15
- package/dist/cli-bundle/chunks/config-UWF3KRP5.js.map +0 -7
- package/dist/cli-bundle/chunks/config-YICACPHA.js.map +0 -1
- package/dist/cli-bundle/chunks/contracts-7G553BHP.js.map +0 -1
- package/dist/cli-bundle/chunks/contracts-B2YWYUV5.js.map +0 -7
- package/dist/cli-bundle/chunks/create-UZLJXHLA.js +0 -30
- package/dist/cli-bundle/chunks/gc-5RTYXLQU.js +0 -211
- package/dist/cli-bundle/chunks/gc-5RTYXLQU.js.map +0 -7
- package/dist/cli-bundle/chunks/gc-FK5732EK.js +0 -208
- package/dist/cli-bundle/chunks/gc-FK5732EK.js.map +0 -1
- package/dist/cli-bundle/chunks/history-TKTULEVE.js +0 -20
- package/dist/cli-bundle/chunks/history-redact-SPIFIXVY.js +0 -21
- package/dist/cli-bundle/chunks/init-A6FTZ5UC.js +0 -20
- package/dist/cli-bundle/chunks/plan-BK3OMLGP.js.map +0 -1
- package/dist/cli-bundle/chunks/plan-X3STKLED.js.map +0 -7
- package/dist/cli-bundle/chunks/register-list-query-FUMXPWZ4.js.map +0 -7
- package/dist/cli-bundle/chunks/register-list-query-XDLFESU7.js.map +0 -1
- package/dist/cli-bundle/chunks/register-operations-DGSHCS75.js.map +0 -1
- package/dist/cli-bundle/chunks/restore-PI3WM4GK.js +0 -19
- package/dist/cli-bundle/chunks/search-2JX776KX.js.map +0 -1
- package/dist/cli-bundle/chunks/search-AZR2JITW.js.map +0 -7
- package/dist/cli-bundle/chunks/update-2BZEAI7B.js +0 -24
- package/dist/cli-bundle/chunks/update-GCNLER2H.js +0 -28
- /package/dist/cli-bundle/chunks/{activity-62I26XZB.js.map → activity-7G7NNNZQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{activity-XJ7WRNWS.js.map → activity-KEEITOTB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{aggregate-OFT4YVB6.js.map → aggregate-5BTHOHW2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{aggregate-LBCWF6UJ.js.map → aggregate-GB2LJNTZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-BP2ARHOK.js.map → append-BBM4MNVD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-5U3XR5SD.js.map → append-BFV5UYWS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RVG3WLY3.js.map → chunk-2LUNPA3U.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OURX4WVG.js.map → chunk-2QJLN4KM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AVMSP2HH.js.map → chunk-3KVCMB2M.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FVZSUIN5.js.map → chunk-3WAKNI2W.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-H3DP6OUM.js.map → chunk-4KFL5OYK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VG3B2CYD.js.map → chunk-4PW4C3ZB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-SDUZTZ55.js.map → chunk-4S4INK3B.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QCHNPN24.js.map → chunk-4YMX7XFI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QSH34DSQ.js.map → chunk-5MWA46UN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UIMLAFOE.js.map → chunk-5XK2RYJR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-B2NEFANY.js.map → chunk-6DZO5NN7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VP4Z36GO.js.map → chunk-6FSPWUBI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-MPEWACTG.js.map → chunk-6KARQMC6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-N7LDJRB4.js.map → chunk-6KSFULO6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-XV6N3QND.js.map → chunk-6LTSLEHD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-USKTNI7P.js.map → chunk-7MMXBIRZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2K56AWDP.js.map → chunk-AOCYDQLT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZBVYKWT2.js.map → chunk-ATRXPXAL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-A5JPMD4Q.js.map → chunk-AW4PYYNF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-MTGMNUMJ.js.map → chunk-B3LROPTV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NPNNW5TU.js.map → chunk-BBSUVIIT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-47BYN6CA.js.map → chunk-BYNJWB5F.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-S673PVHD.js.map → chunk-CNPWCUDR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TYQBGXH2.js.map → chunk-DKWIPIJY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HMQMRHQJ.js.map → chunk-EKMHDL6Z.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-LIVRA6VG.js.map → chunk-EOFROIC5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NNMBNN6Q.js.map → chunk-ETJKPURB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2E3KSWFG.js.map → chunk-F4EYOSNC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DJ3YYLHG.js.map → chunk-FA5O2DEG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QTWWHFI3.js.map → chunk-FBBPCSJM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-EMFDZ7N3.js.map → chunk-FSOJCFDS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-M35R7LFX.js.map → chunk-FXKPUMIR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-II3WDRCM.js.map → chunk-HWHZ7EY7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7R5YKVKO.js.map → chunk-ICEWMJYH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-UMTPQMEG.js.map → chunk-II4BRHKM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QG6M6XQE.js.map → chunk-J7VSEFWB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-22YA6GCA.js.map → chunk-K2LBDYDC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BQVESTOG.js.map → chunk-KCJZREBI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5P2LQV2F.js.map → chunk-MTQK5ZSB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-LEC57E7K.js.map → chunk-NCGQ27PK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5LZPDRFW.js.map → chunk-NMQNXH4U.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-PRUB7RI4.js.map → chunk-OVSFW4KD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4L7Q4OVT.js.map → chunk-PF5GLFPU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-YVYJQR6S.js.map → chunk-QUTJOHGK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CSRFOIHG.js.map → chunk-RICT5QYR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OUG4CL4H.js.map → chunk-RNKUCHUQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-X7RKOJXL.js.map → chunk-SL233DQD.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-USVOBLGB.js.map → chunk-U3WTMYBX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DYZKSIVX.js.map → chunk-VE3BUO3R.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RNWE2HZR.js.map → chunk-W2ZESOQE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GL3QKIET.js.map → chunk-XKJDCJEH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-SO2IOH37.js.map → chunk-XNQ3YH6N.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ZGEWEO7B.js.map → chunk-XXGAWTH5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-4EOS35RL.js.map → chunk-YBQF4CAW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-MTDEEUGV.js.map → chunk-YT4Z2OVB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5NS6TJ2F.js.map → chunk-ZHCSGIUX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{claim-2BSYPJTJ.js.map → claim-G57ZJLZ4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{claim-EZ6JKY5X.js.map → claim-TRSDQO6L.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-3TSX6BYF.js.map → close-4QMUQMON.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-TQZK43Z5.js.map → close-NNZZTZ5V.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-B7DBVA46.js.map → close-many-3UWKJRQK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-HB4UFCS3.js.map → close-many-A7U62CRI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-M7PAINZT.js.map → comments-4EM7XR74.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-X7M7XM6I.js.map → comments-URWDZP2I.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{context-EGUGU4K7.js.map → context-A46YAV2F.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{context-V32ZAPL6.js.map → context-BCR34RKM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-RMLXLZOL.js.map → copy-KBTIUW7L.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-NWFFRYWM.js.map → copy-X7V6AEDB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-UZLJXHLA.js.map → create-4KOAQ6ME.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-GK4MX2LJ.js.map → create-ZPZKJDFQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-EFQLVEAS.js.map → delete-2ZI6CJZM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-RMGNIL2S.js.map → delete-FGKVPUQZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-WKHUPVD3.js.map → deps-IUJOBF2H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-K2I7QV4Y.js.map → deps-SJCEFU3C.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-4LPTFTV4.js.map → extension-VRYTNNSV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{extension-ASUPTDCC.js.map → extension-XFQG3BXL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-UGROAMAX.js.map → focus-7N36RIMT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-ELOPN2SR.js.map → focus-CFE33IYC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{get-OTXPLWYW.js.map → get-577VLZZ7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{get-IWZ7IMPS.js.map → get-LLFWSPXW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-HNWBUDMI.js.map → history-4FJK6Y3O.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-TKTULEVE.js.map → history-ZXNWG6H4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-EQXVPK3V.js.map → history-compact-AXR6R6GU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-MMQC7MCW.js.map → history-compact-HXF3OT7G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-SPIFIXVY.js.map → history-redact-GV633Z4H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-UBDHBEJE.js.map → history-redact-UMPD4G3K.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-GMMHFAGH.js.map → history-repair-WHOK2ICG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-7DSDRPMX.js.map → history-repair-X57HE5EA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-A6FTZ5UC.js.map → init-KQWZSNBX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{init-QGK4JFF6.js.map → init-N7MIIYCU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-A6DGBMG3.js.map → learnings-FPG7WAVW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-DR53TWRA.js.map → learnings-GZRBIEAN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-LJ5DBXC3.js.map → list-MZBCSKLU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{list-KOJN23UL.js.map → list-ZDQ2OBSO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-K5I3TAYR.js.map → notes-LW53PFLH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-7VLTHKPW.js.map → notes-WQAP67EC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-mutation-ZAGVKMBQ.js.map → register-mutation-ANZIWHUF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-mutation-RXRX4P7D.js.map → register-mutation-PLFHAS4N.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-setup-2FEGSFLM.js.map → register-setup-KPTZ36D4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-setup-LTJG52WP.js.map → register-setup-TMEF6V7O.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-SJUWYOCK.js.map → restore-64JKQV7G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-PI3WM4GK.js.map → restore-GKM26SAW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{scheduling-shortcuts-W4F2LKHW.js.map → scheduling-shortcuts-4ION7QAX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{scheduling-shortcuts-VWAMP2S2.js.map → scheduling-shortcuts-X6D6VSZR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-N5ETYD4P.js.map → schema-OA4RSVMI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-DXQRIEFM.js.map → schema-TA3NF3RG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-55RJCGRU.js.map → search-INCM5I4J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-47UQGEXE.js.map → search-UAIHEQZL.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{stats-J563NJBY.js.map → stats-RHEMG4CE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{stats-ZFESFVQC.js.map → stats-WQWTIA5Y.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{telemetry-BNGLIFEM.js.map → telemetry-G6UKGKJU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{telemetry-SC7HPRXX.js.map → telemetry-XA5D2QEO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-2BZEAI7B.js.map → test-XF7BYLMZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-GCNLER2H.js.map → test-ZMQF23P3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-all-DN6KG4FX.js.map → test-all-WUBBJCPU.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-all-5SFTTRNL.js.map → test-all-ZNQBMUOI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-runs-DZEDJ4GH.js.map → test-runs-N7LI7HLH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{test-runs-NHRBT7SN.js.map → test-runs-RFA42EEX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-OKYWFCBO.js.map → update-many-6XFR7TFG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-IRNV3OTG.js.map → update-many-NMRUQZL2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{upgrade-KP4I45V5.js.map → upgrade-EJTME2YQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{upgrade-3RIAFQIK.js.map → upgrade-QMCSONWR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{validate-GVY4VE43.js.map → validate-3SUCHXXX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{validate-ADKGN37M.js.map → validate-KIIJY5RC.js.map} +0 -0
|
@@ -0,0 +1,178 @@
|
|
|
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]="57c1eb74-63b5-5208-abe1-98da8308839d")}catch(e){}}();
|
|
3
|
+
import { tokenizeAlphaNumeric } from "../shared/text-normalization.js";
|
|
4
|
+
/**
|
|
5
|
+
* Default Okapi BM25 term-frequency saturation parameter. `1.2` is the widely
|
|
6
|
+
* used Lucene/Elasticsearch default: higher values reduce the diminishing
|
|
7
|
+
* returns of repeated terms more slowly (terms keep accruing weight), lower
|
|
8
|
+
* values saturate sooner.
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_BM25_K1 = 1.2;
|
|
11
|
+
/**
|
|
12
|
+
* Default Okapi BM25 length-normalization parameter. `0.75` is the Lucene
|
|
13
|
+
* default: `0` disables length normalization entirely, `1` fully normalizes a
|
|
14
|
+
* document's score by its length relative to the corpus average.
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_BM25_B = 0.75;
|
|
17
|
+
/**
|
|
18
|
+
* Tokenize a document/query string into BM25 terms. Shares
|
|
19
|
+
* {@link tokenizeAlphaNumeric} with the lexical scorer so the BM25 vocabulary is
|
|
20
|
+
* identical to the rest of search: lowercase, alphanumeric runs, no stop-word
|
|
21
|
+
* removal or stemming (kept deliberately simple and language-agnostic).
|
|
22
|
+
*/
|
|
23
|
+
export function tokenizeBm25(text) {
|
|
24
|
+
return tokenizeAlphaNumeric(text);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Count occurrences of each token in a token list.
|
|
28
|
+
*/
|
|
29
|
+
function buildTermFrequencies(tokens) {
|
|
30
|
+
const frequencies = new Map();
|
|
31
|
+
for (const token of tokens) {
|
|
32
|
+
frequencies.set(token, (frequencies.get(token) ?? 0) + 1);
|
|
33
|
+
}
|
|
34
|
+
return frequencies;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a BM25 index from a corpus. Computes each document's term frequencies
|
|
38
|
+
* and length, the per-term document frequency, the corpus size, and the average
|
|
39
|
+
* document length. Empty documents (no tokens) are retained with length `0` so
|
|
40
|
+
* they can still be scored (they simply never match a query term). An empty
|
|
41
|
+
* corpus yields an index with `averageDocumentLength` `0`, which
|
|
42
|
+
* {@link scoreBm25Query} handles without dividing by zero.
|
|
43
|
+
*/
|
|
44
|
+
export function buildBm25Index(documents) {
|
|
45
|
+
const stats = [];
|
|
46
|
+
const documentFrequency = new Map();
|
|
47
|
+
let totalLength = 0;
|
|
48
|
+
for (const document of documents) {
|
|
49
|
+
const tokens = tokenizeBm25(document.text);
|
|
50
|
+
const termFrequencies = buildTermFrequencies(tokens);
|
|
51
|
+
totalLength += tokens.length;
|
|
52
|
+
for (const term of termFrequencies.keys()) {
|
|
53
|
+
documentFrequency.set(term, (documentFrequency.get(term) ?? 0) + 1);
|
|
54
|
+
}
|
|
55
|
+
stats.push({ id: document.id, termFrequencies, length: tokens.length });
|
|
56
|
+
}
|
|
57
|
+
const documentCount = stats.length;
|
|
58
|
+
return {
|
|
59
|
+
documents: stats,
|
|
60
|
+
documentFrequency,
|
|
61
|
+
documentCount,
|
|
62
|
+
averageDocumentLength: documentCount > 0 ? totalLength / documentCount : 0,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Inverse document frequency for one term using the BM25 "plus-one" variant
|
|
67
|
+
* (`ln(1 + (N - n + 0.5) / (n + 0.5))`) used by Lucene. The `1 +` inside the
|
|
68
|
+
* logarithm keeps the IDF strictly non-negative even for a term that appears in
|
|
69
|
+
* every document, so a common term can never subtract from a document's score.
|
|
70
|
+
*/
|
|
71
|
+
function inverseDocumentFrequency(documentCount, termDocumentFrequency) {
|
|
72
|
+
return Math.log(1 + (documentCount - termDocumentFrequency + 0.5) / (termDocumentFrequency + 0.5));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Score every document in the index against a query and return an id → score
|
|
76
|
+
* map containing only documents with a strictly positive score (a document that
|
|
77
|
+
* matches no query term is omitted, mirroring the lexical scorer's "no match →
|
|
78
|
+
* no hit" contract). Query tokens are de-duplicated so a token repeated in the
|
|
79
|
+
* query does not multiply its own contribution. Returns an empty map for an
|
|
80
|
+
* empty index, an empty query, or a query whose terms appear in no document.
|
|
81
|
+
*/
|
|
82
|
+
export function scoreBm25Query(index, queryTokens, params) {
|
|
83
|
+
const scores = new Map();
|
|
84
|
+
// Empty corpus, or a corpus where every document is empty (avgdl 0): no term
|
|
85
|
+
// can match, so return early. Guarding here also guarantees a non-zero
|
|
86
|
+
// average document length below, keeping the length-normalization division
|
|
87
|
+
// safe without an unreachable fallback branch.
|
|
88
|
+
if (index.documentCount === 0 || index.averageDocumentLength === 0) {
|
|
89
|
+
return scores;
|
|
90
|
+
}
|
|
91
|
+
const distinctQueryTerms = [...new Set(queryTokens.filter((token) => token.length > 0))];
|
|
92
|
+
if (distinctQueryTerms.length === 0) {
|
|
93
|
+
return scores;
|
|
94
|
+
}
|
|
95
|
+
// Precompute the IDF for each query term once rather than per document.
|
|
96
|
+
const idfByTerm = new Map();
|
|
97
|
+
for (const term of distinctQueryTerms) {
|
|
98
|
+
const termDocumentFrequency = index.documentFrequency.get(term);
|
|
99
|
+
if (termDocumentFrequency === undefined) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
idfByTerm.set(term, inverseDocumentFrequency(index.documentCount, termDocumentFrequency));
|
|
103
|
+
}
|
|
104
|
+
if (idfByTerm.size === 0) {
|
|
105
|
+
return scores;
|
|
106
|
+
}
|
|
107
|
+
for (const document of index.documents) {
|
|
108
|
+
let score = 0;
|
|
109
|
+
for (const [term, idf] of idfByTerm) {
|
|
110
|
+
const termFrequency = document.termFrequencies.get(term);
|
|
111
|
+
if (termFrequency === undefined) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const lengthNormalization = 1 - params.b + (params.b * document.length) / index.averageDocumentLength;
|
|
115
|
+
const denominator = termFrequency + params.k1 * lengthNormalization;
|
|
116
|
+
score += idf * ((termFrequency * (params.k1 + 1)) / denominator);
|
|
117
|
+
}
|
|
118
|
+
if (score > 0) {
|
|
119
|
+
scores.set(document.id, score);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return scores;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Coerce one persisted BM25 parameter to a finite number within `[min, max]`.
|
|
126
|
+
* A finite number is clamped to the range (preserving user intent — e.g.
|
|
127
|
+
* `k1=5000` becomes `1000` rather than being silently ignored); any non-number
|
|
128
|
+
* or non-finite value (string, `NaN`, `Infinity`, missing) falls back to
|
|
129
|
+
* `fallback` so a malformed `settings.json` can never crash or skew scoring.
|
|
130
|
+
*/
|
|
131
|
+
function resolveClampedParam(candidate, fallback, min, max) {
|
|
132
|
+
if (typeof candidate !== "number" || !Number.isFinite(candidate)) {
|
|
133
|
+
return fallback;
|
|
134
|
+
}
|
|
135
|
+
return Math.min(max, Math.max(min, candidate));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Flatten a structured search-corpus record (the shape produced by
|
|
139
|
+
* `buildSearchCorpus`) into a single whitespace-joined string of its *values*
|
|
140
|
+
* only — field names/object keys are deliberately excluded so corpus-wide keys
|
|
141
|
+
* (`title`, `description`, …) never enter the BM25 vocabulary and skew IDF.
|
|
142
|
+
* Strings and numbers contribute their text; arrays and nested objects (tags,
|
|
143
|
+
* dependencies, the plan corpus) are walked recursively; everything else is
|
|
144
|
+
* dropped.
|
|
145
|
+
*/
|
|
146
|
+
export function flattenSearchCorpusText(corpus) {
|
|
147
|
+
const collectValueText = (value) => {
|
|
148
|
+
if (typeof value === "string") {
|
|
149
|
+
return [value];
|
|
150
|
+
}
|
|
151
|
+
if (typeof value === "number") {
|
|
152
|
+
return [String(value)];
|
|
153
|
+
}
|
|
154
|
+
if (Array.isArray(value)) {
|
|
155
|
+
return value.flatMap(collectValueText);
|
|
156
|
+
}
|
|
157
|
+
if (typeof value === "object" && value !== null) {
|
|
158
|
+
return Object.values(value).flatMap(collectValueText);
|
|
159
|
+
}
|
|
160
|
+
return [];
|
|
161
|
+
};
|
|
162
|
+
return collectValueText(Object.values(corpus)).join(" ");
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Resolve the effective BM25 parameters from `settings.search.bm25`, applying
|
|
166
|
+
* {@link DEFAULT_BM25_K1}/{@link DEFAULT_BM25_B} when unset and clamping `k1` to
|
|
167
|
+
* `[0, 1000]` and `b` to `[0, 1]`. Tolerant of partial/invalid config: each
|
|
168
|
+
* knob is resolved independently so one bad value does not discard the other.
|
|
169
|
+
*/
|
|
170
|
+
export function resolveBm25Params(settings) {
|
|
171
|
+
const bm25 = settings?.search?.bm25;
|
|
172
|
+
return {
|
|
173
|
+
k1: resolveClampedParam(bm25?.k1, DEFAULT_BM25_K1, 0, 1_000),
|
|
174
|
+
b: resolveClampedParam(bm25?.b, DEFAULT_BM25_B, 0, 1),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=bm25.js.map
|
|
178
|
+
//# debugId=57c1eb74-63b5-5208-abe1-98da8308839d
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bm25.js","sources":["core/search/bm25.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/search/bm25\n *\n * Offline BM25 lexical retrieval (pm-75k9). Provides an Okapi BM25 ranker that\n * scores the in-memory item corpus with no embedding service, vector store, or\n * network dependency, so semantic/hybrid search degrades to a dense-quality\n * lexical ranker — rather than the naive field-weighted scorer — in air-gapped,\n * CI, and zero-setup environments.\n *\n * BM25 improves on raw term-frequency counting in three ways the legacy keyword\n * scorer cannot: inverse document frequency down-weights terms common across the\n * whole corpus, term-frequency saturation (`k1`) caps the contribution of a term\n * repeated many times in one document, and length normalization (`b`) prevents\n * long documents from dominating purely by size.\n */\nimport type { PmSettings } from \"../../types/index.js\";\nimport { tokenizeAlphaNumeric } from \"../shared/text-normalization.js\";\n\n/**\n * Default Okapi BM25 term-frequency saturation parameter. `1.2` is the widely\n * used Lucene/Elasticsearch default: higher values reduce the diminishing\n * returns of repeated terms more slowly (terms keep accruing weight), lower\n * values saturate sooner.\n */\nexport const DEFAULT_BM25_K1 = 1.2;\n\n/**\n * Default Okapi BM25 length-normalization parameter. `0.75` is the Lucene\n * default: `0` disables length normalization entirely, `1` fully normalizes a\n * document's score by its length relative to the corpus average.\n */\nexport const DEFAULT_BM25_B = 0.75;\n\n/**\n * Resolved BM25 tuning parameters. Both are clamped to sane ranges by\n * {@link resolveBm25Params} before scoring.\n */\nexport interface Bm25Params {\n /** Term-frequency saturation (`k1`); finite and `>= 0`. */\n k1: number;\n /** Length normalization (`b`); finite and within `[0, 1]`. */\n b: number;\n}\n\n/**\n * One corpus document supplied to {@link buildBm25Index}: a stable id and the\n * already-concatenated searchable text. Callers build the text from whichever\n * fields they want indexed (typically the resolved `search.corpus_fields`).\n */\nexport interface Bm25Document {\n id: string;\n text: string;\n}\n\n/**\n * Per-document statistics retained in a {@link Bm25Index}: the term-frequency\n * map and the document length (total token count) used for length\n * normalization.\n */\ninterface Bm25DocumentStats {\n id: string;\n termFrequencies: Map<string, number>;\n length: number;\n}\n\n/**\n * An immutable BM25 index built from a document set. Carries the per-document\n * term frequencies, per-term document frequencies, corpus size, and average\n * document length needed to score any query. Build once per query batch with\n * {@link buildBm25Index}, then score with {@link scoreBm25Query}.\n */\nexport interface Bm25Index {\n documents: Bm25DocumentStats[];\n documentFrequency: Map<string, number>;\n documentCount: number;\n averageDocumentLength: number;\n}\n\n/**\n * Tokenize a document/query string into BM25 terms. Shares\n * {@link tokenizeAlphaNumeric} with the lexical scorer so the BM25 vocabulary is\n * identical to the rest of search: lowercase, alphanumeric runs, no stop-word\n * removal or stemming (kept deliberately simple and language-agnostic).\n */\nexport function tokenizeBm25(text: string): string[] {\n return tokenizeAlphaNumeric(text);\n}\n\n/**\n * Count occurrences of each token in a token list.\n */\nfunction buildTermFrequencies(tokens: string[]): Map<string, number> {\n const frequencies = new Map<string, number>();\n for (const token of tokens) {\n frequencies.set(token, (frequencies.get(token) ?? 0) + 1);\n }\n return frequencies;\n}\n\n/**\n * Build a BM25 index from a corpus. Computes each document's term frequencies\n * and length, the per-term document frequency, the corpus size, and the average\n * document length. Empty documents (no tokens) are retained with length `0` so\n * they can still be scored (they simply never match a query term). An empty\n * corpus yields an index with `averageDocumentLength` `0`, which\n * {@link scoreBm25Query} handles without dividing by zero.\n */\nexport function buildBm25Index(documents: Bm25Document[]): Bm25Index {\n const stats: Bm25DocumentStats[] = [];\n const documentFrequency = new Map<string, number>();\n let totalLength = 0;\n for (const document of documents) {\n const tokens = tokenizeBm25(document.text);\n const termFrequencies = buildTermFrequencies(tokens);\n totalLength += tokens.length;\n for (const term of termFrequencies.keys()) {\n documentFrequency.set(term, (documentFrequency.get(term) ?? 0) + 1);\n }\n stats.push({ id: document.id, termFrequencies, length: tokens.length });\n }\n const documentCount = stats.length;\n return {\n documents: stats,\n documentFrequency,\n documentCount,\n averageDocumentLength: documentCount > 0 ? totalLength / documentCount : 0,\n };\n}\n\n/**\n * Inverse document frequency for one term using the BM25 \"plus-one\" variant\n * (`ln(1 + (N - n + 0.5) / (n + 0.5))`) used by Lucene. The `1 +` inside the\n * logarithm keeps the IDF strictly non-negative even for a term that appears in\n * every document, so a common term can never subtract from a document's score.\n */\nfunction inverseDocumentFrequency(documentCount: number, termDocumentFrequency: number): number {\n return Math.log(1 + (documentCount - termDocumentFrequency + 0.5) / (termDocumentFrequency + 0.5));\n}\n\n/**\n * Score every document in the index against a query and return an id → score\n * map containing only documents with a strictly positive score (a document that\n * matches no query term is omitted, mirroring the lexical scorer's \"no match →\n * no hit\" contract). Query tokens are de-duplicated so a token repeated in the\n * query does not multiply its own contribution. Returns an empty map for an\n * empty index, an empty query, or a query whose terms appear in no document.\n */\nexport function scoreBm25Query(index: Bm25Index, queryTokens: string[], params: Bm25Params): Map<string, number> {\n const scores = new Map<string, number>();\n // Empty corpus, or a corpus where every document is empty (avgdl 0): no term\n // can match, so return early. Guarding here also guarantees a non-zero\n // average document length below, keeping the length-normalization division\n // safe without an unreachable fallback branch.\n if (index.documentCount === 0 || index.averageDocumentLength === 0) {\n return scores;\n }\n const distinctQueryTerms = [...new Set(queryTokens.filter((token) => token.length > 0))];\n if (distinctQueryTerms.length === 0) {\n return scores;\n }\n // Precompute the IDF for each query term once rather than per document.\n const idfByTerm = new Map<string, number>();\n for (const term of distinctQueryTerms) {\n const termDocumentFrequency = index.documentFrequency.get(term);\n if (termDocumentFrequency === undefined) {\n continue;\n }\n idfByTerm.set(term, inverseDocumentFrequency(index.documentCount, termDocumentFrequency));\n }\n if (idfByTerm.size === 0) {\n return scores;\n }\n for (const document of index.documents) {\n let score = 0;\n for (const [term, idf] of idfByTerm) {\n const termFrequency = document.termFrequencies.get(term);\n if (termFrequency === undefined) {\n continue;\n }\n const lengthNormalization =\n 1 - params.b + (params.b * document.length) / index.averageDocumentLength;\n const denominator = termFrequency + params.k1 * lengthNormalization;\n score += idf * ((termFrequency * (params.k1 + 1)) / denominator);\n }\n if (score > 0) {\n scores.set(document.id, score);\n }\n }\n return scores;\n}\n\n/**\n * Coerce one persisted BM25 parameter to a finite number within `[min, max]`.\n * A finite number is clamped to the range (preserving user intent — e.g.\n * `k1=5000` becomes `1000` rather than being silently ignored); any non-number\n * or non-finite value (string, `NaN`, `Infinity`, missing) falls back to\n * `fallback` so a malformed `settings.json` can never crash or skew scoring.\n */\nfunction resolveClampedParam(candidate: unknown, fallback: number, min: number, max: number): number {\n if (typeof candidate !== \"number\" || !Number.isFinite(candidate)) {\n return fallback;\n }\n return Math.min(max, Math.max(min, candidate));\n}\n\n/**\n * Flatten a structured search-corpus record (the shape produced by\n * `buildSearchCorpus`) into a single whitespace-joined string of its *values*\n * only — field names/object keys are deliberately excluded so corpus-wide keys\n * (`title`, `description`, …) never enter the BM25 vocabulary and skew IDF.\n * Strings and numbers contribute their text; arrays and nested objects (tags,\n * dependencies, the plan corpus) are walked recursively; everything else is\n * dropped.\n */\nexport function flattenSearchCorpusText(corpus: Record<string, unknown>): string {\n const collectValueText = (value: unknown): string[] => {\n if (typeof value === \"string\") {\n return [value];\n }\n if (typeof value === \"number\") {\n return [String(value)];\n }\n if (Array.isArray(value)) {\n return value.flatMap(collectValueText);\n }\n if (typeof value === \"object\" && value !== null) {\n return Object.values(value).flatMap(collectValueText);\n }\n return [];\n };\n return collectValueText(Object.values(corpus)).join(\" \");\n}\n\n/**\n * Resolve the effective BM25 parameters from `settings.search.bm25`, applying\n * {@link DEFAULT_BM25_K1}/{@link DEFAULT_BM25_B} when unset and clamping `k1` to\n * `[0, 1000]` and `b` to `[0, 1]`. Tolerant of partial/invalid config: each\n * knob is resolved independently so one bad value does not discard the other.\n */\nexport function resolveBm25Params(settings: Pick<PmSettings, \"search\"> | undefined): Bm25Params {\n const bm25 = (settings?.search as { bm25?: { k1?: unknown; b?: unknown } } | undefined)?.bm25;\n return {\n k1: resolveClampedParam(bm25?.k1, DEFAULT_BM25_K1, 0, 1_000),\n b: resolveClampedParam(bm25?.b, DEFAULT_BM25_B, 0, 1),\n };\n}\n"],"names":[],"mappings":";;AAgBA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AA+CnC;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,MAAgB;IAC5C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,SAAyB;IACtD,MAAM,KAAK,GAAwB,EAAE,CAAC;IACtC,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpD,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,eAAe,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QACrD,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC;QAC7B,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1C,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC;IACnC,OAAO;QACL,SAAS,EAAE,KAAK;QAChB,iBAAiB;QACjB,aAAa;QACb,qBAAqB,EAAE,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;KAC3E,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,wBAAwB,CAAC,aAAqB,EAAE,qBAA6B;IACpF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,aAAa,GAAG,qBAAqB,GAAG,GAAG,CAAC,GAAG,CAAC,qBAAqB,GAAG,GAAG,CAAC,CAAC,CAAC;AACrG,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAAgB,EAAE,WAAqB,EAAE,MAAkB;IACxF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,6EAA6E;IAC7E,uEAAuE;IACvE,2EAA2E;IAC3E,+CAA+C;IAC/C,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,IAAI,KAAK,CAAC,qBAAqB,KAAK,CAAC,EAAE,CAAC;QACnE,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,kBAAkB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,wEAAwE;IACxE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,CAAC;QACtC,MAAM,qBAAqB,GAAG,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChE,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAC;YACxC,SAAS;QACX,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,wBAAwB,CAAC,KAAK,CAAC,aAAa,EAAE,qBAAqB,CAAC,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACvC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,SAAS,EAAE,CAAC;YACpC,MAAM,aAAa,GAAG,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBAChC,SAAS;YACX,CAAC;YACD,MAAM,mBAAmB,GACvB,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,qBAAqB,CAAC;YAC5E,MAAM,WAAW,GAAG,aAAa,GAAG,MAAM,CAAC,EAAE,GAAG,mBAAmB,CAAC;YACpE,KAAK,IAAI,GAAG,GAAG,CAAC,CAAC,aAAa,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,SAAkB,EAAE,QAAgB,EAAE,GAAW,EAAE,GAAW;IACzF,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACjE,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAA+B;IACrE,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAY,EAAE;QACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAChD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IACF,OAAO,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgD;IAChF,MAAM,IAAI,GAAI,QAAQ,EAAE,MAA+D,EAAE,IAAI,CAAC;IAC9F,OAAO;QACL,EAAE,EAAE,mBAAmB,CAAC,IAAI,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,EAAE,KAAK,CAAC;QAC5D,CAAC,EAAE,mBAAmB,CAAC,IAAI,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;KACtD,CAAC;AACJ,CAAC","debugId":"57c1eb74-63b5-5208-abe1-98da8308839d"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/search/eval
|
|
3
|
+
*
|
|
4
|
+
* Search relevance evaluation primitives (pm-u8n5). Implements the standard
|
|
5
|
+
* offline ranking metrics — nDCG@k, MRR@k, precision@k, recall@k — over a
|
|
6
|
+
* human-curated golden-query set, plus the loader/validator for that set. The
|
|
7
|
+
* `pm eval` command (src/cli/commands/eval.ts) runs each golden query through
|
|
8
|
+
* the live retrieval path and feeds the ranked ids here, so relevance
|
|
9
|
+
* regressions from corpus changes, hybrid-weight changes, or provider swaps are
|
|
10
|
+
* measurable and gateable in CI.
|
|
11
|
+
*
|
|
12
|
+
* Relevance is binary: an id is either in a query's `relevant_ids` set or it is
|
|
13
|
+
* not. This keeps the golden set cheap to curate while still supporting the
|
|
14
|
+
* graded-discount behavior of DCG (earlier hits are worth more).
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Retrieval mode a golden query is evaluated under. Mirrors the `pm search`
|
|
18
|
+
* mode surface; omitting it on a query defers to the eval run's default mode.
|
|
19
|
+
*/
|
|
20
|
+
export type EvalSearchMode = "keyword" | "semantic" | "hybrid";
|
|
21
|
+
/** Default cutoff (`@k`) used for every metric when the caller does not override it. */
|
|
22
|
+
export declare const DEFAULT_EVAL_K = 10;
|
|
23
|
+
/**
|
|
24
|
+
* One curated golden query: the query text, the set of item ids considered
|
|
25
|
+
* relevant, an optional per-query retrieval mode override, and an optional
|
|
26
|
+
* human-readable description of the relevance intent.
|
|
27
|
+
*/
|
|
28
|
+
export interface EvalQuery {
|
|
29
|
+
query: string;
|
|
30
|
+
relevant_ids: string[];
|
|
31
|
+
mode?: EvalSearchMode;
|
|
32
|
+
description?: string;
|
|
33
|
+
}
|
|
34
|
+
/** A parsed, validated golden-query set. */
|
|
35
|
+
export interface EvalQuerySet {
|
|
36
|
+
queries: EvalQuery[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Thrown by {@link parseEvalQuerySet} when the raw golden-query payload is
|
|
40
|
+
* structurally invalid. Carries a precise, human-actionable message naming the
|
|
41
|
+
* offending query index/field so an author can fix the JSON directly.
|
|
42
|
+
*/
|
|
43
|
+
export declare class EvalQuerySetError extends Error {
|
|
44
|
+
/** Construct an error describing why a golden-query set failed validation. */
|
|
45
|
+
constructor(message: string);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Compute Discounted Cumulative Gain at cutoff `k` for an ordered list of binary
|
|
49
|
+
* relevance gains (`1` relevant, `0` not). Position `i` (1-based) contributes
|
|
50
|
+
* `gain / log2(i + 1)`, so a relevant hit ranked first is worth `1` and later
|
|
51
|
+
* hits are progressively discounted. Gains beyond `k` are ignored.
|
|
52
|
+
*/
|
|
53
|
+
export declare function dcgAtK(relevanceGains: number[], k: number): number;
|
|
54
|
+
/**
|
|
55
|
+
* Normalized DCG at cutoff `k`: the ranking's DCG divided by the DCG of the
|
|
56
|
+
* ideal ranking (all relevant ids first). Returns `0` when the query has no
|
|
57
|
+
* relevant ids (the ideal DCG is `0` and the score is undefined), giving a
|
|
58
|
+
* stable lower bound for aggregation. Result is in `[0, 1]`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function ndcgAtK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number;
|
|
61
|
+
/**
|
|
62
|
+
* Reciprocal rank of the first relevant id within the top `k` results: `1/rank`
|
|
63
|
+
* (rank is 1-based), or `0` when no relevant id appears in the cutoff. Averaged
|
|
64
|
+
* across queries this is Mean Reciprocal Rank (MRR@k).
|
|
65
|
+
*/
|
|
66
|
+
export declare function reciprocalRankAtK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number;
|
|
67
|
+
/**
|
|
68
|
+
* Precision at cutoff `k`: relevant ids retrieved in the top `k` divided by `k`.
|
|
69
|
+
* Returns `0` for a non-positive `k`.
|
|
70
|
+
*/
|
|
71
|
+
export declare function precisionAtK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number;
|
|
72
|
+
/**
|
|
73
|
+
* Recall at cutoff `k`: relevant ids retrieved in the top `k` divided by the
|
|
74
|
+
* total number of relevant ids. Returns `0` when the query has no relevant ids.
|
|
75
|
+
*/
|
|
76
|
+
export declare function recallAtK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number;
|
|
77
|
+
/** The four ranking metrics computed for a single query, plus match counts. */
|
|
78
|
+
export interface QueryEvalMetrics {
|
|
79
|
+
ndcg: number;
|
|
80
|
+
mrr: number;
|
|
81
|
+
precision: number;
|
|
82
|
+
recall: number;
|
|
83
|
+
relevant_total: number;
|
|
84
|
+
retrieved_relevant: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Evaluate one ranking against its relevant-id set at cutoff `k`, returning all
|
|
88
|
+
* four metrics together so callers compute the document ranking once and read
|
|
89
|
+
* every score off the result.
|
|
90
|
+
*/
|
|
91
|
+
export declare function evaluateRanking(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): QueryEvalMetrics;
|
|
92
|
+
/** Macro-averaged metrics across all evaluated queries. */
|
|
93
|
+
export interface AggregateEvalMetrics {
|
|
94
|
+
ndcg: number;
|
|
95
|
+
mrr: number;
|
|
96
|
+
precision: number;
|
|
97
|
+
recall: number;
|
|
98
|
+
query_count: number;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Macro-average per-query metrics (each query weighted equally). Returns all
|
|
102
|
+
* zeros with `query_count: 0` for an empty input so the gate path has a stable
|
|
103
|
+
* shape to compare against.
|
|
104
|
+
*/
|
|
105
|
+
export declare function aggregateEvalMetrics(perQuery: QueryEvalMetrics[]): AggregateEvalMetrics;
|
|
106
|
+
/**
|
|
107
|
+
* Parse and validate a raw golden-query payload (typically `JSON.parse` of
|
|
108
|
+
* `.agents/pm/search/eval-queries.json`). Accepts either a bare array of query
|
|
109
|
+
* entries or an object with a `queries` array. Throws {@link EvalQuerySetError}
|
|
110
|
+
* with a precise message when the payload is not an array/object, when
|
|
111
|
+
* `queries` is missing/not an array, when the set is empty, or when any entry
|
|
112
|
+
* fails {@link parseEvalQueryEntry}.
|
|
113
|
+
*/
|
|
114
|
+
export declare function parseEvalQuerySet(raw: unknown): EvalQuerySet;
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/search/eval
|
|
3
|
+
*
|
|
4
|
+
* Search relevance evaluation primitives (pm-u8n5). Implements the standard
|
|
5
|
+
* offline ranking metrics — nDCG@k, MRR@k, precision@k, recall@k — over a
|
|
6
|
+
* human-curated golden-query set, plus the loader/validator for that set. The
|
|
7
|
+
* `pm eval` command (src/cli/commands/eval.ts) runs each golden query through
|
|
8
|
+
* the live retrieval path and feeds the ranked ids here, so relevance
|
|
9
|
+
* regressions from corpus changes, hybrid-weight changes, or provider swaps are
|
|
10
|
+
* measurable and gateable in CI.
|
|
11
|
+
*
|
|
12
|
+
* Relevance is binary: an id is either in a query's `relevant_ids` set or it is
|
|
13
|
+
* not. This keeps the golden set cheap to curate while still supporting the
|
|
14
|
+
* graded-discount behavior of DCG (earlier hits are worth more).
|
|
15
|
+
*/
|
|
16
|
+
/** Default cutoff (`@k`) used for every metric when the caller does not override it. */
|
|
17
|
+
|
|
18
|
+
!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]="4ed89138-1775-503e-a08f-7e94a0bd24eb")}catch(e){}}();
|
|
19
|
+
export const DEFAULT_EVAL_K = 10;
|
|
20
|
+
/**
|
|
21
|
+
* Thrown by {@link parseEvalQuerySet} when the raw golden-query payload is
|
|
22
|
+
* structurally invalid. Carries a precise, human-actionable message naming the
|
|
23
|
+
* offending query index/field so an author can fix the JSON directly.
|
|
24
|
+
*/
|
|
25
|
+
export class EvalQuerySetError extends Error {
|
|
26
|
+
/** Construct an error describing why a golden-query set failed validation. */
|
|
27
|
+
constructor(message) {
|
|
28
|
+
super(message);
|
|
29
|
+
this.name = "EvalQuerySetError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const VALID_EVAL_MODES = new Set(["keyword", "semantic", "hybrid"]);
|
|
33
|
+
/**
|
|
34
|
+
* Compute Discounted Cumulative Gain at cutoff `k` for an ordered list of binary
|
|
35
|
+
* relevance gains (`1` relevant, `0` not). Position `i` (1-based) contributes
|
|
36
|
+
* `gain / log2(i + 1)`, so a relevant hit ranked first is worth `1` and later
|
|
37
|
+
* hits are progressively discounted. Gains beyond `k` are ignored.
|
|
38
|
+
*/
|
|
39
|
+
export function dcgAtK(relevanceGains, k) {
|
|
40
|
+
let dcg = 0;
|
|
41
|
+
const limit = Math.min(k, relevanceGains.length);
|
|
42
|
+
for (let index = 0; index < limit; index += 1) {
|
|
43
|
+
dcg += relevanceGains[index] / Math.log2(index + 2);
|
|
44
|
+
}
|
|
45
|
+
return dcg;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Normalized DCG at cutoff `k`: the ranking's DCG divided by the DCG of the
|
|
49
|
+
* ideal ranking (all relevant ids first). Returns `0` when the query has no
|
|
50
|
+
* relevant ids (the ideal DCG is `0` and the score is undefined), giving a
|
|
51
|
+
* stable lower bound for aggregation. Result is in `[0, 1]`.
|
|
52
|
+
*/
|
|
53
|
+
export function ndcgAtK(rankedIds, relevantIds, k) {
|
|
54
|
+
if (relevantIds.size === 0) {
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
const gains = rankedIds.map((id) => (relevantIds.has(id) ? 1 : 0));
|
|
58
|
+
const dcg = dcgAtK(gains, k);
|
|
59
|
+
const idealGains = Array.from({ length: relevantIds.size }, () => 1);
|
|
60
|
+
const idealDcg = dcgAtK(idealGains, k);
|
|
61
|
+
return idealDcg === 0 ? 0 : dcg / idealDcg;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Reciprocal rank of the first relevant id within the top `k` results: `1/rank`
|
|
65
|
+
* (rank is 1-based), or `0` when no relevant id appears in the cutoff. Averaged
|
|
66
|
+
* across queries this is Mean Reciprocal Rank (MRR@k).
|
|
67
|
+
*/
|
|
68
|
+
export function reciprocalRankAtK(rankedIds, relevantIds, k) {
|
|
69
|
+
const limit = Math.min(k, rankedIds.length);
|
|
70
|
+
for (let index = 0; index < limit; index += 1) {
|
|
71
|
+
if (relevantIds.has(rankedIds[index])) {
|
|
72
|
+
return 1 / (index + 1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Count relevant ids within the top `k` results (shared by precision and
|
|
79
|
+
* recall).
|
|
80
|
+
*/
|
|
81
|
+
function countRelevantInTopK(rankedIds, relevantIds, k) {
|
|
82
|
+
const limit = Math.min(k, rankedIds.length);
|
|
83
|
+
let hits = 0;
|
|
84
|
+
for (let index = 0; index < limit; index += 1) {
|
|
85
|
+
if (relevantIds.has(rankedIds[index])) {
|
|
86
|
+
hits += 1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return hits;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Precision at cutoff `k`: relevant ids retrieved in the top `k` divided by `k`.
|
|
93
|
+
* Returns `0` for a non-positive `k`.
|
|
94
|
+
*/
|
|
95
|
+
export function precisionAtK(rankedIds, relevantIds, k) {
|
|
96
|
+
if (k <= 0) {
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
return countRelevantInTopK(rankedIds, relevantIds, k) / k;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Recall at cutoff `k`: relevant ids retrieved in the top `k` divided by the
|
|
103
|
+
* total number of relevant ids. Returns `0` when the query has no relevant ids.
|
|
104
|
+
*/
|
|
105
|
+
export function recallAtK(rankedIds, relevantIds, k) {
|
|
106
|
+
if (relevantIds.size === 0) {
|
|
107
|
+
return 0;
|
|
108
|
+
}
|
|
109
|
+
return countRelevantInTopK(rankedIds, relevantIds, k) / relevantIds.size;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Evaluate one ranking against its relevant-id set at cutoff `k`, returning all
|
|
113
|
+
* four metrics together so callers compute the document ranking once and read
|
|
114
|
+
* every score off the result.
|
|
115
|
+
*/
|
|
116
|
+
export function evaluateRanking(rankedIds, relevantIds, k) {
|
|
117
|
+
return {
|
|
118
|
+
ndcg: ndcgAtK(rankedIds, relevantIds, k),
|
|
119
|
+
mrr: reciprocalRankAtK(rankedIds, relevantIds, k),
|
|
120
|
+
precision: precisionAtK(rankedIds, relevantIds, k),
|
|
121
|
+
recall: recallAtK(rankedIds, relevantIds, k),
|
|
122
|
+
relevant_total: relevantIds.size,
|
|
123
|
+
retrieved_relevant: countRelevantInTopK(rankedIds, relevantIds, k),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Macro-average per-query metrics (each query weighted equally). Returns all
|
|
128
|
+
* zeros with `query_count: 0` for an empty input so the gate path has a stable
|
|
129
|
+
* shape to compare against.
|
|
130
|
+
*/
|
|
131
|
+
export function aggregateEvalMetrics(perQuery) {
|
|
132
|
+
const queryCount = perQuery.length;
|
|
133
|
+
if (queryCount === 0) {
|
|
134
|
+
return { ndcg: 0, mrr: 0, precision: 0, recall: 0, query_count: 0 };
|
|
135
|
+
}
|
|
136
|
+
const sum = perQuery.reduce((accumulator, metrics) => ({
|
|
137
|
+
ndcg: accumulator.ndcg + metrics.ndcg,
|
|
138
|
+
mrr: accumulator.mrr + metrics.mrr,
|
|
139
|
+
precision: accumulator.precision + metrics.precision,
|
|
140
|
+
recall: accumulator.recall + metrics.recall,
|
|
141
|
+
}), { ndcg: 0, mrr: 0, precision: 0, recall: 0 });
|
|
142
|
+
return {
|
|
143
|
+
ndcg: sum.ndcg / queryCount,
|
|
144
|
+
mrr: sum.mrr / queryCount,
|
|
145
|
+
precision: sum.precision / queryCount,
|
|
146
|
+
recall: sum.recall / queryCount,
|
|
147
|
+
query_count: queryCount,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Validate one raw golden-query entry, returning a typed {@link EvalQuery}.
|
|
152
|
+
* Throws {@link EvalQuerySetError} (with the entry index) for a missing/empty
|
|
153
|
+
* `query`, a `relevant_ids` that is not a non-empty string array, or an invalid
|
|
154
|
+
* `mode`. `relevant_ids` are trimmed and de-duplicated; `description` is kept
|
|
155
|
+
* only when it is a non-empty string.
|
|
156
|
+
*/
|
|
157
|
+
function parseEvalQueryEntry(raw, index) {
|
|
158
|
+
if (typeof raw !== "object" || raw === null) {
|
|
159
|
+
throw new EvalQuerySetError(`Eval query at index ${index} must be an object`);
|
|
160
|
+
}
|
|
161
|
+
const entry = raw;
|
|
162
|
+
const query = typeof entry.query === "string" ? entry.query.trim() : "";
|
|
163
|
+
if (query.length === 0) {
|
|
164
|
+
throw new EvalQuerySetError(`Eval query at index ${index} must have a non-empty "query" string`);
|
|
165
|
+
}
|
|
166
|
+
if (!Array.isArray(entry.relevant_ids)) {
|
|
167
|
+
throw new EvalQuerySetError(`Eval query at index ${index} must have a "relevant_ids" array`);
|
|
168
|
+
}
|
|
169
|
+
if (entry.relevant_ids.some((value) => typeof value !== "string")) {
|
|
170
|
+
// Reject (rather than silently drop) non-string members: malformed golden
|
|
171
|
+
// data must fail loudly so it can never quietly change relevance judgments.
|
|
172
|
+
throw new EvalQuerySetError(`Eval query at index ${index} must have a "relevant_ids" array of strings`);
|
|
173
|
+
}
|
|
174
|
+
const relevantIds = [
|
|
175
|
+
...new Set(entry.relevant_ids.map((value) => value.trim()).filter((value) => value.length > 0)),
|
|
176
|
+
];
|
|
177
|
+
if (relevantIds.length === 0) {
|
|
178
|
+
throw new EvalQuerySetError(`Eval query at index ${index} must list at least one relevant id`);
|
|
179
|
+
}
|
|
180
|
+
if (entry.mode !== undefined && (typeof entry.mode !== "string" || !VALID_EVAL_MODES.has(entry.mode))) {
|
|
181
|
+
throw new EvalQuerySetError(`Eval query at index ${index} has an invalid mode (expected keyword|semantic|hybrid)`);
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
query,
|
|
185
|
+
relevant_ids: relevantIds,
|
|
186
|
+
...(entry.mode !== undefined ? { mode: entry.mode } : {}),
|
|
187
|
+
...(typeof entry.description === "string" && entry.description.trim().length > 0
|
|
188
|
+
? { description: entry.description.trim() }
|
|
189
|
+
: {}),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Parse and validate a raw golden-query payload (typically `JSON.parse` of
|
|
194
|
+
* `.agents/pm/search/eval-queries.json`). Accepts either a bare array of query
|
|
195
|
+
* entries or an object with a `queries` array. Throws {@link EvalQuerySetError}
|
|
196
|
+
* with a precise message when the payload is not an array/object, when
|
|
197
|
+
* `queries` is missing/not an array, when the set is empty, or when any entry
|
|
198
|
+
* fails {@link parseEvalQueryEntry}.
|
|
199
|
+
*/
|
|
200
|
+
export function parseEvalQuerySet(raw) {
|
|
201
|
+
const rawQueries = Array.isArray(raw)
|
|
202
|
+
? raw
|
|
203
|
+
: typeof raw === "object" && raw !== null
|
|
204
|
+
? raw.queries
|
|
205
|
+
: undefined;
|
|
206
|
+
if (!Array.isArray(rawQueries)) {
|
|
207
|
+
throw new EvalQuerySetError('Eval query set must be an array of queries or an object with a "queries" array');
|
|
208
|
+
}
|
|
209
|
+
if (rawQueries.length === 0) {
|
|
210
|
+
throw new EvalQuerySetError("Eval query set must contain at least one query");
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
queries: rawQueries.map((entry, index) => parseEvalQueryEntry(entry, index)),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=eval.js.map
|
|
217
|
+
//# debugId=4ed89138-1775-503e-a08f-7e94a0bd24eb
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eval.js","sources":["core/search/eval.ts"],"sourceRoot":"/","sourcesContent":["/**\n * @module core/search/eval\n *\n * Search relevance evaluation primitives (pm-u8n5). Implements the standard\n * offline ranking metrics — nDCG@k, MRR@k, precision@k, recall@k — over a\n * human-curated golden-query set, plus the loader/validator for that set. The\n * `pm eval` command (src/cli/commands/eval.ts) runs each golden query through\n * the live retrieval path and feeds the ranked ids here, so relevance\n * regressions from corpus changes, hybrid-weight changes, or provider swaps are\n * measurable and gateable in CI.\n *\n * Relevance is binary: an id is either in a query's `relevant_ids` set or it is\n * not. This keeps the golden set cheap to curate while still supporting the\n * graded-discount behavior of DCG (earlier hits are worth more).\n */\n\n/**\n * Retrieval mode a golden query is evaluated under. Mirrors the `pm search`\n * mode surface; omitting it on a query defers to the eval run's default mode.\n */\nexport type EvalSearchMode = \"keyword\" | \"semantic\" | \"hybrid\";\n\n/** Default cutoff (`@k`) used for every metric when the caller does not override it. */\nexport const DEFAULT_EVAL_K = 10;\n\n/**\n * One curated golden query: the query text, the set of item ids considered\n * relevant, an optional per-query retrieval mode override, and an optional\n * human-readable description of the relevance intent.\n */\nexport interface EvalQuery {\n query: string;\n relevant_ids: string[];\n mode?: EvalSearchMode;\n description?: string;\n}\n\n/** A parsed, validated golden-query set. */\nexport interface EvalQuerySet {\n queries: EvalQuery[];\n}\n\n/**\n * Thrown by {@link parseEvalQuerySet} when the raw golden-query payload is\n * structurally invalid. Carries a precise, human-actionable message naming the\n * offending query index/field so an author can fix the JSON directly.\n */\nexport class EvalQuerySetError extends Error {\n /** Construct an error describing why a golden-query set failed validation. */\n constructor(message: string) {\n super(message);\n this.name = \"EvalQuerySetError\";\n }\n}\n\nconst VALID_EVAL_MODES: ReadonlySet<string> = new Set<EvalSearchMode>([\"keyword\", \"semantic\", \"hybrid\"]);\n\n/**\n * Compute Discounted Cumulative Gain at cutoff `k` for an ordered list of binary\n * relevance gains (`1` relevant, `0` not). Position `i` (1-based) contributes\n * `gain / log2(i + 1)`, so a relevant hit ranked first is worth `1` and later\n * hits are progressively discounted. Gains beyond `k` are ignored.\n */\nexport function dcgAtK(relevanceGains: number[], k: number): number {\n let dcg = 0;\n const limit = Math.min(k, relevanceGains.length);\n for (let index = 0; index < limit; index += 1) {\n dcg += relevanceGains[index] / Math.log2(index + 2);\n }\n return dcg;\n}\n\n/**\n * Normalized DCG at cutoff `k`: the ranking's DCG divided by the DCG of the\n * ideal ranking (all relevant ids first). Returns `0` when the query has no\n * relevant ids (the ideal DCG is `0` and the score is undefined), giving a\n * stable lower bound for aggregation. Result is in `[0, 1]`.\n */\nexport function ndcgAtK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number {\n if (relevantIds.size === 0) {\n return 0;\n }\n const gains = rankedIds.map((id) => (relevantIds.has(id) ? 1 : 0));\n const dcg = dcgAtK(gains, k);\n const idealGains = Array.from({ length: relevantIds.size }, () => 1);\n const idealDcg = dcgAtK(idealGains, k);\n return idealDcg === 0 ? 0 : dcg / idealDcg;\n}\n\n/**\n * Reciprocal rank of the first relevant id within the top `k` results: `1/rank`\n * (rank is 1-based), or `0` when no relevant id appears in the cutoff. Averaged\n * across queries this is Mean Reciprocal Rank (MRR@k).\n */\nexport function reciprocalRankAtK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number {\n const limit = Math.min(k, rankedIds.length);\n for (let index = 0; index < limit; index += 1) {\n if (relevantIds.has(rankedIds[index])) {\n return 1 / (index + 1);\n }\n }\n return 0;\n}\n\n/**\n * Count relevant ids within the top `k` results (shared by precision and\n * recall).\n */\nfunction countRelevantInTopK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number {\n const limit = Math.min(k, rankedIds.length);\n let hits = 0;\n for (let index = 0; index < limit; index += 1) {\n if (relevantIds.has(rankedIds[index])) {\n hits += 1;\n }\n }\n return hits;\n}\n\n/**\n * Precision at cutoff `k`: relevant ids retrieved in the top `k` divided by `k`.\n * Returns `0` for a non-positive `k`.\n */\nexport function precisionAtK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number {\n if (k <= 0) {\n return 0;\n }\n return countRelevantInTopK(rankedIds, relevantIds, k) / k;\n}\n\n/**\n * Recall at cutoff `k`: relevant ids retrieved in the top `k` divided by the\n * total number of relevant ids. Returns `0` when the query has no relevant ids.\n */\nexport function recallAtK(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): number {\n if (relevantIds.size === 0) {\n return 0;\n }\n return countRelevantInTopK(rankedIds, relevantIds, k) / relevantIds.size;\n}\n\n/** The four ranking metrics computed for a single query, plus match counts. */\nexport interface QueryEvalMetrics {\n ndcg: number;\n mrr: number;\n precision: number;\n recall: number;\n relevant_total: number;\n retrieved_relevant: number;\n}\n\n/**\n * Evaluate one ranking against its relevant-id set at cutoff `k`, returning all\n * four metrics together so callers compute the document ranking once and read\n * every score off the result.\n */\nexport function evaluateRanking(rankedIds: string[], relevantIds: ReadonlySet<string>, k: number): QueryEvalMetrics {\n return {\n ndcg: ndcgAtK(rankedIds, relevantIds, k),\n mrr: reciprocalRankAtK(rankedIds, relevantIds, k),\n precision: precisionAtK(rankedIds, relevantIds, k),\n recall: recallAtK(rankedIds, relevantIds, k),\n relevant_total: relevantIds.size,\n retrieved_relevant: countRelevantInTopK(rankedIds, relevantIds, k),\n };\n}\n\n/** Macro-averaged metrics across all evaluated queries. */\nexport interface AggregateEvalMetrics {\n ndcg: number;\n mrr: number;\n precision: number;\n recall: number;\n query_count: number;\n}\n\n/**\n * Macro-average per-query metrics (each query weighted equally). Returns all\n * zeros with `query_count: 0` for an empty input so the gate path has a stable\n * shape to compare against.\n */\nexport function aggregateEvalMetrics(perQuery: QueryEvalMetrics[]): AggregateEvalMetrics {\n const queryCount = perQuery.length;\n if (queryCount === 0) {\n return { ndcg: 0, mrr: 0, precision: 0, recall: 0, query_count: 0 };\n }\n const sum = perQuery.reduce(\n (accumulator, metrics) => ({\n ndcg: accumulator.ndcg + metrics.ndcg,\n mrr: accumulator.mrr + metrics.mrr,\n precision: accumulator.precision + metrics.precision,\n recall: accumulator.recall + metrics.recall,\n }),\n { ndcg: 0, mrr: 0, precision: 0, recall: 0 },\n );\n return {\n ndcg: sum.ndcg / queryCount,\n mrr: sum.mrr / queryCount,\n precision: sum.precision / queryCount,\n recall: sum.recall / queryCount,\n query_count: queryCount,\n };\n}\n\n/**\n * Validate one raw golden-query entry, returning a typed {@link EvalQuery}.\n * Throws {@link EvalQuerySetError} (with the entry index) for a missing/empty\n * `query`, a `relevant_ids` that is not a non-empty string array, or an invalid\n * `mode`. `relevant_ids` are trimmed and de-duplicated; `description` is kept\n * only when it is a non-empty string.\n */\nfunction parseEvalQueryEntry(raw: unknown, index: number): EvalQuery {\n if (typeof raw !== \"object\" || raw === null) {\n throw new EvalQuerySetError(`Eval query at index ${index} must be an object`);\n }\n const entry = raw as { query?: unknown; relevant_ids?: unknown; mode?: unknown; description?: unknown };\n const query = typeof entry.query === \"string\" ? entry.query.trim() : \"\";\n if (query.length === 0) {\n throw new EvalQuerySetError(`Eval query at index ${index} must have a non-empty \"query\" string`);\n }\n if (!Array.isArray(entry.relevant_ids)) {\n throw new EvalQuerySetError(`Eval query at index ${index} must have a \"relevant_ids\" array`);\n }\n if (entry.relevant_ids.some((value) => typeof value !== \"string\")) {\n // Reject (rather than silently drop) non-string members: malformed golden\n // data must fail loudly so it can never quietly change relevance judgments.\n throw new EvalQuerySetError(`Eval query at index ${index} must have a \"relevant_ids\" array of strings`);\n }\n const relevantIds = [\n ...new Set((entry.relevant_ids as string[]).map((value) => value.trim()).filter((value) => value.length > 0)),\n ];\n if (relevantIds.length === 0) {\n throw new EvalQuerySetError(`Eval query at index ${index} must list at least one relevant id`);\n }\n if (entry.mode !== undefined && (typeof entry.mode !== \"string\" || !VALID_EVAL_MODES.has(entry.mode))) {\n throw new EvalQuerySetError(`Eval query at index ${index} has an invalid mode (expected keyword|semantic|hybrid)`);\n }\n return {\n query,\n relevant_ids: relevantIds,\n ...(entry.mode !== undefined ? { mode: entry.mode as EvalSearchMode } : {}),\n ...(typeof entry.description === \"string\" && entry.description.trim().length > 0\n ? { description: entry.description.trim() }\n : {}),\n };\n}\n\n/**\n * Parse and validate a raw golden-query payload (typically `JSON.parse` of\n * `.agents/pm/search/eval-queries.json`). Accepts either a bare array of query\n * entries or an object with a `queries` array. Throws {@link EvalQuerySetError}\n * with a precise message when the payload is not an array/object, when\n * `queries` is missing/not an array, when the set is empty, or when any entry\n * fails {@link parseEvalQueryEntry}.\n */\nexport function parseEvalQuerySet(raw: unknown): EvalQuerySet {\n const rawQueries = Array.isArray(raw)\n ? raw\n : typeof raw === \"object\" && raw !== null\n ? (raw as { queries?: unknown }).queries\n : undefined;\n if (!Array.isArray(rawQueries)) {\n throw new EvalQuerySetError('Eval query set must be an array of queries or an object with a \"queries\" array');\n }\n if (rawQueries.length === 0) {\n throw new EvalQuerySetError(\"Eval query set must contain at least one query\");\n }\n return {\n queries: rawQueries.map((entry, index) => parseEvalQueryEntry(entry, index)),\n };\n}\n"],"names":[],"mappings":"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","debugId":"4ed89138-1775-503e-a08f-7e94a0bd24eb"}
|
|
@@ -29,6 +29,17 @@ declare function isKnownNoisyConsoleBreadcrumb(breadcrumb: {
|
|
|
29
29
|
category?: string;
|
|
30
30
|
message?: string;
|
|
31
31
|
}): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Resolves the Sentry performance-tracing sample rate, honouring the standard
|
|
34
|
+
* `SENTRY_TRACES_SAMPLE_RATE` env var when it parses to a fraction in `[0, 1]`.
|
|
35
|
+
*
|
|
36
|
+
* The default (20%) keeps span volume modest for a low-frequency developer CLI
|
|
37
|
+
* while leaving an operational lever for full-trace performance debugging
|
|
38
|
+
* (`SENTRY_TRACES_SAMPLE_RATE=1`) or fully disabling traces (`=0`). Unset,
|
|
39
|
+
* non-numeric, or out-of-range values fall back to the default with no
|
|
40
|
+
* behaviour change for existing installs.
|
|
41
|
+
*/
|
|
42
|
+
declare function resolveTracesSampleRate(): number;
|
|
32
43
|
/**
|
|
33
44
|
* Implements ensure sentry init for the public runtime surface of this module.
|
|
34
45
|
*/
|
|
@@ -44,6 +55,9 @@ export declare const _testOnly: {
|
|
|
44
55
|
isKnownNoisyConsoleBreadcrumb: typeof isKnownNoisyConsoleBreadcrumb;
|
|
45
56
|
scrubString: typeof scrubString;
|
|
46
57
|
scrubEventData: typeof scrubEventData;
|
|
58
|
+
resolveTracesSampleRate: typeof resolveTracesSampleRate;
|
|
59
|
+
KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS: readonly ["[starter-extension] activating", "[starter-extension] all 8 capabilities registered.", "[starter-extension] commands:", "[starter] preflight check for workspace", "[starter] output_format service override active", "[pm-ext-ts-starter] activating", "[pm-ext-ts-starter] all capabilities registered.", "run `pm init` first to initialise a pm workspace"];
|
|
60
|
+
MAX_KNOWN_NOISY_CONSOLE_MESSAGE_PATTERNS: number;
|
|
47
61
|
resetSentryStateForTests(): void;
|
|
48
62
|
};
|
|
49
63
|
export {};
|