@unbrained/pm-cli 2026.7.18 → 2026.7.19
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +17 -0
- package/dist/cli/commands/claim.js +6 -4
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/comments.js +5 -2
- package/dist/cli/commands/comments.js.map +1 -1
- package/dist/cli/commands/context.d.ts +10 -1
- package/dist/cli/commands/context.js +44 -6
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/create.js +15 -4
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/next.js +13 -3
- package/dist/cli/commands/next.js.map +1 -1
- package/dist/cli/commands/update.js +14 -3
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/error-guidance.js +23 -4
- package/dist/cli/error-guidance.js.map +1 -1
- package/dist/cli/extension-command-help.d.ts +11 -0
- package/dist/cli/extension-command-help.js +62 -2
- package/dist/cli/extension-command-help.js.map +1 -1
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +16 -11
- package/dist/cli/main.js.map +1 -1
- package/dist/cli-bundle/bundle-manifest.json +326 -350
- package/dist/cli-bundle/chunks/{append-5YF3TO7I.js → append-MBXHNWSX.js} +5 -5
- package/dist/cli-bundle/chunks/append-XUYF7NON.js +11 -0
- package/dist/cli-bundle/chunks/{chunk-BIRYX32V.js → chunk-2UCG5H6B.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-VE6ZSTQW.js → chunk-2XPDCXK5.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-I3INI567.js → chunk-3EZZTFL2.js} +909 -124
- package/dist/cli-bundle/chunks/chunk-3EZZTFL2.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-GLZKZON6.js → chunk-3HSRP6T2.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-XWBD6DSR.js → chunk-3KPNOZOH.js} +23 -23
- package/dist/cli-bundle/chunks/{chunk-MR4SHYR4.js → chunk-3QNUDDY2.js} +104 -23
- package/dist/cli-bundle/chunks/chunk-3QNUDDY2.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-SIPOACV5.js → chunk-46Z6FAVP.js} +888 -124
- package/dist/cli-bundle/chunks/chunk-46Z6FAVP.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-HO4DLBNK.js → chunk-4M6RZJXF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-RXPQ5Q23.js → chunk-4PSJVGRE.js} +11 -11
- package/dist/cli-bundle/chunks/{chunk-ADXDCAKP.js → chunk-5S6IZXK7.js} +146 -32
- package/dist/cli-bundle/chunks/{chunk-IL5SPRMH.js.map → chunk-5S6IZXK7.js.map} +7 -1
- package/dist/cli-bundle/chunks/chunk-66SRNEBK.js +143 -0
- package/dist/cli-bundle/chunks/chunk-66SRNEBK.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-YFE7JHX3.js → chunk-6BNV3G6C.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-43UMFKCK.js → chunk-6V4T4RD3.js} +23 -23
- package/dist/cli-bundle/chunks/chunk-77XFQRTD.js +140 -0
- package/dist/cli-bundle/chunks/chunk-77XFQRTD.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-EHJFUOXL.js → chunk-7B7IHMLH.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-I7DIDUSP.js → chunk-7CHWLT2J.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-L6FVNR7X.js → chunk-A3GAQLBH.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-B57RJHBZ.js → chunk-A4FVWFZY.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-D52ZN3BF.js → chunk-A5EQPNV7.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-TZAE66GQ.js → chunk-AGEBQRBG.js} +15 -15
- package/dist/cli-bundle/chunks/{chunk-WU3KAN6A.js → chunk-AQUNTB7G.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-OGVTB5VO.js → chunk-AR24KW26.js} +237 -36
- package/dist/cli-bundle/chunks/chunk-AR24KW26.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-XWYQ2LT4.js → chunk-BBGR4FKQ.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-HTXXXF45.js → chunk-BDC4TW4B.js} +98 -24
- package/dist/cli-bundle/chunks/chunk-BDC4TW4B.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-2FUOXSRN.js → chunk-BFJP4VYC.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-633PKXLT.js → chunk-BZKE2O5V.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-XPUTSGJU.js → chunk-CZA2DXCV.js} +230 -36
- package/dist/cli-bundle/chunks/chunk-CZA2DXCV.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-KX62NMZC.js → chunk-D35WYXWC.js} +626 -5
- package/dist/cli-bundle/chunks/chunk-D35WYXWC.js.map +1 -0
- package/dist/cli-bundle/chunks/chunk-DOASIOQR.js +289 -0
- package/dist/cli-bundle/chunks/chunk-DOASIOQR.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-L337QKWJ.js → chunk-DUDLSQFG.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-BVLOMU6O.js → chunk-E7KBMWEF.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-3QDR6ZLU.js → chunk-EAV3P54W.js} +9 -9
- package/dist/cli-bundle/chunks/{chunk-3QDR6ZLU.js.map → chunk-EAV3P54W.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WQXRZMFN.js → chunk-EEECAV5M.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-35FHWD4C.js → chunk-EI3UIMZM.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-RGMWJLXF.js → chunk-EVAN5VJA.js} +8 -5
- package/dist/cli-bundle/chunks/{chunk-RGMWJLXF.js.map → chunk-EVAN5VJA.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-PT7MCCGD.js → chunk-FIUTBFC6.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-7H5NNCJ5.js → chunk-FQF6VVPH.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-6DYOZS6C.js → chunk-FQO5THHM.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-5HGZKQUL.js → chunk-FQODDTE7.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-67RO3H4N.js → chunk-G33XIMRT.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-D53RTYVI.js → chunk-GFZB5CLP.js} +20 -10
- package/dist/cli-bundle/chunks/chunk-GFZB5CLP.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-QWBKN3QC.js → chunk-GKCEEXMA.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-DG2EQRIH.js → chunk-GRDK25BN.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-FXFCFL73.js → chunk-H3YKUVDR.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-IL5SPRMH.js → chunk-IEMXESIS.js} +123 -16
- package/dist/cli-bundle/chunks/chunk-IEMXESIS.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-ARGDWQ4J.js → chunk-IGBBTPM5.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-QPGQNLPI.js → chunk-IR3GOO6E.js} +3842 -4109
- package/dist/cli-bundle/chunks/chunk-IR3GOO6E.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-FY4RLHSC.js → chunk-IRJ6F23W.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-66MKH7SZ.js → chunk-IXG5CMBR.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-F3VC3GOV.js → chunk-JBW2S2C6.js} +2090 -253
- package/dist/cli-bundle/chunks/chunk-JBW2S2C6.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-7UCY6DR5.js → chunk-JPWUZOMR.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-FVNWHUME.js → chunk-K2L6FZBX.js} +8 -8
- package/dist/cli-bundle/chunks/chunk-KGPLSHJD.js +286 -0
- package/dist/cli-bundle/chunks/chunk-KGPLSHJD.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-YQEZWI3R.js → chunk-KZ5AC6B5.js} +5 -3
- package/dist/cli-bundle/chunks/chunk-KZ5AC6B5.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-X2MGQMZO.js → chunk-LT5UWU7H.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-KH6QAHME.js → chunk-M4B4RK4J.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-QRZNCRNA.js → chunk-MI3346YW.js} +377 -240
- package/dist/cli-bundle/chunks/chunk-MI3346YW.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-2XOSFSTH.js → chunk-MQOSMBWV.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-YIIIAKCE.js → chunk-MRXAHR4B.js} +28 -22
- package/dist/cli-bundle/chunks/chunk-MRXAHR4B.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-7R6UIHYY.js → chunk-N2TEEOXJ.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-NTRQLE2R.js → chunk-N7FCFJ76.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-37DRDP2B.js → chunk-NPEYH6CE.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-GKPCTQYG.js → chunk-NTS2RKHN.js} +3942 -4216
- package/dist/cli-bundle/chunks/chunk-NTS2RKHN.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-6VHUGVNP.js → chunk-ODEIDKGW.js} +2062 -246
- package/dist/cli-bundle/chunks/chunk-ODEIDKGW.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-2CXL335K.js → chunk-OK7VSX3N.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-NNANAWFH.js → chunk-OKPZDH43.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-G6MYGULG.js → chunk-OKWJUL6F.js} +6 -6
- package/dist/cli-bundle/chunks/{chunk-HPAYDSR2.js → chunk-P24ZU5QV.js} +27 -21
- package/dist/cli-bundle/chunks/chunk-P24ZU5QV.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-TGBTLGPX.js → chunk-Q4PSG2GV.js} +13 -4
- package/dist/cli-bundle/chunks/{chunk-TGBTLGPX.js.map → chunk-Q4PSG2GV.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-5UKQLQM2.js → chunk-Q5NHJ6RO.js} +6 -4
- package/dist/cli-bundle/chunks/chunk-Q5NHJ6RO.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-D5XHO4Q7.js → chunk-Q6JPYR7I.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-P22HGFFI.js → chunk-QFG4MB7P.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-P22HGFFI.js.map → chunk-QFG4MB7P.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-IE5KRAKN.js → chunk-QQ77W23U.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-M7MVOKVV.js → chunk-QYGK2XQ3.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-646MQXFW.js → chunk-RLLOZAM2.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-646MQXFW.js.map → chunk-RLLOZAM2.js.map} +2 -2
- package/dist/cli-bundle/chunks/{chunk-X5YCTFKT.js → chunk-RWAIRGBC.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-W5E2UUSH.js → chunk-RX53WHFI.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-R5XTTZSJ.js → chunk-SBW7EQC4.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-TM5CIO3F.js → chunk-SGJB6PXA.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-DDFGYUCQ.js → chunk-STBCBDKF.js} +7 -7
- package/dist/cli-bundle/chunks/{chunk-EX7OQT3Y.js → chunk-SUNZKVAH.js} +10 -10
- package/dist/cli-bundle/chunks/{chunk-EX7OQT3Y.js.map → chunk-SUNZKVAH.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-FHOBCGQO.js → chunk-SVAWG7EE.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-6O44IN44.js → chunk-T6MOTLOJ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-HSYV4ZYT.js → chunk-TELI67UP.js} +9 -6
- package/dist/cli-bundle/chunks/{chunk-HSYV4ZYT.js.map → chunk-TELI67UP.js.map} +1 -1
- package/dist/cli-bundle/chunks/{chunk-EWIT5WIC.js → chunk-U6RYD446.js} +11 -11
- package/dist/cli-bundle/chunks/{chunk-E4FXM2XB.js → chunk-UE7LK3RE.js} +5 -5
- package/dist/cli-bundle/chunks/{chunk-N33FD2UI.js → chunk-UNNCT5QY.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-2IPNL3DR.js → chunk-UOIFZ66L.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-LSOWTLEM.js → chunk-UU6EP25G.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-HYTOJW2Q.js → chunk-UW6HCMP2.js} +15 -15
- package/dist/cli-bundle/chunks/{chunk-47HXN6RX.js → chunk-UWAQI3B7.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-YKFHF37B.js → chunk-V4QHAMI5.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-VAHZIPWS.js → chunk-VA3H7VVC.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-XC2HEEOV.js → chunk-VFA5EIEN.js} +21 -11
- package/dist/cli-bundle/chunks/chunk-VFA5EIEN.js.map +1 -0
- package/dist/cli-bundle/chunks/{chunk-TLWJP5BF.js → chunk-VQOG2ETB.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-H5IOT54C.js → chunk-VSQE43NO.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-BDA35QG5.js → chunk-W6IEJXNC.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WACRQ26A.js → chunk-WCBB6VI3.js} +637 -9
- package/dist/cli-bundle/chunks/chunk-WCBB6VI3.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-OWP6QFBV.js → chunk-XDWXPG2E.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-CKX4WOPC.js → chunk-XKVHL3MB.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WL3SS45P.js → chunk-XVB6BATY.js} +3 -3
- package/dist/cli-bundle/chunks/{chunk-NVZ6NVHJ.js → chunk-XXWDEQ6O.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-ILVOOAT4.js → chunk-Y2VSGFT4.js} +8 -8
- package/dist/cli-bundle/chunks/{chunk-NCVT6XEL.js → chunk-YG56M3NE.js} +11 -11
- package/dist/cli-bundle/chunks/{chunk-AFGKSHAM.js → chunk-YGEA4CLH.js} +4 -4
- package/dist/cli-bundle/chunks/{chunk-AXRT7K5V.js → chunk-YIC5NGXF.js} +11 -11
- package/dist/cli-bundle/chunks/{chunk-DHNG452T.js → chunk-ZF52NVRT.js} +396 -245
- package/dist/cli-bundle/chunks/chunk-ZF52NVRT.js.map +7 -0
- package/dist/cli-bundle/chunks/{chunk-XXLXJL7V.js → chunk-ZUCBPXNA.js} +4 -4
- package/dist/cli-bundle/chunks/{close-X3CF6FQP.js → close-7NWA3GLA.js} +5 -5
- package/dist/cli-bundle/chunks/close-ZZCDDWJT.js +12 -0
- package/dist/cli-bundle/chunks/close-many-QCZHFCON.js +23 -0
- package/dist/cli-bundle/chunks/{close-many-J7A5EHOQ.js → close-many-YALQ7AXS.js} +14 -14
- package/dist/cli-bundle/chunks/comments-FMQNYPSZ.js +13 -0
- package/dist/cli-bundle/chunks/{comments-TMHMALA5.js → comments-SQIQ5WYR.js} +7 -7
- package/dist/cli-bundle/chunks/copy-GI3RCVZP.js +9 -0
- package/dist/cli-bundle/chunks/{copy-FWQA5OU4.js → copy-YDAMENCP.js} +4 -4
- package/dist/cli-bundle/chunks/{create-AQ5SIGZC.js → create-JSL6CXU3.js} +11 -9
- package/dist/cli-bundle/chunks/create-LXMLYJNM.js +29 -0
- package/dist/cli-bundle/chunks/delete-5DFAXJNI.js +10 -0
- package/dist/cli-bundle/chunks/{delete-YYYFOSEA.js → delete-IGVOZEU2.js} +4 -4
- package/dist/cli-bundle/chunks/{deps-NIIKXLPB.js → deps-BQAXUQAK.js} +6 -6
- package/dist/cli-bundle/chunks/{deps-MQ4ZIGZB.js → deps-CBPPSS6J.js} +6 -6
- package/dist/cli-bundle/chunks/docs-KCWPLQOV.js +14 -0
- package/dist/cli-bundle/chunks/{docs-53NUGMIQ.js → docs-NS2AZWCN.js} +7 -7
- package/dist/cli-bundle/chunks/{files-3PXGXYDB.js → files-PVWEPT5J.js} +7 -7
- package/dist/cli-bundle/chunks/{files-EGLKHD7O.js → files-XUUBQ76I.js} +7 -7
- package/dist/cli-bundle/chunks/focus-3EJVFI3D.js +10 -0
- package/dist/cli-bundle/chunks/{focus-SRPASFTN.js → focus-DHBHKK3E.js} +5 -5
- package/dist/cli-bundle/chunks/{history-compact-G4DULDCX.js → history-compact-3TNPYVFG.js} +6 -6
- package/dist/cli-bundle/chunks/history-compact-JHYVDYLW.js +16 -0
- package/dist/cli-bundle/chunks/{history-redact-IUSJ6X3E.js → history-redact-ELRL73XN.js} +4 -4
- package/dist/cli-bundle/chunks/{history-redact-THHGRQXV.js → history-redact-KKFDICCF.js} +4 -4
- package/dist/cli-bundle/chunks/{history-repair-LUQWRS7X.js → history-repair-J7WKZFAG.js} +6 -6
- package/dist/cli-bundle/chunks/history-repair-REMI7DDI.js +16 -0
- package/dist/cli-bundle/chunks/learnings-O6V5WDCV.js +13 -0
- package/dist/cli-bundle/chunks/{learnings-2MRNBFJF.js → learnings-X4D6JCCG.js} +7 -7
- package/dist/cli-bundle/chunks/{notes-73JWKWUD.js → notes-UQC6VS6N.js} +7 -7
- package/dist/cli-bundle/chunks/notes-ZSZREWZA.js +13 -0
- package/dist/cli-bundle/chunks/{plan-AZPMCG37.js → plan-5GKRBJJO.js} +12 -10
- package/dist/cli-bundle/chunks/plan-EZW2YDDY.js +26 -0
- package/dist/cli-bundle/chunks/{profile-AVCIIZID.js → profile-5PQAPCLF.js} +10 -10
- package/dist/cli-bundle/chunks/{profile-LFYO3HHX.js → profile-CW4BD3FO.js} +10 -10
- package/dist/cli-bundle/chunks/{register-list-query-UKMF55FT.js → register-list-query-HTDQE6VI.js} +24 -24
- package/dist/cli-bundle/chunks/{register-list-query-MZUF2EEC.js → register-list-query-PHIPDFP2.js} +24 -24
- package/dist/cli-bundle/chunks/{register-mutation-T6RVNJC4.js → register-mutation-BLEWM5I6.js} +32 -32
- package/dist/cli-bundle/chunks/{register-mutation-2PBW2GEX.js → register-mutation-OTYHR7J6.js} +32 -32
- package/dist/cli-bundle/chunks/{register-operations-KHZYR6MG.js → register-operations-AMCUFYEW.js} +38 -40
- package/dist/cli-bundle/chunks/{register-operations-KHZYR6MG.js.map → register-operations-AMCUFYEW.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-operations-WPQ2LWZJ.js → register-operations-MRLHOZYR.js} +36 -38
- package/dist/cli-bundle/chunks/{register-operations-WPQ2LWZJ.js.map → register-operations-MRLHOZYR.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-PGDNOXDQ.js → register-setup-N2FOSWAG.js} +15 -17
- package/dist/cli-bundle/chunks/{register-setup-PGDNOXDQ.js.map → register-setup-N2FOSWAG.js.map} +1 -1
- package/dist/cli-bundle/chunks/{register-setup-TDN7WAO6.js → register-setup-ZVKTDL4G.js} +17 -19
- package/dist/cli-bundle/chunks/{register-setup-TDN7WAO6.js.map → register-setup-ZVKTDL4G.js.map} +1 -1
- package/dist/cli-bundle/chunks/restore-A55MLFAI.js +14 -0
- package/dist/cli-bundle/chunks/{restore-E3PRGDN3.js → restore-HEQAG6EK.js} +6 -6
- package/dist/cli-bundle/chunks/{schema-5JNFQFUW.js → schema-MAXAIHEC.js} +6 -6
- package/dist/cli-bundle/chunks/{schema-TMIW4XZC.js → schema-Q5DAWJ2S.js} +6 -6
- package/dist/cli-bundle/chunks/update-5DTSCWVF.js +23 -0
- package/dist/cli-bundle/chunks/{update-SQYZA3ZW.js → update-DWFXXJKP.js} +15 -13
- package/dist/cli-bundle/chunks/update-many-6T4ZLZS7.js +34 -0
- package/dist/cli-bundle/chunks/update-many-MYRK6VBJ.js +38 -0
- package/dist/cli-bundle/main.js +152 -29
- package/dist/cli-bundle/main.js.map +3 -3
- package/dist/cli-bundle/sdk-runtime.js +72 -75
- package/dist/cli-bundle/sdk-testing.js +8 -8
- package/dist/cli-bundle/sdk.js +288 -642
- package/dist/cli-bundle/sdk.js.map +4 -4
- package/dist/core/extensions/activation-summary.d.ts +2 -0
- package/dist/core/extensions/activation-summary.js +7 -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 +5 -2
- package/dist/core/extensions/capability-usage.js.map +1 -1
- package/dist/core/extensions/extension-hook-runtime.js +3 -2
- package/dist/core/extensions/extension-hook-runtime.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 +38 -1
- package/dist/core/extensions/extension-types.js +3 -2
- package/dist/core/extensions/extension-types.js.map +1 -1
- package/dist/core/extensions/loader.js +36 -2
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/store/item-store.d.ts +4 -1
- package/dist/core/store/item-store.js +3 -3
- package/dist/core/store/item-store.js.map +1 -1
- package/dist/core/store/paths.d.ts +2 -0
- package/dist/core/store/paths.js +26 -3
- package/dist/core/store/paths.js.map +1 -1
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
- package/dist/sdk/compose.d.ts +3 -0
- package/dist/sdk/compose.js +14 -2
- package/dist/sdk/compose.js.map +1 -1
- package/dist/sdk/dependencies.js +3 -3
- package/dist/sdk/dependencies.js.map +1 -1
- package/dist/sdk/extension-command-context.d.ts +10 -0
- package/dist/sdk/extension-command-context.js +30 -0
- package/dist/sdk/extension-command-context.js.map +1 -0
- package/dist/sdk/graph/assembly.js +14 -4
- package/dist/sdk/graph/assembly.js.map +1 -1
- package/dist/sdk/graph/index.d.ts +1 -0
- package/dist/sdk/graph/index.js +3 -2
- package/dist/sdk/graph/index.js.map +1 -1
- package/dist/sdk/graph/mutation-advisory.d.ts +20 -0
- package/dist/sdk/graph/mutation-advisory.js +80 -0
- package/dist/sdk/graph/mutation-advisory.js.map +1 -0
- package/dist/sdk/graph/run.d.ts +5 -1
- package/dist/sdk/graph/run.js +11 -3
- package/dist/sdk/graph/run.js.map +1 -1
- package/dist/sdk/index.d.ts +4 -1
- package/dist/sdk/index.js +5 -2
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/ownership-source.d.ts +2 -0
- package/dist/sdk/ownership-source.js +22 -0
- package/dist/sdk/ownership-source.js.map +1 -0
- package/dist/sdk/relationship-history.d.ts +38 -0
- package/dist/sdk/relationship-history.js +60 -2
- package/dist/sdk/relationship-history.js.map +1 -1
- package/dist/sdk/relationships.js +49 -8
- package/dist/sdk/relationships.js.map +1 -1
- package/dist/sdk/runtime-input.js +3 -2
- package/dist/sdk/runtime-input.js.map +1 -1
- package/dist/sdk/runtime.d.ts +2 -0
- package/dist/sdk/runtime.js +19 -2
- package/dist/sdk/runtime.js.map +1 -1
- package/dist/sdk/tracker-root-discovery.d.ts +6 -0
- package/dist/sdk/tracker-root-discovery.js +10 -0
- package/dist/sdk/tracker-root-discovery.js.map +1 -0
- package/dist/sdk/workspace-transaction.d.ts +83 -0
- package/dist/sdk/workspace-transaction.js +364 -0
- package/dist/sdk/workspace-transaction.js.map +1 -0
- package/docs/AGENT_UX_CONTRACTS.md +41 -0
- package/docs/EXTENSIONS.md +4 -4
- package/docs/README.md +1 -0
- package/docs/SDK.md +102 -1
- package/marketplace.json +2 -2
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/GAP_REPORT.md +31 -0
- package/packages/pm-vcs/README.md +62 -0
- package/packages/pm-vcs/extensions/vcs/index.ts +745 -0
- package/packages/pm-vcs/extensions/vcs/manifest.json +19 -0
- package/packages/pm-vcs/extensions/vcs/package.json +3 -0
- package/packages/pm-vcs/package.json +55 -0
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/dist/cli-bundle/chunks/append-JHO5K6RP.js +0 -11
- package/dist/cli-bundle/chunks/chunk-2BX74BAS.js +0 -125
- package/dist/cli-bundle/chunks/chunk-2BX74BAS.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-3CUQZNQ6.js +0 -672
- package/dist/cli-bundle/chunks/chunk-3CUQZNQ6.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-5UKQLQM2.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-6VHUGVNP.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-74FKFFXO.js +0 -172
- package/dist/cli-bundle/chunks/chunk-74FKFFXO.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-ADXDCAKP.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-BAP7G3N2.js +0 -178
- package/dist/cli-bundle/chunks/chunk-BAP7G3N2.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-D53RTYVI.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-DHNG452T.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-EY7ZE3TG.js +0 -1831
- package/dist/cli-bundle/chunks/chunk-EY7ZE3TG.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-F3VC3GOV.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-FL4D53ND.js +0 -162
- package/dist/cli-bundle/chunks/chunk-FL4D53ND.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-GKPCTQYG.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-HPAYDSR2.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-HTXXXF45.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-I3INI567.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-KX62NMZC.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-L5BTTDU5.js +0 -662
- package/dist/cli-bundle/chunks/chunk-L5BTTDU5.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-MR4SHYR4.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-OGVTB5VO.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-QPGQNLPI.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-QRZNCRNA.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-RC4UOUXA.js +0 -122
- package/dist/cli-bundle/chunks/chunk-RC4UOUXA.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-RTBX3C4C.js +0 -1841
- package/dist/cli-bundle/chunks/chunk-RTBX3C4C.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-SIPOACV5.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-WACRQ26A.js.map +0 -7
- package/dist/cli-bundle/chunks/chunk-XC2HEEOV.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-XPUTSGJU.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-YIIIAKCE.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-YJSURTBB.js +0 -175
- package/dist/cli-bundle/chunks/chunk-YJSURTBB.js.map +0 -1
- package/dist/cli-bundle/chunks/chunk-YQEZWI3R.js.map +0 -7
- package/dist/cli-bundle/chunks/close-GPD7DTJV.js +0 -12
- package/dist/cli-bundle/chunks/close-many-NQLYGPYW.js +0 -23
- package/dist/cli-bundle/chunks/comments-2AOZQ5D2.js +0 -13
- package/dist/cli-bundle/chunks/copy-N3LCQBMC.js +0 -9
- package/dist/cli-bundle/chunks/create-KOGQ3JKD.js +0 -27
- package/dist/cli-bundle/chunks/delete-6G3MBZ6S.js +0 -10
- package/dist/cli-bundle/chunks/docs-OWRGDMNY.js +0 -14
- package/dist/cli-bundle/chunks/focus-KZLIA6WS.js +0 -10
- package/dist/cli-bundle/chunks/history-compact-HHIUOMZ7.js +0 -16
- package/dist/cli-bundle/chunks/history-repair-KG7SWXI6.js +0 -16
- package/dist/cli-bundle/chunks/learnings-ZVHSALJY.js +0 -13
- package/dist/cli-bundle/chunks/notes-BAKUL5DJ.js +0 -13
- package/dist/cli-bundle/chunks/plan-LEAGLPGP.js +0 -24
- package/dist/cli-bundle/chunks/restore-KIUYTAEJ.js +0 -14
- package/dist/cli-bundle/chunks/update-XZJYS5X7.js +0 -21
- package/dist/cli-bundle/chunks/update-many-R24B3GBK.js +0 -36
- package/dist/cli-bundle/chunks/update-many-WQ3R3J6N.js +0 -32
- /package/dist/cli-bundle/chunks/{append-5YF3TO7I.js.map → append-MBXHNWSX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{append-JHO5K6RP.js.map → append-XUYF7NON.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BIRYX32V.js.map → chunk-2UCG5H6B.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VE6ZSTQW.js.map → chunk-2XPDCXK5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-GLZKZON6.js.map → chunk-3HSRP6T2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-XWBD6DSR.js.map → chunk-3KPNOZOH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HO4DLBNK.js.map → chunk-4M6RZJXF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-RXPQ5Q23.js.map → chunk-4PSJVGRE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-YFE7JHX3.js.map → chunk-6BNV3G6C.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-43UMFKCK.js.map → chunk-6V4T4RD3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-EHJFUOXL.js.map → chunk-7B7IHMLH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-I7DIDUSP.js.map → chunk-7CHWLT2J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-L6FVNR7X.js.map → chunk-A3GAQLBH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-B57RJHBZ.js.map → chunk-A4FVWFZY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-D52ZN3BF.js.map → chunk-A5EQPNV7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TZAE66GQ.js.map → chunk-AGEBQRBG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WU3KAN6A.js.map → chunk-AQUNTB7G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-XWYQ2LT4.js.map → chunk-BBGR4FKQ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2FUOXSRN.js.map → chunk-BFJP4VYC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-633PKXLT.js.map → chunk-BZKE2O5V.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-L337QKWJ.js.map → chunk-DUDLSQFG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BVLOMU6O.js.map → chunk-E7KBMWEF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WQXRZMFN.js.map → chunk-EEECAV5M.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-35FHWD4C.js.map → chunk-EI3UIMZM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-PT7MCCGD.js.map → chunk-FIUTBFC6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7H5NNCJ5.js.map → chunk-FQF6VVPH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-6DYOZS6C.js.map → chunk-FQO5THHM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-5HGZKQUL.js.map → chunk-FQODDTE7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-67RO3H4N.js.map → chunk-G33XIMRT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-QWBKN3QC.js.map → chunk-GKCEEXMA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DG2EQRIH.js.map → chunk-GRDK25BN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FXFCFL73.js.map → chunk-H3YKUVDR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ARGDWQ4J.js.map → chunk-IGBBTPM5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FY4RLHSC.js.map → chunk-IRJ6F23W.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-66MKH7SZ.js.map → chunk-IXG5CMBR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7UCY6DR5.js.map → chunk-JPWUZOMR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FVNWHUME.js.map → chunk-K2L6FZBX.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-X2MGQMZO.js.map → chunk-LT5UWU7H.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-KH6QAHME.js.map → chunk-M4B4RK4J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2XOSFSTH.js.map → chunk-MQOSMBWV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-7R6UIHYY.js.map → chunk-N2TEEOXJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NTRQLE2R.js.map → chunk-N7FCFJ76.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-37DRDP2B.js.map → chunk-NPEYH6CE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2CXL335K.js.map → chunk-OK7VSX3N.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NNANAWFH.js.map → chunk-OKPZDH43.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-G6MYGULG.js.map → chunk-OKWJUL6F.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-D5XHO4Q7.js.map → chunk-Q6JPYR7I.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-IE5KRAKN.js.map → chunk-QQ77W23U.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-M7MVOKVV.js.map → chunk-QYGK2XQ3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-X5YCTFKT.js.map → chunk-RWAIRGBC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-W5E2UUSH.js.map → chunk-RX53WHFI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-R5XTTZSJ.js.map → chunk-SBW7EQC4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TM5CIO3F.js.map → chunk-SGJB6PXA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-DDFGYUCQ.js.map → chunk-STBCBDKF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-FHOBCGQO.js.map → chunk-SVAWG7EE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-6O44IN44.js.map → chunk-T6MOTLOJ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-EWIT5WIC.js.map → chunk-U6RYD446.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-E4FXM2XB.js.map → chunk-UE7LK3RE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-N33FD2UI.js.map → chunk-UNNCT5QY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-2IPNL3DR.js.map → chunk-UOIFZ66L.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-LSOWTLEM.js.map → chunk-UU6EP25G.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-HYTOJW2Q.js.map → chunk-UW6HCMP2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-47HXN6RX.js.map → chunk-UWAQI3B7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-YKFHF37B.js.map → chunk-V4QHAMI5.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-VAHZIPWS.js.map → chunk-VA3H7VVC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-TLWJP5BF.js.map → chunk-VQOG2ETB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-H5IOT54C.js.map → chunk-VSQE43NO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-BDA35QG5.js.map → chunk-W6IEJXNC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-OWP6QFBV.js.map → chunk-XDWXPG2E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-CKX4WOPC.js.map → chunk-XKVHL3MB.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-WL3SS45P.js.map → chunk-XVB6BATY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NVZ6NVHJ.js.map → chunk-XXWDEQ6O.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-ILVOOAT4.js.map → chunk-Y2VSGFT4.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-NCVT6XEL.js.map → chunk-YG56M3NE.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AFGKSHAM.js.map → chunk-YGEA4CLH.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-AXRT7K5V.js.map → chunk-YIC5NGXF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{chunk-XXLXJL7V.js.map → chunk-ZUCBPXNA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-X3CF6FQP.js.map → close-7NWA3GLA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-GPD7DTJV.js.map → close-ZZCDDWJT.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-NQLYGPYW.js.map → close-many-QCZHFCON.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{close-many-J7A5EHOQ.js.map → close-many-YALQ7AXS.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-2AOZQ5D2.js.map → comments-FMQNYPSZ.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{comments-TMHMALA5.js.map → comments-SQIQ5WYR.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-N3LCQBMC.js.map → copy-GI3RCVZP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{copy-FWQA5OU4.js.map → copy-YDAMENCP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-AQ5SIGZC.js.map → create-JSL6CXU3.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{create-KOGQ3JKD.js.map → create-LXMLYJNM.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-6G3MBZ6S.js.map → delete-5DFAXJNI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{delete-YYYFOSEA.js.map → delete-IGVOZEU2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-NIIKXLPB.js.map → deps-BQAXUQAK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{deps-MQ4ZIGZB.js.map → deps-CBPPSS6J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-OWRGDMNY.js.map → docs-KCWPLQOV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{docs-53NUGMIQ.js.map → docs-NS2AZWCN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-3PXGXYDB.js.map → files-PVWEPT5J.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{files-EGLKHD7O.js.map → files-XUUBQ76I.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-KZLIA6WS.js.map → focus-3EJVFI3D.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{focus-SRPASFTN.js.map → focus-DHBHKK3E.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-G4DULDCX.js.map → history-compact-3TNPYVFG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-compact-HHIUOMZ7.js.map → history-compact-JHYVDYLW.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-IUSJ6X3E.js.map → history-redact-ELRL73XN.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-redact-THHGRQXV.js.map → history-redact-KKFDICCF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-LUQWRS7X.js.map → history-repair-J7WKZFAG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{history-repair-KG7SWXI6.js.map → history-repair-REMI7DDI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-ZVHSALJY.js.map → learnings-O6V5WDCV.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{learnings-2MRNBFJF.js.map → learnings-X4D6JCCG.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-73JWKWUD.js.map → notes-UQC6VS6N.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{notes-BAKUL5DJ.js.map → notes-ZSZREWZA.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-AZPMCG37.js.map → plan-5GKRBJJO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{plan-LEAGLPGP.js.map → plan-EZW2YDDY.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-AVCIIZID.js.map → profile-5PQAPCLF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{profile-LFYO3HHX.js.map → profile-CW4BD3FO.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-list-query-UKMF55FT.js.map → register-list-query-HTDQE6VI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-list-query-MZUF2EEC.js.map → register-list-query-PHIPDFP2.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-mutation-T6RVNJC4.js.map → register-mutation-BLEWM5I6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{register-mutation-2PBW2GEX.js.map → register-mutation-OTYHR7J6.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-KIUYTAEJ.js.map → restore-A55MLFAI.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{restore-E3PRGDN3.js.map → restore-HEQAG6EK.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-5JNFQFUW.js.map → schema-MAXAIHEC.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{schema-TMIW4XZC.js.map → schema-Q5DAWJ2S.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-XZJYS5X7.js.map → update-5DTSCWVF.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-SQYZA3ZW.js.map → update-DWFXXJKP.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-WQ3R3J6N.js.map → update-many-6T4ZLZS7.js.map} +0 -0
- /package/dist/cli-bundle/chunks/{update-many-R24B3GBK.js.map → update-many-MYRK6VBJ.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../../cli/commands/aggregate.ts","../../../../../../../../sdk/graph/traversal.ts","../../../../../../../../sdk/graph/analytics.ts","../../../../../../../../sdk/graph/governance.ts","../../../../../../../../sdk/graph/remediation.ts","../../../../../../../../sdk/graph/run.ts","../../../../../../../../sdk/item-children.ts","../../../../../../../../sdk/item-schedule.ts","../../../../../../../../cli/commands/get.ts","../../../../../../../../sdk/query/search.ts","../../../../../../../../core/shared/text-normalization.ts","../../../../../../../../core/search/relevance.ts","../../../../../../../../core/search/bm25.ts","../../../../../../../../sdk/query/search-rendering.ts","../../../../../../../../sdk/query/search-pagination.ts","../../../../../../../../sdk/eval.ts","../../../../../../../../core/search/eval.ts"],"sourcesContent":["/**\n * @module cli/commands/aggregate\n *\n * Implements the pm aggregate command surface and its agent-facing runtime behavior.\n */\nimport { EXIT_CODE } from \"../../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport { splitCommaList } from \"../../core/shared/split-comma-list.js\";\nimport { nowIso } from \"../../core/shared/time.js\";\nimport { normalizeStatusInput } from \"../../core/item/status.js\";\nimport { parseStatusFilterCsv } from \"../../core/item/status-filter.js\";\nimport {\n resolveRuntimeFieldRegistry,\n resolveRuntimeStatusRegistry,\n type RuntimeStatusRegistry,\n} from \"../../core/schema/runtime-schema.js\";\nimport { resolvePmRoot } from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport { type ItemStatus } from \"../../types/index.js\";\nimport { buildListQueryFilters } from \"./list-filter-shared.js\";\nimport { runList } from \"./list.js\";\n\ntype AggregateGroupField =\n | \"parent\"\n | \"type\"\n | \"priority\"\n | \"status\"\n | \"assignee\"\n | \"tags\"\n | \"sprint\"\n | \"release\";\ntype AggregateGroupValue = string | number | null;\ntype AggregateGroupRecord = Partial<\n Record<AggregateGroupField, AggregateGroupValue>\n>;\ntype AggregateListedItem = {\n type: string;\n status: ItemStatus;\n priority: number;\n parent?: string;\n assignee?: string;\n tags: string[];\n sprint?: string;\n release?: string;\n};\n\nconst AGGREGATE_GROUP_FIELDS: AggregateGroupField[] = [\n \"parent\",\n \"type\",\n \"priority\",\n \"status\",\n \"assignee\",\n \"tags\",\n \"sprint\",\n \"release\",\n];\n\n/** Documents the aggregate options payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateOptions {\n /** Value that configures or reports group by for this contract. */\n groupBy?: string;\n /** Value that configures or reports count for this contract. */\n count?: boolean;\n /** Value that configures or reports completion for this contract. */\n completion?: boolean;\n /** Value that configures or reports sum for this contract. */\n sum?: string;\n /** Value that configures or reports avg for this contract. */\n avg?: string;\n /** Value that configures or reports include unparented for this contract. */\n includeUnparented?: boolean;\n /** Lifecycle state reported for status. */\n status?: string;\n /** Schema type that determines the shape and validation rules for this value. */\n type?: string;\n /** Value that configures or reports tag for this contract. */\n tag?: string;\n /** Value that configures or reports priority for this contract. */\n priority?: string;\n /** Value that configures or reports deadline before for this contract. */\n deadlineBefore?: string;\n /** Value that configures or reports deadline after for this contract. */\n deadlineAfter?: string;\n /** Value that configures or reports assignee for this contract. */\n assignee?: string;\n /** Value that configures or reports assignee filter for this contract. */\n assigneeFilter?: string;\n /** Value that configures or reports parent for this contract. */\n parent?: string;\n /** Value that configures or reports sprint for this contract. */\n sprint?: string;\n /** Value that configures or reports release for this contract. */\n release?: string;\n}\n\n/** Documents the aggregate row payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateRow {\n /** Value that configures or reports group for this contract. */\n group: AggregateGroupRecord;\n /** Human-readable display label for this group. Blank/null group values render with an explicit \"(unassigned)\"-style label (per dimension) so terminal and grep-based consumers are never faced with an ambiguous empty key. The structured `group` record keeps the raw null for machine consumers. */\n group_label: string;\n /** Value that configures or reports count for this contract. */\n count: number;\n /** Value that configures or reports open for this contract. */\n open?: number;\n /** Value that configures or reports in progress for this contract. */\n in_progress?: number;\n /** Value that configures or reports closed for this contract. */\n closed?: number;\n /** Value that configures or reports other for this contract. */\n other?: number;\n /** Value that configures or reports completion pct for this contract. */\n completion_pct?: number;\n /** Number of null entries represented by this result. */\n null_count?: number;\n /** Value that configures or reports sum for this contract. */\n sum?: number | null;\n /** Value that configures or reports avg for this contract. */\n avg?: number | null;\n}\n\n/** Documents the aggregate result payload exchanged by command, SDK, and package integrations. */\nexport interface AggregateResult {\n /** Value that configures or reports groups for this contract. */\n groups: AggregateRow[];\n /** Value that configures or reports count for this contract. */\n count: number;\n /** Value that configures or reports totals for this contract. */\n totals: {\n items_considered: number;\n items_grouped: number;\n items_skipped_unparented: number;\n };\n /** Value that configures or reports filters for this contract. */\n filters: {\n group_by: AggregateGroupField[];\n count: boolean;\n completion: boolean;\n sum?: string | null;\n avg?: string | null;\n numeric_field?: string | null;\n include_unparented: boolean;\n status: ItemStatus | null;\n type: string | null;\n tag: string | null;\n priority: string | null;\n deadline_before: string | null;\n deadline_after: string | null;\n assignee: string | null;\n assignee_filter: string | null;\n parent: string | null;\n sprint: string | null;\n release: string | null;\n };\n /** Value that configures or reports now for this contract. */\n now: string;\n /** Value that configures or reports warnings for this contract. */\n warnings?: string[];\n}\n\nfunction parseStatus(\n raw: string | undefined,\n statusRegistry: RuntimeStatusRegistry,\n): ItemStatus | undefined {\n const statuses = parseStatusFilterCsv(raw, statusRegistry, {\n strict: true,\n flagLabel: \"--status\",\n });\n if (!statuses || statuses.length === 0) {\n return undefined;\n }\n if (statuses.length > 1) {\n throw new PmCliError(\n 'Aggregate --status accepts one status, or the standalone \"all\" sentinel.',\n EXIT_CODE.USAGE,\n );\n }\n return statuses[0];\n}\n\ninterface NumericAggregation {\n field: string;\n sum: boolean;\n avg: boolean;\n}\n\nfunction parseNumericAggregation(\n options: AggregateOptions,\n allowedFields: readonly string[] = [\"estimate\", \"estimated_minutes\", \"priority\"],\n): NumericAggregation | null {\n const sumField = options.sum?.trim();\n const avgField = options.avg?.trim();\n const normalizedSum = sumField && sumField.length > 0 ? sumField : undefined;\n const normalizedAvg = avgField && avgField.length > 0 ? avgField : undefined;\n if (!normalizedSum && !normalizedAvg) {\n return null;\n }\n if (normalizedSum && normalizedAvg && normalizedSum !== normalizedAvg) {\n throw new PmCliError(\n \"Aggregate --sum and --avg must target the same numeric field\",\n EXIT_CODE.USAGE,\n );\n }\n const field = normalizedSum ?? normalizedAvg!;\n if (!allowedFields.includes(field)) {\n throw new PmCliError(\n `Aggregate numeric field \"${field}\" is not registered. Allowed: ${allowedFields.join(\", \")}`,\n EXIT_CODE.USAGE,\n );\n }\n return {\n field,\n sum: normalizedSum !== undefined,\n avg: normalizedAvg !== undefined,\n };\n}\n\nfunction parseGroupBy(raw: string | undefined): AggregateGroupField[] {\n const value = raw?.trim() ?? \"status\";\n if (value.length === 0) {\n throw new PmCliError(\n \"--group-by requires at least one field name\",\n EXIT_CODE.USAGE,\n );\n }\n const requested = splitCommaList(value);\n if (requested.length === 0) {\n throw new PmCliError(\n \"--group-by requires a comma-separated list of fields\",\n EXIT_CODE.USAGE,\n );\n }\n for (const field of requested) {\n if (!AGGREGATE_GROUP_FIELDS.includes(field as AggregateGroupField)) {\n throw new PmCliError(\n `Aggregate group fields must be one of ${AGGREGATE_GROUP_FIELDS.join(\"|\")}; received \"${field}\"`,\n EXIT_CODE.USAGE,\n );\n }\n }\n return requested as AggregateGroupField[];\n}\n\nfunction normalizeTagGroupValue(tags: string[]): string | null {\n const normalized = [\n ...new Set(\n tags\n .map((tag) => tag.trim().toLowerCase())\n .filter((tag) => tag.length > 0),\n ),\n ].sort((left, right) => left.localeCompare(right));\n if (normalized.length === 0) {\n return null;\n }\n return normalized.join(\",\");\n}\n\nfunction resolveGroupValue(\n field: AggregateGroupField,\n item: AggregateListedItem,\n): AggregateGroupValue {\n switch (field) {\n case \"parent\":\n return item.parent ?? null;\n case \"type\":\n return item.type;\n case \"priority\":\n return item.priority;\n case \"status\":\n return item.status;\n case \"assignee\":\n return item.assignee ?? null;\n case \"tags\":\n return normalizeTagGroupValue(item.tags);\n case \"sprint\":\n return item.sprint ?? null;\n case \"release\":\n return item.release ?? null;\n default:\n return null;\n }\n}\n\nfunction compareNullableGroupValue(\n left: AggregateGroupValue | undefined,\n right: AggregateGroupValue | undefined,\n): number {\n const leftValue = left ?? null;\n const rightValue = right ?? null;\n if (leftValue === rightValue) {\n return 0;\n }\n if (leftValue === null) {\n return 1;\n }\n if (rightValue === null) {\n return -1;\n }\n if (typeof leftValue === \"number\" && typeof rightValue === \"number\") {\n return leftValue - rightValue;\n }\n return String(leftValue).localeCompare(String(rightValue));\n}\n\nfunction buildGroupKey(\n groupBy: AggregateGroupField[],\n group: AggregateGroupRecord,\n): string {\n return groupBy\n .map((field) => `${field}:${JSON.stringify(group[field] ?? null)}`)\n .join(\"|\");\n}\n\n/** Explicit display label for an empty/blank group value, keyed by dimension. */\nconst EMPTY_AGGREGATE_GROUP_LABELS: Record<AggregateGroupField, string> = {\n parent: \"(unparented)\",\n type: \"(untyped)\",\n priority: \"(no priority)\",\n status: \"(no status)\",\n assignee: \"(unassigned)\",\n tags: \"(untagged)\",\n sprint: \"(no sprint)\",\n release: \"(no release)\",\n};\n\n/** Render a single group field's value, substituting an explicit label for null. */\nfunction formatGroupFieldLabel(\n field: AggregateGroupField,\n value: AggregateGroupValue | undefined,\n): string {\n if (value === null || value === undefined || value === \"\") {\n return EMPTY_AGGREGATE_GROUP_LABELS[field];\n }\n return String(value);\n}\n\n/** Build the human-readable label for an aggregate row. Single-field grouping yields the bare (possibly substituted) value; multi-field grouping joins each \"field=value\" pair so composite groups stay unambiguous. */\nfunction buildGroupLabel(\n groupBy: AggregateGroupField[],\n group: AggregateGroupRecord,\n): string {\n if (groupBy.length === 1) {\n return formatGroupFieldLabel(groupBy[0], group[groupBy[0]]);\n }\n return groupBy\n .map((field) => `${field}=${formatGroupFieldLabel(field, group[field])}`)\n .join(\" | \");\n}\n\nfunction compareAggregateRows(\n left: AggregateRow,\n right: AggregateRow,\n groupBy: AggregateGroupField[],\n): number {\n for (const field of groupBy) {\n const byField = compareNullableGroupValue(\n left.group[field],\n right.group[field],\n );\n if (byField !== 0) {\n return byField;\n }\n }\n return 0;\n}\n\nfunction readNumericAggregateValue(\n item: AggregateListedItem,\n field: string,\n): number | null {\n const source = item as unknown as Record<string, unknown>;\n const raw = source[field];\n if (typeof raw === \"number\" && Number.isFinite(raw)) {\n return raw;\n }\n if (typeof raw === \"string\") {\n const trimmed = raw.trim();\n if (trimmed.length === 0) {\n return null;\n }\n const parsed = Number(trimmed);\n if (Number.isFinite(parsed)) {\n return parsed;\n }\n }\n return null;\n}\n\ninterface AggregateAccumulator {\n /** group_label is derived once at finalization, so the accumulator omits it. */\n row: Omit<AggregateRow, \"group_label\">;\n numeric_count: number;\n numeric_sum: number;\n null_count: number;\n open_count: number;\n in_progress_count: number;\n closed_count: number;\n other_count: number;\n}\n\nfunction completionPct(closed: number, total: number): number {\n if (total <= 0) {\n return 0;\n }\n return Math.round((closed / total) * 10000) / 100;\n}\n\nfunction updateCompletionCounts(\n accumulator: AggregateAccumulator,\n status: ItemStatus,\n statusRegistry: RuntimeStatusRegistry,\n): void {\n const normalizedStatus =\n normalizeStatusInput(String(status), statusRegistry) ?? status;\n if (normalizedStatus === statusRegistry.open_status) {\n accumulator.open_count += 1;\n return;\n }\n if (\n normalizedStatus === \"in_progress\" ||\n (statusRegistry.active_statuses.has(normalizedStatus) &&\n normalizedStatus !== statusRegistry.open_status)\n ) {\n accumulator.in_progress_count += 1;\n return;\n }\n if (\n statusRegistry.terminal_done_statuses.has(normalizedStatus) ||\n normalizedStatus === statusRegistry.close_status\n ) {\n accumulator.closed_count += 1;\n return;\n }\n accumulator.other_count += 1;\n}\n\nfunction createAggregateAccumulator(\n group: AggregateGroupRecord,\n numericValue: number | null,\n): AggregateAccumulator {\n return {\n row: {\n group,\n count: 1,\n },\n numeric_count: numericValue === null ? 0 : 1,\n numeric_sum: numericValue ?? 0,\n null_count: numericValue === null ? 1 : 0,\n open_count: 0,\n in_progress_count: 0,\n closed_count: 0,\n other_count: 0,\n };\n}\n\nfunction updateNumericAggregation(\n accumulator: AggregateAccumulator,\n numericValue: number | null,\n): void {\n if (numericValue === null) {\n accumulator.null_count += 1;\n return;\n }\n accumulator.numeric_count += 1;\n accumulator.numeric_sum += numericValue;\n}\n\nfunction updateAggregateAccumulator(params: {\n accumulator: AggregateAccumulator;\n item: AggregateListedItem;\n statusRegistry: RuntimeStatusRegistry;\n includeCompletion: boolean;\n numericAggregation: NumericAggregation | null;\n numericValue: number | null;\n}): void {\n params.accumulator.row.count += 1;\n if (params.includeCompletion) {\n updateCompletionCounts(\n params.accumulator,\n params.item.status,\n params.statusRegistry,\n );\n }\n if (params.numericAggregation !== null) {\n updateNumericAggregation(params.accumulator, params.numericValue);\n }\n}\n\nfunction buildAggregateGroup(\n groupBy: AggregateGroupField[],\n item: AggregateListedItem,\n): AggregateGroupRecord {\n const group: AggregateGroupRecord = {};\n for (const field of groupBy) {\n group[field] = resolveGroupValue(field, item);\n }\n return group;\n}\n\nfunction finalizeAggregateRow(\n entry: AggregateAccumulator,\n groupBy: AggregateGroupField[],\n includeCompletion: boolean,\n numericAggregation: NumericAggregation | null,\n): AggregateRow {\n const row: AggregateRow = {\n ...entry.row,\n group_label: buildGroupLabel(groupBy, entry.row.group),\n };\n if (includeCompletion) {\n row.open = entry.open_count;\n row.in_progress = entry.in_progress_count;\n row.closed = entry.closed_count;\n row.other = entry.other_count;\n row.completion_pct = completionPct(entry.closed_count, entry.row.count);\n }\n if (numericAggregation !== null) {\n row.null_count = entry.null_count;\n if (numericAggregation.sum) {\n row.sum = entry.numeric_sum;\n }\n if (numericAggregation.avg) {\n row.avg =\n entry.numeric_count === 0\n ? null\n : entry.numeric_sum / entry.numeric_count;\n }\n }\n return row;\n}\n\nfunction buildAggregateFilters(params: {\n groupBy: AggregateGroupField[];\n includeCompletion: boolean;\n includeUnparented: boolean;\n status: ItemStatus | undefined;\n options: AggregateOptions;\n numericAggregation: NumericAggregation | null;\n}): AggregateResult[\"filters\"] {\n return {\n group_by: params.groupBy,\n count: true,\n completion: params.includeCompletion,\n include_unparented: params.includeUnparented,\n status: params.status ?? null,\n type: params.options.type ?? null,\n tag: params.options.tag ?? null,\n priority: params.options.priority ?? null,\n deadline_before: params.options.deadlineBefore ?? null,\n deadline_after: params.options.deadlineAfter ?? null,\n assignee: params.options.assignee ?? null,\n assignee_filter: params.options.assigneeFilter ?? null,\n parent: params.options.parent ?? null,\n sprint: params.options.sprint ?? null,\n release: params.options.release ?? null,\n ...(params.numericAggregation !== null\n ? {\n sum: params.options.sum ?? null,\n avg: params.options.avg ?? null,\n numeric_field: params.numericAggregation.field,\n }\n : {}),\n };\n}\n\n/** Implements run aggregate for the public runtime surface of this module. */\nexport async function runAggregate(\n options: AggregateOptions,\n global: GlobalOptions,\n): Promise<AggregateResult> {\n if (options.count === false) {\n throw new PmCliError(\n \"Aggregate grouped counts are always enabled; omit count=false.\",\n EXIT_CODE.USAGE,\n );\n }\n\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n const settings = await readSettings(pmRoot);\n const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);\n const numericFields = [\n \"estimate\",\n \"estimated_minutes\",\n \"priority\",\n ...resolveRuntimeFieldRegistry(settings.schema).definitions\n .filter((definition) => definition.type === \"number\")\n .map((definition) => definition.metadata_key),\n ];\n const groupBy = parseGroupBy(options.groupBy);\n const status = parseStatus(options.status, statusRegistry);\n const numericAggregation = parseNumericAggregation(\n options,\n [...new Set(numericFields)].sort((left, right) => left.localeCompare(right)),\n );\n const includeCompletion = options.completion === true;\n const includeUnparented = options.includeUnparented === true;\n\n const listed = await runList(status, buildListQueryFilters(options), global);\n\n const grouped = new Map<string, AggregateAccumulator>();\n let skippedUnparented = 0;\n let groupedItemCount = 0;\n\n for (const listedItem of listed.items) {\n const item = listedItem as AggregateListedItem;\n const group = buildAggregateGroup(groupBy, item);\n if (\n groupBy.includes(\"parent\") &&\n group.parent === null &&\n !includeUnparented\n ) {\n skippedUnparented += 1;\n continue;\n }\n const key = buildGroupKey(groupBy, group);\n const existing = grouped.get(key);\n const numericValue =\n numericAggregation === null\n ? null\n : readNumericAggregateValue(item, numericAggregation.field);\n if (existing) {\n updateAggregateAccumulator({\n accumulator: existing,\n item,\n statusRegistry,\n includeCompletion,\n numericAggregation,\n numericValue,\n });\n } else {\n const accumulator = createAggregateAccumulator(group, numericValue);\n if (includeCompletion) {\n updateCompletionCounts(accumulator, item.status, statusRegistry);\n }\n grouped.set(key, accumulator);\n }\n groupedItemCount += 1;\n }\n\n const groups = [...grouped.values()]\n .map((entry) =>\n finalizeAggregateRow(\n entry,\n groupBy,\n includeCompletion,\n numericAggregation,\n ),\n )\n .sort((left, right) => compareAggregateRows(left, right, groupBy));\n const warnings =\n listed.warnings && listed.warnings.length > 0 ? listed.warnings : undefined;\n\n return {\n groups,\n count: groups.length,\n totals: {\n items_considered: listed.items.length,\n items_grouped: groupedItemCount,\n items_skipped_unparented: skippedUnparented,\n },\n filters: buildAggregateFilters({\n groupBy,\n includeCompletion,\n includeUnparented,\n status,\n options,\n numericAggregation,\n }),\n now: nowIso(),\n ...(warnings ? { warnings } : {}),\n };\n}\n\n/** Public contract for test only aggregate command, shared by SDK and presentation-layer consumers. */\nexport const _testOnlyAggregateCommand = {\n buildGroupKey,\n compareAggregateRows,\n compareNullableGroupValue,\n completionPct,\n normalizeTagGroupValue,\n parseGroupBy,\n parseNumericAggregation,\n parseStatus,\n readNumericAggregateValue,\n resolveGroupValue,\n updateCompletionCounts,\n};\n","/**\n * @module sdk/graph/traversal\n *\n * Registry-semantics graph traversal primitives layered over the bounded\n * relationship kernel: hierarchy walks (ancestors/descendants), execution-order\n * walks (predecessors/successors), and bounded simple-path enumeration. Every\n * query is deterministic, cancellable, resumable via an explicit cursor, and\n * reports exact cost and truncation metadata so agents can budget follow-up\n * calls without re-reading the workspace.\n */\nimport {\n RelationshipGraph,\n type RelationshipEdge,\n type RelationshipKindDefinition,\n type RelationshipNeighborEdge,\n type RelationshipQueryOptions,\n type RelationshipQueryResult,\n} from \"../relationships.js\";\n\n/**\n * Shared bounded-traversal controls extended with deterministic resumption.\n * Semantic hierarchy and ordering orientation comes from the relationship-kind\n * registry, so callers cannot supply the generic graph `direction` option.\n */\nexport interface GraphTraversalOptions extends Omit<\n RelationshipQueryOptions,\n \"direction\"\n> {\n /**\n * Resume emission after this previously returned node identifier. The\n * traversal re-walks the same deterministic sequence and starts emitting\n * after the cursor node; an identifier the sequence never reaches fails fast\n * instead of silently returning an empty page.\n */\n after?: string;\n}\n\n/** One enumerated simple path between two nodes. */\nexport interface RelationshipPath {\n /** Ordered node identifiers from source to target inclusive. */\n nodes: string[];\n /** Edges connecting consecutive path nodes, in traversal order. */\n edges: RelationshipEdge[];\n /** Number of edges in the path. */\n length: number;\n}\n\n/** Bounded-path enumeration controls. */\nexport interface GraphPathOptions extends RelationshipQueryOptions {\n /** Maximum number of returned paths; defaults to 5. */\n maxPaths?: number;\n /** Safety bound on expanded partial paths before truncation; defaults to 10000. */\n maxVisitedPaths?: number;\n}\n\n/** Default number of paths returned by bounded path enumeration. */\nconst DEFAULT_MAX_PATHS = 5;\n/** Default expansion-safety bound for bounded path enumeration. */\nconst DEFAULT_MAX_VISITED_PATHS = 10_000;\n/** Default depth bound applied to bounded path enumeration. */\nconst DEFAULT_PATH_MAX_DEPTH = 8;\n\n/** Require a finite non-negative integer for one path-enumeration bound. */\nfunction assertPathBound(name: string, value: number): void {\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 0)\n throw new TypeError(`Invalid path ${name} bound: ${String(value)}`);\n}\n\n/** Endpoint of a hierarchy edge that represents the structural parent. */\nexport function hierarchyParentEndpoint(\n edge: RelationshipEdge,\n definition: RelationshipKindDefinition,\n): string {\n // Custom hierarchy kinds may omit the direction; the registry documents the\n // source endpoint as the default parent.\n return definition.hierarchyDirection === \"target_parent\"\n ? edge.target\n : edge.source;\n}\n\n/** Endpoint of an ordering edge that must finish first. */\nexport function orderingPredecessorEndpoint(\n edge: RelationshipEdge,\n definition: RelationshipKindDefinition,\n): string {\n // Ordering kinds registered without explicit precedence default to\n // source-before-target, matching the execution-analytics interpretation.\n return (definition.precedence ?? \"source_before_target\") ===\n \"target_before_source\"\n ? edge.target\n : edge.source;\n}\n\n/** Validate optional kind filters against one semantic edge family. */\nfunction resolveFamilyKinds(\n graph: RelationshipGraph,\n kinds: readonly string[] | undefined,\n family: \"hierarchy\" | \"ordering\",\n): Set<string> | undefined {\n if (kinds === undefined) return undefined;\n const registry = graph.registry();\n const resolved = new Set<string>();\n for (const kind of kinds) {\n const definition = registry.require(kind);\n if (!definition[family])\n throw new TypeError(\n `Relationship kind ${definition.kind} is not a ${family} kind`,\n );\n resolved.add(definition.kind);\n }\n return resolved;\n}\n\n/** Predicate deciding whether a neighbor row participates in one semantic walk. */\ntype SemanticNeighborPredicate = (\n row: RelationshipNeighborEdge,\n definition: RelationshipKindDefinition,\n nodeId: string,\n) => boolean;\n\n/** Mutable state for one bounded semantic breadth-first walk. */\ninterface SemanticWalkState {\n /** Nodes already discovered during the walk. */\n seen: Set<string>;\n /** Nodes emitted for the current page. */\n value: string[];\n /** Pending breadth-first nodes and their depths. */\n queue: { id: string; depth: number }[];\n /** Whether the optional cursor has been reached. */\n resumed: boolean;\n /** Whether a configured bound omitted reachable work. */\n truncated: boolean;\n}\n\n/** Mutable state for bounded simple-path enumeration. */\ninterface PathEnumerationState {\n /** Completed source-to-target paths. */\n value: RelationshipPath[];\n /** Partial simple paths pending expansion. */\n queue: { nodes: string[]; nodeSet: Set<string>; edges: RelationshipEdge[] }[];\n /** Total graph edges inspected by neighbor queries. */\n inspectedEdges: number;\n}\n\n/** Expand one node into its deterministic semantic neighbors. */\nfunction expandSemanticNeighbors(\n graph: RelationshipGraph,\n nodeId: string,\n familyKinds: Set<string> | undefined,\n family: \"hierarchy\" | \"ordering\",\n matches: SemanticNeighborPredicate,\n): { neighbors: string[]; inspectedEdges: number } {\n const registry = graph.registry();\n const rows = graph.neighborEdges(nodeId, {\n direction: \"both\",\n ...(familyKinds === undefined ? {} : { kinds: [...familyKinds] }),\n });\n const neighbors: string[] = [];\n const seen = new Set<string>();\n for (const row of rows.value) {\n const definition = registry.require(row.edge.kind);\n if (!definition[family]) continue;\n if (!matches(row, definition, nodeId)) continue;\n if (seen.has(row.id)) continue;\n seen.add(row.id);\n neighbors.push(row.id);\n }\n return { neighbors, inspectedEdges: rows.meta.inspectedEdges };\n}\n\n/** Append one semantic expansion and report whether the page limit was reached. */\nfunction appendSemanticExpansion(\n expansion: { neighbors: string[] },\n currentDepth: number,\n maxDepth: number,\n limit: number,\n after: string | undefined,\n state: SemanticWalkState,\n): boolean {\n if (currentDepth >= maxDepth) {\n if (expansion.neighbors.some((neighbor) => !state.seen.has(neighbor)))\n state.truncated = true;\n return false;\n }\n for (const neighbor of expansion.neighbors) {\n if (state.seen.has(neighbor)) continue;\n state.seen.add(neighbor);\n state.queue.push({ id: neighbor, depth: currentDepth + 1 });\n if (!state.resumed) {\n if (neighbor === after) state.resumed = true;\n continue;\n }\n if (state.value.length >= limit) {\n state.truncated = true;\n return true;\n }\n state.value.push(neighbor);\n }\n return false;\n}\n\n/** Run one deterministic bounded breadth-first semantic walk. */\nfunction boundedSemanticWalk(\n graph: RelationshipGraph,\n start: string,\n options: GraphTraversalOptions,\n family: \"hierarchy\" | \"ordering\",\n matches: SemanticNeighborPredicate,\n): RelationshipQueryResult<string[]> {\n if (!graph.hasNode(start))\n throw new TypeError(`Relationship node not found: ${start}`);\n const familyKinds = resolveFamilyKinds(graph, options.kinds, family);\n const limit = options.limit ?? Number.POSITIVE_INFINITY;\n const maxDepth = options.maxDepth ?? Number.POSITIVE_INFINITY;\n const after = options.after;\n const state: SemanticWalkState = {\n seen: new Set([start]),\n value: [],\n queue: [{ id: start, depth: 0 }],\n resumed: after === undefined,\n truncated: false,\n };\n let visitedNodes = 0;\n let inspectedEdges = 0;\n for (let index = 0; index < state.queue.length; index += 1) {\n options.signal?.throwIfAborted();\n const current = state.queue[index]!;\n visitedNodes += 1;\n const expansion = expandSemanticNeighbors(\n graph,\n current.id,\n familyKinds,\n family,\n matches,\n );\n inspectedEdges += expansion.inspectedEdges;\n if (\n appendSemanticExpansion(\n expansion,\n current.depth,\n maxDepth,\n limit,\n after,\n state,\n )\n )\n break;\n }\n if (!state.resumed)\n throw new TypeError(`Traversal cursor not found in sequence: ${after}`);\n return {\n value: state.value,\n meta: {\n visitedNodes,\n inspectedEdges,\n truncated: state.truncated,\n nextCursor: state.value.at(-1),\n },\n };\n}\n/** Validate one path endpoint against the indexed graph. */\nfunction assertPathEndpoint(graph: RelationshipGraph, id: string): void {\n if (!graph.hasNode(id))\n throw new TypeError(`Relationship node not found: ${id}`);\n}\n\n/** Return eligible simple-path continuations and account for inspected edges. */\nfunction readPathContinuations(\n graph: RelationshipGraph,\n partial: { nodes: string[]; nodeSet: Set<string>; edges: RelationshipEdge[] },\n options: GraphPathOptions,\n direction: \"outgoing\" | \"incoming\" | \"both\",\n state: PathEnumerationState,\n): ReturnType<RelationshipGraph[\"neighborEdges\"]>[\"value\"] {\n const rows = graph.neighborEdges(partial.nodes.at(-1)!, {\n direction,\n ...(options.kinds === undefined ? {} : { kinds: options.kinds }),\n });\n state.inspectedEdges += rows.meta.inspectedEdges;\n return rows.value.filter((row) => !partial.nodeSet.has(row.id));\n}\n\n/** Expand one partial simple path and report whether the probe cap was reached. */\nfunction expandPartialPath(\n graph: RelationshipGraph,\n partial: { nodes: string[]; nodeSet: Set<string>; edges: RelationshipEdge[] },\n target: string,\n options: GraphPathOptions,\n direction: \"outgoing\" | \"incoming\" | \"both\",\n probeLimit: number,\n state: PathEnumerationState,\n): boolean {\n for (const row of readPathContinuations(\n graph,\n partial,\n options,\n direction,\n state,\n )) {\n const nodes = [...partial.nodes, row.id];\n const nodeSet = new Set(partial.nodeSet).add(row.id);\n const edges = [...partial.edges, row.edge];\n if (row.id === target) {\n state.value.push({ nodes, edges, length: edges.length });\n if (state.value.length >= probeLimit) return true;\n } else {\n state.queue.push({ nodes, nodeSet, edges });\n }\n }\n return false;\n}\n\n/**\n * Return the bounded transitive hierarchy ancestors of one node in\n * breadth-first discovery order, honoring each hierarchy kind's declared\n * parent endpoint (so `parent` and inverse `child` spellings agree).\n */\nexport function hierarchyAncestors(\n graph: RelationshipGraph,\n id: string,\n options: GraphTraversalOptions = {},\n): RelationshipQueryResult<string[]> {\n return boundedSemanticWalk(\n graph,\n id,\n options,\n \"hierarchy\",\n (row, definition) =>\n hierarchyParentEndpoint(row.edge, definition) === row.id,\n );\n}\n\n/**\n * Return the bounded transitive hierarchy descendants of one node in\n * breadth-first discovery order, honoring each hierarchy kind's declared\n * parent endpoint.\n */\nexport function hierarchyDescendants(\n graph: RelationshipGraph,\n id: string,\n options: GraphTraversalOptions = {},\n): RelationshipQueryResult<string[]> {\n return boundedSemanticWalk(\n graph,\n id,\n options,\n \"hierarchy\",\n (row, definition, nodeId) =>\n hierarchyParentEndpoint(row.edge, definition) === nodeId,\n );\n}\n\n/**\n * Return the bounded transitive execution predecessors of one node — the work\n * that must finish before it — in breadth-first discovery order, honoring each\n * ordering kind's declared precedence (so `blocked_by` and inverse `blocks`\n * spellings agree).\n */\nexport function orderingPredecessors(\n graph: RelationshipGraph,\n id: string,\n options: GraphTraversalOptions = {},\n): RelationshipQueryResult<string[]> {\n return boundedSemanticWalk(\n graph,\n id,\n options,\n \"ordering\",\n (row, definition) =>\n orderingPredecessorEndpoint(row.edge, definition) === row.id,\n );\n}\n\n/**\n * Return the bounded transitive execution successors of one node — the work\n * this node gates — in breadth-first discovery order, honoring each ordering\n * kind's declared precedence.\n */\nexport function orderingSuccessors(\n graph: RelationshipGraph,\n id: string,\n options: GraphTraversalOptions = {},\n): RelationshipQueryResult<string[]> {\n return boundedSemanticWalk(\n graph,\n id,\n options,\n \"ordering\",\n (row, definition, nodeId) =>\n orderingPredecessorEndpoint(row.edge, definition) === nodeId,\n );\n}\n\n/** Run bounded non-zero path enumeration after public option validation. */\nfunction enumerateNonZeroRelationshipPaths(\n graph: RelationshipGraph,\n source: string,\n target: string,\n options: GraphPathOptions,\n maxPaths: number,\n maxVisitedPaths: number,\n maxDepth: number,\n direction: \"outgoing\" | \"incoming\" | \"both\",\n): RelationshipQueryResult<RelationshipPath[]> {\n const state: PathEnumerationState = {\n value: [],\n queue: [{ nodes: [source], nodeSet: new Set([source]), edges: [] }],\n inspectedEdges: 0,\n };\n let visitedNodes = 0;\n let truncated = false;\n const probeLimit = maxPaths + 1;\n for (let index = 0; index < state.queue.length; index += 1) {\n options.signal?.throwIfAborted();\n if (state.value.length >= probeLimit || visitedNodes >= maxVisitedPaths) {\n truncated = true;\n break;\n }\n const partial = state.queue[index]!;\n visitedNodes += 1;\n if (partial.edges.length >= maxDepth) {\n if (\n readPathContinuations(graph, partial, options, direction, state)\n .length > 0\n )\n truncated = true;\n continue;\n }\n if (\n expandPartialPath(\n graph,\n partial,\n target,\n options,\n direction,\n probeLimit,\n state,\n )\n ) {\n truncated = true;\n break;\n }\n }\n return {\n value: state.value.slice(0, maxPaths),\n meta: { visitedNodes, inspectedEdges: state.inspectedEdges, truncated },\n };\n}\n\n/**\n * Enumerate bounded simple paths between two nodes, shortest first and\n * lexicographic within equal length. Traversal honors direction and kind\n * filters, caps returned paths, and reports truncation when depth, path-count,\n * or the expansion-safety bound stops the search early.\n */\nexport function enumerateRelationshipPaths(\n graph: RelationshipGraph,\n source: string,\n target: string,\n options: GraphPathOptions = {},\n): RelationshipQueryResult<RelationshipPath[]> {\n assertPathEndpoint(graph, source);\n assertPathEndpoint(graph, target);\n const maxPaths = options.maxPaths ?? DEFAULT_MAX_PATHS;\n const maxVisitedPaths = options.maxVisitedPaths ?? DEFAULT_MAX_VISITED_PATHS;\n const maxDepth = options.maxDepth ?? DEFAULT_PATH_MAX_DEPTH;\n assertPathBound(\"maxPaths\", maxPaths);\n assertPathBound(\"maxVisitedPaths\", maxVisitedPaths);\n assertPathBound(\"maxDepth\", maxDepth);\n const direction = options.direction ?? \"outgoing\";\n options.signal?.throwIfAborted();\n for (const kind of options.kinds ?? []) graph.registry().require(kind);\n if (source === target) {\n if (maxPaths === 0) {\n return {\n value: [],\n meta: { visitedNodes: 1, inspectedEdges: 0, truncated: true },\n };\n }\n return {\n value: [{ nodes: [source], edges: [], length: 0 }],\n meta: { visitedNodes: 1, inspectedEdges: 0, truncated: false },\n };\n }\n return enumerateNonZeroRelationshipPaths(\n graph,\n source,\n target,\n options,\n maxPaths,\n maxVisitedPaths,\n maxDepth,\n direction,\n );\n}\n","/**\n * @module sdk/graph/analytics\n *\n * Structural graph analytics beyond exact components: deterministic\n * label-propagation community detection over the undirected relationship\n * structure, transitively redundant edge discovery over ordering and\n * hierarchy families, and dominator (bottleneck) analysis over one node's\n * reachable subgraph. Every analysis is deterministic, cancellable, bounded,\n * and reports exact cost metadata so agents can budget follow-up reads\n * without re-scanning the workspace.\n */\nimport {\n RelationshipGraph,\n type RelationshipEdge,\n type RelationshipKindDefinition,\n type RelationshipNeighborEdge,\n type RelationshipQueryResult,\n type RelationshipTraversalDirection,\n} from \"../relationships.js\";\nimport {\n hierarchyParentEndpoint,\n orderingPredecessorEndpoint,\n} from \"./traversal.js\";\n\n/** Default label-propagation sweeps before reporting non-convergence. */\nconst DEFAULT_MAX_ITERATIONS = 16;\n/** Default minimum member count for a reported community. */\nconst DEFAULT_MIN_COMMUNITY_SIZE = 2;\n/** Default witness-path depth searched per candidate redundant edge. */\nconst DEFAULT_REDUNDANCY_MAX_DEPTH = 8;\n\n/** One detected relationship community. */\nexport interface RelationshipCommunity {\n /** Lexicographically smallest member id, naming the community. */\n representative: string;\n /** Total member count. */\n size: number;\n /** Sorted member node ids. */\n members: string[];\n}\n\n/** Bounded community-detection controls. */\nexport interface GraphCommunityOptions {\n /** Registered relationship kinds whose edges define adjacency. */\n kinds?: readonly string[];\n /** Maximum label-propagation sweeps before reporting non-convergence; defaults to 16. */\n maxIterations?: number;\n /** Minimum member count for a reported community; defaults to 2. */\n minSize?: number;\n /** Abort signal checked once per sweep. */\n signal?: AbortSignal;\n}\n\n/** Deterministic label-propagation community analysis. */\nexport interface RelationshipCommunityAnalysis {\n /** Detected communities, largest first and by representative within equal size. */\n communities: RelationshipCommunity[];\n /** Label-propagation sweeps executed. */\n iterations: number;\n /** Whether labels stabilized before the iteration bound stopped the sweep. */\n converged: boolean;\n}\n\n/** One stored edge implied by a longer same-family witness path. */\nexport interface RedundantRelationshipEdge {\n /** The stored redundant edge in its original spelling. */\n edge: RelationshipEdge;\n /** Semantic-orientation witness node path proving the implication, endpoints inclusive. */\n witness: string[];\n}\n\n/** Bounded redundancy-scan controls. */\nexport interface GraphRedundancyOptions {\n /** Directed ordering or hierarchy kinds to scan; defaults to every eligible registered kind. */\n kinds?: readonly string[];\n /** Maximum witness-path depth searched per edge; defaults to 8. */\n maxDepth?: number;\n /** Maximum reported redundant edges. */\n limit?: number;\n /** Abort signal checked once per scanned edge. */\n signal?: AbortSignal;\n}\n\n/** One reachable node with its immediate dominator and gating weight. */\nexport interface RelationshipDominatorRow {\n /** Reachable node id. */\n id: string;\n /** Immediate dominator appearing on every root-to-node path. */\n idom: string;\n /** Nodes strictly dominated by this node — its dominator-subtree size minus itself. */\n dominatedCount: number;\n}\n\n/** Bounded dominator-analysis controls. */\nexport interface GraphDominatorOptions {\n /** Registered relationship kinds whose edges define reachability. */\n kinds?: readonly string[];\n /** Traversal direction relative to each visited node; defaults to \"outgoing\". */\n direction?: RelationshipTraversalDirection;\n /** Maximum reachability depth from the root as a non-negative integer. */\n maxDepth?: number;\n /** Abort signal checked once per processed node. */\n signal?: AbortSignal;\n}\n\n/** Dominator-tree analysis of one node's reachable subgraph. */\nexport interface RelationshipDominatorAnalysis {\n /** Analyzed root id. */\n root: string;\n /** Reachable node count including the root. */\n reachableCount: number;\n /** Non-root reachable rows sorted by gating weight, then id. */\n rows: RelationshipDominatorRow[];\n}\n\n/** Require a positive integer for one analytics bound. */\nfunction assertPositiveBound(name: string, value: number): void {\n if (!Number.isInteger(value) || value < 1)\n throw new TypeError(`Invalid ${name} bound: ${String(value)}`);\n}\n\n/** Build the deterministic undirected adjacency restricted to canonicalized kinds. */\nfunction buildUndirectedAdjacency(\n graph: RelationshipGraph,\n kinds: readonly string[] | undefined,\n): Map<string, string[]> {\n const registry = graph.registry();\n const wanted =\n kinds === undefined\n ? undefined\n : new Set(kinds.map((kind) => registry.require(kind).kind));\n const adjacency = new Map<string, string[]>();\n for (const edge of graph.edges()) {\n if (edge.source === edge.target) continue;\n if (wanted !== undefined) {\n const definition = registry.require(edge.kind);\n const matches =\n wanted.has(definition.kind) ||\n (definition.inverse !== undefined && wanted.has(definition.inverse));\n if (!matches) continue;\n }\n appendAdjacency(adjacency, edge.source, edge.target);\n appendAdjacency(adjacency, edge.target, edge.source);\n }\n for (const neighbors of adjacency.values()) neighbors.sort();\n return adjacency;\n}\n\n/** Append one neighbor to a node's adjacency list, creating the list on demand. */\nfunction appendAdjacency(\n adjacency: Map<string, string[]>,\n from: string,\n to: string,\n): void {\n const neighbors = adjacency.get(from);\n if (neighbors === undefined) adjacency.set(from, [to]);\n else neighbors.push(to);\n}\n\n/** Adopt the most frequent neighbor label with lexicographic tie-breaking. */\nfunction dominantNeighborLabel(\n neighbors: readonly string[],\n labels: Map<string, string>,\n): string {\n const counts = new Map<string, number>();\n for (const neighbor of neighbors) {\n const label = labels.get(neighbor)!;\n counts.set(label, (counts.get(label) ?? 0) + 1);\n }\n let best: string | undefined;\n let bestCount = 0;\n for (const [label, count] of counts) {\n if (count > bestCount || (count === bestCount && label < best!)) {\n best = label;\n bestCount = count;\n }\n }\n return best!;\n}\n\n/** Group stabilized labels into sorted communities meeting the size floor. */\nfunction collectCommunities(\n labels: Map<string, string>,\n minSize: number,\n): RelationshipCommunity[] {\n const groups = new Map<string, string[]>();\n for (const [id, label] of labels) {\n const members = groups.get(label);\n if (members === undefined) groups.set(label, [id]);\n else members.push(id);\n }\n const communities: RelationshipCommunity[] = [];\n for (const members of groups.values()) {\n if (members.length < minSize) continue;\n members.sort();\n communities.push({\n representative: members[0]!,\n size: members.length,\n members,\n });\n }\n return communities.sort(\n (left, right) =>\n right.size - left.size ||\n left.representative.localeCompare(right.representative),\n );\n}\n\n/**\n * Detect communities with deterministic asynchronous label propagation: nodes\n * are swept in sorted order, each adopting the most frequent label among its\n * neighbors with lexicographic tie-breaking, until labels stabilize or the\n * iteration bound stops the sweep. Adjacency is undirected — every\n * participating edge connects both endpoints symmetrically and parallel edges\n * weight their neighbor. `meta.truncated` reports non-convergence.\n */\nexport function detectRelationshipCommunities(\n graph: RelationshipGraph,\n options: GraphCommunityOptions = {},\n): RelationshipQueryResult<RelationshipCommunityAnalysis> {\n const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;\n const minSize = options.minSize ?? DEFAULT_MIN_COMMUNITY_SIZE;\n assertPositiveBound(\"maxIterations\", maxIterations);\n assertPositiveBound(\"minSize\", minSize);\n const adjacency = buildUndirectedAdjacency(graph, options.kinds);\n const nodes = graph.nodes();\n const labels = new Map(nodes.map((id) => [id, id]));\n let iterations = 0;\n let converged = false;\n let visitedNodes = 0;\n let inspectedEdges = 0;\n while (iterations < maxIterations && !converged) {\n options.signal?.throwIfAborted();\n iterations += 1;\n converged = true;\n for (const id of nodes) {\n visitedNodes += 1;\n const neighbors = adjacency.get(id);\n if (neighbors === undefined) continue;\n inspectedEdges += neighbors.length;\n const dominant = dominantNeighborLabel(neighbors, labels);\n if (dominant !== labels.get(id)) {\n labels.set(id, dominant);\n converged = false;\n }\n }\n }\n return {\n value: {\n communities: collectCommunities(labels, minSize),\n iterations,\n converged,\n },\n meta: { visitedNodes, inspectedEdges, truncated: !converged },\n };\n}\n\n/** Decide whether a kind carries transitive semantics eligible for redundancy and duplicate analysis. */\nexport function isTransitiveKind(definition: RelationshipKindDefinition): boolean {\n return (\n definition.direction === \"directed\" &&\n (definition.ordering || definition.hierarchy)\n );\n}\n\n/** Family grouping key joining a directed kind with its inverse spelling. */\nexport function transitiveFamilyKey(definition: RelationshipKindDefinition): string {\n return definition.inverse !== undefined &&\n definition.inverse < definition.kind\n ? definition.inverse\n : definition.kind;\n}\n\n/** Orient one transitive edge into its semantic forward direction. */\nexport function orientTransitiveEdge(\n edge: RelationshipEdge,\n definition: RelationshipKindDefinition,\n): { from: string; to: string } {\n // Hierarchy families flow child -> parent; ordering families flow\n // predecessor -> successor, so inverse spellings land in one relation.\n const head = definition.hierarchy\n ? hierarchyParentEndpoint(edge, definition)\n : edge.source === orderingPredecessorEndpoint(edge, definition)\n ? edge.target\n : edge.source;\n return head === edge.target\n ? { from: edge.source, to: edge.target }\n : { from: edge.target, to: edge.source };\n}\n\n/** One semantically oriented transitive edge retaining its stored spelling. */\ninterface OrientedTransitiveEdge {\n /** Semantic tail node. */\n from: string;\n /** Semantic head node. */\n to: string;\n /** Original stored edge. */\n edge: RelationshipEdge;\n}\n\n/** Per-family oriented edges and their deterministic forward adjacency. */\ninterface TransitiveFamily {\n /** Deduplicated forward adjacency in semantic orientation, sorted after collection. */\n adjacency: Map<string, Set<string>>;\n /** Oriented edges in deterministic stored order. */\n records: OrientedTransitiveEdge[];\n}\n\n/** Resolve explicit redundancy kind filters into their family keys. */\nfunction resolveRedundancyFamilies(\n graph: RelationshipGraph,\n kinds: readonly string[] | undefined,\n): Set<string> | undefined {\n if (kinds === undefined) return undefined;\n const registry = graph.registry();\n const families = new Set<string>();\n for (const kind of kinds) {\n const definition = registry.require(kind);\n if (!isTransitiveKind(definition))\n throw new TypeError(\n `Relationship kind ${definition.kind} is not a directed ordering or hierarchy kind`,\n );\n families.add(transitiveFamilyKey(definition));\n }\n return families;\n}\n\n/** Group eligible stored edges into oriented per-family scan structures. */\nfunction collectTransitiveFamilies(\n graph: RelationshipGraph,\n wanted: Set<string> | undefined,\n): Map<string, TransitiveFamily> {\n const registry = graph.registry();\n const families = new Map<string, TransitiveFamily>();\n for (const edge of graph.edges()) {\n const definition = registry.require(edge.kind);\n if (!isTransitiveKind(definition)) continue;\n const key = transitiveFamilyKey(definition);\n if (wanted !== undefined && !wanted.has(key)) continue;\n const oriented = orientTransitiveEdge(edge, definition);\n if (oriented.from === oriented.to) continue;\n let family = families.get(key);\n if (family === undefined) {\n family = { adjacency: new Map(), records: [] };\n families.set(key, family);\n }\n const targets = family.adjacency.get(oriented.from);\n if (targets === undefined)\n family.adjacency.set(oriented.from, new Set([oriented.to]));\n else targets.add(oriented.to);\n family.records.push({ ...oriented, edge });\n }\n return families;\n}\n\n/** Freeze one family's adjacency sets into deterministic sorted lists. */\nfunction sortedFamilyAdjacency(\n family: TransitiveFamily,\n): Map<string, readonly string[]> {\n const sorted = new Map<string, readonly string[]>();\n for (const [from, targets] of family.adjacency)\n sorted.set(from, [...targets].sort());\n return sorted;\n}\n\n/** Rebuild the witness node path from breadth-first parent pointers. */\nfunction reconstructWitness(\n parents: Map<string, string>,\n from: string,\n tail: string,\n head: string,\n): string[] {\n const witness = [head];\n for (let node = tail; node !== from; node = parents.get(node)!)\n witness.push(node);\n witness.push(from);\n return witness.reverse();\n}\n\n/** Expand one witness frontier node; return the completed witness when the head is reached. */\nfunction expandWitnessFrontier(\n adjacency: Map<string, readonly string[]>,\n record: OrientedTransitiveEdge,\n current: { id: string; depth: number },\n parents: Map<string, string>,\n queue: { id: string; depth: number }[],\n cost: { visitedNodes: number; inspectedEdges: number },\n): string[] | undefined {\n for (const next of adjacency.get(current.id) ?? []) {\n cost.inspectedEdges += 1;\n // Skip the direct edge under test; deeper hops may still reach the head.\n if (current.depth === 0 && next === record.to) continue;\n if (parents.has(next)) continue;\n parents.set(next, current.id);\n if (next === record.to)\n return reconstructWitness(parents, record.from, current.id, next);\n queue.push({ id: next, depth: current.depth + 1 });\n }\n return undefined;\n}\n\n/** Search one bounded same-family witness path that implies a direct edge. */\nfunction findWitnessPath(\n adjacency: Map<string, readonly string[]>,\n record: OrientedTransitiveEdge,\n maxDepth: number,\n cost: { visitedNodes: number; inspectedEdges: number },\n): string[] | undefined {\n const parents = new Map<string, string>([[record.from, record.from]]);\n const queue = [{ id: record.from, depth: 0 }];\n for (let index = 0; index < queue.length; index += 1) {\n const current = queue[index]!;\n cost.visitedNodes += 1;\n if (current.depth >= maxDepth) continue;\n const witness = expandWitnessFrontier(\n adjacency,\n record,\n current,\n parents,\n queue,\n cost,\n );\n if (witness !== undefined) return witness;\n }\n return undefined;\n}\n\n/**\n * Find stored edges implied by a longer path of the same semantic family —\n * the transitive-reduction view of ordering and hierarchy relations. Each\n * family joins a directed kind with its inverse spelling in semantic\n * orientation, so `blocked_by` and `blocks` witness each other. The witness\n * search is breadth-first, shortest and lexicographic first, bounded by\n * `maxDepth` per edge; `meta.truncated` reports only the `limit` bound.\n */\nexport function findRedundantRelationshipEdges(\n graph: RelationshipGraph,\n options: GraphRedundancyOptions = {},\n): RelationshipQueryResult<RedundantRelationshipEdge[]> {\n const maxDepth = options.maxDepth ?? DEFAULT_REDUNDANCY_MAX_DEPTH;\n assertPositiveBound(\"maxDepth\", maxDepth);\n if (options.limit !== undefined) assertPositiveBound(\"limit\", options.limit);\n const limit = options.limit ?? Number.POSITIVE_INFINITY;\n const wanted = resolveRedundancyFamilies(graph, options.kinds);\n const families = collectTransitiveFamilies(graph, wanted);\n const value: RedundantRelationshipEdge[] = [];\n const cost = { visitedNodes: 0, inspectedEdges: 0 };\n let truncated = false;\n scan: for (const key of [...families.keys()].sort()) {\n const family = families.get(key)!;\n const adjacency = sortedFamilyAdjacency(family);\n for (const record of family.records) {\n options.signal?.throwIfAborted();\n const witness = findWitnessPath(adjacency, record, maxDepth, cost);\n if (witness === undefined) continue;\n if (value.length >= limit) {\n truncated = true;\n break scan;\n }\n value.push({ edge: record.edge, witness });\n }\n }\n return {\n value,\n meta: {\n visitedNodes: cost.visitedNodes,\n inspectedEdges: cost.inspectedEdges,\n truncated,\n },\n };\n}\n\n/** Reachability index of one root's directed subgraph. */\ninterface ReachableSubgraph {\n /** Reachable node ids in breadth-first discovery order. */\n order: string[];\n /** Deterministic successor lists per reachable node. */\n successors: Map<string, string[]>;\n /** Reachable predecessor sets per reachable node. */\n predecessors: Map<string, Set<string>>;\n /** Candidate edges inspected while indexing. */\n inspectedEdges: number;\n /** Whether the depth bound excluded reachable nodes. */\n truncated: boolean;\n}\n\n/** Mutable frontier state threaded through bounded reachability expansion. */\ninterface ReachabilityState {\n /** Nodes already discovered. */\n seen: Set<string>;\n /** Pending breadth-first nodes and their depths. */\n queue: { id: string; depth: number }[];\n /** Reachable predecessor sets per discovered node. */\n predecessors: Map<string, Set<string>>;\n /** Whether the depth bound excluded reachable nodes. */\n truncated: boolean;\n}\n\n/** Expand one node's neighbor rows into successors, predecessors, and frontier work. */\nfunction expandReachableNode(\n id: string,\n depth: number,\n rows: readonly RelationshipNeighborEdge[],\n maxDepth: number,\n state: ReachabilityState,\n): string[] {\n const nextSet = new Set<string>();\n const nexts: string[] = [];\n for (const row of rows) {\n if (row.id === id || nextSet.has(row.id)) continue;\n if (!state.seen.has(row.id)) {\n // A depth-boundary node keeps its edges to already-indexed nodes but\n // may not discover new ones; excluded discoveries mark truncation.\n if (depth >= maxDepth) {\n state.truncated = true;\n continue;\n }\n state.seen.add(row.id);\n state.queue.push({ id: row.id, depth: depth + 1 });\n }\n nextSet.add(row.id);\n nexts.push(row.id);\n let incoming = state.predecessors.get(row.id);\n if (incoming === undefined) {\n incoming = new Set();\n state.predecessors.set(row.id, incoming);\n }\n incoming.add(id);\n }\n return nexts;\n}\n\n/** Index the bounded reachable subgraph used by dominator analysis. */\nfunction indexReachableSubgraph(\n graph: RelationshipGraph,\n root: string,\n options: GraphDominatorOptions,\n): ReachableSubgraph {\n const direction = options.direction ?? \"outgoing\";\n const maxDepth = options.maxDepth ?? Number.POSITIVE_INFINITY;\n const order: string[] = [];\n const successors = new Map<string, string[]>();\n const state: ReachabilityState = {\n seen: new Set([root]),\n queue: [{ id: root, depth: 0 }],\n predecessors: new Map(),\n truncated: false,\n };\n let inspectedEdges = 0;\n for (let index = 0; index < state.queue.length; index += 1) {\n options.signal?.throwIfAborted();\n const { id, depth } = state.queue[index]!;\n order.push(id);\n const rows = graph.neighborEdges(id, {\n direction,\n ...(options.kinds === undefined ? {} : { kinds: options.kinds }),\n });\n inspectedEdges += rows.meta.inspectedEdges;\n successors.set(id, expandReachableNode(id, depth, rows.value, maxDepth, state));\n }\n return {\n order,\n successors,\n predecessors: state.predecessors,\n inspectedEdges,\n truncated: state.truncated,\n };\n}\n\n/** Compute the deterministic reverse postorder of one reachable subgraph. */\nfunction reversePostorder(subgraph: ReachableSubgraph, root: string): string[] {\n const postorder: string[] = [];\n const visited = new Set([root]);\n const stack = [{ id: root, index: 0 }];\n while (stack.length > 0) {\n const frame = stack.at(-1)!;\n const nexts = subgraph.successors.get(frame.id)!;\n if (frame.index < nexts.length) {\n const next = nexts[frame.index]!;\n frame.index += 1;\n if (!visited.has(next)) {\n visited.add(next);\n stack.push({ id: next, index: 0 });\n }\n } else {\n postorder.push(frame.id);\n stack.pop();\n }\n }\n return postorder.reverse();\n}\n\n/** Walk two dominator-tree fingers to their common ancestor by reverse-postorder number. */\nfunction intersectDominators(\n left: string,\n right: string,\n idom: Map<string, string>,\n ordinal: Map<string, number>,\n): string {\n let first = left;\n let second = right;\n while (first !== second) {\n while (ordinal.get(first)! > ordinal.get(second)!) first = idom.get(first)!;\n while (ordinal.get(second)! > ordinal.get(first)!) second = idom.get(second)!;\n }\n return first;\n}\n\n/** Fold one node's processed predecessors into its dominator candidate. */\nfunction dominatorCandidate(\n predecessors: ReadonlySet<string>,\n idom: Map<string, string>,\n ordinal: Map<string, number>,\n): string | undefined {\n let candidate: string | undefined;\n for (const pred of [...predecessors].sort()) {\n if (!idom.has(pred)) continue;\n candidate =\n candidate === undefined\n ? pred\n : intersectDominators(candidate, pred, idom, ordinal);\n }\n return candidate;\n}\n\n/** Run the Cooper–Harvey–Kennedy fixed-point over one reverse postorder. */\nfunction solveImmediateDominators(\n subgraph: ReachableSubgraph,\n root: string,\n order: readonly string[],\n ordinal: Map<string, number>,\n signal: AbortSignal | undefined,\n): Map<string, string> {\n const idom = new Map<string, string>([[root, root]]);\n let changed = true;\n while (changed) {\n changed = false;\n for (const id of order) {\n signal?.throwIfAborted();\n if (id === root) continue;\n // Every non-root node in the order was discovered through at least one\n // predecessor, so the set is always present.\n const candidate = dominatorCandidate(\n subgraph.predecessors.get(id)!,\n idom,\n ordinal,\n );\n if (candidate !== undefined && idom.get(id) !== candidate) {\n idom.set(id, candidate);\n changed = true;\n }\n }\n }\n return idom;\n}\n\n/**\n * Compute immediate dominators and gating weights over one node's reachable\n * subgraph using the Cooper–Harvey–Kennedy fixed-point. A node dominates the\n * work that every path from the root must pass through it to reach, so rows\n * with a positive `dominatedCount` are the structural bottlenecks of the\n * root's blast radius. Rows sort by gating weight, then id; `meta.truncated`\n * reports when the `maxDepth` bound excluded reachable nodes.\n */\nexport function computeRelationshipDominators(\n graph: RelationshipGraph,\n root: string,\n options: GraphDominatorOptions = {},\n): RelationshipQueryResult<RelationshipDominatorAnalysis> {\n if (!graph.hasNode(root))\n throw new TypeError(`Relationship node not found: ${root}`);\n if (\n options.maxDepth !== undefined &&\n (!Number.isInteger(options.maxDepth) || options.maxDepth < 0)\n )\n throw new TypeError(`Invalid maxDepth bound: ${String(options.maxDepth)}`);\n const subgraph = indexReachableSubgraph(graph, root, options);\n const order = reversePostorder(subgraph, root);\n const ordinal = new Map(order.map((id, index) => [id, index]));\n const idom = solveImmediateDominators(\n subgraph,\n root,\n order,\n ordinal,\n options.signal,\n );\n const subtreeSizes = new Map(order.map((id) => [id, 1]));\n for (let index = order.length - 1; index >= 0; index -= 1) {\n const id = order[index]!;\n if (id === root) continue;\n const parent = idom.get(id)!;\n subtreeSizes.set(parent, subtreeSizes.get(parent)! + subtreeSizes.get(id)!);\n }\n const rows = order\n .filter((id) => id !== root)\n .map((id) => ({\n id,\n idom: idom.get(id)!,\n dominatedCount: subtreeSizes.get(id)! - 1,\n }))\n .sort(\n (left, right) =>\n right.dominatedCount - left.dominatedCount ||\n left.id.localeCompare(right.id),\n );\n return {\n value: { root, reachableCount: subgraph.order.length, rows },\n meta: {\n visitedNodes: subgraph.order.length,\n inspectedEdges: subgraph.inspectedEdges,\n truncated: subgraph.truncated,\n },\n };\n}\n","/**\n * @module sdk/graph/governance\n *\n * Policy-aware relationship-graph quality audit shared by validation, health,\n * and package governance surfaces. The audit inspects one assembled workspace\n * graph and reports machine-readable findings — integrity gaps, ordering\n * cycles, duplicated edge spellings, stale lifecycle blocks, and coverage\n * outliers — without inventing edges or assuming that sparse connectivity is\n * defective. Findings gate severity on lifecycle: contradictions confined to\n * terminal items downgrade to informational `legacy_*` codes because repairing\n * them would mutate closed history. Every finding names the violated policy,\n * carries a deterministic bounded sample, and proposes a safe next action so\n * agents can plan remediation without re-deriving context.\n */\nimport type { RelationshipEdge } from \"../relationships.js\";\nimport {\n isTransitiveKind,\n orientTransitiveEdge,\n transitiveFamilyKey,\n} from \"./analytics.js\";\nimport type { WorkspaceRelationshipAssembly } from \"./assembly.js\";\n\n/** Severity ladder shared by every relationship audit finding. */\nexport type RelationshipAuditSeverity = \"error\" | \"warning\" | \"info\";\n\n/** Machine-readable identifier for one relationship audit finding family. */\nexport type RelationshipAuditFindingCode =\n | \"missing_reference_active\"\n | \"missing_reference_terminal\"\n | \"legacy_no_blocker_sentinel\"\n | \"ordering_cycle\"\n | \"legacy_ordering_cycle\"\n | \"duplicate_edge\"\n | \"legacy_duplicate_edge\"\n | \"stale_lifecycle_block\"\n | \"isolated_active_node\"\n | \"sparse_active_node\";\n\n/** One policy-aware relationship audit finding with bounded evidence. */\nexport interface RelationshipAuditFinding {\n /** Machine-readable finding family identifier. */\n code: RelationshipAuditFindingCode;\n /** Severity of the violated policy. */\n severity: RelationshipAuditSeverity;\n /** Policy statement this finding violates. */\n policy: string;\n /** Human-readable summary including the affected count. */\n message: string;\n /** Total number of affected subjects, independent of sample bounding. */\n count: number;\n /** Deterministic bounded sample of affected subjects. */\n sample: string[];\n /** Whether {@link sample} was truncated by the configured sample bound. */\n sample_truncated: boolean;\n /** Safe machine-actionable next step; audits never invent or auto-apply edges. */\n remediation: string;\n}\n\n/** Aggregate structural coverage metrics for one assembled workspace graph. */\nexport interface RelationshipCoverageProfile {\n /** Total indexed nodes including materialized missing placeholders. */\n nodes: number;\n /** Total deduplicated indexed edges. */\n edges: number;\n /** Deterministic per-kind edge counts. */\n edges_by_kind: Record<string, number>;\n /** Nodes whose lifecycle status is active (non-terminal, non-missing). */\n active_nodes: number;\n /** Materialized placeholder nodes for referenced-but-absent items. */\n missing_nodes: number;\n /** Active nodes with no incident edges at all. */\n isolated_active_nodes: number;\n /** Active nodes with at most one incident edge, isolates included. */\n degree_leq_one_active_nodes: number;\n}\n\n/** Tuning and policy inputs accepted by the relationship audit. */\nexport interface RelationshipAuditOptions {\n /** Terminal-lifecycle predicate; defaults to the built-in closed/canceled statuses. */\n isTerminal?: (status: string) => boolean;\n /** Blocked-lifecycle predicate for stale-block detection; defaults to `status === \"blocked\"`. */\n isBlocked?: (status: string) => boolean;\n /** Node identifiers that are explicitly valid isolates (roots, archives, scratch work). */\n exemptIsolates?: readonly string[];\n /** Maximum sample entries retained per finding; defaults to 25. */\n maxSampleSize?: number;\n /** Abort signal checked between finding families. */\n signal?: AbortSignal;\n}\n\n/** Complete deterministic result of one relationship-graph audit. */\nexport interface RelationshipAuditReport {\n /** Findings ordered by severity, then code, then first sample subject. */\n findings: RelationshipAuditFinding[];\n /** Structural coverage metrics computed during the audit. */\n profile: RelationshipCoverageProfile;\n}\n\n/** Default bounded sample size applied to every finding family. */\nconst DEFAULT_MAX_SAMPLE_SIZE = 25;\n\n/** Rank used to order findings by decreasing severity. */\nconst SEVERITY_RANK: Record<RelationshipAuditSeverity, number> = {\n error: 0,\n warning: 1,\n info: 2,\n};\n\n/** Internal per-node lifecycle classification resolved once per audit. */\ninterface AuditNodeState {\n /** Original-case node identifier. */\n id: string;\n /** Raw lifecycle status string from assembly details. */\n status: string;\n /** Whether the node is a materialized missing placeholder. */\n missing: boolean;\n /** Whether the node's lifecycle status is terminal. */\n terminal: boolean;\n}\n\n/** Mutable state shared by iterative Tarjan frames. */\ninterface TarjanState {\n /** Discovery index assigned to each visited node. */\n indexes: Map<string, number>;\n /** Lowest reachable discovery index per visited node. */\n lowLinks: Map<string, number>;\n /** Nodes that still belong to an unfinished component. */\n onStack: Set<string>;\n /** Component-membership stack. */\n stack: string[];\n /** Completed cyclic components. */\n components: string[][];\n /** Discovery index assigned to the next unseen node. */\n nextIndex: number;\n}\n\n/** One explicit depth-first frame used by iterative Tarjan traversal. */\ninterface TarjanFrame {\n /** Node currently being expanded. */\n node: string;\n /** Index of the next successor to inspect. */\n neighborIndex: number;\n}\n\n/** Build one finding with deterministic bounded sampling over sorted subjects. */\nfunction buildFinding(\n code: RelationshipAuditFindingCode,\n severity: RelationshipAuditSeverity,\n policy: string,\n describe: (count: number) => string,\n subjects: readonly string[],\n maxSampleSize: number,\n remediation: string,\n): RelationshipAuditFinding {\n const sorted = [...subjects].sort((left, right) => left.localeCompare(right));\n return {\n code,\n severity,\n policy,\n message: describe(sorted.length),\n count: sorted.length,\n sample: sorted.slice(0, maxSampleSize),\n sample_truncated: sorted.length > maxSampleSize,\n remediation,\n };\n}\n/** Resolve the ordering-only successor adjacency for cycle analysis. */\nfunction buildOrderingAdjacency(\n assembly: WorkspaceRelationshipAssembly,\n): Map<string, string[]> {\n const registry = assembly.graph.registry();\n const successors = new Map<string, string[]>();\n for (const edge of assembly.graph.edges()) {\n const definition = registry.require(edge.kind);\n if (!definition.ordering) continue;\n // Orient every ordering edge predecessor -> successor so inverse spellings\n // (blocked_by/blocks) land in one canonical execution-order digraph.\n const [predecessor, successor] =\n (definition.precedence ?? \"source_before_target\") ===\n \"target_before_source\"\n ? [edge.target, edge.source]\n : [edge.source, edge.target];\n const adjacent = successors.get(predecessor);\n if (adjacent) adjacent.push(successor);\n else successors.set(predecessor, [successor]);\n }\n for (const adjacent of successors.values())\n adjacent.sort((left, right) => left.localeCompare(right));\n return successors;\n}\n\n/** Register one newly discovered Tarjan node. */\nfunction registerTarjanNode(node: string, state: TarjanState): void {\n state.indexes.set(node, state.nextIndex);\n state.lowLinks.set(node, state.nextIndex);\n state.nextIndex += 1;\n state.stack.push(node);\n state.onStack.add(node);\n}\n\n/** Visit one pending successor, returning whether the frame had work left. */\nfunction visitNextTarjanNeighbor(\n frame: TarjanFrame,\n frames: TarjanFrame[],\n successors: Map<string, string[]>,\n state: TarjanState,\n): boolean {\n const neighbors = successors.get(frame.node) ?? [];\n if (frame.neighborIndex >= neighbors.length) return false;\n const neighbor = neighbors[frame.neighborIndex]!;\n frame.neighborIndex += 1;\n if (!state.indexes.has(neighbor)) {\n registerTarjanNode(neighbor, state);\n frames.push({ node: neighbor, neighborIndex: 0 });\n } else if (state.onStack.has(neighbor)) {\n state.lowLinks.set(\n frame.node,\n Math.min(state.lowLinks.get(frame.node)!, state.indexes.get(neighbor)!),\n );\n }\n return true;\n}\n\n/** Complete one Tarjan frame and emit its component when it is a root. */\nfunction completeTarjanFrame(\n frame: TarjanFrame,\n frames: TarjanFrame[],\n successors: Map<string, string[]>,\n state: TarjanState,\n): void {\n frames.pop();\n const parent = frames.at(-1);\n if (parent)\n state.lowLinks.set(\n parent.node,\n Math.min(\n state.lowLinks.get(parent.node)!,\n state.lowLinks.get(frame.node)!,\n ),\n );\n if (state.lowLinks.get(frame.node) !== state.indexes.get(frame.node)) return;\n const component: string[] = [];\n while (true) {\n const member = state.stack.pop()!;\n state.onStack.delete(member);\n component.push(member);\n if (member === frame.node) break;\n }\n if (\n component.length > 1 ||\n (component.length === 1 &&\n successors.get(component[0]!)?.includes(component[0]!))\n )\n state.components.push(\n component.sort((left, right) => left.localeCompare(right)),\n );\n}\n\n/**\n * Enumerate strongly connected components with more than one member over the\n * ordering-only digraph using an iterative Tarjan traversal. Only order-bearing\n * kinds participate: associative kinds such as `related` cannot create\n * execution-order contradictions and stay out of cycle analysis by policy.\n */\nfunction collectOrderingCycles(successors: Map<string, string[]>): string[][] {\n const state: TarjanState = {\n indexes: new Map(),\n lowLinks: new Map(),\n onStack: new Set(),\n stack: [],\n components: [],\n nextIndex: 0,\n };\n const roots = [...successors.keys()].sort((left, right) =>\n left.localeCompare(right),\n );\n for (const root of roots) {\n if (state.indexes.has(root)) continue;\n // Explicit frame stack keeps the traversal safe on deep dependency chains.\n const frames: TarjanFrame[] = [{ node: root, neighborIndex: 0 }];\n registerTarjanNode(root, state);\n while (frames.length > 0) {\n const frame = frames.at(-1)!;\n if (visitNextTarjanNeighbor(frame, frames, successors, state)) continue;\n completeTarjanFrame(frame, frames, successors, state);\n }\n }\n return state.components.sort((left, right) =>\n left[0]!.localeCompare(right[0]!),\n );\n}\n\n/** Format one dangling reference as a compact deterministic evidence string. */\nfunction formatDanglingReference(reference: {\n holder_id: string;\n target_id: string;\n kind: string;\n}): string {\n return `${reference.holder_id} -> ${reference.target_id} (${reference.kind})`;\n}\n\n/** Append one finding only when its subject collection is non-empty. */\nfunction appendFinding(\n findings: RelationshipAuditFinding[],\n subjects: readonly string[],\n maxSampleSize: number,\n code: RelationshipAuditFindingCode,\n severity: RelationshipAuditSeverity,\n policy: string,\n describe: (count: number) => string,\n remediation: string,\n): void {\n if (subjects.length === 0) return;\n findings.push(\n buildFinding(\n code,\n severity,\n policy,\n describe,\n subjects,\n maxSampleSize,\n remediation,\n ),\n );\n}\n\n/** Collect dangling-reference and retired-sentinel governance findings. */\nfunction collectIntegrityFindings(\n assembly: WorkspaceRelationshipAssembly,\n isTerminal: (status: string) => boolean,\n maxSampleSize: number,\n): RelationshipAuditFinding[] {\n const findings: RelationshipAuditFinding[] = [];\n const references = [\n ...assembly.dangling.active,\n ...assembly.dangling.legacy_terminal,\n ].filter((reference) => !reference.no_active_blocker_sentinel);\n appendFinding(\n findings,\n references\n .filter((reference) => !isTerminal(reference.holder_status))\n .map(formatDanglingReference),\n maxSampleSize,\n \"missing_reference_active\",\n \"error\",\n \"Active items must not reference absent targets; missing prerequisites distort scheduling.\",\n (count) => `${count} active dangling reference(s) to absent items`,\n \"Restore or re-create the referenced item, or remove/retype the reference on the holder.\",\n );\n appendFinding(\n findings,\n references\n .filter((reference) => isTerminal(reference.holder_status))\n .map(formatDanglingReference),\n maxSampleSize,\n \"missing_reference_terminal\",\n \"info\",\n \"Terminal items may retain historical references, but absent targets remain unexplainable context.\",\n (count) => `${count} terminal dangling reference(s) to absent items`,\n \"Leave as history debt or clean up in a dedicated changelog-safe closed-item batch.\",\n );\n appendFinding(\n findings,\n assembly.dangling.no_active_blocker_sentinels.map(formatDanglingReference),\n maxSampleSize,\n \"legacy_no_blocker_sentinel\",\n \"info\",\n \"The pre-structured-dependency no-active-blocker sentinel is retired; real edges carry blocker state.\",\n (count) => `${count} legacy no-active-blocker sentinel reference(s)`,\n \"Delete the sentinel reference; blocker state is derived from blocked_by edges.\",\n );\n return findings;\n}\n\n/** Decide whether one audited node still participates in active scheduling. */\nfunction isActiveAuditMember(\n member: string,\n nodeStates: Map<string, AuditNodeState>,\n): boolean {\n const state = nodeStates.get(member);\n // A trimmed or custom assembly may omit a member's details. Treat that\n // unknown lifecycle conservatively as active so contradictions are never\n // silently downgraded to legacy history debt.\n if (!state) return true;\n return !state.terminal;\n}\n\n/** Collect ordering-cycle and lifecycle-block governance findings. */\nfunction collectOrderingFindings(\n assembly: WorkspaceRelationshipAssembly,\n nodeStates: Map<string, AuditNodeState>,\n isBlocked: (status: string) => boolean,\n maxSampleSize: number,\n): RelationshipAuditFinding[] {\n const findings: RelationshipAuditFinding[] = [];\n const orderingAdjacency = buildOrderingAdjacency(assembly);\n for (const cycle of collectOrderingCycles(orderingAdjacency)) {\n // A cycle whose members are all terminal is a historical contradiction:\n // it cannot make live work unschedulable, and \"repairing\" it would touch\n // closed items (changelog drag), so it downgrades to informational debt.\n const active = cycle.some((member) =>\n isActiveAuditMember(member, nodeStates),\n );\n findings.push(\n active\n ? buildFinding(\n \"ordering_cycle\",\n \"error\",\n \"Order-bearing relationship kinds must stay acyclic; a cycle makes every member unschedulable.\",\n (count) => `execution-order cycle across ${count} item(s)`,\n cycle,\n maxSampleSize,\n \"Remove or retype one ordering edge inside the cycle, or split the work so precedence is linear.\",\n )\n : buildFinding(\n \"legacy_ordering_cycle\",\n \"info\",\n \"Ordering cycles between exclusively terminal items are historical contradictions with no scheduling effect.\",\n (count) => `terminal-only execution-order cycle across ${count} item(s)`,\n cycle,\n maxSampleSize,\n \"Leave as history debt, or clean up in a dedicated changelog-safe closed-item batch; never repair closed items ad hoc.\",\n ),\n );\n }\n const predecessorsByNode = new Map<string, string[]>();\n for (const [predecessor, adjacent] of orderingAdjacency)\n for (const successor of adjacent) {\n const predecessors = predecessorsByNode.get(successor);\n if (predecessors) predecessors.push(predecessor);\n else predecessorsByNode.set(successor, [predecessor]);\n }\n const staleLifecycleBlocks = [...nodeStates.values()]\n .filter(\n (state) =>\n !state.missing &&\n !state.terminal &&\n isBlocked(state.status) &&\n !(predecessorsByNode.get(state.id) ?? []).some((predecessor) => {\n const predecessorState = nodeStates.get(predecessor);\n // A trimmed/custom assembly may omit predecessor details. Treat that\n // unknown state conservatively as potentially open instead of\n // falsely declaring the lifecycle block stale.\n return predecessorState === undefined || !predecessorState.terminal;\n }),\n )\n .map((state) => state.id);\n appendFinding(\n findings,\n staleLifecycleBlocks,\n maxSampleSize,\n \"stale_lifecycle_block\",\n \"warning\",\n \"A blocked lifecycle status must be backed by at least one open ordering predecessor.\",\n (count) => `${count} status-blocked item(s) with no open blocker edge`,\n \"Re-open the missing prerequisite as an edge, or move the item back to an active status.\",\n );\n return findings;\n}\n\n/** One duplicate-edge group in semantic orientation with its stored spellings. */\nexport interface DuplicateRelationshipEdgeGroup {\n /** Semantic tail node shared by every stored spelling. */\n from: string;\n /** Semantic head node shared by every stored spelling. */\n to: string;\n /** Stored parallel edges sorted by kind. */\n edges: RelationshipEdge[];\n}\n\n/** Format one duplicate-edge group as a compact deterministic evidence string. */\nexport function formatDuplicateEdgeGroup(\n group: DuplicateRelationshipEdgeGroup,\n): string {\n const kinds = group.edges\n .map((edge) => edge.kind)\n .sort((left, right) => left.localeCompare(right));\n return `${group.from} -> ${group.to} (${kinds.join(\" + \")})`;\n}\n\n/**\n * Collect the groups of parallel same-family stored edges over the directed\n * ordering and hierarchy families. Each family joins a kind with its inverse\n * spelling in semantic orientation, so a reciprocal pair such as\n * `A blocked_by B` plus `B blocks A` collapses onto one oriented endpoint\n * pair. Only groups holding at least two stored spellings are returned, in\n * deterministic orientation order with per-group edges sorted by kind, source,\n * then target — the exact stored identities remediation planning targets.\n */\nexport function collectDuplicateRelationshipEdgeGroups(\n assembly: WorkspaceRelationshipAssembly,\n): DuplicateRelationshipEdgeGroup[] {\n const registry = assembly.graph.registry();\n const groups = new Map<string, DuplicateRelationshipEdgeGroup>();\n for (const edge of assembly.graph.edges()) {\n const definition = registry.require(edge.kind);\n if (!isTransitiveKind(definition)) continue;\n const oriented = orientTransitiveEdge(edge, definition);\n if (oriented.from === oriented.to) continue;\n const key = `${transitiveFamilyKey(definition)}::${oriented.from}::${oriented.to}`;\n const group = groups.get(key);\n if (group) group.edges.push(edge);\n else groups.set(key, { ...oriented, edges: [edge] });\n }\n const duplicated = [...groups.values()].filter(\n (group) => group.edges.length >= 2,\n );\n // Within one oriented group every stored spelling has a distinct kind: a\n // same-kind restatement of the same oriented pair would carry identical\n // endpoints and is deduplicated by edge identity during graph construction.\n for (const group of duplicated)\n group.edges.sort((left, right) => left.kind.localeCompare(right.kind));\n return duplicated.sort(\n (left, right) =>\n left.from.localeCompare(right.from) || left.to.localeCompare(right.to),\n );\n}\n\n/**\n * Collect duplicate stored-edge findings from the oriented duplicate groups.\n * Transitive-reduction redundancy analysis deliberately skips the direct edge\n * under test, so these exact parallels are invisible there and this is the\n * only surface that reports them.\n */\nfunction collectDuplicateEdgeFindings(\n assembly: WorkspaceRelationshipAssembly,\n nodeStates: Map<string, AuditNodeState>,\n maxSampleSize: number,\n): RelationshipAuditFinding[] {\n const active: string[] = [];\n const legacy: string[] = [];\n for (const group of collectDuplicateRelationshipEdgeGroups(assembly)) {\n const subjects =\n isActiveAuditMember(group.from, nodeStates) ||\n isActiveAuditMember(group.to, nodeStates)\n ? active\n : legacy;\n subjects.push(formatDuplicateEdgeGroup(group));\n }\n const findings: RelationshipAuditFinding[] = [];\n appendFinding(\n findings,\n active,\n maxSampleSize,\n \"duplicate_edge\",\n \"info\",\n \"One semantic relationship should be stored once; parallel same-family spellings (reciprocal inverse pairs included) add no information and skew degree metrics.\",\n (count) => `${count} duplicated relationship(s) between active endpoints`,\n \"Remove all but one stored spelling of the relationship; keep the canonical direction the holder declared first.\",\n );\n appendFinding(\n findings,\n legacy,\n maxSampleSize,\n \"legacy_duplicate_edge\",\n \"info\",\n \"Duplicated spellings between exclusively terminal items are historical noise with no scheduling effect.\",\n (count) => `${count} duplicated relationship(s) between terminal endpoints`,\n \"Leave as history debt or clean up in a dedicated changelog-safe closed-item batch.\",\n );\n return findings;\n}\n\n/** Compute structural coverage metrics and coverage-policy findings. */\nfunction collectCoverageReport(\n assembly: WorkspaceRelationshipAssembly,\n nodeStates: Map<string, AuditNodeState>,\n exemptIsolates: Set<string>,\n maxSampleSize: number,\n edgesByKind: Record<string, number>,\n): RelationshipAuditReport {\n let activeNodes = 0;\n let missingNodes = 0;\n let isolatedActiveNodes = 0;\n let degreeLeqOneActive = 0;\n const isolates: string[] = [];\n const sparse: string[] = [];\n for (const id of assembly.graph.nodes()) {\n const state = nodeStates.get(id);\n /* c8 ignore next -- every graph node originates from assembly details by construction */\n if (!state) continue;\n if (state.missing) {\n missingNodes += 1;\n continue;\n }\n if (state.terminal) continue;\n activeNodes += 1;\n const degree = assembly.graph.incidentEdges(id).length;\n if (degree > 1) continue;\n degreeLeqOneActive += 1;\n if (degree === 0) isolatedActiveNodes += 1;\n if (exemptIsolates.has(id.toLowerCase())) continue;\n if (degree === 0) isolates.push(id);\n else sparse.push(id);\n }\n const findings: RelationshipAuditFinding[] = [];\n appendFinding(\n findings,\n isolates,\n maxSampleSize,\n \"isolated_active_node\",\n \"warning\",\n \"Active work should be reachable from the graph unless explicitly declared a valid isolate.\",\n (count) => `${count} active item(s) with no relationships`,\n \"Link the item to its parent, prerequisite, or origin — or register it as an exempt isolate.\",\n );\n appendFinding(\n findings,\n sparse,\n maxSampleSize,\n \"sparse_active_node\",\n \"info\",\n \"Active items with a single edge often miss an honest semantic partner; sparse is not automatically defective.\",\n (count) => `${count} active item(s) with exactly one relationship`,\n \"Investigate for an honest second edge (story->task, defect family, cross-epic complement); do not fabricate one.\",\n );\n return {\n findings,\n profile: {\n nodes: assembly.graph.nodes().length,\n edges: assembly.graph.edges().length,\n edges_by_kind: Object.fromEntries(\n Object.entries(edgesByKind).sort(([left], [right]) =>\n left.localeCompare(right),\n ),\n ),\n active_nodes: activeNodes,\n missing_nodes: missingNodes,\n isolated_active_nodes: isolatedActiveNodes,\n degree_leq_one_active_nodes: degreeLeqOneActive,\n },\n };\n}\n\n/**\n * Audit one assembled workspace relationship graph against the shared\n * governance policy and return deterministic machine-readable findings plus a\n * structural coverage profile.\n *\n * The audit is read-only and never proposes inventing an edge: integrity\n * findings report evidence for investigation, coverage findings honor explicit\n * isolate exemptions, and cycle findings enumerate the strongly connected\n * members so callers can decide which edge to retype, remove, or waive.\n */\nexport function auditWorkspaceRelationshipGraph(\n assembly: WorkspaceRelationshipAssembly,\n options: RelationshipAuditOptions = {},\n): RelationshipAuditReport {\n const isTerminal =\n options.isTerminal ??\n ((status: string) => status === \"closed\" || status === \"canceled\");\n const isBlocked =\n options.isBlocked ?? ((status: string) => status === \"blocked\");\n const maxSampleSize = options.maxSampleSize ?? DEFAULT_MAX_SAMPLE_SIZE;\n if (!Number.isInteger(maxSampleSize) || maxSampleSize < 1)\n throw new TypeError(\n `Invalid audit sample bound: ${String(options.maxSampleSize)}`,\n );\n const exemptIsolates = new Set(\n (options.exemptIsolates ?? [])\n .filter((id): id is string => typeof id === \"string\")\n .map((id) => id.trim().toLowerCase()),\n );\n const nodeStates = new Map<string, AuditNodeState>(\n assembly.details.map((detail) => [\n detail.id,\n {\n id: detail.id,\n status: detail.status,\n missing: assembly.missingIdSet.has(detail.id.toLowerCase()),\n terminal: isTerminal(detail.status),\n },\n ]),\n );\n options.signal?.throwIfAborted();\n\n const edgesByKind: Record<string, number> = {};\n for (const edge of assembly.graph.edges())\n edgesByKind[edge.kind] = (edgesByKind[edge.kind] ?? 0) + 1;\n const findings = collectIntegrityFindings(\n assembly,\n isTerminal,\n maxSampleSize,\n );\n options.signal?.throwIfAborted();\n findings.push(\n ...collectOrderingFindings(assembly, nodeStates, isBlocked, maxSampleSize),\n );\n options.signal?.throwIfAborted();\n findings.push(\n ...collectDuplicateEdgeFindings(assembly, nodeStates, maxSampleSize),\n );\n options.signal?.throwIfAborted();\n const coverage = collectCoverageReport(\n assembly,\n nodeStates,\n exemptIsolates,\n maxSampleSize,\n edgesByKind,\n );\n findings.push(...coverage.findings);\n\n findings.sort(\n (left, right) =>\n SEVERITY_RANK[left.severity] - SEVERITY_RANK[right.severity] ||\n left.code.localeCompare(right.code) ||\n left.sample[0]!.localeCompare(right.sample[0]!),\n );\n return {\n findings,\n profile: coverage.profile,\n };\n}\n","/**\n * @module sdk/graph/remediation\n *\n * Dry-run remediation planning over the relationship governance audit. The\n * planner turns bounded audit findings and transitive-redundancy evidence into\n * exact, machine-readable proposed operations — remove, retype, supersede,\n * waive, or investigate — each carrying its policy code, evidence, confidence,\n * and rationale. Planning never mutates the workspace and never invents an\n * edge: proposals with structural proof (duplicates, retired sentinels,\n * witnessed shortcuts) get actionable operations, while judgment calls stay\n * explicit `investigate` steps for a human or agent to resolve.\n */\nimport type { RelationshipEdge } from \"../relationships.js\";\nimport { findRedundantRelationshipEdges } from \"./analytics.js\";\nimport type { WorkspaceRelationshipAssembly } from \"./assembly.js\";\nimport {\n auditWorkspaceRelationshipGraph,\n collectDuplicateRelationshipEdgeGroups,\n formatDuplicateEdgeGroup,\n type DuplicateRelationshipEdgeGroup,\n type RelationshipAuditFinding,\n type RelationshipAuditFindingCode,\n type RelationshipAuditOptions,\n type RelationshipAuditReport,\n} from \"./governance.js\";\n\n/** Exact operation family a remediation step proposes; audits never auto-apply. */\nexport type RelationshipRemediationOperation =\n | \"add\"\n | \"remove\"\n | \"retype\"\n | \"supersede\"\n | \"waive\"\n | \"investigate\";\n\n/** Planner confidence that applying the proposed operation is safe and correct. */\nexport type RelationshipRemediationConfidence = \"high\" | \"medium\" | \"low\";\n\n/** Policy source a remediation step was derived from. */\nexport type RelationshipRemediationCode =\n | RelationshipAuditFindingCode\n | \"redundant_edge\";\n\n/** One exact dry-run remediation proposal with evidence and confidence. */\nexport interface RelationshipRemediationStep {\n /** Proposed operation family. */\n op: RelationshipRemediationOperation;\n /** Audit finding code or `redundant_edge` for witnessed transitive shortcuts. */\n code: RelationshipRemediationCode;\n /** Compact deterministic subject — the edge, reference, or node to act on. */\n subject: string;\n /** Why this operation is proposed and what applying it means. */\n rationale: string;\n /** Deterministic evidence strings backing the proposal. */\n evidence: string[];\n /** Planner confidence in the proposal. */\n confidence: RelationshipRemediationConfidence;\n}\n\n/** Tuning inputs accepted by dry-run remediation planning. */\nexport interface RelationshipRemediationPlanOptions\n extends RelationshipAuditOptions {\n /** Maximum witnessed redundant edges scanned into proposals; defaults to the audit sample bound. */\n redundancyLimit?: number;\n}\n\n/** Complete deterministic result of one dry-run remediation planning pass. */\nexport interface RelationshipRemediationPlan {\n /** Proposed steps in audit severity order, redundancy proposals last. */\n steps: RelationshipRemediationStep[];\n /** The governance-audit report the plan was derived from. */\n report: RelationshipAuditReport;\n /** Whether bounded samples or scan limits omitted derivable proposals. */\n truncated: boolean;\n /** Nodes visited and edges inspected by the redundancy witness scan. */\n cost: { visitedNodes: number; inspectedEdges: number };\n}\n\n/** Per-finding-code operation template applied to every sampled subject. */\nconst FINDING_STEP_TEMPLATES: Record<\n RelationshipAuditFindingCode,\n {\n op: RelationshipRemediationOperation;\n confidence: RelationshipRemediationConfidence;\n rationale: string;\n }\n> = {\n missing_reference_active: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Restore or re-create the referenced item, or remove/retype the reference on the active holder; the correct fix depends on why the target is absent.\",\n },\n missing_reference_terminal: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Terminal-holder reference to an absent item is historical debt; waive it or clean it up only in a dedicated changelog-safe closed-item batch.\",\n },\n legacy_no_blocker_sentinel: {\n op: \"remove\",\n confidence: \"high\",\n rationale:\n \"The pre-structured-dependency no-active-blocker sentinel is retired and carries no information; blocker state derives from blocked_by edges.\",\n },\n ordering_cycle: {\n op: \"investigate\",\n confidence: \"low\",\n rationale:\n \"Every cycle member is unschedulable until one ordering edge is removed or retyped; the planner never chooses which edge to cut.\",\n },\n legacy_ordering_cycle: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Terminal-only ordering cycles have no scheduling effect; repairing them would mutate closed history (changelog drag).\",\n },\n // duplicate_edge findings are expanded into per-stored-edge remove steps by\n // the planner itself (see stepsFromDuplicateGroup); this template documents\n // the family for exhaustiveness and backs any future sample-only fallback.\n duplicate_edge: {\n op: \"remove\",\n confidence: \"high\",\n rationale:\n \"Parallel same-family spellings state one relationship twice; remove all but one stored spelling, keeping the holder's canonical direction.\",\n },\n legacy_duplicate_edge: {\n op: \"waive\",\n confidence: \"high\",\n rationale:\n \"Duplicated spellings between terminal items are historical noise; waive or batch changelog-safe cleanup.\",\n },\n stale_lifecycle_block: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Re-open the missing prerequisite as an ordering edge, or move the item back to an active status; only the holder's owner knows which is true.\",\n },\n isolated_active_node: {\n op: \"investigate\",\n confidence: \"medium\",\n rationale:\n \"Link the item to its parent, prerequisite, or origin — or register it as an explicitly exempt isolate; the audit never fabricates an edge.\",\n },\n sparse_active_node: {\n op: \"investigate\",\n confidence: \"low\",\n rationale:\n \"Investigate for an honest second edge (story-to-task, defect family, cross-epic complement); sparse is not automatically defective.\",\n },\n};\n\n/** Format one stored edge as a concrete removable identity. */\nfunction formatStoredEdge(edge: RelationshipEdge): string {\n return `${edge.source} -${edge.kind}-> ${edge.target}`;\n}\n\n/**\n * Expand one active duplicate group into concrete per-stored-edge removals.\n * The deterministic keeper is the group's first sorted edge; every other\n * stored spelling gets its own remove proposal naming the exact edge to drop,\n * so the plan stays machine-executable instead of pointing at a display\n * string that spans several stored rows.\n */\nfunction stepsFromDuplicateGroup(\n group: DuplicateRelationshipEdgeGroup,\n): RelationshipRemediationStep[] {\n const [keeper, ...extras] = group.edges;\n return extras.map((edge) => ({\n op: \"remove\" as const,\n code: \"duplicate_edge\" as const,\n subject: formatStoredEdge(edge),\n rationale:\n \"This stored spelling restates the kept canonical edge of the same semantic family; removing it leaves the relationship stated exactly once.\",\n evidence: [\n `keep: ${formatStoredEdge(keeper!)}`,\n `group: ${formatDuplicateEdgeGroup(group)}`,\n ],\n confidence: \"high\" as const,\n }));\n}\n\n/** Derive one proposal per bounded sample subject of an audit finding. */\nfunction stepsFromFinding(\n finding: RelationshipAuditFinding,\n duplicateGroups: Map<string, DuplicateRelationshipEdgeGroup>,\n): RelationshipRemediationStep[] {\n if (finding.code === \"duplicate_edge\") {\n // Sample subjects are the deterministic group format strings, so each one\n // resolves to its concrete stored-edge group for exact removal targeting.\n return finding.sample.flatMap((subject) =>\n stepsFromDuplicateGroup(duplicateGroups.get(subject)!),\n );\n }\n const template = FINDING_STEP_TEMPLATES[finding.code];\n return finding.sample.map((subject) => ({\n op: template.op,\n code: finding.code,\n subject,\n rationale: template.rationale,\n evidence: [finding.policy],\n confidence: template.confidence,\n }));\n}\n\n/**\n * Build one deterministic dry-run remediation plan over an assembled workspace\n * relationship graph. The plan runs the shared governance audit, derives one\n * exact proposal per bounded finding subject, then appends witnessed\n * transitive-shortcut removal proposals from the redundancy scan (medium\n * confidence, because shortcut edges are sometimes deliberate emphasis).\n * `truncated` reports whether sample or scan bounds omitted derivable steps;\n * nothing is ever applied automatically.\n */\nexport function planRelationshipRemediation(\n assembly: WorkspaceRelationshipAssembly,\n options: RelationshipRemediationPlanOptions = {},\n): RelationshipRemediationPlan {\n const { redundancyLimit, ...auditOptions } = options;\n const report = auditWorkspaceRelationshipGraph(assembly, auditOptions);\n const duplicateGroups = new Map(\n collectDuplicateRelationshipEdgeGroups(assembly).map((group) => [\n formatDuplicateEdgeGroup(group),\n group,\n ]),\n );\n const steps = report.findings.flatMap((finding) =>\n stepsFromFinding(finding, duplicateGroups),\n );\n let truncated = report.findings.some((finding) => finding.sample_truncated);\n options.signal?.throwIfAborted();\n const redundancy = findRedundantRelationshipEdges(assembly.graph, {\n limit: redundancyLimit ?? options.maxSampleSize ?? 25,\n ...(options.signal === undefined ? {} : { signal: options.signal }),\n });\n for (const row of redundancy.value) {\n steps.push({\n op: \"remove\",\n code: \"redundant_edge\",\n subject: `${row.edge.source} -> ${row.edge.target} (${row.edge.kind})`,\n rationale:\n \"The stored edge is implied by a longer same-family witness path; shortcut edges are sometimes deliberate emphasis, so confirm intent before removing.\",\n evidence: [`witness: ${row.witness.join(\" -> \")}`],\n confidence: \"medium\",\n });\n }\n truncated = truncated || redundancy.meta.truncated;\n return {\n steps,\n report,\n truncated,\n cost: {\n visitedNodes: redundancy.meta.visitedNodes,\n inspectedEdges: redundancy.meta.inspectedEdges,\n },\n };\n}\n","/**\n * @module sdk/graph/run\n *\n * Workspace-facing `pm graph` runner: one thin orchestrator that loads the\n * tracker once, resolves the fingerprint-keyed workspace assembly through the\n * shared graph cache, and dispatches bounded traversal, path, impact,\n * analytics, governance-audit, and remediation-planning queries through the\n * public graph toolkit. Every projection is counts-first, deterministic, and\n * carries explicit cost, truncation, and cache metadata so agents can budget\n * follow-up reads without re-scanning the workspace; identical repeated\n * queries in long-lived hosts are answered from the memoized snapshot.\n */\nimport { getActiveExtensionRegistrations } from \"../../core/extensions/index.js\";\nimport { pathExists } from \"../../core/fs/fs-utils.js\";\nimport { isTerminalStatus } from \"../../core/item/status.js\";\nimport { resolveItemTypeRegistry } from \"../../core/item/type-registry.js\";\nimport { resolveRuntimeStatusRegistry } from \"../../core/schema/runtime-schema.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { EXIT_CODE } from \"../../core/shared/constants.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport { listAllItemMetadataLight } from \"../../core/store/item-store.js\";\nimport { getSettingsPath, resolvePmRoot } from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport {\n parseDirection,\n parseKinds,\n parseMaxDepth,\n parsePositiveInteger,\n} from \"../dependencies.js\";\nimport {\n analyzeGraphImpact,\n analyzeKnowledgeGraph,\n analyzeRelationshipExecution,\n} from \"../relationship-analytics.js\";\nimport type { RelationshipQueryMeta } from \"../relationships.js\";\nimport {\n computeRelationshipDominators,\n detectRelationshipCommunities,\n findRedundantRelationshipEdges,\n} from \"./analytics.js\";\nimport {\n assembleWorkspaceRelationshipGraph,\n type WorkspaceRelationshipAssembly,\n} from \"./assembly.js\";\nimport {\n computeWorkspaceGraphFingerprint,\n workspaceGraphCache,\n type GraphCacheMetadata,\n} from \"./cache.js\";\nimport {\n auditWorkspaceRelationshipGraph,\n type RelationshipAuditReport,\n} from \"./governance.js\";\nimport {\n planRelationshipRemediation,\n type RelationshipRemediationStep,\n} from \"./remediation.js\";\nimport {\n enumerateRelationshipPaths,\n hierarchyAncestors,\n hierarchyDescendants,\n orderingPredecessors,\n orderingSuccessors,\n} from \"./traversal.js\";\n\nimport {\n GRAPH_SUBCOMMAND_VALUES,\n type GraphSubcommand,\n} from \"../cli-contracts/enum-contracts.js\";\n\nexport { GRAPH_SUBCOMMAND_VALUES, type GraphSubcommand };\n\n/** Graph subcommands that require a root item id. */\nconst ROOTED_SUBCOMMANDS = new Set<GraphSubcommand>([\n \"ancestors\",\n \"descendants\",\n \"predecessors\",\n \"successors\",\n \"paths\",\n \"impact\",\n \"dominators\",\n]);\n\n/** Default bounded sample rows returned by analyze/audit projections. */\nconst DEFAULT_SAMPLE_LIMIT = 10;\n\n/** Documents the graph command options payload exchanged by command, SDK, and package integrations. */\nexport interface GraphCommandOptions {\n /** Restricts traversal to registered relationship kinds (repeatable or comma-separated). */\n kind?: string | string[];\n /** Maximum traversal depth as a non-negative integer. */\n maxDepth?: string | number;\n /** Maximum returned rows per bounded collection. */\n limit?: string | number;\n /** Resume a traversal after this previously returned node id. */\n after?: string;\n /** Edge orientation for paths and impact queries (outgoing, incoming, or both). */\n direction?: string;\n /** Maximum enumerated paths for the paths subcommand. */\n maxPaths?: string | number;\n /** Maximum evidence sample entries per audit finding. */\n sample?: string | number;\n /** Item ids treated as explicitly valid isolates by the audit. */\n exemptIsolate?: string | string[];\n /** Return counts-first envelopes without row collections. */\n summary?: boolean;\n}\n\n/** Cost metadata attached to every graph query projection. */\nexport interface GraphQueryCost {\n /** Nodes expanded while answering the query. */\n visited_nodes: number;\n /** Edges inspected while answering the query. */\n inspected_edges: number;\n}\n\n/** Result envelope for the transitive traversal subcommands. */\nexport interface GraphTraversalResult {\n /** Executed graph subcommand. */\n subcommand: \"ancestors\" | \"descendants\" | \"predecessors\" | \"successors\";\n /** Canonical root item id. */\n root: string;\n /** Total emitted node ids before summary suppression. */\n count: number;\n /** Whether configured bounds omitted reachable work. */\n truncated: boolean;\n /** Cursor resuming emission after the last returned node. */\n next_cursor?: string;\n /** Query cost metadata. */\n cost: GraphQueryCost;\n /** Emitted node ids in deterministic breadth-first order; absent with summary. */\n ids?: string[];\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** One enumerated path projected with relationship kinds instead of raw edges. */\nexport interface GraphPathRow {\n /** Ordered node ids from source to target inclusive. */\n nodes: string[];\n /** Relationship kind of each traversed edge, in path order. */\n kinds: string[];\n /** Number of edges in the path. */\n length: number;\n}\n\n/** Result envelope for the paths subcommand. */\nexport interface GraphPathsResult {\n /** Executed graph subcommand. */\n subcommand: \"paths\";\n /** Canonical source item id. */\n root: string;\n /** Canonical target item id. */\n target: string;\n /** Traversal orientation used for the enumeration. */\n direction: string;\n /** Total enumerated paths before summary suppression. */\n count: number;\n /** Whether depth, path-count, or safety bounds stopped the search early. */\n truncated: boolean;\n /** Query cost metadata. */\n cost: GraphQueryCost;\n /** Enumerated paths, shortest first; absent with summary. */\n paths?: GraphPathRow[];\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** One affected item row in an impact projection. */\nexport interface GraphImpactRow {\n /** Affected item id. */\n id: string;\n /** Shortest relationship distance from the root. */\n distance: number;\n /** Exact node path explaining why the item is affected. */\n path: string[];\n}\n\n/** Result envelope for the impact subcommand. */\nexport interface GraphImpactResult {\n /** Executed graph subcommand. */\n subcommand: \"impact\";\n /** Canonical impact-origin item id. */\n root: string;\n /** Traversal orientation used for the blast-radius walk. */\n direction: string;\n /** Total affected items before summary suppression. */\n count: number;\n /** Whether configured bounds omitted reachable work. */\n truncated: boolean;\n /** Query cost metadata. */\n cost: GraphQueryCost;\n /** Affected item rows ordered by discovery; absent with summary. */\n affected?: GraphImpactRow[];\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** Bounded execution-graph projection inside an analyze result. */\nexport interface GraphExecutionSummary {\n /** Whether the order-bearing graph is acyclic. */\n acyclic: boolean;\n /** Nodes participating in the topological order. */\n ordered_node_count: number;\n /** Number of parallelizable topological layers. */\n layer_count: number;\n /** Total items with no open prerequisites. */\n frontier_count: number;\n /** Bounded prerequisite-free sample; absent with summary. */\n frontier?: string[];\n /** Edge count of the longest execution path. */\n critical_path_length: number;\n /** Longest deterministic execution path; absent with summary. */\n critical_path?: string[];\n /** Total genuine ordering cycles. */\n cycle_count: number;\n /** Bounded ordering-cycle sample; absent with summary. */\n cycles?: string[][];\n}\n\n/** Bounded knowledge-graph projection inside an analyze result. */\nexport interface GraphKnowledgeSummary {\n /** Total weakly connected components. */\n component_count: number;\n /** Node count of the largest component. */\n largest_component_size: number;\n /** Total nodes without any relationship edges. */\n orphan_count: number;\n /** Bounded orphan sample; absent with summary. */\n orphans?: string[];\n /** Bounded maximum-degree hubs; absent with summary. */\n hubs?: { id: string; degree: number }[];\n}\n\n/** Result envelope for the analyze subcommand. */\nexport interface GraphAnalyzeResult {\n /** Executed graph subcommand. */\n subcommand: \"analyze\";\n /** Total indexed graph nodes. */\n node_count: number;\n /** Total deduplicated graph edges. */\n edge_count: number;\n /** Bound applied to every sample collection. */\n sample_limit: number;\n /** Execution-order analytics over registered ordering kinds. */\n execution: GraphExecutionSummary;\n /** Structural analytics over every stored edge. */\n knowledge: GraphKnowledgeSummary;\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** Result envelope for the audit subcommand. */\nexport interface GraphAuditResult {\n /** Executed graph subcommand. */\n subcommand: \"audit\";\n /** Total audit findings. */\n finding_count: number;\n /** Finding counts keyed by severity. */\n findings_by_severity: Record<string, number>;\n /** Finding-row counts keyed by finding code. Before 2026.7.19 this field incorrectly accumulated affected subjects; consumers of that unit must migrate to affected_subjects_by_code. */\n findings_by_code: Record<string, number>;\n /** Affected-subject counts keyed by severity. */\n affected_subjects_by_severity: Record<string, number>;\n /** Affected-subject counts keyed by finding code. */\n affected_subjects_by_code: Record<string, number>;\n /** Structural coverage metrics computed during the audit. */\n profile: RelationshipAuditReport[\"profile\"];\n /** Ordered findings with bounded evidence samples; absent with summary. */\n findings?: RelationshipAuditReport[\"findings\"];\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** One bounded community row projected by the communities subcommand. */\nexport interface GraphCommunityRow {\n /** Lexicographically smallest member id, naming the community. */\n representative: string;\n /** Total member count before sampling. */\n size: number;\n /** Bounded sorted member sample. */\n members: string[];\n}\n\n/** Result envelope for the communities subcommand. */\nexport interface GraphCommunitiesResult {\n /** Executed graph subcommand. */\n subcommand: \"communities\";\n /** Total detected communities meeting the size floor. */\n community_count: number;\n /** Member count of the largest community. */\n largest_community_size: number;\n /** Label-propagation sweeps executed. */\n iterations: number;\n /** Whether labels stabilized before the iteration bound. */\n converged: boolean;\n /** Whether the iteration bound stopped propagation early or the sample bound omitted rows. */\n truncated: boolean;\n /** Query cost metadata. */\n cost: GraphQueryCost;\n /** Bounded community rows, largest first; absent with summary. */\n communities?: GraphCommunityRow[];\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** One redundant stored edge projected with its witness path. */\nexport interface GraphRedundancyRow {\n /** Stored edge source id. */\n source: string;\n /** Stored edge target id. */\n target: string;\n /** Stored relationship kind. */\n kind: string;\n /** Semantic-orientation node path proving the edge is implied. */\n witness: string[];\n}\n\n/** Result envelope for the redundancy subcommand. */\nexport interface GraphRedundancyResult {\n /** Executed graph subcommand. */\n subcommand: \"redundancy\";\n /** Total redundant edges found within configured bounds. */\n redundant_count: number;\n /** Whether the row limit omitted further redundant edges. */\n truncated: boolean;\n /** Query cost metadata. */\n cost: GraphQueryCost;\n /** Redundant edge rows in deterministic scan order; absent with summary. */\n redundant?: GraphRedundancyRow[];\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** One structural bottleneck row projected by the dominators subcommand. */\nexport interface GraphDominatorRow {\n /** Bottleneck node id. */\n id: string;\n /** Immediate dominator appearing on every root-to-node path. */\n idom: string;\n /** Reachable nodes strictly gated by this node. */\n dominated_count: number;\n}\n\n/** Result envelope for the dominators subcommand. */\nexport interface GraphDominatorsResult {\n /** Executed graph subcommand. */\n subcommand: \"dominators\";\n /** Canonical analyzed root id. */\n root: string;\n /** Traversal orientation used for reachability. */\n direction: string;\n /** Reachable node count including the root. */\n reachable_count: number;\n /** Total nodes gating at least one other reachable node. */\n bottleneck_count: number;\n /** Whether the depth bound cut reachability or the row limit omitted bottleneck rows. */\n truncated: boolean;\n /** Query cost metadata. */\n cost: GraphQueryCost;\n /** Bounded bottleneck rows, most-gating first; absent with summary. */\n bottlenecks?: GraphDominatorRow[];\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** Result envelope for the dry-run remediation planning subcommand. */\nexport interface GraphPlanResult {\n /** Executed graph subcommand. */\n subcommand: \"plan\";\n /** Total derived remediation proposals before row bounding. */\n step_count: number;\n /** Proposal counts keyed by operation family. */\n steps_by_op: Record<string, number>;\n /** Proposal counts keyed by policy code. */\n steps_by_code: Record<string, number>;\n /** Total governance-audit findings the plan was derived from. */\n finding_count: number;\n /** Whether sample, scan, or row bounds omitted derivable proposals. */\n truncated: boolean;\n /** Query cost metadata. */\n cost: GraphQueryCost;\n /** Bounded proposal rows in audit severity order; absent with summary. */\n steps?: RelationshipRemediationStep[];\n /** Cache observability for this invocation. */\n cache?: GraphCacheMetadata;\n}\n\n/** Union of every graph subcommand result envelope. */\nexport type GraphResult =\n | GraphTraversalResult\n | GraphPathsResult\n | GraphImpactResult\n | GraphAnalyzeResult\n | GraphAuditResult\n | GraphCommunitiesResult\n | GraphRedundancyResult\n | GraphDominatorsResult\n | GraphPlanResult;\n\n/** Fully parsed graph invocation shared by the subcommand executors. */\ninterface GraphInvocation {\n /** Assembled workspace relationship graph and node details. */\n assembly: WorkspaceRelationshipAssembly;\n /** Canonical registered kind filters, when provided. */\n kinds?: string[];\n /** Parsed non-negative depth bound. */\n maxDepth?: number;\n /** Parsed positive row bound. */\n limit?: number;\n /** Traversal resume cursor. */\n after?: string;\n /** Validated traversal orientation. */\n direction: \"outgoing\" | \"incoming\" | \"both\";\n /** Parsed positive path-count bound. */\n maxPaths?: number;\n /** Parsed positive audit sample bound. */\n sample?: number;\n /** Normalized audit isolate exemptions. */\n exemptIsolates: string[];\n /** Whether row collections are suppressed. */\n summary: boolean;\n}\n\n/** Normalize repeatable or comma-separated id options into a flat list. */\nfunction normalizeIdList(raw: string | string[] | undefined): string[] {\n if (raw === undefined) return [];\n return (Array.isArray(raw) ? raw : [raw])\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter((value) => value.length > 0);\n}\n\n/** Validate the graph subcommand and its positional-id requirements. */\nexport function parseGraphSubcommand(\n raw: string,\n id: string | undefined,\n target: string | undefined,\n): GraphSubcommand {\n const candidate = raw.trim().toLowerCase();\n if (!(GRAPH_SUBCOMMAND_VALUES as readonly string[]).includes(candidate)) {\n throw new PmCliError(\n `Invalid graph subcommand \"${raw}\". Use one of: ${GRAPH_SUBCOMMAND_VALUES.join(\", \")}.`,\n EXIT_CODE.USAGE,\n );\n }\n const subcommand = candidate as GraphSubcommand;\n if (ROOTED_SUBCOMMANDS.has(subcommand) && !id?.trim()) {\n throw new PmCliError(\n `graph ${subcommand} requires an item id.`,\n EXIT_CODE.USAGE,\n );\n }\n if (subcommand === \"paths\" && !target?.trim()) {\n throw new PmCliError(\n \"graph paths requires a source and a target item id.\",\n EXIT_CODE.USAGE,\n );\n }\n return subcommand;\n}\n\n/**\n * Re-throw graph-kernel semantic option misuse (non-family kind, unknown\n * cursor, non-transitive redundancy kind) as a usage error carrying the\n * original explanation instead of an opaque crash.\n */\nfunction rethrowGraphUsage(error: unknown): never {\n if (error instanceof TypeError)\n throw new PmCliError(error.message, EXIT_CODE.USAGE);\n throw error;\n}\n\n/** Convert traversal metadata into the shared cost/truncation projection. */\nfunction projectQueryMeta(meta: RelationshipQueryMeta): {\n truncated: boolean;\n cost: GraphQueryCost;\n} {\n return {\n truncated: meta.truncated,\n cost: {\n visited_nodes: meta.visitedNodes,\n inspected_edges: meta.inspectedEdges,\n },\n };\n}\n\n/** Resolve one item id case-insensitively against the assembled graph. */\nfunction canonicalizeGraphId(\n assembly: WorkspaceRelationshipAssembly,\n raw: string,\n): string {\n const wanted = raw.trim().toLowerCase();\n for (const detail of assembly.details) {\n if (\n detail.id.trim().toLowerCase() === wanted &&\n !assembly.missingIdSet.has(detail.id.toLowerCase())\n ) {\n return detail.id;\n }\n }\n throw new PmCliError(`Item ${raw} not found`, EXIT_CODE.NOT_FOUND);\n}\n\n/** Execute one transitive traversal subcommand over the assembled graph. */\nfunction runGraphTraversal(\n subcommand: \"ancestors\" | \"descendants\" | \"predecessors\" | \"successors\",\n root: string,\n invocation: GraphInvocation,\n): GraphTraversalResult {\n const walk = {\n ancestors: hierarchyAncestors,\n descendants: hierarchyDescendants,\n predecessors: orderingPredecessors,\n successors: orderingSuccessors,\n }[subcommand];\n let result;\n try {\n result = walk(invocation.assembly.graph, root, {\n ...(invocation.kinds === undefined ? {} : { kinds: invocation.kinds }),\n ...(invocation.maxDepth === undefined\n ? {}\n : { maxDepth: invocation.maxDepth }),\n ...(invocation.limit === undefined ? {} : { limit: invocation.limit }),\n ...(invocation.after === undefined ? {} : { after: invocation.after }),\n });\n } catch (error) {\n rethrowGraphUsage(error);\n }\n const meta = projectQueryMeta(result.meta);\n return {\n subcommand,\n root,\n count: result.value.length,\n ...meta,\n ...(result.meta.nextCursor === undefined\n ? {}\n : { next_cursor: result.meta.nextCursor }),\n ...(invocation.summary ? {} : { ids: result.value }),\n };\n}\n\n/** Execute the bounded simple-path enumeration subcommand. */\nfunction runGraphPaths(\n root: string,\n target: string,\n invocation: GraphInvocation,\n): GraphPathsResult {\n const result = enumerateRelationshipPaths(\n invocation.assembly.graph,\n root,\n target,\n {\n direction: invocation.direction,\n ...(invocation.kinds === undefined ? {} : { kinds: invocation.kinds }),\n ...(invocation.maxDepth === undefined\n ? {}\n : { maxDepth: invocation.maxDepth }),\n ...(invocation.maxPaths === undefined\n ? {}\n : { maxPaths: invocation.maxPaths }),\n },\n );\n return {\n subcommand: \"paths\",\n root,\n target,\n direction: invocation.direction,\n count: result.value.length,\n ...projectQueryMeta(result.meta),\n ...(invocation.summary\n ? {}\n : {\n paths: result.value.map((path) => ({\n nodes: path.nodes,\n kinds: path.edges.map((edge) => edge.kind),\n length: path.length,\n })),\n }),\n };\n}\n\n/** Execute the bounded blast-radius impact subcommand. */\nfunction runGraphImpact(\n root: string,\n invocation: GraphInvocation,\n): GraphImpactResult {\n const analysis = analyzeGraphImpact(invocation.assembly.graph, root, {\n direction: invocation.direction,\n ...(invocation.kinds === undefined ? {} : { kinds: invocation.kinds }),\n ...(invocation.maxDepth === undefined\n ? {}\n : { maxDepth: invocation.maxDepth }),\n ...(invocation.limit === undefined ? {} : { limit: invocation.limit }),\n });\n return {\n subcommand: \"impact\",\n root,\n direction: invocation.direction,\n count: analysis.affected.length,\n truncated: analysis.truncated,\n cost: {\n visited_nodes: analysis.cost.visitedNodes,\n inspected_edges: analysis.cost.inspectedEdges,\n },\n ...(invocation.summary ? {} : { affected: analysis.affected }),\n };\n}\n\n/** Execute the workspace-wide execution and knowledge analytics subcommand. */\nfunction runGraphAnalyze(invocation: GraphInvocation): GraphAnalyzeResult {\n const graph = invocation.assembly.graph;\n const sampleLimit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;\n const execution = analyzeRelationshipExecution(graph, {\n registry: graph.registry(),\n });\n const knowledge = analyzeKnowledgeGraph(graph);\n return {\n subcommand: \"analyze\",\n node_count: graph.nodes().length,\n edge_count: graph.edges().length,\n sample_limit: sampleLimit,\n execution: {\n acyclic: execution.acyclic,\n ordered_node_count: execution.order.length,\n layer_count: execution.layers.length,\n frontier_count: execution.frontier.length,\n critical_path_length: execution.criticalPathLength,\n cycle_count: execution.cycles.length,\n ...(invocation.summary\n ? {}\n : {\n frontier: execution.frontier.slice(0, sampleLimit),\n critical_path: execution.criticalPath.slice(0, sampleLimit),\n cycles: execution.cycles.slice(0, sampleLimit),\n }),\n },\n knowledge: {\n component_count: knowledge.components.length,\n largest_component_size: knowledge.components[0]?.length ?? 0,\n orphan_count: knowledge.orphans.length,\n ...(invocation.summary\n ? {}\n : {\n orphans: knowledge.orphans.slice(0, sampleLimit),\n hubs: knowledge.hubs.slice(0, sampleLimit),\n }),\n },\n };\n}\n\n/** Execute the governance-audit subcommand over the assembled graph. */\nfunction runGraphAudit(\n invocation: GraphInvocation,\n isTerminal: (status: string) => boolean,\n): GraphAuditResult {\n const report = auditWorkspaceRelationshipGraph(invocation.assembly, {\n isTerminal,\n ...(invocation.sample === undefined\n ? {}\n : { maxSampleSize: invocation.sample }),\n ...(invocation.exemptIsolates.length === 0\n ? {}\n : { exemptIsolates: invocation.exemptIsolates }),\n });\n const bySeverity: Record<string, number> = {};\n const byCode: Record<string, number> = {};\n const affectedBySeverity: Record<string, number> = {};\n const affectedByCode: Record<string, number> = {};\n for (const finding of report.findings) {\n bySeverity[finding.severity] = (bySeverity[finding.severity] ?? 0) + 1;\n byCode[finding.code] = (byCode[finding.code] ?? 0) + 1;\n affectedBySeverity[finding.severity] =\n (affectedBySeverity[finding.severity] ?? 0) + finding.count;\n affectedByCode[finding.code] =\n (affectedByCode[finding.code] ?? 0) + finding.count;\n }\n return {\n subcommand: \"audit\",\n finding_count: report.findings.length,\n findings_by_severity: bySeverity,\n findings_by_code: byCode,\n affected_subjects_by_severity: affectedBySeverity,\n affected_subjects_by_code: affectedByCode,\n profile: report.profile,\n ...(invocation.summary ? {} : { findings: report.findings }),\n };\n}\n\n/** Execute the deterministic community-detection subcommand. */\nfunction runGraphCommunities(\n invocation: GraphInvocation,\n): GraphCommunitiesResult {\n const sampleLimit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;\n const result = detectRelationshipCommunities(invocation.assembly.graph, {\n ...(invocation.kinds === undefined ? {} : { kinds: invocation.kinds }),\n });\n const analysis = result.value;\n return {\n subcommand: \"communities\",\n community_count: analysis.communities.length,\n largest_community_size: analysis.communities[0]?.size ?? 0,\n iterations: analysis.iterations,\n converged: analysis.converged,\n truncated: !analysis.converged || analysis.communities.length > sampleLimit,\n cost: {\n visited_nodes: result.meta.visitedNodes,\n inspected_edges: result.meta.inspectedEdges,\n },\n ...(invocation.summary\n ? {}\n : {\n communities: analysis.communities\n .slice(0, sampleLimit)\n .map((community) => ({\n representative: community.representative,\n size: community.size,\n members: community.members.slice(0, sampleLimit),\n })),\n }),\n };\n}\n\n/** Execute the transitive-redundancy scan subcommand. */\nfunction runGraphRedundancy(\n invocation: GraphInvocation,\n): GraphRedundancyResult {\n let result;\n try {\n result = findRedundantRelationshipEdges(invocation.assembly.graph, {\n ...(invocation.kinds === undefined ? {} : { kinds: invocation.kinds }),\n ...(invocation.maxDepth === undefined\n ? {}\n : { maxDepth: invocation.maxDepth }),\n ...(invocation.limit === undefined ? {} : { limit: invocation.limit }),\n });\n } catch (error) {\n rethrowGraphUsage(error);\n }\n return {\n subcommand: \"redundancy\",\n redundant_count: result.value.length,\n ...projectQueryMeta(result.meta),\n ...(invocation.summary\n ? {}\n : {\n redundant: result.value.map((row) => ({\n source: row.edge.source,\n target: row.edge.target,\n kind: row.edge.kind,\n witness: row.witness,\n })),\n }),\n };\n}\n\n/** Execute the dominator/bottleneck analysis subcommand. */\nfunction runGraphDominators(\n root: string,\n invocation: GraphInvocation,\n): GraphDominatorsResult {\n const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;\n const result = computeRelationshipDominators(\n invocation.assembly.graph,\n root,\n {\n direction: invocation.direction,\n ...(invocation.kinds === undefined ? {} : { kinds: invocation.kinds }),\n ...(invocation.maxDepth === undefined\n ? {}\n : { maxDepth: invocation.maxDepth }),\n },\n );\n const bottlenecks = result.value.rows.filter((row) => row.dominatedCount > 0);\n return {\n subcommand: \"dominators\",\n root,\n direction: invocation.direction,\n reachable_count: result.value.reachableCount,\n bottleneck_count: bottlenecks.length,\n truncated: result.meta.truncated || bottlenecks.length > limit,\n cost: {\n visited_nodes: result.meta.visitedNodes,\n inspected_edges: result.meta.inspectedEdges,\n },\n ...(invocation.summary\n ? {}\n : {\n bottlenecks: bottlenecks.slice(0, limit).map((row) => ({\n id: row.id,\n idom: row.idom,\n dominated_count: row.dominatedCount,\n })),\n }),\n };\n}\n\n/** Execute the dry-run remediation planning subcommand. */\nfunction runGraphPlan(\n invocation: GraphInvocation,\n isTerminal: (status: string) => boolean,\n): GraphPlanResult {\n const limit = invocation.limit ?? DEFAULT_SAMPLE_LIMIT;\n const plan = planRelationshipRemediation(invocation.assembly, {\n isTerminal,\n redundancyLimit: limit,\n ...(invocation.sample === undefined\n ? {}\n : { maxSampleSize: invocation.sample }),\n ...(invocation.exemptIsolates.length === 0\n ? {}\n : { exemptIsolates: invocation.exemptIsolates }),\n });\n const byOp: Record<string, number> = {};\n const byCode: Record<string, number> = {};\n for (const step of plan.steps) {\n byOp[step.op] = (byOp[step.op] ?? 0) + 1;\n byCode[step.code] = (byCode[step.code] ?? 0) + 1;\n }\n return {\n subcommand: \"plan\",\n step_count: plan.steps.length,\n steps_by_op: byOp,\n steps_by_code: byCode,\n finding_count: plan.report.findings.length,\n truncated: plan.truncated || plan.steps.length > limit,\n cost: {\n visited_nodes: plan.cost.visitedNodes,\n inspected_edges: plan.cost.inspectedEdges,\n },\n ...(invocation.summary ? {} : { steps: plan.steps.slice(0, limit) }),\n };\n}\n\n/** Build the deterministic memoization key covering every query-shaping input. */\nfunction buildGraphQueryKey(\n subcommand: GraphSubcommand,\n root: string | undefined,\n pathsTarget: string | undefined,\n invocation: GraphInvocation,\n): string {\n return JSON.stringify({\n subcommand,\n root: root ?? null,\n target: pathsTarget ?? null,\n kinds: invocation.kinds ?? null,\n maxDepth: invocation.maxDepth ?? null,\n limit: invocation.limit ?? null,\n after: invocation.after ?? null,\n direction: invocation.direction,\n maxPaths: invocation.maxPaths ?? null,\n sample: invocation.sample ?? null,\n // The audit consumes exemptions as a case-insensitive set, so the key\n // must not distinguish logically identical spellings or orderings.\n exemptIsolates: [\n ...new Set(invocation.exemptIsolates.map((id) => id.toLowerCase())),\n ].sort(),\n summary: invocation.summary,\n });\n}\n\n/** Dispatch one parsed graph subcommand to its executor. */\nfunction executeGraphSubcommand(\n subcommand: GraphSubcommand,\n root: string | undefined,\n pathsTarget: string | undefined,\n invocation: GraphInvocation,\n isTerminal: (status: string) => boolean,\n): GraphResult {\n if (subcommand === \"analyze\") return runGraphAnalyze(invocation);\n if (subcommand === \"audit\") return runGraphAudit(invocation, isTerminal);\n if (subcommand === \"plan\") return runGraphPlan(invocation, isTerminal);\n if (subcommand === \"communities\") return runGraphCommunities(invocation);\n if (subcommand === \"redundancy\") return runGraphRedundancy(invocation);\n if (subcommand === \"dominators\") return runGraphDominators(root!, invocation);\n if (subcommand === \"paths\")\n return runGraphPaths(root!, pathsTarget!, invocation);\n if (subcommand === \"impact\") return runGraphImpact(root!, invocation);\n return runGraphTraversal(subcommand, root!, invocation);\n}\n\n/** Implements run graph for the public runtime surface of this module. */\nexport async function runGraph(\n subcommandRaw: string,\n id: string | undefined,\n target: string | undefined,\n options: GraphCommandOptions,\n global: GlobalOptions,\n): Promise<GraphResult> {\n const subcommand = parseGraphSubcommand(subcommandRaw, id, target);\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(\n `Tracker is not initialized at ${pmRoot}. Run pm init first.`,\n EXIT_CODE.NOT_FOUND,\n );\n }\n const settings = await readSettings(pmRoot);\n const typeRegistry = resolveItemTypeRegistry(\n settings,\n getActiveExtensionRegistrations(),\n );\n const items = await listAllItemMetadataLight(\n pmRoot,\n settings.item_format,\n typeRegistry.type_to_folder,\n undefined,\n settings.schema,\n );\n const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);\n const isTerminal = (status: string): boolean =>\n isTerminalStatus(status, statusRegistry);\n const kinds = parseKinds(options.kind);\n const lookup = workspaceGraphCache().lookup(\n pmRoot,\n computeWorkspaceGraphFingerprint(items, isTerminal),\n () => assembleWorkspaceRelationshipGraph(items, isTerminal),\n );\n const invocation: GraphInvocation = {\n assembly: lookup.assembly,\n ...(kinds === undefined ? {} : { kinds }),\n maxDepth: parseMaxDepth(options.maxDepth),\n limit: parsePositiveInteger(options.limit, \"limit\"),\n after: options.after?.trim() || undefined,\n direction: parseDirection(options.direction),\n maxPaths: parsePositiveInteger(options.maxPaths, \"max-paths\"),\n sample: parsePositiveInteger(options.sample, \"sample\"),\n exemptIsolates: normalizeIdList(options.exemptIsolate),\n summary: options.summary === true,\n };\n const root = ROOTED_SUBCOMMANDS.has(subcommand)\n ? canonicalizeGraphId(invocation.assembly, id!)\n : undefined;\n const pathsTarget =\n subcommand === \"paths\"\n ? canonicalizeGraphId(invocation.assembly, target!)\n : undefined;\n const memo = lookup.memoize(\n buildGraphQueryKey(subcommand, root, pathsTarget, invocation),\n () =>\n executeGraphSubcommand(\n subcommand,\n root,\n pathsTarget,\n invocation,\n isTerminal,\n ),\n );\n return {\n ...memo.value,\n cache: {\n fingerprint: lookup.fingerprint.slice(0, 12),\n assembly: lookup.assemblyReused ? \"hit\" : \"miss\",\n result: memo.reused ? \"hit\" : \"miss\",\n },\n };\n}\n","/**\n * @module sdk/item-children\n *\n * Builds deterministic, bounded direct-child projections for every item type.\n * The primitive accepts metadata from either the persistent derived index or a\n * source scan, allowing CLI, MCP, packages, and custom hosts to share one graph\n * projection contract.\n */\nimport { isTerminalStatus } from \"../core/item/status.js\";\nimport type { RuntimeStatusRegistry } from \"../core/schema/runtime-schema.js\";\nimport { EXIT_CODE } from \"../core/shared/constants.js\";\nimport { PmCliError } from \"../core/shared/errors.js\";\nimport type { ItemMetadata } from \"../types/index.js\";\n\n/** Maximum corpus rows inspected by one child projection. */\nexport const MAX_CHILD_PROJECTION_ITEMS = 1_000_000;\n/** Default number of child summaries retained inline. */\nexport const DEFAULT_CHILD_SAMPLE_LIMIT = 20;\n\n/** Stable compact child row embedded in a parent read. */\nexport interface ChildRollupSample {\n /** Stable child identifier. */\n id: string;\n /** Human-readable child title. */\n title: string;\n /** Schema type of the child item. */\n type: string;\n /** Current lifecycle status of the child item. */\n status: string;\n /** Current priority of the child item. */\n priority: number;\n}\n\n/** Bounded direct-child summary shared across SDK and presentation surfaces. */\nexport interface ChildRollupContext {\n /** Total direct children discovered. */\n count: number;\n /** Direct children whose statuses are non-terminal. */\n active: number;\n /** Counts grouped by normalized lifecycle status. */\n by_status: Record<string, number>;\n /** Deterministic id-sorted inline sample. */\n sample: ChildRollupSample[];\n /** Configured maximum sample size. */\n sample_limit: number;\n /** Whether additional children exist beyond the inline sample. */\n truncated: boolean;\n /** Offset for the next page, or null when the sample is complete. */\n next_offset: number | null;\n /** Token-efficient CLI continuation command, or null when complete. */\n continuation: string | null;\n /** Number of corpus rows inspected to produce this projection. */\n scanned: number;\n}\n\n/**\n * Build a type-agnostic child rollup from indexed or source metadata. Input is\n * capped at one million rows to keep custom-host behavior explicitly bounded.\n */\nexport function buildItemChildrenRollup(\n parentId: string,\n corpus: Iterable<ItemMetadata>,\n statusRegistry: RuntimeStatusRegistry,\n sampleLimit = DEFAULT_CHILD_SAMPLE_LIMIT,\n): ChildRollupContext {\n if (!Number.isSafeInteger(sampleLimit) || sampleLimit < 0) {\n throw new PmCliError(\n \"Child projection sample limit must be a non-negative integer.\",\n EXIT_CODE.USAGE,\n );\n }\n const normalizedParentId = parentId.trim().toLowerCase();\n const byStatus: Record<string, number> = {};\n const children: ItemMetadata[] = [];\n let active = 0;\n let scanned = 0;\n for (const candidate of corpus) {\n scanned += 1;\n if (scanned > MAX_CHILD_PROJECTION_ITEMS) {\n throw new PmCliError(\n `Child projection exceeded the ${MAX_CHILD_PROJECTION_ITEMS.toLocaleString(\"en-US\")} item safety bound.`,\n EXIT_CODE.GENERIC_FAILURE,\n {\n code: \"child_projection_item_bound_exceeded\",\n required: \"Use an indexed or parent-filtered metadata source.\",\n why: \"Unbounded graph scans can exhaust memory in universal project stores.\",\n nextSteps: [\"Build the derived item index, then retry the parent read.\"],\n },\n );\n }\n if (candidate.parent?.trim().toLowerCase() !== normalizedParentId) {\n continue;\n }\n children.push(candidate);\n const status = candidate.status.trim().toLowerCase();\n byStatus[status] = (byStatus[status] ?? 0) + 1;\n if (!isTerminalStatus(status, statusRegistry)) {\n active += 1;\n }\n }\n children.sort((left, right) => left.id.localeCompare(right.id));\n const sample = children.slice(0, sampleLimit).map((child) => ({\n id: child.id,\n title: child.title,\n type: child.type,\n status: child.status,\n priority: child.priority,\n }));\n const truncated = children.length > sample.length;\n return {\n count: children.length,\n active,\n by_status: Object.fromEntries(\n Object.entries(byStatus).sort(([left], [right]) => left.localeCompare(right)),\n ),\n sample,\n sample_limit: sampleLimit,\n truncated,\n next_offset: truncated ? sample.length : null,\n continuation: truncated\n ? `pm list --status all --parent ${parentId} --offset ${sample.length} --limit ${sampleLimit}`\n : null,\n scanned,\n };\n}\n","/**\n * @module sdk/item-schedule\n *\n * Normalizes scheduling metadata into one stable read facet so scheduled item\n * types remain useful through generic SDK, CLI, MCP, JSON, and TOON reads.\n */\nimport type { CalendarEvent, ItemMetadata, Reminder } from \"../types/index.js\";\n\nconst BUILTIN_SCHEDULE_TYPES = new Set([\"event\", \"meeting\", \"reminder\"]);\n\n/** Schedule projection attached to standard and deep item reads. */\nexport interface ItemScheduleContext {\n /** Item deadline when present. */\n deadline: string | null;\n /** Earliest event start, convenient for single-event consumers. */\n start_at: string | null;\n /** End of the earliest event when present. */\n end_at: string | null;\n /** Location of the earliest event when present. */\n location: string | null;\n /** All configured reminders. */\n reminders: Reminder[];\n /** All configured events ordered by start timestamp. */\n events: CalendarEvent[];\n}\n\n/** Return whether an item carries or semantically represents schedule data. */\nexport function itemHasSchedule(item: ItemMetadata): boolean {\n return (\n BUILTIN_SCHEDULE_TYPES.has(item.type.trim().toLowerCase()) ||\n item.deadline !== undefined ||\n (item.reminders?.length ?? 0) > 0 ||\n (item.events?.length ?? 0) > 0\n );\n}\n\n/** Build a deterministic schedule facet, or undefined for unscheduled items. */\nexport function buildItemSchedule(\n item: ItemMetadata,\n): ItemScheduleContext | undefined {\n if (!itemHasSchedule(item)) {\n return undefined;\n }\n const events = [...(item.events ?? [])].sort((left, right) =>\n left.start_at.localeCompare(right.start_at),\n );\n const primary = events[0];\n return {\n deadline: item.deadline ?? null,\n start_at: primary?.start_at ?? null,\n end_at: primary?.end_at ?? null,\n location: primary?.location ?? null,\n reminders: [...(item.reminders ?? [])],\n events,\n };\n}\n","/**\n * @module cli/commands/get\n *\n * Implements the pm get command surface and its agent-facing runtime behavior.\n */\nimport { pathExists } from \"../../core/fs/fs-utils.js\";\nimport { getActiveExtensionRegistrations } from \"../../core/extensions/index.js\";\nimport { toItemRecord } from \"../../core/item/item-record.js\";\nimport { resolveItemTypeRegistry } from \"../../core/item/type-registry.js\";\nimport {\n resolveRuntimeFieldRegistry,\n resolveRuntimeStatusRegistry,\n} from \"../../core/schema/runtime-schema.js\";\nimport {\n EXIT_CODE,\n ITEM_METADATA_KEY_ORDER,\n TYPE_TO_FOLDER,\n} from \"../../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport {\n buildItemNotFoundError,\n listAllItemMetadataLight,\n locateItem,\n readLocatedItem,\n} from \"../../core/store/item-store.js\";\nimport {\n getHistoryPath,\n getSettingsPath,\n resolvePmRoot,\n} from \"../../core/store/paths.js\";\nimport { readHistoryEntries } from \"../../sdk/history-read.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport { recordContextUsageTouches } from \"../../sdk/context-usage.js\";\nimport {\n buildItemChildrenRollup,\n type ChildRollupContext,\n} from \"../../sdk/item-children.js\";\nimport {\n buildItemSchedule,\n type ItemScheduleContext,\n} from \"../../sdk/item-schedule.js\";\nimport { getItemAt, type GetItemAtResult } from \"../../sdk/history-read.js\";\nimport { parseIntegerLimit } from \"../shared-parsers.js\";\nimport type {\n ItemMetadata,\n LinkedDoc,\n LinkedFile,\n LinkedTest,\n} from \"../../types/index.js\";\nimport { runList } from \"./list.js\";\n\ninterface ClaimHistoryContext {\n ts: string;\n author: string;\n message: string | null;\n}\n\ninterface ClaimHistoryEntry {\n op: string;\n ts: string;\n author: string;\n message?: string;\n}\n\ninterface ClaimStateContext {\n claimed: boolean;\n assignee: string | null;\n last_claim: ClaimHistoryContext | null;\n last_release: ClaimHistoryContext | null;\n}\n\n/** Documents the get result payload exchanged by command, SDK, and package integrations. */\nexport interface GetResult {\n // `body` lives inside `item` (alongside `description`/`acceptance_criteria`)\n // for parity with `pm list --include-body`, so agents reliably find it at\n // `.item.body` in JSON output instead of a top-level sibling.\n /** Value that configures or reports item for this contract. */\n item: Partial<ItemMetadata> & { body?: string };\n /** Value that configures or reports linked for this contract. */\n linked?: {\n files: LinkedFile[];\n tests: LinkedTest[];\n docs: LinkedDoc[];\n };\n /** Value that configures or reports claim state for this contract. */\n claim_state?: ClaimStateContext;\n /** Value that configures or reports children for this contract. */\n children?: ChildRollupContext;\n /** Normalized scheduling data for scheduled item types and metadata. */\n schedule?: Partial<ItemScheduleContext>;\n /** True when the item was reconstructed from immutable history. */\n reconstructed?: true;\n /** One-based history version represented by a reconstructed read. */\n as_of_version?: number;\n /** Timestamp of the last history entry included in a reconstructed read. */\n as_of_timestamp?: string;\n /** Value that configures or reports tree for this contract. */\n tree?: {\n root_id: string;\n root_title: string | null;\n depth_limit: number | null;\n count: number;\n items: Record<string, unknown>[];\n };\n}\n\nconst GET_DEPTH_VALUES = [\"brief\", \"standard\", \"deep\"] as const;\n\nconst AUTOMATIC_CHILD_ROLLUP_TYPES = new Set([\n \"epic\",\n \"feature\",\n \"milestone\",\n \"plan\",\n]);\nconst BUILTIN_ITEM_TYPES = new Set(\n Object.keys(TYPE_TO_FOLDER).map((type) => type.toLowerCase()),\n);\n\ntype GetDepth = (typeof GET_DEPTH_VALUES)[number];\n\n/** Decide whether a normal read should pay for a workspace-wide child projection. */\nfunction shouldAutoIncludeGetChildren(itemType: string): boolean {\n const normalizedType = itemType.trim().toLowerCase();\n return (\n normalizedType.length > 0 &&\n (AUTOMATIC_CHILD_ROLLUP_TYPES.has(normalizedType) ||\n !BUILTIN_ITEM_TYPES.has(normalizedType))\n );\n}\n\n/** Documents the get options payload exchanged by command, SDK, and package integrations. */\nexport interface GetOptions {\n /** Value that configures or reports depth for this contract. */\n depth?: string;\n /** Value that configures or reports fields for this contract. */\n fields?: string;\n /** Value that configures or reports full for this contract. */\n full?: boolean;\n /** Value that configures or reports tree for this contract. */\n tree?: boolean;\n /** Value that configures or reports tree depth for this contract. */\n treeDepth?: string;\n /** One-based history version or ISO timestamp for a mutation-free read. */\n at?: string;\n}\n\nfunction toClaimHistoryContext(entry: ClaimHistoryEntry): ClaimHistoryContext {\n return {\n ts: entry.ts,\n author: entry.author,\n message: entry.message ?? null,\n };\n}\n\nfunction resolveClaimStateContext(\n assigneeValue: string | undefined,\n history: ClaimHistoryEntry[],\n): ClaimStateContext {\n const assignee = assigneeValue?.trim();\n const normalizedAssignee = assignee && assignee.length > 0 ? assignee : null;\n const lastClaim = [...history]\n .reverse()\n .find((entry) => entry.op === \"claim\");\n const lastRelease = [...history]\n .reverse()\n .find((entry) => entry.op === \"release\");\n return {\n claimed: normalizedAssignee !== null,\n assignee: normalizedAssignee,\n last_claim: lastClaim ? toClaimHistoryContext(lastClaim) : null,\n last_release: lastRelease ? toClaimHistoryContext(lastRelease) : null,\n };\n}\n\nfunction parseGetDepth(raw: string | undefined): GetDepth {\n if (raw === undefined || raw.trim().length === 0) {\n return \"standard\";\n }\n const normalized = raw.trim().toLowerCase();\n if (normalized === \"full\") {\n return \"deep\";\n }\n if (GET_DEPTH_VALUES.includes(normalized as GetDepth)) {\n return normalized as GetDepth;\n }\n throw new PmCliError(\n \"Get --depth must be one of brief|standard|deep|full\",\n EXIT_CODE.USAGE,\n );\n}\n\nfunction projectItemForDepth(\n item: ItemMetadata,\n depth: GetDepth,\n): Partial<ItemMetadata> {\n if (depth === \"deep\") {\n return item;\n }\n const {\n comments: _comments,\n notes: _notes,\n learnings: _learnings,\n files: _files,\n tests: _tests,\n docs: _docs,\n reminders: _reminders,\n events: _events,\n ...projected\n } = item;\n return projected;\n}\n\nfunction parseGetFields(raw: string | undefined): string[] | null {\n if (raw === undefined) {\n return null;\n }\n const fields = raw\n .split(\",\")\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n if (fields.length === 0) {\n throw new PmCliError(\n \"Get --fields requires a comma-separated list of field names\",\n EXIT_CODE.USAGE,\n );\n }\n return fields;\n}\n\nfunction normalizeGetField(field: string): string {\n return field.startsWith(\"item.\") ? field.slice(\"item.\".length) : field;\n}\n\nfunction validateGetFields(\n fields: string[] | null,\n runtimeMetadataKeys: Iterable<string>,\n): void {\n if (fields === null) {\n return;\n }\n const itemFields = new Set([\n ...ITEM_METADATA_KEY_ORDER,\n ...runtimeMetadataKeys,\n ]);\n const allowedRootFields = new Set([\n \"body\",\n \"linked\",\n \"claim_state\",\n \"children\",\n \"schedule\",\n ]);\n const allowedLinkedFields = new Set([\n \"linked.files\",\n \"linked.tests\",\n \"linked.docs\",\n ]);\n const allowedClaimStateFields = new Set([\n \"claim_state.claimed\",\n \"claim_state.assignee\",\n \"claim_state.last_claim\",\n \"claim_state.last_release\",\n ]);\n const allowedScheduleFields = new Set([\n \"schedule.deadline\",\n \"schedule.start_at\",\n \"schedule.end_at\",\n \"schedule.location\",\n \"schedule.reminders\",\n \"schedule.events\",\n ]);\n const unknown = fields.filter((field) => {\n const normalized = normalizeGetField(field);\n return (\n !itemFields.has(normalized) &&\n !allowedRootFields.has(normalized) &&\n !allowedLinkedFields.has(normalized) &&\n !allowedClaimStateFields.has(normalized) &&\n !allowedScheduleFields.has(normalized)\n );\n });\n if (unknown.length > 0) {\n throw new PmCliError(\n `Unknown get --fields value(s): ${unknown.join(\", \")}`,\n EXIT_CODE.USAGE,\n {\n code: \"unknown_field_projection\",\n examples: [\n \"pm get <id> --fields id,title,status,type,updated_at\",\n \"pm get <id> --fields id,title,claim_state\",\n \"pm get <id> --fields id,title,body,linked.files\",\n ],\n },\n );\n }\n}\n\nfunction projectItemForFields(\n item: ItemMetadata,\n fields: string[],\n): Partial<ItemMetadata> {\n const source = toItemRecord(item);\n const projected: Record<string, unknown> = {};\n for (const field of fields) {\n const normalized = normalizeGetField(field);\n if (\n normalized === \"body\" ||\n normalized === \"linked\" ||\n normalized.startsWith(\"linked.\") ||\n normalized === \"claim_state\" ||\n normalized.startsWith(\"claim_state.\") ||\n normalized === \"children\" ||\n normalized.startsWith(\"children.\") ||\n normalized === \"schedule\" ||\n normalized.startsWith(\"schedule.\")\n ) {\n continue;\n }\n projected[normalized] = source[normalized];\n }\n return projected as Partial<ItemMetadata>;\n}\n\nfunction fieldsInclude(fields: string[] | null, name: string): boolean {\n return (\n fields?.some((field) => field === name || field === `item.${name}`) ?? false\n );\n}\n\nfunction fieldsIncludeRoot(fields: string[], name: string): boolean {\n return fields.some((field) => {\n const normalized = normalizeGetField(field);\n return normalized === name || normalized.startsWith(`${name}.`);\n });\n}\n\ninterface ResolvedGetProjection {\n depth: GetDepth;\n treeDepth: number | undefined;\n fields: string[] | null;\n fieldProjection: boolean;\n}\n\ninterface GetItemContext {\n pmRoot: string;\n settings: Awaited<ReturnType<typeof readSettings>>;\n typeToFolder: Record<string, string>;\n locatedId: string;\n metadata: ItemMetadata;\n body: string;\n historical?: GetItemAtResult;\n}\n\nfunction resolveGetProjection(options: GetOptions): ResolvedGetProjection {\n if (\n options.full &&\n (options.fields !== undefined || options.depth !== undefined)\n ) {\n throw new PmCliError(\n \"Get projection options are mutually exclusive; remove the extra projection flag and retry.\",\n EXIT_CODE.USAGE,\n );\n }\n if (options.tree !== true && options.treeDepth !== undefined) {\n throw new PmCliError(\"Get --tree-depth requires --tree\", EXIT_CODE.USAGE);\n }\n if (options.at !== undefined && options.tree === true) {\n throw new PmCliError(\n \"Get --at cannot be combined with --tree because workspace-level historical projections are not yet indexed.\",\n EXIT_CODE.USAGE,\n );\n }\n return {\n depth: options.full ? \"deep\" : parseGetDepth(options.depth),\n treeDepth:\n options.tree === true\n ? parseIntegerLimit(options.treeDepth, \"--tree-depth\")\n : undefined,\n fields: parseGetFields(options.fields),\n fieldProjection: options.fields !== undefined,\n };\n}\n\nasync function loadGetItemContext(\n id: string,\n global: GlobalOptions,\n at?: string,\n): Promise<GetItemContext> {\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(\n `Tracker is not initialized at ${pmRoot}. Run pm init first.`,\n EXIT_CODE.NOT_FOUND,\n );\n }\n const settings = await readSettings(pmRoot);\n const typeRegistry = resolveItemTypeRegistry(\n settings,\n getActiveExtensionRegistrations(),\n );\n if (at !== undefined) {\n const historical = await getItemAt(id, at, { pmRoot: global.path });\n return {\n pmRoot,\n settings,\n typeToFolder: typeRegistry.type_to_folder,\n locatedId: historical.document.metadata.id,\n metadata: historical.document.metadata,\n body: historical.document.body,\n historical,\n };\n }\n const located = await locateItem(\n pmRoot,\n id,\n settings.id_prefix,\n settings.item_format,\n typeRegistry.type_to_folder,\n );\n if (!located) {\n throw await buildItemNotFoundError(\n pmRoot,\n id,\n settings.id_prefix,\n typeRegistry.type_to_folder,\n );\n }\n const loaded = await readLocatedItem(located, { schema: settings.schema });\n return {\n pmRoot,\n settings,\n typeToFolder: typeRegistry.type_to_folder,\n locatedId: located.id,\n metadata: loaded.document.metadata,\n body: loaded.document.body,\n };\n}\n\nfunction validateGetProjectionFields(\n fields: string[] | null,\n settings: Awaited<ReturnType<typeof readSettings>>,\n historical: boolean,\n): void {\n const runtimeMetadataKeys = resolveRuntimeFieldRegistry(\n settings.schema,\n ).definitions.map((field) => field.metadata_key);\n validateGetFields(fields, runtimeMetadataKeys);\n if (historical && fieldsIncludeRoot(fields ?? [], \"children\")) {\n throw new PmCliError(\n \"Get --at cannot project children because workspace-level historical relationships are not yet indexed.\",\n EXIT_CODE.USAGE,\n );\n }\n}\n\nfunction shouldIncludeGetField(params: {\n fieldProjection: boolean;\n depth: GetDepth;\n fields: string[] | null;\n field: \"body\" | \"linked\" | \"claim_state\";\n}): boolean {\n const { fieldProjection, depth, fields, field } = params;\n if (fieldProjection) {\n if (field === \"body\" || field === \"linked\") {\n return fieldsInclude(fields, field);\n }\n return fieldsIncludeRoot(fields as string[], field);\n }\n return depth !== \"brief\";\n}\n\nasync function resolveGetClaimState(\n context: GetItemContext,\n includeClaimState: boolean,\n): Promise<ClaimStateContext | undefined> {\n if (!includeClaimState) {\n return undefined;\n }\n const historyPath = getHistoryPath(context.pmRoot, context.locatedId);\n const history = await readHistoryEntries(historyPath, context.locatedId);\n return resolveClaimStateContext(\n context.metadata.assignee,\n context.historical\n ? history.slice(0, context.historical.as_of_version)\n : history,\n );\n}\n\nfunction attachGetLinked(\n result: GetResult,\n context: GetItemContext,\n fields: string[] | null,\n includeLinked: boolean,\n): void {\n const includeLinkedFiles =\n includeLinked || fieldsInclude(fields, \"linked.files\");\n const includeLinkedTests =\n includeLinked || fieldsInclude(fields, \"linked.tests\");\n const includeLinkedDocs =\n includeLinked || fieldsInclude(fields, \"linked.docs\");\n if (\n !includeLinked &&\n !includeLinkedFiles &&\n !includeLinkedTests &&\n !includeLinkedDocs\n ) {\n return;\n }\n result.linked = {\n files: includeLinkedFiles ? (context.metadata.files ?? []) : [],\n tests: includeLinkedTests ? (context.metadata.tests ?? []) : [],\n docs: includeLinkedDocs ? (context.metadata.docs ?? []) : [],\n };\n}\n\nasync function buildGetChildrenRollup(\n context: GetItemContext,\n includeChildren: boolean,\n includeEmpty: boolean,\n): Promise<ChildRollupContext | undefined> {\n if (!includeChildren) {\n return undefined;\n }\n const statusRegistry = resolveRuntimeStatusRegistry(context.settings.schema);\n const corpus = await listAllItemMetadataLight(\n context.pmRoot,\n context.settings.item_format,\n context.typeToFolder,\n undefined,\n context.settings.schema,\n );\n const rollup = buildItemChildrenRollup(\n context.locatedId,\n corpus,\n statusRegistry,\n );\n return rollup.count > 0 || includeEmpty ? rollup : undefined;\n}\n\nfunction attachGetSchedule(\n result: GetResult,\n context: GetItemContext,\n fields: string[] | null,\n includeSchedule: boolean,\n): void {\n if (!includeSchedule) {\n return;\n }\n const schedule = buildItemSchedule(context.metadata);\n if (!schedule) {\n return;\n }\n if (fields === null || fieldsInclude(fields, \"schedule\")) {\n result.schedule = schedule;\n return;\n }\n result.schedule = Object.fromEntries(\n Object.entries(schedule).filter(([key]) =>\n fields.some(\n (field) => normalizeGetField(field) === `schedule.${key}`,\n ),\n ),\n ) as Partial<ItemScheduleContext>;\n}\n\nasync function buildGetTree(\n context: GetItemContext,\n options: GetOptions,\n treeDepth: number | undefined,\n global: GlobalOptions,\n): Promise<GetResult[\"tree\"] | undefined> {\n if (options.tree !== true) {\n return undefined;\n }\n const subtree = await runList(\n undefined,\n {\n parent: context.locatedId,\n tree: true,\n treeDepth: treeDepth === undefined ? undefined : String(treeDepth),\n full: true,\n },\n global,\n );\n return {\n root_id: context.locatedId,\n root_title: context.metadata.title,\n depth_limit: treeDepth ?? null,\n count: subtree.count,\n items: subtree.items.map((entry) => toItemRecord(entry)),\n };\n}\n\n/** Implements run get for the public runtime surface of this module. */\nexport async function runGet(\n id: string,\n global: GlobalOptions,\n options: GetOptions = {},\n): Promise<GetResult> {\n const projection = resolveGetProjection(options);\n const context = await loadGetItemContext(id, global, options.at);\n validateGetProjectionFields(\n projection.fields,\n context.settings,\n context.historical !== undefined,\n );\n const includeBody = shouldIncludeGetField({ ...projection, field: \"body\" });\n const includeLinked = shouldIncludeGetField({\n ...projection,\n field: \"linked\",\n });\n const includeClaimState = shouldIncludeGetField({\n ...projection,\n field: \"claim_state\",\n });\n const includeChildren =\n context.historical === undefined &&\n (projection.fieldProjection\n ? fieldsIncludeRoot(projection.fields as string[], \"children\")\n : projection.depth !== \"brief\" &&\n shouldAutoIncludeGetChildren(context.metadata.type));\n const includeSchedule = projection.fieldProjection\n ? fieldsIncludeRoot(projection.fields as string[], \"schedule\")\n : projection.depth !== \"brief\";\n const claimState = await resolveGetClaimState(context, includeClaimState);\n const result: GetResult = {\n item: projection.fieldProjection\n ? projectItemForFields(context.metadata, projection.fields as string[])\n : projectItemForDepth(context.metadata, projection.depth),\n };\n if (includeBody) {\n result.item.body = context.body;\n }\n attachGetLinked(result, context, projection.fields, includeLinked);\n if (claimState) {\n result.claim_state = claimState;\n }\n attachGetSchedule(result, context, projection.fields, includeSchedule);\n result.children = await buildGetChildrenRollup(\n context,\n includeChildren,\n projection.fieldProjection,\n );\n result.tree = await buildGetTree(\n context,\n options,\n projection.treeDepth,\n global,\n );\n if (context.historical) {\n result.reconstructed = true;\n result.as_of_version = context.historical.as_of_version;\n result.as_of_timestamp = context.historical.as_of_timestamp;\n }\n if (context.historical === undefined) {\n try {\n await recordContextUsageTouches({\n pmRoot: context.pmRoot,\n author:\n (process.env.PM_AUTHOR ?? context.settings.author_default).trim() ||\n \"unknown\",\n itemIds: [context.locatedId],\n intent: \"get\",\n });\n } catch {\n // Derived usage feedback must never make the source-of-truth read fail.\n }\n }\n return result;\n}\n\n/** Public contract for test-only get command policy helpers. */\nexport const _testOnlyGetCommand = {\n shouldAutoIncludeGetChildren,\n};\n","/**\n * @module sdk/query/search\n *\n * Implements the pm search command surface and its agent-facing runtime behavior.\n */\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n coerceNumberInRange,\n toNonEmptyStringOrUndefined,\n} from \"../../core/shared/primitives.js\";\nimport { isPathWithinDirectory } from \"../../core/fs/path-utils.js\";\nimport {\n getActiveExtensionRegistrations,\n runActiveOnReadHooks,\n} from \"../../core/extensions/index.js\";\nimport { collectRegisteredItemFieldNames } from \"../../core/extensions/item-fields.js\";\nimport {\n resolveRegisteredSearchProvider,\n resolveRegisteredVectorStoreAdapter,\n} from \"../../core/extensions/runtime-registrations.js\";\nimport {\n resolveItemTypeRegistry,\n type ItemTypeRegistry,\n} from \"../../core/item/type-registry.js\";\nimport { parseLimit, parsePriority, parseType } from \"./parsers.js\";\nimport {\n executeEmbeddingRequest,\n resolveEmbeddingProviders,\n type EmbeddingProviderConfig,\n type EmbeddingProviderResolution,\n} from \"../../core/search/providers.js\";\nimport {\n buildDeterministicQueryExpansions,\n mergeQueryExpansions,\n normalizeQueryExpansionOutput,\n normalizeRerankOutput,\n rerankCandidatesWithEmbeddings,\n resolveQueryExpansionConfig,\n resolveRerankConfig,\n type QueryExpansionConfig,\n type RerankCandidate,\n type RerankConfig,\n} from \"../../core/search/relevance.js\";\nimport { resolveSettingsWithSemanticRuntimeDefaults } from \"../../core/search/semantic-defaults.js\";\nimport {\n executeVectorQuery,\n resolveVectorStores,\n type VectorQueryHit,\n type VectorStoreConfig,\n type VectorStoreResolution,\n} from \"../../core/search/vector-stores.js\";\nimport { readVectorizationStatusLedger } from \"../../core/search/cache.js\";\nimport {\n buildEventCorpus,\n buildPlanFlatCorpus,\n buildReminderCorpus,\n buildSearchCorpus,\n resolveSearchCorpusFields,\n} from \"../../core/search/corpus.js\";\nimport {\n buildBm25Index,\n flattenSearchCorpusText,\n resolveBm25Params,\n scoreBm25Query,\n tokenizeBm25,\n type Bm25Params,\n} from \"../../core/search/bm25.js\";\nimport { collectStaleVectorizationIds } from \"../../core/search/staleness.js\";\nimport { pathExists } from \"../../core/fs/fs-utils.js\";\nimport { parseItemDocument } from \"../../core/item/item-format.js\";\nimport { toItemRecord } from \"../../core/item/item-record.js\";\nimport { isTerminalStatus } from \"../../core/item/status.js\";\nimport { parseStatusFilterCsv } from \"../../core/item/status-filter.js\";\nimport {\n collectRuntimeFilterValues,\n matchesRuntimeFilters,\n} from \"../../core/schema/runtime-field-filters.js\";\nimport {\n hasMissingMetadataFilter,\n itemMatchesMissingMetadata,\n lifecycleClassifierFromStatusRegistry,\n type LifecycleClassifier,\n} from \"../../core/governance/metadata-coverage.js\";\nimport {\n hasContentFieldFilter,\n itemMatchesContentFilters,\n} from \"../../core/governance/content-fields.js\";\nimport {\n resolveContentFieldFilters,\n resolveMissingMetadataFilters,\n} from \"./list.js\";\nimport {\n buildCompactSearchFilterSummary,\n buildVerboseSearchFilters,\n type SearchMode,\n} from \"./search-rendering.js\";\nimport {\n resolveRuntimeFieldRegistry,\n resolveRuntimeStatusRegistry,\n type RuntimeFieldRegistry,\n type RuntimeStatusRegistry,\n} from \"../../core/schema/runtime-schema.js\";\nimport { EXIT_CODE } from \"../../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../../core/shared/command-types.js\";\nimport { PmCliError } from \"../../core/shared/errors.js\";\nimport { tokenizeAlphaNumeric } from \"../../core/shared/text-normalization.js\";\nimport {\n compareTimestampStrings,\n matchesTimestampFilters,\n nowIso,\n resolveIsoOrRelative,\n} from \"../../core/shared/time.js\";\nimport { listAllDocumentCandidatesCached } from \"../../core/store/item-metadata-cache.js\";\nimport { listAllItemMetadata } from \"../../core/store/item-store.js\";\nimport {\n getItemPath,\n getSettingsPath,\n resolveGlobalPmRoot,\n resolvePmRoot,\n} from \"../../core/store/paths.js\";\nimport { readSettings } from \"../../core/store/settings.js\";\nimport type {\n ItemDocument,\n ItemFormat,\n ItemMetadata,\n ItemStatus,\n ItemType,\n PmSettings,\n} from \"../../types/index.js\";\nimport type { SharedItemFilterOptions } from \"./item-filter-options.js\";\nimport { resolveSearchPage } from \"./search-pagination.js\";\n\n/** Documents the search options payload exchanged by command, SDK, and package integrations. */\nexport interface SearchOptions extends SharedItemFilterOptions {\n /** Value that configures or reports mode for this contract. */\n mode?: string;\n /** Strategy used to control match behavior. */\n matchMode?: string;\n /** Value that configures or reports min score for this contract. */\n minScore?: string | number;\n /** Value that configures or reports count for this contract. */\n count?: boolean;\n /** Value that configures or reports semantic weight for this contract. */\n semanticWeight?: string | number;\n /** Value that configures or reports include linked for this contract. */\n includeLinked?: boolean;\n /** Value that configures or reports title exact for this contract. */\n titleExact?: boolean;\n /** Value that configures or reports phrase exact for this contract. */\n phraseExact?: boolean;\n /** Value that configures or reports limit for this contract. */\n limit?: string;\n /** Opaque cursor returned by a previous search page. */\n after?: string;\n /** Value that configures or reports compact for this contract. */\n compact?: boolean;\n /** Value that configures or reports full for this contract. */\n full?: boolean;\n /** Value that configures or reports fields for this contract. */\n fields?: string;\n // GH-157: emit per-field matched-text snippets on each hit (off by default for\n // token efficiency). Highlighted spans are wrapped with the «…» markers.\n /** Value that configures or reports highlight for this contract. */\n highlight?: boolean;\n}\n\n/** Restricts search match mode values accepted by command, SDK, and storage contracts. */\nexport type SearchMatchMode = \"and\" | \"or\" | \"exact\";\n\ntype SearchProjectionMode = \"compact\" | \"full\" | \"fields\";\n\ninterface SearchProjectionConfig {\n mode: SearchProjectionMode;\n fields: string[];\n}\n\nconst DEFAULT_COMPACT_SEARCH_FIELDS = [\n \"id\",\n \"title\",\n \"status\",\n \"type\",\n \"priority\",\n \"updated_at\",\n \"score\",\n \"matched_fields\",\n] as const;\n\nconst SEARCH_HIT_FIELD_KEYS = new Set([\n \"score\",\n \"matched_fields\",\n \"highlights\",\n]);\nconst SEARCH_ITEM_FIELD_KEYS = new Set([\n \"id\",\n \"title\",\n \"description\",\n \"type\",\n \"status\",\n \"priority\",\n \"tags\",\n \"created_at\",\n \"updated_at\",\n \"deadline\",\n \"assignee\",\n \"author\",\n \"estimated_minutes\",\n \"acceptance_criteria\",\n \"dependencies\",\n \"comments\",\n \"notes\",\n \"learnings\",\n \"reminders\",\n \"events\",\n \"files\",\n \"tests\",\n \"docs\",\n \"close_reason\",\n \"parent\",\n \"reviewer\",\n \"risk\",\n \"confidence\",\n \"sprint\",\n \"release\",\n \"blocked_by\",\n \"blocked_reason\",\n \"reporter\",\n \"severity\",\n \"environment\",\n \"repro_steps\",\n \"resolution\",\n \"expected_result\",\n \"actual_result\",\n \"affected_version\",\n \"fixed_version\",\n \"component\",\n \"regression\",\n \"customer_impact\",\n \"definition_of_ready\",\n \"order\",\n \"rank\",\n \"goal\",\n \"objective\",\n \"value\",\n \"impact\",\n \"outcome\",\n \"why_now\",\n \"plan\",\n]);\n\nconst LONG_QUERY_TOKEN_THRESHOLD = 2;\nconst LONG_QUERY_TITLE_EXACT_BONUS = 120;\nconst LONG_QUERY_PHRASE_MULTIPLIER = 6;\n// GH-181: in default (OR) match mode, multi-token queries that match EVERY\n// distinct query token in some searchable field get an additive ranking bonus so\n// items covering all terms outrank items matching only a subset. This is a\n// RANKING preference, not a hard filter (use --match-mode and for that).\nconst ALL_TERMS_COVERAGE_BONUS = 40;\nconst EXACT_ID_MATCH_SCORE = 1_000;\nconst SHORT_ID_MATCH_SCORE = 900;\n\n// GH-157 matched-text highlighting (--highlight): markers wrapping each matching\n// token run, and the number of characters of surrounding context retained on\n// each side of the first match in a field. The «…» guillemets are single\n// characters with negligible collision risk against item text, keeping the\n// snippet token-cheap while staying visually unambiguous for agents.\nconst HIGHLIGHT_OPEN = \"«\";\nconst HIGHLIGHT_CLOSE = \"»\";\nconst HIGHLIGHT_SNIPPET_RADIUS = 60;\n\n// GH-157 inline query syntax: bare `field:value` tokens parsed out of the query\n// string and applied as the equivalent filter. The value may itself contain\n// colons (e.g. `tag:area:search`), so only the FIRST colon delimits field from\n// value. Explicit --field flags take precedence over an inline token (see\n// resolveInlineQueryFilters).\nconst INLINE_QUERY_FILTER_FIELDS = [\n \"tag\",\n \"status\",\n \"type\",\n \"priority\",\n] as const;\ntype InlineQueryFilterField = (typeof INLINE_QUERY_FILTER_FIELDS)[number];\n\n/** Documents the search hit payload exchanged by command, SDK, and package integrations. */\nexport interface SearchHit {\n /** Value that configures or reports item for this contract. */\n item: ItemMetadata;\n /** Value that configures or reports score for this contract. */\n score: number;\n /** Value that configures or reports matched fields for this contract. */\n matched_fields: string[];\n // GH-181: whether every distinct query token matched some searchable field.\n // Used by --match-mode and (hard filter) and the default all-terms ranking\n // bonus. Not projected into output rows.\n /** Value that configures or reports matched all terms for this contract. */\n matched_all_terms?: boolean;\n // GH-281: marks the keyword hit produced by the exact full-ID / short-ID\n // early-return in scoreDocument(). The semantic & hybrid ranking paths use it\n // to guarantee the exact-ID target ALWAYS ranks #1 (and is exempt from the\n // score threshold / limit), so the keyword-mode exact-ID guarantee is never\n // lost once vector blending is active. SHORT_ID matches keep score=900 and\n // full-ID matches keep score=1000, so sortHits still orders full above short.\n // Not projected into output rows.\n /** Value that configures or reports exact id match for this contract. */\n exact_id_match?: boolean;\n // GH-157: per-field matched-text snippets, populated only when the caller\n // passes --highlight. Each entry pairs a matched field name with a snippet of\n // its text where the matching token runs are wrapped in the «…» markers.\n /** Value that configures or reports highlights for this contract. */\n highlights?: SearchHitHighlight[];\n}\n\n/**\n * Pairs a matched field name with a snippet of its text where every matching\n * token run is wrapped in the {@link HIGHLIGHT_OPEN}/{@link HIGHLIGHT_CLOSE}\n * markers. Emitted on {@link SearchHit.highlights} when `--highlight` is set.\n */\nexport interface SearchHitHighlight {\n /** Value that configures or reports field for this contract. */\n field: string;\n /** Value that configures or reports snippet for this contract. */\n snippet: string;\n}\n\n/** Restricts search result item values accepted by command, SDK, and storage contracts. */\nexport type SearchResultItem = SearchHit | Record<string, unknown>;\n\ninterface SearchResultBase {\n query: string;\n mode: SearchMode;\n items: SearchResultItem[];\n count: number;\n // GH-181: total matched hits after filters/threshold but BEFORE the limit\n // truncation. Lets callers see how many matched before the (now-default)\n // keyword limit dropped rows. Only emitted when it differs from count.\n total?: number;\n /** Whether additional ranked hits remain after this page. */\n has_more?: boolean;\n /** Opaque continuation cursor when additional hits remain. */\n next_cursor?: string;\n /** Effective page size for this response. */\n applied_limit?: number;\n /** Explicit marker that the response is a bounded page. */\n truncated?: true;\n // --count mode: count-only response carries the matched total and skips the\n // hit rows entirely (items is empty). `count` reflects the same total.\n count_only?: boolean;\n warnings?: string[];\n}\n\n/** Documents the search compact result payload exchanged by command, SDK, and package integrations. */\nexport interface SearchCompactResult extends SearchResultBase {\n /** Value that configures or reports filters for this contract. */\n filters: Record<string, unknown>;\n /** Value that configures or reports projection for this contract. */\n projection?: undefined;\n /** Value that configures or reports now for this contract. */\n now?: undefined;\n}\n\n/** Documents the search verbose result payload exchanged by command, SDK, and package integrations. */\nexport interface SearchVerboseResult extends SearchResultBase {\n /** Value that configures or reports filters for this contract. */\n filters: Record<string, unknown>;\n /** Value that configures or reports projection for this contract. */\n projection: {\n mode: SearchProjectionMode;\n fields: string[] | null;\n };\n /** Value that configures or reports now for this contract. */\n now: string;\n}\n\n/** Restricts search result values accepted by command, SDK, and storage contracts. */\nexport type SearchResult = SearchCompactResult | SearchVerboseResult;\n\ninterface ExtensionSearchProviderContext {\n query: string;\n mode: SearchMode;\n tokens: string[];\n options: SearchOptions;\n settings: PmSettings;\n documents: ItemDocument[];\n}\n\ninterface ExtensionSearchProviderHit {\n id: string;\n score: number;\n matched_fields?: string[];\n}\n\ntype ExtensionSearchProviderQuery = (\n context: ExtensionSearchProviderContext,\n) =>\n | Promise<\n ExtensionSearchProviderHit[] | { hits?: ExtensionSearchProviderHit[] }\n >\n | ExtensionSearchProviderHit[]\n | { hits?: ExtensionSearchProviderHit[] };\n\ninterface ExtensionSearchProviderQueryExpansionContext {\n query: string;\n mode: Exclude<SearchMode, \"keyword\">;\n settings: PmSettings;\n}\n\ntype ExtensionSearchProviderQueryExpansion = (\n context: ExtensionSearchProviderQueryExpansionContext,\n) =>\n | Promise<string[] | { queries?: string[] }>\n | string[]\n | { queries?: string[] };\n\ninterface ExtensionSearchProviderRerankCandidate {\n id: string;\n text: string;\n score: number;\n}\n\ninterface ExtensionSearchProviderRerankContext {\n query: string;\n mode: \"hybrid\";\n model: string;\n top_k: number;\n settings: PmSettings;\n candidates: ExtensionSearchProviderRerankCandidate[];\n}\n\ntype ExtensionSearchProviderRerank = (\n context: ExtensionSearchProviderRerankContext,\n) =>\n | Promise<\n | Array<{ id?: unknown; score?: unknown }>\n | { hits?: Array<{ id?: unknown; score?: unknown }> }\n >\n | Array<{ id?: unknown; score?: unknown }>\n | { hits?: Array<{ id?: unknown; score?: unknown }> };\n\ntype ExtensionVectorQuery = (context: {\n vector: number[];\n limit: number;\n settings: PmSettings;\n}) => Promise<VectorQueryHit[]> | VectorQueryHit[];\n\ntype ExtensionVectorUpsert = (context: {\n points: Array<{\n id: string;\n vector: number[];\n payload: Record<string, unknown>;\n }>;\n settings: PmSettings;\n}) => Promise<void> | void;\n\ntype ExtensionVectorAdapter = {\n adapterName: string;\n query?: ExtensionVectorQuery;\n upsert?: ExtensionVectorUpsert;\n};\n\ninterface SearchModeContext {\n hasProvider: boolean;\n hasVectorStore: boolean;\n}\n\ntype ImplicitSemanticFallbackReason = \"timeout\" | \"connection\" | \"error\";\n\n/**\n * Aggregate the `code` strings found along an error's `cause` chain.\n *\n * undici (Node's fetch) collapses connection errors to the generic message\n * \"fetch failed\" and stashes the real syscall code (e.g. `ECONNREFUSED`) on\n * `error.cause.code`. Walking the chain (bounded depth) lets the fallback\n * classifier label a downed/unreachable Ollama backend as \"connection\" rather\n * than the catch-all \"error\".\n */\nexport function collectErrorCauseCodes(error: unknown): string {\n const codes: string[] = [];\n let current: unknown = error;\n for (\n let depth = 0;\n depth < 5 && current && typeof current === \"object\";\n depth += 1\n ) {\n const code = (current as { code?: unknown }).code;\n if (typeof code === \"string\") {\n codes.push(code.toLowerCase());\n }\n current = (current as { cause?: unknown }).cause;\n }\n return codes.join(\" \");\n}\n\n/**\n * Classify why an implicit/explicit semantic search degraded to keyword mode,\n * inspecting both the error message and the {@link collectErrorCauseCodes} chain\n * so undici's generic \"fetch failed\" is recognised as a connection failure.\n */\nexport function classifyImplicitSemanticFallbackReason(\n error: unknown,\n): ImplicitSemanticFallbackReason {\n const message = (\n error instanceof Error ? error.message : String(error)\n ).toLowerCase();\n const causeCodes = collectErrorCauseCodes(error);\n const haystack = `${message} ${causeCodes}`;\n if (\n haystack.includes(\"timed out\") ||\n haystack.includes(\"timeout\") ||\n haystack.includes(\"etimedout\")\n ) {\n return \"timeout\";\n }\n if (\n haystack.includes(\"econnrefused\") ||\n haystack.includes(\"connection refused\") ||\n haystack.includes(\"connect \") ||\n haystack.includes(\"enotfound\") ||\n haystack.includes(\"eai_again\") ||\n haystack.includes(\"econnreset\") ||\n haystack.includes(\"fetch failed\")\n ) {\n return \"connection\";\n }\n return \"error\";\n}\n\n// Explicit --semantic/--hybrid searches must never hard-fail an agent when the\n// embedding/vector backend is unreachable or unconfigured: degrade to keyword\n// search and surface a machine-readable warning instead of an unknown_error.\nfunction buildExplicitSemanticFallbackWarning(\n requestedMode: SearchMode,\n error: unknown,\n): string {\n const reason = classifyImplicitSemanticFallbackReason(error);\n return `search_${requestedMode}_fallback:${reason}:using_keyword_mode`;\n}\n\n/** Compare the vectorization-status ledger against the filtered corpus and, when the vector index is behind, emit a one-line stderr warning plus a structured `vector_index_stale:N` entry in the JSON warnings array. Best-effort: ledger read failures fall through silently — the existing semantic/hybrid fallback paths cover backend errors. */\nasync function maybeEmitVectorIndexStaleWarning(\n pmRoot: string,\n filteredDocuments: ItemDocument[],\n warnings: string[],\n): Promise<void> {\n try {\n const ledger = await readVectorizationStatusLedger(pmRoot);\n if (ledger.warnings.length > 0) {\n warnings.push(...ledger.warnings);\n }\n const staleIds = collectStaleVectorizationIds(\n filteredDocuments.map((document) => ({\n id: document.metadata.id,\n updated_at: document.metadata.updated_at,\n })),\n ledger.entries,\n );\n if (staleIds.length === 0) {\n return;\n }\n warnings.push(`vector_index_stale:${staleIds.length}`);\n /* c8 ignore start -- singular/plural warning text branches are cosmetic and validated in integration UX tests */\n process.stderr.write(\n `[pm] warning: ${staleIds.length} item${staleIds.length === 1 ? \" is\" : \"s are\"} new or modified since the last reindex and ${staleIds.length === 1 ? \"is\" : \"are\"} NOT in the semantic index yet — they will be missing from semantic/hybrid results until you run 'pm reindex --mode hybrid'. (Write-time embedding is governed by search.mutation_refresh_policy; staleness means the embed was skipped, failed, or the backend was unreachable.)\\n`,\n );\n /* c8 ignore stop */\n } catch {\n // Best-effort: missing/unreadable ledger is not a query-blocking concern.\n }\n}\n\nfunction parseMode(\n raw: string | undefined,\n _context: SearchModeContext,\n): SearchMode {\n if (raw === undefined) {\n return \"keyword\";\n }\n const normalized = raw.trim().toLowerCase();\n if (\n normalized !== \"keyword\" &&\n normalized !== \"semantic\" &&\n normalized !== \"hybrid\"\n ) {\n throw new PmCliError(\n \"Search mode must be one of keyword|semantic|hybrid\",\n EXIT_CODE.USAGE,\n );\n }\n return normalized;\n}\n\nfunction parseIncludeLinked(raw: boolean | undefined): boolean {\n return raw === true;\n}\n\nfunction parseTitleExact(raw: boolean | undefined): boolean {\n return raw === true;\n}\n\nfunction parsePhraseExact(raw: boolean | undefined): boolean {\n return raw === true;\n}\n\nfunction parseSemanticWeightOverride(raw: unknown): number | undefined {\n return coerceNumberInRange(raw, 0, 1) ?? undefined;\n}\n\nfunction parseMatchMode(raw: string | undefined): SearchMatchMode {\n if (raw === undefined) {\n return \"or\";\n }\n const normalized = raw.trim().toLowerCase();\n if (normalized !== \"and\" && normalized !== \"or\" && normalized !== \"exact\") {\n throw new PmCliError(\n \"Search --match-mode must be one of and|or|exact\",\n EXIT_CODE.USAGE,\n );\n }\n return normalized;\n}\n\n// Per-query --min-score overrides the persistent search.score_threshold for this\n// query only. Accepts a finite number >= 0; anything else is a usage error.\nfunction parseMinScoreOverride(raw: unknown): number | undefined {\n if (raw === undefined || raw === null || raw === \"\") {\n return undefined;\n }\n /* c8 ignore start -- numeric-vs-string coercion branch is exercised via integration CLI parsing */\n const parsed = typeof raw === \"number\" ? raw : Number(String(raw).trim());\n /* c8 ignore stop */\n if (!Number.isFinite(parsed) || parsed < 0) {\n throw new PmCliError(\n \"Search --min-score must be a finite number >= 0\",\n EXIT_CODE.USAGE,\n );\n }\n return parsed;\n}\n\n// updated/created date-window filters share the deadline ISO+relative resolver\n// so `pm search` matches `pm list` semantics exactly: pass an ISO timestamp or a\n// SIGNED relative offset (\"-2h\"/\"-7d\" reach into the past, \"+1d\" the future;\n// units h/d/w/m, m = months — there is no minutes unit).\nfunction parseTimestampWindow(\n raw: unknown,\n fieldLabel: string,\n): string | undefined {\n if (raw == null) return undefined;\n const value = String(raw).trim();\n if (value.length === 0) return undefined;\n return resolveIsoOrRelative(value, new Date(), fieldLabel);\n}\n\nfunction normalizeSearchPhrase(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\nfunction parseDeadline(\n raw: string | undefined,\n fieldLabel: string,\n): string | undefined {\n if (raw === undefined) return undefined;\n return resolveIsoOrRelative(raw, new Date(), fieldLabel);\n}\n\nfunction parseFieldSelectors(raw: string | undefined): string[] | undefined {\n if (raw === undefined) {\n return undefined;\n }\n const selectors = raw\n .split(\",\")\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n if (selectors.length === 0) {\n throw new PmCliError(\n \"Search --fields requires a comma-separated list of field names\",\n EXIT_CODE.USAGE,\n );\n }\n return [...new Set(selectors)];\n}\n\nfunction parseProjectionConfig(options: SearchOptions): SearchProjectionConfig {\n const compactRequested = options.compact === true;\n const fullRequested = options.full === true;\n const fieldSelectors = parseFieldSelectors(options.fields);\n const enabledModes =\n Number(compactRequested) +\n Number(fullRequested) +\n Number(fieldSelectors !== undefined);\n if (enabledModes > 1) {\n throw new PmCliError(\n \"Search projection options are mutually exclusive. Use one of --compact, --full, or --fields.\",\n EXIT_CODE.USAGE,\n );\n }\n if (compactRequested) {\n return {\n mode: \"compact\",\n fields: [...DEFAULT_COMPACT_SEARCH_FIELDS],\n };\n }\n if (fullRequested) {\n return {\n mode: \"full\",\n fields: [],\n };\n }\n if (fieldSelectors) {\n return {\n mode: \"fields\",\n fields: fieldSelectors,\n };\n }\n return {\n mode: \"full\",\n fields: [],\n };\n}\n\n/** Public contract for test only search command, shared by SDK and presentation-layer consumers. */\nexport const _testOnlySearchCommand = {\n applyFilters,\n applyExactQueryFilters,\n applyInlineQueryFilters,\n buildHitHighlights,\n buildVerboseSearchFilters,\n buildExplicitSemanticFallbackWarning,\n buildCompactSearchFilterSummary,\n buildHybridLexicalScore,\n buildRerankCorpus,\n buildSemanticHits,\n classifyImplicitSemanticFallbackReason,\n collectErrorCauseCodes,\n collectExactPhraseFields,\n collectLinkedPaths,\n combineHybridHits,\n computeBuiltInBm25Hits,\n computeSemanticOrHybridHits,\n resolveBuiltInBm25Mode,\n countOccurrences,\n dependencyEntries,\n documentContainsExactPhrase,\n emptySearchResult,\n highlightFieldSnippet,\n loadDocuments,\n markTokenRuns,\n parseInlineQueryFilters,\n maybeEmitVectorIndexStaleWarning,\n loadLinkedCorpus,\n mergeVectorHitsById,\n normalizeExtensionProviderHits,\n normalizeScoreMap,\n parseProjectionConfig,\n parseTimestampWindow,\n parseTokens,\n projectSearchHits,\n readSearchFieldValue,\n requireSemanticDependencies,\n resolveExtensionSearchProvider,\n resolveExtensionSearchProviderByName,\n resolveExtensionVectorAdapter,\n resolveLinkedCorpusRoots,\n scoreDocument,\n sortHits,\n stringArray,\n textEntries,\n validateSearchProjectionFields,\n};\n\n/* c8 ignore start -- projection/runtime-field validation edge permutations are covered by integration query-contract tests */\nfunction validateSearchProjectionFields(\n projection: SearchProjectionConfig,\n runtimeFieldRegistry: RuntimeFieldRegistry,\n): void {\n if (projection.mode !== \"fields\") {\n return;\n }\n const runtimeKeys = new Set(\n runtimeFieldRegistry.definitions.flatMap((field) => [\n field.key,\n field.metadata_key,\n ]),\n );\n const unknown = projection.fields.filter((field) => {\n const normalized = field.trim();\n const itemKey = normalized.startsWith(\"item.\")\n ? normalized.slice(\"item.\".length)\n : normalized;\n return (\n !SEARCH_HIT_FIELD_KEYS.has(normalized) &&\n !SEARCH_ITEM_FIELD_KEYS.has(itemKey) &&\n !runtimeKeys.has(itemKey)\n );\n });\n if (unknown.length > 0) {\n throw new PmCliError(\n `Unknown search --fields value(s): ${unknown.join(\", \")}`,\n EXIT_CODE.USAGE,\n {\n examples: [\n \"pm search <query> --fields id,title,status,score\",\n \"pm search <query> --fields id,title,item.description,matched_fields\",\n ],\n nextSteps: [\n \"Use item.<field> for explicit item metadata fields, or run pm search --help for projection examples.\",\n ],\n },\n );\n }\n}\n/* c8 ignore stop */\n\nfunction parseTokens(query: string): string[] {\n const normalized = normalizeSearchPhrase(query);\n if (!normalized) {\n throw new PmCliError(\"Search query must not be empty\", EXIT_CODE.USAGE);\n }\n return normalized.split(/\\s+/).filter(Boolean);\n}\n\n/** Result of extracting inline `field:value` tokens from a raw search query. */\ninterface InlineQueryParse {\n /** The query with all recognized inline filter tokens removed. */\n residualQuery: string;\n /** Recognized inline filters keyed by field name; first occurrence per field wins. */\n inlineFilters: Partial<Record<InlineQueryFilterField, string>>;\n}\n\n/**\n * Split a raw search query into its residual keyword text and any inline\n * `field:value` filter tokens (GH-157). Recognized fields are\n * {@link INLINE_QUERY_FILTER_FIELDS}; the value runs to the end of the token so\n * colon-bearing values like `tag:area:search` parse as `{ tag: \"area:search\" }`.\n * Only the first occurrence of each field is captured — later duplicates are left\n * in the residual query so they are never silently dropped. Tokens whose prefix\n * is not a recognized field (`foo:bar`) stay in the residual query verbatim.\n */\nfunction parseInlineQueryFilters(query: string): InlineQueryParse {\n const inlineFilters: Partial<Record<InlineQueryFilterField, string>> = {};\n const residualTokens: string[] = [];\n for (const token of query.split(/\\s+/).filter((entry) => entry.length > 0)) {\n const separatorIndex = token.indexOf(\":\");\n const field =\n separatorIndex > 0 ? token.slice(0, separatorIndex).toLowerCase() : \"\";\n const value = separatorIndex > 0 ? token.slice(separatorIndex + 1) : \"\";\n const matchedField = (\n INLINE_QUERY_FILTER_FIELDS as ReadonlyArray<string>\n ).includes(field)\n ? (field as InlineQueryFilterField)\n : undefined;\n if (\n matchedField &&\n value.length > 0 &&\n inlineFilters[matchedField] === undefined\n ) {\n inlineFilters[matchedField] = value;\n continue;\n }\n residualTokens.push(token);\n }\n return {\n residualQuery: residualTokens.join(\" \"),\n inlineFilters,\n };\n}\n\n/** Merge inline `field:value` filters into a search options object (GH-157). Explicit `--field` flags always win: an inline token is applied only when the corresponding option is not already set, and a conflicting inline token is recorded as a `search_inline_filter_ignored:<field>:flag_takes_precedence` warning so the override is observable rather than silent. Returns a fresh options object — the caller's input is never mutated. */\nfunction applyInlineQueryFilters(\n options: SearchOptions,\n inlineFilters: Partial<Record<InlineQueryFilterField, string>>,\n warnings: string[],\n): SearchOptions {\n const merged: SearchOptions = { ...options };\n for (const field of INLINE_QUERY_FILTER_FIELDS) {\n const inlineValue = inlineFilters[field];\n if (inlineValue === undefined) {\n continue;\n }\n if (toNonEmptyStringOrUndefined(merged[field]) !== undefined) {\n warnings.push(\n `search_inline_filter_ignored:${field}:flag_takes_precedence`,\n );\n continue;\n }\n merged[field] = inlineValue;\n }\n return merged;\n}\n\nfunction stringArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((entry): entry is string => typeof entry === \"string\")\n : [];\n}\n\nfunction textEntries(value: unknown): Array<{ text: string }> {\n return Array.isArray(value)\n ? value.filter(\n (entry): entry is { text: string } =>\n typeof entry === \"object\" &&\n entry !== null &&\n typeof (entry as { text?: unknown }).text === \"string\",\n )\n : [];\n}\n\nfunction dependencyEntries(\n value: unknown,\n): Array<{ id: string; kind: string }> {\n return Array.isArray(value)\n ? value.filter(\n (entry): entry is { id: string; kind: string } =>\n typeof entry === \"object\" &&\n entry !== null &&\n typeof (entry as { id?: unknown }).id === \"string\" &&\n typeof (entry as { kind?: unknown }).kind === \"string\",\n )\n : [];\n}\n\nfunction collectExactPhraseFields(document: ItemDocument): string[] {\n const item = document.metadata;\n return [\n item.title,\n item.description,\n item.status,\n stringArray(item.tags).join(\" \"),\n document.body,\n textEntries(item.comments)\n .map((entry) => entry.text)\n .join(\" \"),\n textEntries(item.notes)\n .map((entry) => entry.text)\n .join(\" \"),\n textEntries(item.learnings)\n .map((entry) => entry.text)\n .join(\" \"),\n buildReminderCorpus(item).join(\" \"),\n buildEventCorpus(item).join(\" \"),\n dependencyEntries(item.dependencies)\n .map((entry) => `${entry.id} ${entry.kind}`)\n .join(\" \"),\n buildPlanFlatCorpus(item),\n ];\n}\n\nfunction documentContainsExactPhrase(\n document: ItemDocument,\n normalizedQuery: string,\n): boolean {\n return collectExactPhraseFields(document).some((fieldValue) =>\n normalizeSearchPhrase(fieldValue).includes(normalizedQuery),\n );\n}\n\nfunction applyExactQueryFilters(\n items: ItemDocument[],\n normalizedQuery: string,\n options: { titleExact: boolean; phraseExact: boolean },\n): ItemDocument[] {\n if (!options.titleExact && !options.phraseExact) {\n return items;\n }\n return items.filter((document) => {\n if (\n options.titleExact &&\n normalizeSearchPhrase(document.metadata.title) !== normalizedQuery\n ) {\n return false;\n }\n if (\n options.phraseExact &&\n !documentContainsExactPhrase(document, normalizedQuery)\n ) {\n return false;\n }\n return true;\n });\n}\n\ntype SearchMissingMetadataFilters = ReturnType<\n typeof resolveMissingMetadataFilters\n>;\ntype SearchContentFieldFilters = ReturnType<typeof resolveContentFieldFilters>;\n\ninterface SearchMetadataFilterSet {\n typeFilter: ItemType | undefined;\n tagFilter: string | undefined;\n priorityFilter: number | undefined;\n deadlineBefore: string | undefined;\n deadlineAfter: string | undefined;\n updatedAfter: string | undefined;\n updatedBefore: string | undefined;\n createdAfter: string | undefined;\n createdBefore: string | undefined;\n assigneeFilter: string | undefined;\n sprintFilter: string | undefined;\n releaseFilter: string | undefined;\n parentFilter: string | undefined;\n statusSet: Set<ItemStatus> | undefined;\n missingMetadataFilters: SearchMissingMetadataFilters;\n missingMetadataActive: boolean;\n contentFieldFilters: SearchContentFieldFilters;\n contentFiltersActive: boolean;\n}\n\nfunction assertSearchAssigneeFilter(assigneeFilter: string | undefined): void {\n // Match pm list: --assignee no longer accepts none/null (unassigned filtering\n // belongs to a dedicated flag there; pm search has no presence flag so reject\n // the sentinel values explicitly rather than silently matching a literal).\n if (\n assigneeFilter &&\n (assigneeFilter.toLowerCase() === \"none\" ||\n assigneeFilter.toLowerCase() === \"null\")\n ) {\n throw new PmCliError(\n '--assignee no longer accepts \"none\" or \"null\".',\n EXIT_CODE.USAGE,\n );\n }\n}\n\nfunction resolveSearchMetadataFilterSet(\n options: SearchOptions,\n typeRegistry: ItemTypeRegistry,\n statusFilter: ItemStatus[] | undefined,\n): SearchMetadataFilterSet {\n const assigneeFilter = options.assignee?.trim();\n assertSearchAssigneeFilter(assigneeFilter);\n const missingMetadataFilters = resolveMissingMetadataFilters(options);\n const contentFieldFilters = resolveContentFieldFilters(\n options as Record<string, unknown>,\n );\n return {\n typeFilter: parseType(options.type, typeRegistry),\n tagFilter: options.tag?.trim().toLowerCase(),\n priorityFilter: parsePriority(options.priority),\n deadlineBefore: parseDeadline(options.deadlineBefore, \"deadline-before\"),\n deadlineAfter: parseDeadline(options.deadlineAfter, \"deadline-after\"),\n updatedAfter: parseTimestampWindow(options.updatedAfter, \"updated-after\"),\n updatedBefore: parseTimestampWindow(\n options.updatedBefore,\n \"updated-before\",\n ),\n createdAfter: parseTimestampWindow(options.createdAfter, \"created-after\"),\n createdBefore: parseTimestampWindow(\n options.createdBefore,\n \"created-before\",\n ),\n assigneeFilter,\n sprintFilter: options.sprint?.trim(),\n releaseFilter: options.release?.trim(),\n parentFilter: options.parent?.trim(),\n statusSet:\n statusFilter && statusFilter.length > 0\n ? new Set<ItemStatus>(statusFilter)\n : undefined,\n missingMetadataFilters,\n missingMetadataActive: hasMissingMetadataFilter(missingMetadataFilters),\n contentFieldFilters,\n contentFiltersActive: hasContentFieldFilter(contentFieldFilters),\n };\n}\n\nfunction matchesScalarSearchFilters(\n item: ItemMetadata,\n filters: SearchMetadataFilterSet,\n): boolean {\n return (\n matchesIdentitySearchFilters(item, filters) &&\n matchesTimestampSearchFilters(item, filters) &&\n matchesOwnerSearchFilters(item, filters)\n );\n}\n\nfunction matchesIdentitySearchFilters(\n item: ItemMetadata,\n filters: SearchMetadataFilterSet,\n): boolean {\n if (filters.statusSet && !filters.statusSet.has(item.status)) return false;\n if (filters.typeFilter && item.type !== filters.typeFilter) return false;\n if (filters.tagFilter && !stringArray(item.tags).includes(filters.tagFilter))\n return false;\n if (\n filters.priorityFilter !== undefined &&\n item.priority !== filters.priorityFilter\n )\n return false;\n return true;\n}\n\nfunction matchesTimestampSearchFilters(\n item: ItemMetadata,\n filters: SearchMetadataFilterSet,\n): boolean {\n return matchesTimestampFilters(item, filters);\n}\n\nfunction matchesOwnerSearchFilters(\n item: ItemMetadata,\n filters: SearchMetadataFilterSet,\n): boolean {\n if (\n filters.assigneeFilter !== undefined &&\n item.assignee !== filters.assigneeFilter\n )\n return false;\n if (\n filters.sprintFilter !== undefined &&\n item.sprint !== filters.sprintFilter\n )\n return false;\n /* c8 ignore start -- release/parent metadata filter combinations are covered by integration search fixtures */\n if (\n filters.releaseFilter !== undefined &&\n item.release !== filters.releaseFilter\n )\n return false;\n if (\n filters.parentFilter !== undefined &&\n item.parent !== filters.parentFilter\n )\n return false;\n /* c8 ignore stop */\n return true;\n}\n\nfunction matchesSearchMetadataFilters(\n document: ItemDocument,\n filters: SearchMetadataFilterSet,\n runtimeFieldFilters: Record<string, unknown>,\n lifecycleClassifier: LifecycleClassifier,\n): boolean {\n const item = document.metadata;\n if (!matchesScalarSearchFilters(item, filters)) {\n return false;\n }\n if (\n !matchesRuntimeFilters(item as Record<string, unknown>, runtimeFieldFilters)\n ) {\n return false;\n }\n if (\n filters.missingMetadataActive &&\n !itemMatchesMissingMetadata(\n item,\n filters.missingMetadataFilters,\n lifecycleClassifier,\n )\n ) {\n return false;\n }\n if (\n filters.contentFiltersActive &&\n !itemMatchesContentFilters(item, filters.contentFieldFilters)\n ) {\n return false;\n }\n return true;\n}\n\nfunction applyFilters(\n items: ItemDocument[],\n options: SearchOptions,\n typeRegistry: ItemTypeRegistry,\n runtimeFieldFilters: Record<string, unknown>,\n statusFilter: ItemStatus[] | undefined,\n lifecycleClassifier: LifecycleClassifier,\n): ItemDocument[] {\n const filters = resolveSearchMetadataFilterSet(\n options,\n typeRegistry,\n statusFilter,\n );\n return items.filter((document) =>\n matchesSearchMetadataFilters(\n document,\n filters,\n runtimeFieldFilters,\n lifecycleClassifier,\n ),\n );\n}\n\nfunction countOccurrences(haystack: string, needle: string): number {\n let count = 0;\n let index = 0;\n while (true) {\n const foundAt = haystack.indexOf(needle, index);\n if (foundAt < 0) {\n return count;\n }\n count += 1;\n index = foundAt + needle.length;\n }\n}\n\nfunction tokenizeForExactTokenMatch(value: string): string[] {\n return tokenizeAlphaNumeric(value);\n}\n\nfunction collectLinkedPaths(\n item: ItemMetadata,\n): Array<{ scope: \"project\" | \"global\"; path: string }> {\n const fromFiles = (item.files ?? []).map((entry) => ({\n scope: entry.scope,\n path: entry.path.trim(),\n }));\n const fromDocs = (item.docs ?? []).map((entry) => ({\n scope: entry.scope,\n path: entry.path.trim(),\n }));\n const fromTests = (item.tests ?? [])\n .filter(\n (entry): entry is typeof entry & { path: string } =>\n typeof entry.path === \"string\" && entry.path.trim().length > 0,\n )\n .map((entry) => ({\n scope: entry.scope,\n path: entry.path.trim(),\n }));\n const sorted = [...fromFiles, ...fromDocs, ...fromTests]\n .filter((entry) => entry.path.length > 0)\n .sort(\n (a, b) => a.scope.localeCompare(b.scope) || a.path.localeCompare(b.path),\n );\n const deduped = new Map<\n string,\n { scope: \"project\" | \"global\"; path: string }\n >();\n for (const entry of sorted) {\n deduped.set(`${entry.scope}:${entry.path}`, entry);\n }\n return [...deduped.values()];\n}\n\ninterface ContainmentRoot {\n resolved: string;\n realpath: string;\n}\n\ninterface LinkedCorpusRoots {\n projectContainmentRoot: ContainmentRoot | null;\n globalContainmentRoot: ContainmentRoot | null;\n}\n\nasync function resolveContainmentRoot(\n root: string,\n): Promise<ContainmentRoot | null> {\n const resolved = path.resolve(root);\n try {\n const realpathRoot = await fs.realpath(resolved);\n return {\n resolved,\n realpath: realpathRoot,\n };\n } catch {\n return null;\n }\n}\n\nasync function resolveLinkedCorpusRoots(\n projectRoot: string,\n globalRoot: string,\n): Promise<LinkedCorpusRoots> {\n const [projectContainmentRoot, globalContainmentRoot] = await Promise.all([\n resolveContainmentRoot(projectRoot),\n resolveContainmentRoot(globalRoot),\n ]);\n return {\n projectContainmentRoot,\n globalContainmentRoot,\n };\n}\n\nasync function loadLinkedCorpus(\n document: ItemDocument,\n roots: LinkedCorpusRoots,\n): Promise<string> {\n const linkedPaths = collectLinkedPaths(document.metadata);\n const chunks: string[] = [];\n for (const linkedPath of linkedPaths) {\n const containmentRoot =\n linkedPath.scope === \"global\"\n ? roots.globalContainmentRoot\n : roots.projectContainmentRoot;\n if (!containmentRoot) {\n continue;\n }\n const resolved = path.resolve(containmentRoot.resolved, linkedPath.path);\n if (!isPathWithinDirectory(containmentRoot.resolved, resolved)) {\n continue;\n }\n let linkedRealpath: string;\n try {\n linkedRealpath = await fs.realpath(resolved);\n } catch {\n continue;\n }\n if (!isPathWithinDirectory(containmentRoot.realpath, linkedRealpath)) {\n continue;\n }\n try {\n await runActiveOnReadHooks({\n path: resolved,\n scope: linkedPath.scope,\n });\n chunks.push(await fs.readFile(resolved, \"utf8\"));\n } catch {\n // Best-effort linked-content indexing: unreadable paths are ignored.\n }\n }\n return chunks.join(\"\\n\");\n}\n\n/** Documents the search tuning payload exchanged by command, SDK, and package integrations. */\nexport interface SearchTuning {\n /** Value that configures or reports title exact bonus for this contract. */\n title_exact_bonus: number;\n /** Value that configures or reports title weight for this contract. */\n title_weight: number;\n /** Value that configures or reports description weight for this contract. */\n description_weight: number;\n /** Value that configures or reports tags weight for this contract. */\n tags_weight: number;\n /** Value that configures or reports status weight for this contract. */\n status_weight: number;\n /** Value that configures or reports body weight for this contract. */\n body_weight: number;\n /** Value that configures or reports comments weight for this contract. */\n comments_weight: number;\n /** Value that configures or reports notes weight for this contract. */\n notes_weight: number;\n /** Value that configures or reports learnings weight for this contract. */\n learnings_weight: number;\n /** Value that configures or reports reminders weight for this contract. */\n reminders_weight: number;\n /** Value that configures or reports events weight for this contract. */\n events_weight: number;\n /** Value that configures or reports dependencies weight for this contract. */\n dependencies_weight: number;\n /** Value that configures or reports linked content weight for this contract. */\n linked_content_weight: number;\n}\n\n/**\n * Canonical definition of the document-derived searchable fields shared by the\n * lexical scorer ({@link scoreDocument}) and the matched-text highlighter\n * ({@link buildHitHighlights}). Keeping a single source of field name → text\n * extractor → tuning weight guarantees the highlighter can only ever produce\n * snippets for fields the scorer actually inspected. The `linked_content` field\n * is appended separately by the scorer because its text is supplied per-query\n * rather than derived from the document.\n */\nconst SEARCHABLE_FIELD_BUILDERS: ReadonlyArray<{\n name: string;\n weightKey: keyof SearchTuning;\n value: (document: ItemDocument) => string;\n}> = [\n {\n name: \"title\",\n weightKey: \"title_weight\",\n value: (document) => document.metadata.title,\n },\n {\n name: \"description\",\n weightKey: \"description_weight\",\n value: (document) => document.metadata.description,\n },\n {\n name: \"tags\",\n weightKey: \"tags_weight\",\n value: (document) => stringArray(document.metadata.tags).join(\" \"),\n },\n {\n name: \"status\",\n weightKey: \"status_weight\",\n value: (document) =>\n typeof document.metadata.status === \"string\"\n ? document.metadata.status\n : \"\",\n },\n {\n name: \"body\",\n weightKey: \"body_weight\",\n value: (document) => document.body,\n },\n {\n name: \"comments\",\n weightKey: \"comments_weight\",\n value: (document) =>\n textEntries(document.metadata.comments)\n .map((entry) => entry.text)\n .join(\" \"),\n },\n {\n name: \"notes\",\n weightKey: \"notes_weight\",\n value: (document) =>\n textEntries(document.metadata.notes)\n .map((entry) => entry.text)\n .join(\" \"),\n },\n {\n name: \"learnings\",\n weightKey: \"learnings_weight\",\n value: (document) =>\n textEntries(document.metadata.learnings)\n .map((entry) => entry.text)\n .join(\" \"),\n },\n {\n name: \"reminders\",\n weightKey: \"reminders_weight\",\n value: (document) => buildReminderCorpus(document.metadata).join(\" \"),\n },\n {\n name: \"events\",\n weightKey: \"events_weight\",\n value: (document) => buildEventCorpus(document.metadata).join(\" \"),\n },\n {\n name: \"dependencies\",\n weightKey: \"dependencies_weight\",\n value: (document) =>\n dependencyEntries(document.metadata.dependencies)\n .map((entry) => `${entry.id} ${entry.kind}`)\n .join(\" \"),\n },\n {\n name: \"plan\",\n weightKey: \"body_weight\",\n value: (document) => buildPlanFlatCorpus(document.metadata),\n },\n];\n\n// Name → builder index so the highlighter can resolve a matched field to its\n// text extractor in O(1) and evaluate ONLY the matched fields' values, instead\n// of materializing all twelve (several of which join/build corpora) per hit.\nconst SEARCHABLE_FIELD_BUILDER_BY_NAME = new Map(\n SEARCHABLE_FIELD_BUILDERS.map((builder) => [builder.name, builder]),\n);\n\nfunction escapeRegExpLiteral(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/**\n * Wrap every case-insensitive occurrence of any query token in `text` with the\n * {@link HIGHLIGHT_OPEN}/{@link HIGHLIGHT_CLOSE} markers. Token boundaries follow\n * the same substring semantics as the lexical scorer (a token highlights inside\n * longer words, matching how it scored), and overlapping matches are coalesced\n * by the single combined alternation so markers never nest.\n */\nfunction markTokenRuns(text: string, tokens: string[]): string {\n // Sort by length descending before building the alternation so a longer token\n // wins over a shorter token that is its prefix (regex alternation is greedy\n // left-to-right, so `auth|authority` would mark «auth»ority instead of\n // «authority»). `.filter` already returns a fresh array, so the in-place sort\n // never mutates the caller's token list.\n const escaped = tokens\n .filter((token) => token.length > 0)\n .sort((left, right) => right.length - left.length)\n .map(escapeRegExpLiteral);\n if (escaped.length === 0) {\n return text;\n }\n const pattern = new RegExp(escaped.join(\"|\"), \"gi\");\n return text.replace(\n pattern,\n (match) => `${HIGHLIGHT_OPEN}${match}${HIGHLIGHT_CLOSE}`,\n );\n}\n\n/**\n * Build a single highlighted snippet for one field value (GH-157), or null when\n * no token matches. The snippet is a window of {@link HIGHLIGHT_SNIPPET_RADIUS}\n * characters on each side of the first match with the matching token runs\n * wrapped in markers, prefixed/suffixed with an ellipsis when the field text was\n * trimmed. Returning null lets the caller skip fields with no concrete textual\n * match (e.g. a field flagged purely by the phrase-coverage bonus).\n */\nfunction highlightFieldSnippet(text: string, tokens: string[]): string | null {\n if (text.length === 0) {\n return null;\n }\n const lowerText = text.toLowerCase();\n let firstMatchIndex = -1;\n let firstMatchLength = 0;\n for (const token of tokens) {\n if (token.length === 0) {\n continue;\n }\n const index = lowerText.indexOf(token);\n if (index >= 0 && (firstMatchIndex < 0 || index < firstMatchIndex)) {\n firstMatchIndex = index;\n firstMatchLength = token.length;\n }\n }\n if (firstMatchIndex < 0) {\n return null;\n }\n const windowStart = Math.max(0, firstMatchIndex - HIGHLIGHT_SNIPPET_RADIUS);\n const windowEnd = Math.min(\n text.length,\n firstMatchIndex + firstMatchLength + HIGHLIGHT_SNIPPET_RADIUS,\n );\n const marked = markTokenRuns(text.slice(windowStart, windowEnd), tokens);\n const prefix = windowStart > 0 ? \"…\" : \"\";\n const suffix = windowEnd < text.length ? \"…\" : \"\";\n return `${prefix}${marked}${suffix}`;\n}\n\n/** Produce per-field matched-text snippets for a hit (GH-157, `--highlight`). Iterates the hit's already-sorted `matched_fields`, retains only the document-derived searchable fields (skipping synthetic markers like `id`, `semantic`, `rerank`, and `linked_content`), and emits a snippet for each field that still contains a concrete token match. */\nfunction buildHitHighlights(\n document: ItemDocument,\n matchedFields: string[],\n tokens: string[],\n): SearchHitHighlight[] {\n const highlights: SearchHitHighlight[] = [];\n for (const field of matchedFields) {\n const builder = SEARCHABLE_FIELD_BUILDER_BY_NAME.get(field);\n if (builder === undefined) {\n continue;\n }\n const snippet = highlightFieldSnippet(builder.value(document), tokens);\n if (snippet !== null) {\n highlights.push({ field, snippet });\n }\n }\n return highlights;\n}\n\ninterface SearchableScoringField {\n name: string;\n value: string;\n weight: number;\n}\n\ninterface SearchScoreState {\n score: number;\n matched: Set<string>;\n matchedTokens: Set<string>;\n}\n\nfunction buildSearchableScoringFields(\n document: ItemDocument,\n linkedCorpus: string,\n tuning: SearchTuning,\n): SearchableScoringField[] {\n return [\n ...SEARCHABLE_FIELD_BUILDERS.map((builder) => ({\n name: builder.name,\n value: builder.value(document),\n weight: tuning[builder.weightKey],\n })),\n {\n name: \"linked_content\",\n value: linkedCorpus,\n weight: tuning.linked_content_weight,\n },\n ];\n}\n\nfunction buildExactIdSearchHit(\n item: ItemMetadata,\n normalizedQuery: string,\n idPrefix: string,\n): SearchHit | null {\n const normalizedId = normalizeSearchPhrase(item.id);\n const normalizedIdPrefix =\n typeof idPrefix === \"string\" ? idPrefix.trim().toLowerCase() : \"\";\n const normalizedIdPrefixPhrase = normalizeSearchPhrase(normalizedIdPrefix);\n const normalizedShortId =\n normalizedIdPrefixPhrase.length > 0 &&\n normalizedId.startsWith(normalizedIdPrefixPhrase)\n ? normalizedId.slice(normalizedIdPrefixPhrase.length).trim()\n : normalizedId;\n if (\n normalizedQuery !== normalizedId &&\n normalizedQuery !== normalizedShortId\n ) {\n return null;\n }\n return {\n item,\n score:\n normalizedQuery === normalizedId\n ? EXACT_ID_MATCH_SCORE\n : SHORT_ID_MATCH_SCORE,\n matched_fields: [\"id\"],\n matched_all_terms: true,\n exact_id_match: true,\n };\n}\n\nfunction scoreTokenMatches(\n tokens: string[],\n titleTokenCounts: Map<string, number>,\n searchableFields: SearchableScoringField[],\n tuning: SearchTuning,\n state: SearchScoreState,\n): void {\n for (const token of tokens) {\n const exactTitleMatches = titleTokenCounts.get(token) ?? 0;\n if (exactTitleMatches > 0) {\n state.score += exactTitleMatches * tuning.title_exact_bonus;\n state.matched.add(\"title\");\n state.matchedTokens.add(token);\n }\n for (const field of searchableFields) {\n const occurrences = countOccurrences(field.value.toLowerCase(), token);\n if (occurrences > 0) {\n state.score += occurrences * field.weight;\n state.matched.add(field.name);\n state.matchedTokens.add(token);\n }\n }\n }\n}\n\nfunction scorePhraseMatches(\n item: ItemMetadata,\n normalizedQuery: string,\n searchableFields: SearchableScoringField[],\n state: SearchScoreState,\n): void {\n const normalizedTitle = normalizeSearchPhrase(item.title);\n if (normalizedTitle === normalizedQuery) {\n state.score += LONG_QUERY_TITLE_EXACT_BONUS;\n state.matched.add(\"title\");\n }\n for (const field of searchableFields) {\n const phraseOccurrences = countOccurrences(\n normalizeSearchPhrase(field.value),\n normalizedQuery,\n );\n if (phraseOccurrences > 0) {\n state.score +=\n phraseOccurrences * field.weight * LONG_QUERY_PHRASE_MULTIPLIER;\n state.matched.add(field.name);\n }\n }\n}\n\nfunction scoreDocument(\n document: ItemDocument,\n tokens: string[],\n normalizedQuery: string,\n linkedCorpus: string,\n tuning: SearchTuning,\n idPrefix: string,\n applyCoverageBonus = false,\n): SearchHit | null {\n const item = document.metadata;\n const exactIdHit = buildExactIdSearchHit(item, normalizedQuery, idPrefix);\n if (exactIdHit) {\n return exactIdHit;\n }\n const titleTokenCounts = new Map<string, number>();\n for (const token of tokenizeForExactTokenMatch(item.title)) {\n titleTokenCounts.set(token, (titleTokenCounts.get(token) ?? 0) + 1);\n }\n const searchableFields = buildSearchableScoringFields(\n document,\n linkedCorpus,\n tuning,\n );\n const state: SearchScoreState = {\n score: 0,\n matched: new Set(),\n matchedTokens: new Set(),\n };\n scoreTokenMatches(tokens, titleTokenCounts, searchableFields, tuning, state);\n const distinctTokens = new Set(tokens);\n // matchedTokens only ever holds entries drawn from `tokens`, so it is always a\n // subset of distinctTokens — exact size equality means every distinct term matched.\n const matchedAllTerms =\n distinctTokens.size > 0 && state.matchedTokens.size === distinctTokens.size;\n // GH-181 default-mode all-terms ranking bonus: only meaningful for multi-token\n // queries where every distinct token matched somewhere.\n if (applyCoverageBonus && distinctTokens.size > 1 && matchedAllTerms) {\n state.score += ALL_TERMS_COVERAGE_BONUS;\n }\n\n const isLongPhraseQuery =\n tokens.length >= LONG_QUERY_TOKEN_THRESHOLD &&\n normalizedQuery.includes(\" \");\n if (isLongPhraseQuery) {\n scorePhraseMatches(item, normalizedQuery, searchableFields, state);\n }\n\n if (state.score <= 0) {\n return null;\n }\n\n return {\n item,\n score: state.score,\n matched_fields: [...state.matched].sort((a, b) => a.localeCompare(b)),\n matched_all_terms: matchedAllTerms,\n };\n}\n\nfunction sortHits(\n items: SearchHit[],\n statusRegistry: RuntimeStatusRegistry,\n): SearchHit[] {\n return [...items].sort((a, b) => {\n const byScore = b.score - a.score;\n if (byScore !== 0) return byScore;\n const aTerminal = isTerminalStatus(a.item.status, statusRegistry);\n const bTerminal = isTerminalStatus(b.item.status, statusRegistry);\n if (aTerminal !== bTerminal) {\n return aTerminal ? 1 : -1;\n }\n const byPriority = a.item.priority - b.item.priority;\n if (byPriority !== 0) return byPriority;\n const byUpdated = compareTimestampStrings(\n b.item.updated_at,\n a.item.updated_at,\n );\n if (byUpdated !== 0) return byUpdated;\n return a.item.id.localeCompare(b.item.id);\n });\n}\n\nfunction buildHybridLexicalScore(\n document: ItemDocument,\n tokens: string[],\n normalizedQuery: string,\n includeLinked: boolean,\n linkedCorpusById: Map<string, string>,\n tuning: SearchTuning,\n idPrefix: string,\n applyCoverageBonus = false,\n): SearchHit | null {\n /* c8 ignore start -- linked corpus presence branch is covered by keyword/hybrid integration query tests */\n return scoreDocument(\n document,\n tokens,\n normalizedQuery,\n includeLinked ? (linkedCorpusById.get(document.metadata.id) ?? \"\") : \"\",\n tuning,\n idPrefix,\n applyCoverageBonus,\n );\n /* c8 ignore stop */\n}\n\nfunction normalizeScoreMap(\n scoreById: Map<string, number>,\n): Map<string, number> {\n if (scoreById.size === 0) {\n return new Map();\n }\n const values = [...scoreById.values()];\n const minScore = Math.min(...values);\n const maxScore = Math.max(...values);\n if (maxScore === minScore) {\n return new Map([...scoreById.keys()].map((id) => [id, 1]));\n }\n const normalized = new Map<string, number>();\n for (const [id, score] of scoreById) {\n normalized.set(id, (score - minScore) / (maxScore - minScore));\n }\n return normalized;\n}\n\n/** Implements resolve search max results for the public runtime surface of this module. */\nexport function resolveSearchMaxResults(settings: unknown): number {\n const candidate = (settings as { search?: { max_results?: unknown } }).search\n ?.max_results;\n if (\n typeof candidate === \"number\" &&\n Number.isFinite(candidate) &&\n candidate > 0\n ) {\n return Math.floor(candidate);\n }\n return 50;\n}\n\n/** Implements resolve search score threshold for the public runtime surface of this module. */\nexport function resolveSearchScoreThreshold(settings: unknown): number {\n const candidate = (settings as { search?: { score_threshold?: unknown } })\n .search?.score_threshold;\n if (typeof candidate === \"number\" && Number.isFinite(candidate)) {\n return candidate;\n }\n return 0;\n}\n\n/** Implements resolve hybrid semantic weight for the public runtime surface of this module. */\nexport function resolveHybridSemanticWeight(settings: unknown): number {\n const candidate = (\n settings as { search?: { hybrid_semantic_weight?: unknown } }\n ).search?.hybrid_semantic_weight;\n if (\n typeof candidate === \"number\" &&\n Number.isFinite(candidate) &&\n candidate >= 0 &&\n candidate <= 1\n ) {\n return candidate;\n }\n return 0.7;\n}\n\n/** Implements resolve search tuning for the public runtime surface of this module. */\nexport function resolveSearchTuning(settings: unknown): SearchTuning {\n const defaults: SearchTuning = {\n title_exact_bonus: 10,\n title_weight: 8,\n description_weight: 5,\n tags_weight: 6,\n status_weight: 2,\n body_weight: 1,\n comments_weight: 1,\n notes_weight: 1,\n learnings_weight: 1,\n reminders_weight: 2,\n events_weight: 2,\n dependencies_weight: 3,\n linked_content_weight: 1,\n };\n const tuning = (settings as { search?: { tuning?: Partial<SearchTuning> } })\n .search?.tuning;\n if (!tuning) return defaults;\n\n const resolveWeight = (candidate: unknown, fallback: number) => {\n if (\n typeof candidate === \"number\" &&\n Number.isFinite(candidate) &&\n candidate >= 0\n ) {\n return candidate;\n }\n return fallback;\n };\n\n return {\n title_exact_bonus: resolveWeight(\n tuning.title_exact_bonus,\n defaults.title_exact_bonus,\n ),\n title_weight: resolveWeight(tuning.title_weight, defaults.title_weight),\n description_weight: resolveWeight(\n tuning.description_weight,\n defaults.description_weight,\n ),\n tags_weight: resolveWeight(tuning.tags_weight, defaults.tags_weight),\n status_weight: resolveWeight(tuning.status_weight, defaults.status_weight),\n body_weight: resolveWeight(tuning.body_weight, defaults.body_weight),\n comments_weight: resolveWeight(\n tuning.comments_weight,\n defaults.comments_weight,\n ),\n notes_weight: resolveWeight(tuning.notes_weight, defaults.notes_weight),\n learnings_weight: resolveWeight(\n tuning.learnings_weight,\n defaults.learnings_weight,\n ),\n reminders_weight: resolveWeight(\n tuning.reminders_weight,\n defaults.reminders_weight,\n ),\n events_weight: resolveWeight(tuning.events_weight, defaults.events_weight),\n dependencies_weight: resolveWeight(\n tuning.dependencies_weight,\n defaults.dependencies_weight,\n ),\n linked_content_weight: resolveWeight(\n tuning.linked_content_weight,\n defaults.linked_content_weight,\n ),\n };\n}\n\n/* c8 ignore start -- empty-result projection/count/warnings shape matrix is validated by integration response-contract tests */\nfunction emptySearchResult(\n query: string,\n mode: SearchMode,\n matchMode: SearchMatchMode,\n options: SearchOptions,\n includeLinked: boolean,\n scoreThreshold: number,\n hybridSemanticWeight: number,\n queryExpansion: QueryExpansionConfig,\n rerank: RerankConfig,\n projection: SearchProjectionConfig,\n warnings: string[],\n runtimeFieldFilters?: Record<string, unknown>,\n countOnly = false,\n): SearchResult {\n // --count consistency: a count-only query that matches nothing must still\n // carry the same { count_only: true, total } shape as the non-empty path.\n const countExtras = countOnly ? { total: 0, count_only: true } : {};\n const compactSummaryMode =\n projection.mode === \"compact\" && options.compact === true;\n if (compactSummaryMode) {\n const compactFilters = buildCompactSearchFilterSummary({\n mode,\n matchMode,\n options,\n includeLinked,\n titleExact: options.titleExact === true,\n phraseExact: options.phraseExact === true,\n scoreThreshold,\n hybridSemanticWeight,\n runtimeFieldFilters,\n });\n return {\n query: query.trim(),\n mode,\n items: [],\n count: 0,\n ...countExtras,\n filters: compactFilters,\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n }\n const projectionFields =\n projection.mode === \"full\" ? null : [...projection.fields];\n return {\n query: query.trim(),\n mode,\n items: [],\n count: 0,\n ...countExtras,\n filters: buildVerboseSearchFilters({\n effectiveMode: mode,\n matchMode,\n options,\n includeLinked,\n titleExact: options.titleExact === true,\n phraseExact: options.phraseExact === true,\n scoreThreshold,\n hybridSemanticWeight,\n queryExpansion,\n rerank,\n runtimeFieldFilters: runtimeFieldFilters ?? {},\n }),\n projection: {\n mode: projection.mode,\n fields: projectionFields,\n },\n now: nowIso(),\n ...(warnings.length > 0 ? { warnings } : {}),\n };\n}\n/* c8 ignore stop */\n\nfunction requireSemanticDependencies(\n requestedMode: Exclude<SearchMode, \"keyword\">,\n providerResolution: EmbeddingProviderResolution,\n vectorResolution: VectorStoreResolution,\n hasExtensionVectorQuery: boolean,\n): {\n provider: EmbeddingProviderConfig;\n vectorStore: VectorStoreConfig | null;\n} {\n if (!providerResolution.active) {\n throw new PmCliError(\n `Search mode '${requestedMode}' requires a configured embedding provider in settings.providers.openai or settings.providers.ollama`,\n EXIT_CODE.USAGE,\n );\n }\n if (!vectorResolution.active && !hasExtensionVectorQuery) {\n throw new PmCliError(\n `Search mode '${requestedMode}' requires a configured vector store in settings.vector_store.qdrant/settings.vector_store.lancedb or an extension adapter selected by settings.vector_store.adapter`,\n EXIT_CODE.USAGE,\n );\n }\n return {\n provider: providerResolution.active,\n vectorStore: vectorResolution.active ?? null,\n };\n}\n\nconst toOptionalNonEmptyString = toNonEmptyStringOrUndefined;\n\ninterface ExtensionSearchProviderHooks {\n providerName: string;\n query?: ExtensionSearchProviderQuery;\n queryExpansion?: ExtensionSearchProviderQueryExpansion;\n rerank?: ExtensionSearchProviderRerank;\n}\n\n/* c8 ignore start -- extension search-provider registration permutations are covered by extension integration suites */\nfunction resolveExtensionSearchProviderByName(\n providerName: string | undefined,\n): ExtensionSearchProviderHooks | null {\n const registrations = getActiveExtensionRegistrations();\n const resolved = resolveRegisteredSearchProvider(registrations, providerName);\n if (!resolved) {\n return null;\n }\n const runtimeDefinition = resolved.runtime_definition ?? resolved.definition;\n const query = (runtimeDefinition as { query?: unknown }).query;\n const queryExpansion =\n (\n runtimeDefinition as {\n queryExpansion?: unknown;\n query_expansion?: unknown;\n }\n ).queryExpansion ??\n (\n runtimeDefinition as {\n queryExpansion?: unknown;\n query_expansion?: unknown;\n }\n ).query_expansion;\n const rerank = (runtimeDefinition as { rerank?: unknown }).rerank;\n const registeredName =\n toOptionalNonEmptyString((runtimeDefinition as { name?: unknown }).name) ??\n toOptionalNonEmptyString(\n (resolved.definition as { name?: unknown }).name,\n ) ??\n providerName;\n /* c8 ignore next 2 -- providerName is required for lookup and remains a non-empty fallback */\n if (!registeredName) {\n return null;\n }\n const hooks: ExtensionSearchProviderHooks = {\n providerName: registeredName,\n ...(typeof query === \"function\"\n ? { query: query as ExtensionSearchProviderQuery }\n : {}),\n ...(typeof queryExpansion === \"function\"\n ? {\n queryExpansion:\n queryExpansion as ExtensionSearchProviderQueryExpansion,\n }\n : {}),\n ...(typeof rerank === \"function\"\n ? { rerank: rerank as ExtensionSearchProviderRerank }\n : {}),\n };\n if (!hooks.query && !hooks.queryExpansion && !hooks.rerank) {\n return null;\n }\n return hooks;\n}\n/* c8 ignore stop */\n\nfunction resolveExtensionSearchProvider(\n settings: PmSettings,\n): { providerName: string; query: ExtensionSearchProviderQuery } | null {\n const providerName = toOptionalNonEmptyString(\n (settings.search as { provider?: unknown } | undefined)?.provider,\n );\n const resolved = resolveExtensionSearchProviderByName(providerName);\n if (!resolved?.query) {\n return null;\n }\n return {\n providerName: resolved.providerName,\n query: resolved.query,\n };\n}\n\n/* c8 ignore start -- vector adapter runtime definition permutations are covered by extension integration suites */\nfunction resolveExtensionVectorAdapter(\n settings: PmSettings,\n): ExtensionVectorAdapter | null {\n const registrations = getActiveExtensionRegistrations();\n const adapterName = toOptionalNonEmptyString(\n (settings.vector_store as { adapter?: unknown } | undefined)?.adapter,\n );\n const resolved = resolveRegisteredVectorStoreAdapter(\n registrations,\n adapterName,\n );\n if (!resolved) {\n return null;\n }\n const runtimeDefinition = resolved.runtime_definition ?? resolved.definition;\n const query = (runtimeDefinition as { query?: unknown }).query;\n if (typeof query !== \"function\") {\n return null;\n }\n const upsert = (runtimeDefinition as { upsert?: unknown }).upsert;\n const runtimeAdapterName =\n toOptionalNonEmptyString((runtimeDefinition as { name?: unknown }).name) ??\n toOptionalNonEmptyString(\n (resolved.definition as { name?: unknown }).name,\n ) ??\n adapterName ??\n \"extension\";\n return {\n adapterName: runtimeAdapterName,\n query: query as ExtensionVectorQuery,\n ...(typeof upsert === \"function\"\n ? { upsert: upsert as ExtensionVectorUpsert }\n : {}),\n };\n}\n/* c8 ignore stop */\n\nfunction normalizeExtensionProviderHits(\n providerName: string,\n raw: unknown,\n filteredById: Map<string, ItemDocument>,\n): SearchHit[] {\n const rawHits = Array.isArray(raw)\n ? raw\n : (raw as { hits?: unknown } | null | undefined)?.hits;\n if (!Array.isArray(rawHits)) {\n throw new PmCliError(\n `Extension search provider \"${providerName}\" must return an array of hits or { hits: [...] }`,\n EXIT_CODE.GENERIC_FAILURE,\n );\n }\n\n const seen = new Set<string>();\n const hits: SearchHit[] = [];\n for (const rawHit of rawHits) {\n if (typeof rawHit !== \"object\" || rawHit === null) {\n continue;\n }\n const id = toOptionalNonEmptyString((rawHit as { id?: unknown }).id);\n const score = (rawHit as { score?: unknown }).score;\n if (\n !id ||\n typeof score !== \"number\" ||\n !Number.isFinite(score) ||\n seen.has(id)\n ) {\n continue;\n }\n const document = filteredById.get(id);\n if (!document) {\n continue;\n }\n const matchedFieldsRaw = (rawHit as { matched_fields?: unknown })\n .matched_fields;\n const matchedFields =\n Array.isArray(matchedFieldsRaw) &&\n matchedFieldsRaw.every((entry) => typeof entry === \"string\")\n ? [\n ...new Set(\n (matchedFieldsRaw as string[])\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0),\n ),\n ].sort((a, b) => a.localeCompare(b))\n : [`provider:${providerName}`];\n seen.add(id);\n hits.push({\n item: document.metadata,\n score,\n matched_fields: matchedFields,\n });\n }\n return hits;\n}\n\nfunction buildSemanticHits(\n vectorHits: VectorQueryHit[],\n filteredById: Map<string, ItemDocument>,\n): { semanticHits: SearchHit[]; semanticScores: Map<string, number> } {\n const semanticHits: SearchHit[] = [];\n const semanticScores = new Map<string, number>();\n for (const vectorHit of vectorHits) {\n if (semanticScores.has(vectorHit.id)) {\n continue;\n }\n const document = filteredById.get(vectorHit.id);\n if (!document) {\n continue;\n }\n semanticScores.set(vectorHit.id, vectorHit.score);\n semanticHits.push({\n item: document.metadata,\n score: vectorHit.score,\n matched_fields: [\"semantic\"],\n });\n }\n return {\n semanticHits,\n semanticScores,\n };\n}\n\n// GH-281: in semantic & hybrid mode the blended/vector scores live on an\n// arbitrary scale (blended hybrid scores are [0,1]; raw vector similarities are\n// provider-defined), so an exact full-ID or short-ID keyword match can be\n// out-ranked by a high-semantic body mention. This reattaches the exact-ID\n// keyword hit(s) to the top of the ranked set in a reserved band ABOVE every\n// other hit, preserving matched_fields:[\"id\"] and keeping full-ID above\n// short-ID. The reserved scores are derived from the current max so the\n// guarantee holds no matter what scale the backend returns, and the hit is\n// re-inserted even if it was dropped from `rankedHits` (e.g. it had no semantic\n// vector match) so it is never lost to the threshold or the result-limit slice.\nfunction forceExactIdHitsToTop(\n rankedHits: SearchHit[],\n keywordHits: SearchHit[],\n): SearchHit[] {\n const exactIdHits = keywordHits.filter((hit) => hit.exact_id_match === true);\n if (exactIdHits.length === 0) {\n return rankedHits;\n }\n const exactIdIds = new Set(exactIdHits.map((hit) => hit.item.id));\n const remaining = rankedHits.filter((hit) => !exactIdIds.has(hit.item.id));\n // reduce (not Math.max(...spread)) so a very large pre-truncation candidate\n // set can never overflow the call stack.\n const maxRemainingScore = remaining.reduce(\n (max, hit) => Math.max(max, hit.score),\n 0,\n );\n // Full-ID hits (score 1000) must rank above short-ID hits (score 900): rank\n // within the exact-ID band by the original keyword score (descending) so a\n // full-ID match always precedes a short-ID match for the same query, then\n // offset the whole band above every remaining hit. ids are unique, so two\n // exact-ID hits can never tie on score — sorting on score alone is total.\n // exactIdHits is already a fresh array from keywordHits.filter(...), so sort\n // it in place — no defensive copy needed.\n const orderedExactHits = exactIdHits.sort(\n (left, right) => right.score - left.score,\n );\n const bandBase = maxRemainingScore + orderedExactHits.length + 1;\n const promoted = orderedExactHits.map((hit, index) => ({\n // Spread the original keyword hit so flags like matched_all_terms /\n // exact_id_match are preserved; only the band-slot score and the id-only\n // matched_fields are overridden.\n ...hit,\n // Higher band slot for earlier (higher original keyword score) hits.\n score: bandBase - index,\n matched_fields: [\"id\"],\n }));\n return [...promoted, ...remaining];\n}\n\nfunction combineHybridHits(\n filteredById: Map<string, ItemDocument>,\n semanticScores: Map<string, number>,\n keywordHits: SearchHit[],\n hybridSemanticWeight: number,\n // Matched-field label for the dense-ranking component. Defaults to \"semantic\"\n // (vector retrieval); the offline BM25 hybrid path passes \"bm25\" so hits carry\n // an honest provenance marker instead of implying a vector match (pm-75k9).\n semanticFieldLabel = \"semantic\",\n): SearchHit[] {\n const keywordScores = new Map(\n keywordHits.map((entry) => [entry.item.id, entry.score]),\n );\n const keywordMatches = new Map(\n keywordHits.map((entry) => [entry.item.id, entry.matched_fields]),\n );\n const normalizedSemantic = normalizeScoreMap(semanticScores);\n const normalizedKeyword = normalizeScoreMap(keywordScores);\n const candidateIds = new Set<string>([\n ...semanticScores.keys(),\n ...keywordScores.keys(),\n ]);\n const keywordWeight = 1 - hybridSemanticWeight;\n return [...candidateIds]\n .map((id) => {\n const document = filteredById.get(id)!;\n const semanticScore = normalizedSemantic.get(id) ?? 0;\n const keywordScore = normalizedKeyword.get(id) ?? 0;\n const combinedScore =\n semanticScore * hybridSemanticWeight + keywordScore * keywordWeight;\n if (combinedScore <= 0) {\n return null;\n }\n const matchedFields = new Set<string>();\n if (semanticScores.has(id)) {\n matchedFields.add(semanticFieldLabel);\n }\n for (const field of keywordMatches.get(id) ?? []) {\n matchedFields.add(field);\n }\n return {\n item: document.metadata,\n score: combinedScore,\n matched_fields: [...matchedFields].sort((a, b) => a.localeCompare(b)),\n };\n })\n .filter((entry): entry is SearchHit => entry !== null);\n}\n\n/** Built-in BM25 activation outcome for semantic/hybrid search (pm-75k9): - `\"explicit\"`: `search.provider` is `bm25` — the user opted into offline lexical ranking, so it is used even if an embedding provider is configured. - `\"auto-fallback\"`: `search.provider` is `auto` and neither an embedding provider nor an extension search provider is available — BM25 is used in place of degrading to the naive field-weighted keyword scorer. - `null`: BM25 does not apply; the existing embedding/extension path runs. */\ntype BuiltInBm25Mode = \"explicit\" | \"auto-fallback\";\n\nfunction resolveBuiltInBm25Mode(params: {\n configuredProvider: string | undefined;\n hasEmbeddingProvider: boolean;\n hasExtensionSearchProvider: boolean;\n}): BuiltInBm25Mode | null {\n const normalized = params.configuredProvider?.trim().toLowerCase();\n if (normalized === \"bm25\") {\n return \"explicit\";\n }\n if (\n normalized === \"auto\" &&\n !params.hasEmbeddingProvider &&\n !params.hasExtensionSearchProvider\n ) {\n return \"auto-fallback\";\n }\n return null;\n}\n\n/**\n * Rank the filtered corpus with the offline BM25 provider (pm-75k9). Builds a\n * BM25 index over each document's resolved search corpus (honoring\n * `search.corpus_fields`), scores the query, and shapes hits for the requested\n * mode: semantic mode returns pure BM25-ranked hits tagged\n * `matched_fields: [\"bm25\"]`, while hybrid mode blends the BM25 scores with the\n * locally computed keyword scores via {@link combineHybridHits}. The exact\n * full-ID / short-ID guarantee is preserved in both modes via\n * {@link forceExactIdHitsToTop}. No network, embedding service, or vector store\n * is involved, so this path cannot fail on a backend error.\n */\nfunction computeBuiltInBm25Hits(params: {\n requestedMode: Exclude<SearchMode, \"keyword\">;\n query: string;\n filteredDocuments: ItemDocument[];\n keywordHits: SearchHit[];\n corpusFields: string[];\n bm25Params: Bm25Params;\n hybridSemanticWeight: number;\n}): SearchHit[] {\n const bm25Documents = params.filteredDocuments.map((document) => ({\n id: document.metadata.id,\n text: flattenSearchCorpusText(\n buildSearchCorpus(document, { fields: params.corpusFields }),\n ),\n }));\n const index = buildBm25Index(bm25Documents);\n const bm25Scores = scoreBm25Query(\n index,\n tokenizeBm25(params.query),\n params.bm25Params,\n );\n const filteredById = new Map(\n params.filteredDocuments.map((document) => [\n document.metadata.id,\n document,\n ]),\n );\n if (params.requestedMode === \"semantic\") {\n const semanticHits: SearchHit[] = [...bm25Scores].map(([id, score]) => ({\n item: filteredById.get(id)!.metadata,\n score,\n matched_fields: [\"bm25\"],\n }));\n return forceExactIdHitsToTop(semanticHits, params.keywordHits);\n }\n const hybridHits = combineHybridHits(\n filteredById,\n bm25Scores,\n params.keywordHits,\n params.hybridSemanticWeight,\n \"bm25\",\n );\n return forceExactIdHitsToTop(hybridHits, params.keywordHits);\n}\n\ninterface SemanticQueryContext {\n requestedMode: Exclude<SearchMode, \"keyword\">;\n query: string;\n filteredDocuments: ItemDocument[];\n keywordHits: SearchHit[];\n hybridSemanticWeight: number;\n limit: number | undefined;\n maxResults: number;\n provider: EmbeddingProviderConfig;\n vectorStore: VectorStoreConfig | null;\n extensionVectorAdapter: ExtensionVectorAdapter | null;\n queryExpansion: QueryExpansionConfig;\n queryExpansionExtension: {\n providerName: string;\n expand: ExtensionSearchProviderQueryExpansion;\n } | null;\n rerank: RerankConfig;\n rerankExtension: {\n providerName: string;\n rerank: ExtensionSearchProviderRerank;\n } | null;\n warnings: string[];\n settings: PmSettings;\n embeddingTimeoutMs?: number;\n vectorQueryTimeoutMs?: number;\n}\n\ninterface SemanticQueryResult {\n hits: SearchHit[];\n // Number of documents returned by the vector stage for this query after the\n // current metadata filters. When this is 0 the semantic/hybrid query ran\n // successfully, but vector ranking contributed nothing to the returned hits.\n vectorMatchCount: number;\n}\n\nfunction mergeVectorHitsById(\n vectorHitGroups: VectorQueryHit[][],\n): VectorQueryHit[] {\n const bestById = new Map<string, VectorQueryHit>();\n for (const group of vectorHitGroups) {\n for (const hit of group) {\n const existing = bestById.get(hit.id);\n if (!existing || hit.score > existing.score) {\n bestById.set(hit.id, hit);\n }\n }\n }\n const merged = [...bestById.values()];\n merged.sort((left, right) => {\n if (left.score !== right.score) {\n return right.score - left.score;\n }\n return left.id.localeCompare(right.id);\n });\n return merged;\n}\n\n/* c8 ignore start -- rerank corpus metadata-shape permutations are covered by semantic integration tests */\nfunction buildRerankCorpus(document: ItemDocument): string {\n const metadata = (document as { metadata?: ItemDocument[\"metadata\"] | null })\n .metadata;\n const tags = Array.isArray(metadata?.tags) ? metadata.tags.join(\" \") : \"\";\n return [\n metadata?.title,\n metadata?.description,\n metadata?.type,\n metadata?.status,\n tags,\n document.body,\n ]\n .map((entry) => (typeof entry === \"string\" ? entry.trim() : \"\"))\n .filter((entry) => entry.length > 0)\n .join(\"\\n\");\n}\n/* c8 ignore stop */\n\n/* c8 ignore start -- semantic expansion/rerank fallback matrices are covered by end-to-end semantic search tests */\nasync function resolveExpandedSemanticQueries(\n context: SemanticQueryContext,\n queryTrimmed: string,\n): Promise<string[]> {\n const baseExpandedQueries = context.queryExpansion.enabled\n ? buildDeterministicQueryExpansions(\n queryTrimmed,\n context.queryExpansion.max_queries,\n )\n : [queryTrimmed];\n const expandedQueries =\n baseExpandedQueries.length > 0 ? baseExpandedQueries : [queryTrimmed];\n if (!context.queryExpansion.enabled) {\n return expandedQueries;\n }\n if (context.queryExpansionExtension?.expand) {\n try {\n const rawExpansion = await Promise.resolve(\n context.queryExpansionExtension.expand({\n query: queryTrimmed,\n mode: context.requestedMode,\n settings: context.settings,\n }),\n );\n return mergeQueryExpansions(\n expandedQueries,\n normalizeQueryExpansionOutput(rawExpansion),\n context.queryExpansion.max_queries,\n );\n } catch {\n context.warnings.push(\n `search_query_expansion_provider_failed:${context.queryExpansionExtension.providerName}:using_builtin`,\n );\n return expandedQueries;\n }\n }\n if (\n context.queryExpansion.provider &&\n context.queryExpansion.provider !== \"openai\" &&\n context.queryExpansion.provider !== \"ollama\"\n ) {\n context.warnings.push(\n `search_query_expansion_provider_unavailable:${context.queryExpansion.provider}:using_builtin`,\n );\n }\n return expandedQueries;\n}\n\nasync function executeSemanticVectorQuery(\n context: SemanticQueryContext,\n semanticVector: number[],\n semanticLimit: number,\n vectorQueryOptions: { timeout_ms?: number },\n): Promise<VectorQueryHit[]> {\n if (context.extensionVectorAdapter?.query) {\n try {\n return await Promise.resolve(\n context.extensionVectorAdapter.query({\n vector: semanticVector,\n limit: semanticLimit,\n settings: context.settings,\n }),\n );\n } catch (error: unknown) {\n if (!context.vectorStore) {\n throw new PmCliError(\n `Extension vector adapter query failed and no built-in fallback store is configured (${error instanceof Error ? error.message : String(error)})`,\n EXIT_CODE.GENERIC_FAILURE,\n );\n }\n context.warnings.push(\n `search_vector_adapter_failed:${context.extensionVectorAdapter.adapterName}:using_builtin`,\n );\n return await executeVectorQuery(\n context.vectorStore,\n semanticVector,\n semanticLimit,\n vectorQueryOptions,\n );\n }\n }\n if (context.vectorStore) {\n return await executeVectorQuery(\n context.vectorStore,\n semanticVector,\n semanticLimit,\n vectorQueryOptions,\n );\n }\n throw new PmCliError(\n \"Semantic search requires either a configured vector store or an extension vector adapter query handler\",\n EXIT_CODE.USAGE,\n );\n}\n\nfunction buildRerankCandidateContexts(\n hybridHits: SearchHit[],\n filteredById: Map<string, ItemDocument>,\n topK: number,\n): Array<{ hit: SearchHit; text: string }> {\n const sortedForCandidates = [...hybridHits].sort((left, right) => {\n if (left.score !== right.score) {\n return right.score - left.score;\n }\n return left.item.id.localeCompare(right.item.id);\n });\n return sortedForCandidates\n .slice(0, topK)\n .map((hit) => {\n const document = filteredById.get(hit.item.id);\n return document ? { hit, text: buildRerankCorpus(document) } : null;\n })\n .filter(\n (entry): entry is { hit: SearchHit; text: string } => entry !== null,\n );\n}\n\nasync function resolveExtensionRerankScores(\n context: SemanticQueryContext,\n queryTrimmed: string,\n candidateContexts: Array<{ hit: SearchHit; text: string }>,\n): Promise<Map<string, number> | null> {\n if (!context.rerankExtension?.rerank) {\n return null;\n }\n try {\n const rawRerank = await Promise.resolve(\n context.rerankExtension.rerank({\n query: queryTrimmed,\n mode: \"hybrid\",\n model: context.rerank.model,\n top_k: context.rerank.top_k,\n settings: context.settings,\n candidates: candidateContexts.map((entry) => ({\n id: entry.hit.item.id,\n text: entry.text,\n score: entry.hit.score,\n })),\n }),\n );\n const normalizedRerank = normalizeRerankOutput(rawRerank);\n if (normalizedRerank.length > 0) {\n return new Map(normalizedRerank.map((entry) => [entry.id, entry.score]));\n }\n context.warnings.push(\n `search_rerank_provider_invalid_response:${context.rerankExtension.providerName}:using_builtin`,\n );\n return null;\n } catch {\n context.warnings.push(\n `search_rerank_provider_failed:${context.rerankExtension.providerName}:using_builtin`,\n );\n return null;\n }\n}\n\nasync function resolveRerankScores(\n context: SemanticQueryContext,\n queryTrimmed: string,\n candidateContexts: Array<{ hit: SearchHit; text: string }>,\n): Promise<Map<string, number> | null> {\n const extensionScores = await resolveExtensionRerankScores(\n context,\n queryTrimmed,\n candidateContexts,\n );\n if (extensionScores) {\n return extensionScores;\n }\n const rerankCandidates: RerankCandidate[] = candidateContexts.map(\n (entry) => ({\n id: entry.hit.item.id,\n text: entry.text,\n }),\n );\n try {\n return await rerankCandidatesWithEmbeddings(\n context.provider,\n context.rerank.model,\n queryTrimmed,\n rerankCandidates,\n context.embeddingTimeoutMs,\n );\n } catch {\n context.warnings.push(\"search_rerank_failed:using_hybrid_scores\");\n return null;\n }\n}\n\nfunction applyRerankScores(\n hybridHits: SearchHit[],\n rerankScores: Map<string, number>,\n): SearchHit[] {\n const rerankedIds = new Set(rerankScores.keys());\n const rerankedHits = hybridHits.map((hit) => {\n const rerankScore = rerankScores.get(hit.item.id);\n if (rerankScore === undefined) {\n return hit;\n }\n const matchedFields = new Set(hit.matched_fields);\n matchedFields.add(\"rerank\");\n return {\n ...hit,\n score: rerankScore,\n matched_fields: [...matchedFields].sort((left, right) =>\n left.localeCompare(right),\n ),\n };\n });\n rerankedHits.sort((left, right) => {\n const leftWasReranked = rerankedIds.has(left.item.id);\n const rightWasReranked = rerankedIds.has(right.item.id);\n if (leftWasReranked !== rightWasReranked) {\n return leftWasReranked ? -1 : 1;\n }\n if (left.score !== right.score) {\n return right.score - left.score;\n }\n return left.item.id.localeCompare(right.item.id);\n });\n return rerankedHits;\n}\n\nasync function applyHybridRerank(\n context: SemanticQueryContext,\n queryTrimmed: string,\n hybridHits: SearchHit[],\n filteredById: Map<string, ItemDocument>,\n): Promise<SearchHit[]> {\n if (!context.rerank.enabled || hybridHits.length <= 1) {\n return hybridHits;\n }\n const candidateContexts = buildRerankCandidateContexts(\n hybridHits,\n filteredById,\n context.rerank.top_k,\n );\n const rerankScores = await resolveRerankScores(\n context,\n queryTrimmed,\n candidateContexts,\n );\n return rerankScores && rerankScores.size > 0\n ? applyRerankScores(hybridHits, rerankScores)\n : hybridHits;\n}\n\nasync function computeSemanticOrHybridHits(\n context: SemanticQueryContext,\n): Promise<SemanticQueryResult> {\n const semanticLimit = Math.max(\n context.limit ?? context.maxResults,\n context.maxResults,\n );\n const embeddingOptions =\n context.embeddingTimeoutMs !== undefined\n ? { timeout_ms: context.embeddingTimeoutMs }\n : {};\n const vectorQueryOptions =\n context.vectorQueryTimeoutMs !== undefined\n ? { timeout_ms: context.vectorQueryTimeoutMs }\n : {};\n const queryTrimmed = context.query.trim();\n const expandedQueries = await resolveExpandedSemanticQueries(\n context,\n queryTrimmed,\n );\n const queryVectors = await executeEmbeddingRequest(\n context.provider,\n expandedQueries,\n embeddingOptions,\n );\n const queryVectorGroups = await Promise.all(\n queryVectors.map(\n async (semanticVector) =>\n await executeSemanticVectorQuery(\n context,\n semanticVector,\n semanticLimit,\n vectorQueryOptions,\n ),\n ),\n );\n const vectorHits = mergeVectorHitsById(queryVectorGroups);\n const filteredById = new Map(\n context.filteredDocuments.map((document) => [\n document.metadata.id,\n document,\n ]),\n );\n const { semanticHits, semanticScores } = buildSemanticHits(\n vectorHits,\n filteredById,\n );\n const vectorMatchCount = semanticScores.size;\n if (context.requestedMode === \"semantic\") {\n // GH-281: guarantee an exact full-ID / short-ID match ranks #1 even in pure\n // semantic mode, where it otherwise carries no vector hit at all.\n return {\n hits: forceExactIdHitsToTop(semanticHits, context.keywordHits),\n vectorMatchCount,\n };\n }\n const hybridHits = await applyHybridRerank(\n context,\n queryTrimmed,\n combineHybridHits(\n filteredById,\n semanticScores,\n context.keywordHits,\n context.hybridSemanticWeight,\n ),\n filteredById,\n );\n return {\n // GH-281: applied LAST (after any rerank reordering) so an exact full-ID /\n // short-ID keyword match always ranks #1 in hybrid mode regardless of the\n // semantic blend weight or rerank scores.\n hits: forceExactIdHitsToTop(hybridHits, context.keywordHits),\n vectorMatchCount,\n };\n}\n/* c8 ignore stop */\n\n/* c8 ignore start -- item body fallback read-path combinations are covered by document-cache integration tests */\nasync function loadDocuments(\n pmRoot: string,\n itemFormat: ItemFormat,\n typeToFolder: Record<string, string>,\n schema: PmSettings[\"schema\"],\n): Promise<{ documents: ItemDocument[]; warnings: string[] }> {\n const extensionFieldNames = collectRegisteredItemFieldNames(\n getActiveExtensionRegistrations(),\n );\n const readDocumentBody = async (\n metadata: ItemMetadata,\n preferredPath: string,\n preferredFormat: ItemFormat,\n ): Promise<string> => {\n const tryRead = async (\n targetPath: string,\n format: ItemFormat,\n ): Promise<string> => {\n await runActiveOnReadHooks({ path: targetPath, scope: \"project\" });\n const raw = await fs.readFile(targetPath, \"utf8\");\n const parsed = parseItemDocument(raw, {\n format,\n schema,\n extensionFieldNames,\n onWarning: (warning) => listWarnings.push(warning),\n });\n return parsed.body;\n };\n\n try {\n return await tryRead(preferredPath, preferredFormat);\n } catch {\n const alternateFormat: ItemFormat =\n preferredFormat === \"toon\" ? \"json_markdown\" : \"toon\";\n const alternatePath = getItemPath(\n pmRoot,\n metadata.type as ItemType,\n metadata.id,\n alternateFormat,\n typeToFolder,\n );\n try {\n return await tryRead(alternatePath, alternateFormat);\n } catch {\n listWarnings.push(\n `item_list_item_read_failed:${path.relative(pmRoot, alternatePath)}`,\n );\n return \"\";\n }\n }\n };\n\n const listWarnings: string[] = [];\n const cachedDocuments = await listAllDocumentCandidatesCached(\n pmRoot,\n itemFormat,\n typeToFolder,\n listWarnings,\n schema,\n );\n const documents: ItemDocument[] = [];\n if (cachedDocuments.length === 0) {\n const itemMetadataDocuments = await listAllItemMetadata(\n pmRoot,\n itemFormat,\n typeToFolder,\n listWarnings,\n schema,\n );\n for (const metadata of itemMetadataDocuments) {\n const preferredPath = getItemPath(\n pmRoot,\n metadata.type as ItemType,\n metadata.id,\n itemFormat,\n typeToFolder,\n );\n const body = await readDocumentBody(metadata, preferredPath, itemFormat);\n documents.push({ metadata, body });\n }\n return {\n documents,\n warnings: [...new Set(listWarnings)].sort((left, right) =>\n left.localeCompare(right),\n ),\n };\n }\n\n for (const cachedDocument of cachedDocuments) {\n if (typeof cachedDocument.body === \"string\") {\n documents.push({\n metadata: cachedDocument.metadata,\n body: cachedDocument.body,\n });\n continue;\n }\n const body = await readDocumentBody(\n cachedDocument.metadata,\n cachedDocument.item_path,\n cachedDocument.item_format,\n );\n documents.push({\n metadata: cachedDocument.metadata,\n body,\n });\n }\n return {\n documents,\n warnings: [...new Set(listWarnings)].sort((left, right) =>\n left.localeCompare(right),\n ),\n };\n}\n/* c8 ignore stop */\n\n/* c8 ignore start -- field projection lookup precedence is validated by output-shaping integration tests */\nfunction readSearchFieldValue(hit: SearchHit, field: string): unknown {\n const normalized = field.trim();\n if (normalized.length === 0) {\n return null;\n }\n if (normalized === \"score\") {\n return hit.score;\n }\n if (normalized === \"matched_fields\") {\n return hit.matched_fields;\n }\n if (normalized.startsWith(\"item.\")) {\n const itemKey = normalized.slice(\"item.\".length);\n if (itemKey.length === 0) {\n return null;\n }\n const itemRecord = toItemRecord(hit.item);\n return itemRecord[itemKey] ?? null;\n }\n const hitRecord = hit as unknown as Record<string, unknown>;\n const itemRecord = toItemRecord(hit.item);\n if (Object.prototype.hasOwnProperty.call(itemRecord, normalized)) {\n return itemRecord[normalized] ?? null;\n }\n if (Object.prototype.hasOwnProperty.call(hitRecord, normalized)) {\n return hitRecord[normalized] ?? null;\n }\n return null;\n}\n/* c8 ignore stop */\n\nfunction projectSearchHits(\n hits: SearchHit[],\n projection: SearchProjectionConfig,\n): SearchResultItem[] {\n if (projection.mode === \"full\") {\n // matched_all_terms is an internal ranking signal (GH-181); strip it from\n // full-mode output rows so the public hit shape stays { item, score, matched_fields }.\n return hits.map(\n ({\n matched_all_terms: _matchedAllTerms,\n exact_id_match: _exactIdMatch,\n ...hit\n }) => hit,\n );\n }\n return hits.map((hit) => {\n const projected: Record<string, unknown> = {};\n for (const field of projection.fields) {\n projected[field] = readSearchFieldValue(hit, field);\n }\n return projected;\n });\n}\n\ninterface PreparedSearchInput {\n query: string;\n options: SearchOptions;\n inlineWarnings: string[];\n highlight: boolean;\n includeLinked: boolean;\n titleExact: boolean;\n phraseExact: boolean;\n matchMode: SearchMatchMode;\n minScoreOverride: number | undefined;\n countOnly: boolean;\n tokens: string[];\n normalizedQuery: string;\n limit: number | undefined;\n projection: SearchProjectionConfig;\n modeWasExplicit: boolean;\n}\n\ninterface SearchRuntimeContext {\n pmRoot: string;\n settings: PmSettings;\n statusRegistry: RuntimeStatusRegistry;\n runtimeFieldRegistry: RuntimeFieldRegistry;\n runtimeFieldFilters: Record<string, unknown>;\n typeRegistry: ItemTypeRegistry;\n maxResults: number;\n scoreThreshold: number;\n semanticWeightProvided: boolean;\n semanticWeightOverride: number | undefined;\n hybridSemanticWeight: number;\n tuning: SearchTuning;\n providerResolution: EmbeddingProviderResolution;\n vectorResolution: VectorStoreResolution;\n extensionSearchProvider: ReturnType<typeof resolveExtensionSearchProvider>;\n extensionVectorAdapter: ReturnType<typeof resolveExtensionVectorAdapter>;\n bm25Mode: BuiltInBm25Mode | null;\n queryExpansion: QueryExpansionConfig;\n queryExpansionExtension: {\n providerName: string;\n expand: ExtensionSearchProviderQueryExpansion;\n } | null;\n rerank: RerankConfig;\n rerankExtension: {\n providerName: string;\n rerank: ExtensionSearchProviderRerank;\n } | null;\n effectiveMode: SearchMode;\n}\n\ninterface FilteredSearchCorpus {\n warnings: string[];\n allDocuments: ItemDocument[];\n filteredDocuments: ItemDocument[];\n}\n\ninterface SearchResponseContext {\n query: string;\n effectiveMode: SearchMode;\n matchMode: SearchMatchMode;\n options: SearchOptions;\n includeLinked: boolean;\n titleExact: boolean;\n phraseExact: boolean;\n scoreThreshold: number;\n hybridSemanticWeight: number;\n queryExpansion: QueryExpansionConfig;\n rerank: RerankConfig;\n projection: SearchProjectionConfig;\n warnings: string[];\n runtimeFieldFilters: Record<string, unknown>;\n}\n\ninterface SearchModeExecutionInput {\n prepared: PreparedSearchInput;\n runtime: SearchRuntimeContext;\n filteredDocuments: ItemDocument[];\n keywordHits: SearchHit[];\n warnings: string[];\n modeWasExplicit: boolean;\n}\n\ninterface SearchModeExecutionResult {\n effectiveMode: SearchMode;\n hits: SearchHit[];\n}\n\nfunction resolveQueryExpansionExtension(queryExpansion: QueryExpansionConfig): {\n providerName: string;\n expand: ExtensionSearchProviderQueryExpansion;\n} | null {\n const provider = resolveExtensionSearchProviderByName(\n queryExpansion.provider ?? undefined,\n );\n return provider?.queryExpansion\n ? { providerName: provider.providerName, expand: provider.queryExpansion }\n : null;\n}\n\nfunction resolveRerankExtension(\n settings: PmSettings,\n): { providerName: string; rerank: ExtensionSearchProviderRerank } | null {\n const provider = resolveExtensionSearchProviderByName(\n toOptionalNonEmptyString(settings.search?.provider),\n );\n return provider?.rerank\n ? { providerName: provider.providerName, rerank: provider.rerank }\n : null;\n}\n\nfunction prepareSearchInput(\n rawQuery: string,\n rawOptions: SearchOptions,\n): PreparedSearchInput {\n const inlineWarnings: string[] = [];\n const inlineParse = parseInlineQueryFilters(rawQuery);\n const hasInlineFilters = Object.keys(inlineParse.inlineFilters).length > 0;\n if (hasInlineFilters && inlineParse.residualQuery.trim().length === 0) {\n throw new PmCliError(\n \"Inline field:value tokens consumed the entire query, leaving no search terms.\",\n EXIT_CODE.USAGE,\n {\n examples: [\n \"pm search auth tag:area:search\",\n \"pm list --tag area:search --status open\",\n ],\n nextSteps: [\n \"Add keyword terms alongside the inline filters, or use pm list for pure tag/status/type/priority filtering.\",\n ],\n },\n );\n }\n const query = hasInlineFilters ? inlineParse.residualQuery : rawQuery;\n const options = applyInlineQueryFilters(\n rawOptions,\n inlineParse.inlineFilters,\n inlineWarnings,\n );\n return {\n query,\n options,\n inlineWarnings,\n highlight: options.highlight === true,\n includeLinked: parseIncludeLinked(options.includeLinked),\n titleExact: parseTitleExact(options.titleExact),\n phraseExact: parsePhraseExact(options.phraseExact),\n matchMode: parseMatchMode(\n typeof options.matchMode === \"string\" ? options.matchMode : undefined,\n ),\n minScoreOverride: parseMinScoreOverride(options.minScore),\n countOnly: options.count === true,\n tokens: parseTokens(query),\n normalizedQuery: normalizeSearchPhrase(query),\n limit: parseLimit(options.limit),\n projection: parseProjectionConfig(options),\n modeWasExplicit:\n typeof options.mode === \"string\" && options.mode.trim().length > 0,\n };\n}\n\nasync function resolveSearchRuntimeContext(\n prepared: PreparedSearchInput,\n global: GlobalOptions,\n): Promise<SearchRuntimeContext> {\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(\n `Tracker is not initialized at ${pmRoot}. Run pm init first.`,\n EXIT_CODE.NOT_FOUND,\n );\n }\n const storedSettings = await readSettings(pmRoot);\n const settings =\n resolveSettingsWithSemanticRuntimeDefaults(storedSettings).settings;\n const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);\n const runtimeFieldRegistry = resolveRuntimeFieldRegistry(settings.schema);\n validateSearchProjectionFields(prepared.projection, runtimeFieldRegistry);\n const runtimeFieldFilters = collectRuntimeFilterValues(\n prepared.options as Record<string, unknown>,\n runtimeFieldRegistry,\n \"search\",\n );\n const typeRegistry = resolveItemTypeRegistry(\n settings,\n getActiveExtensionRegistrations(),\n );\n const providerResolution = resolveEmbeddingProviders(settings);\n const vectorResolution = resolveVectorStores(settings, pmRoot);\n const extensionSearchProvider = resolveExtensionSearchProvider(settings);\n const extensionVectorAdapter = resolveExtensionVectorAdapter(settings);\n const semanticWeightOverride = parseSemanticWeightOverride(\n prepared.options.semanticWeight,\n );\n const queryExpansion = resolveQueryExpansionConfig(\n settings,\n providerResolution.active?.name ?? null,\n );\n const rerank = resolveRerankConfig(\n settings,\n providerResolution.active?.model ??\n toOptionalNonEmptyString(settings.search?.embedding_model) ??\n \"text-embedding-3-small\",\n );\n return {\n pmRoot,\n settings,\n statusRegistry,\n runtimeFieldRegistry,\n runtimeFieldFilters,\n typeRegistry,\n maxResults: resolveSearchMaxResults(settings),\n scoreThreshold:\n prepared.minScoreOverride ?? resolveSearchScoreThreshold(settings),\n semanticWeightProvided: prepared.options.semanticWeight !== undefined,\n semanticWeightOverride,\n hybridSemanticWeight:\n semanticWeightOverride ?? resolveHybridSemanticWeight(settings),\n tuning: resolveSearchTuning(settings),\n providerResolution,\n vectorResolution,\n extensionSearchProvider,\n extensionVectorAdapter,\n bm25Mode: resolveBuiltInBm25Mode({\n configuredProvider: toOptionalNonEmptyString(settings.search?.provider),\n hasEmbeddingProvider: providerResolution.active !== null,\n hasExtensionSearchProvider: extensionSearchProvider !== null,\n }),\n queryExpansion,\n queryExpansionExtension: resolveQueryExpansionExtension(queryExpansion),\n rerank,\n rerankExtension: resolveRerankExtension(settings),\n effectiveMode: parseMode(prepared.options.mode, {\n hasProvider:\n providerResolution.active !== null || extensionSearchProvider !== null,\n hasVectorStore:\n vectorResolution.active !== null || extensionVectorAdapter !== null,\n }),\n };\n}\n\nasync function loadFilteredSearchCorpus(\n prepared: PreparedSearchInput,\n runtime: SearchRuntimeContext,\n): Promise<FilteredSearchCorpus> {\n const loadedDocuments = await loadDocuments(\n runtime.pmRoot,\n runtime.settings.item_format ?? \"toon\",\n runtime.typeRegistry.type_to_folder,\n runtime.settings.schema,\n );\n const statusFilter = parseStatusFilterCsv(\n typeof prepared.options.status === \"string\"\n ? prepared.options.status\n : undefined,\n runtime.statusRegistry,\n { strict: true },\n );\n const lifecycleClassifier = lifecycleClassifierFromStatusRegistry(\n runtime.statusRegistry,\n );\n const metadataFilteredDocuments = applyFilters(\n loadedDocuments.documents,\n prepared.options,\n runtime.typeRegistry,\n runtime.runtimeFieldFilters,\n statusFilter,\n lifecycleClassifier,\n );\n return {\n warnings: loadedDocuments.warnings,\n allDocuments: loadedDocuments.documents,\n filteredDocuments: applyExactQueryFilters(\n metadataFilteredDocuments,\n prepared.normalizedQuery,\n {\n titleExact: prepared.titleExact,\n phraseExact: prepared.phraseExact || prepared.matchMode === \"exact\",\n },\n ),\n };\n}\n\nasync function collectLinkedCorpusById(\n includeLinked: boolean,\n effectiveMode: SearchMode,\n filteredDocuments: ItemDocument[],\n): Promise<Map<string, string>> {\n const linkedCorpusById = new Map<string, string>();\n if (\n !includeLinked ||\n (effectiveMode !== \"keyword\" && effectiveMode !== \"hybrid\")\n ) {\n return linkedCorpusById;\n }\n const projectRoot = process.cwd();\n const linkedCorpusRoots = await resolveLinkedCorpusRoots(\n projectRoot,\n resolveGlobalPmRoot(projectRoot),\n );\n const linkedCorpusEntries = await Promise.all(\n filteredDocuments.map(\n async (document) =>\n [\n document.metadata.id,\n await loadLinkedCorpus(document, linkedCorpusRoots),\n ] as const,\n ),\n );\n for (const [id, corpus] of linkedCorpusEntries) {\n linkedCorpusById.set(id, corpus);\n }\n return linkedCorpusById;\n}\n\nasync function computeKeywordSearchHits(\n prepared: PreparedSearchInput,\n runtime: SearchRuntimeContext,\n filteredDocuments: ItemDocument[],\n): Promise<SearchHit[]> {\n const linkedCorpusById = await collectLinkedCorpusById(\n prepared.includeLinked,\n runtime.effectiveMode,\n filteredDocuments,\n );\n const applyCoverageBonus = prepared.matchMode === \"or\";\n return filteredDocuments\n .map((document) =>\n buildHybridLexicalScore(\n document,\n prepared.tokens,\n prepared.normalizedQuery,\n prepared.includeLinked,\n linkedCorpusById,\n runtime.tuning,\n runtime.settings.id_prefix,\n applyCoverageBonus,\n ),\n )\n .filter((entry): entry is SearchHit => entry !== null)\n .filter(\n (entry) =>\n prepared.matchMode !== \"and\" || entry.matched_all_terms === true,\n );\n}\n\nfunction buildEmptySearchResultFromContext(\n response: SearchResponseContext,\n countOnly: boolean,\n): SearchResult {\n return emptySearchResult(\n response.query,\n response.effectiveMode,\n response.matchMode,\n response.options,\n response.includeLinked,\n response.scoreThreshold,\n response.hybridSemanticWeight,\n response.queryExpansion,\n response.rerank,\n response.projection,\n response.warnings,\n response.runtimeFieldFilters,\n countOnly,\n );\n}\n\nasync function executeBuiltInBm25Search(\n prepared: PreparedSearchInput,\n runtime: SearchRuntimeContext,\n filteredDocuments: ItemDocument[],\n keywordHits: SearchHit[],\n warnings: string[],\n): Promise<SearchHit[] | null> {\n if (runtime.bm25Mode === null || runtime.effectiveMode === \"keyword\") {\n return null;\n }\n const hits = computeBuiltInBm25Hits({\n requestedMode: runtime.effectiveMode,\n query: prepared.query,\n filteredDocuments,\n keywordHits,\n corpusFields: resolveSearchCorpusFields(runtime.settings),\n bm25Params: resolveBm25Params(runtime.settings),\n hybridSemanticWeight: runtime.hybridSemanticWeight,\n });\n if (runtime.bm25Mode === \"auto-fallback\") {\n warnings.push(\n `search_${runtime.effectiveMode}_offline_bm25:no_embedding_provider:using_lexical_bm25`,\n );\n }\n return hits;\n}\n\nasync function executeExtensionSearchProvider(\n prepared: PreparedSearchInput,\n runtime: SearchRuntimeContext,\n filteredDocuments: ItemDocument[],\n filteredById: Map<string, ItemDocument>,\n): Promise<SearchHit[] | null> {\n if (!runtime.extensionSearchProvider) {\n return null;\n }\n const canUseBuiltInSemantic =\n runtime.providerResolution.active !== null &&\n (runtime.vectorResolution.active !== null ||\n runtime.extensionVectorAdapter !== null);\n try {\n const providerResponse = await Promise.resolve(\n runtime.extensionSearchProvider.query({\n query: prepared.query,\n mode: runtime.effectiveMode,\n tokens: prepared.tokens,\n options: prepared.options,\n settings: runtime.settings,\n documents: filteredDocuments,\n }),\n );\n return normalizeExtensionProviderHits(\n runtime.extensionSearchProvider.providerName,\n providerResponse,\n filteredById,\n );\n } catch (error: unknown) {\n if (!canUseBuiltInSemantic) {\n throw new PmCliError(\n `Extension search provider \"${runtime.extensionSearchProvider.providerName}\" failed: ${error instanceof Error ? error.message : String(error)}`,\n EXIT_CODE.GENERIC_FAILURE,\n );\n }\n return null;\n }\n}\n\nfunction maybeApplyNoVectorFallback(\n effectiveMode: Exclude<SearchMode, \"keyword\">,\n semanticResult: Awaited<ReturnType<typeof computeSemanticOrHybridHits>>,\n keywordHits: SearchHit[],\n warnings: string[],\n): SearchHit[] {\n if (semanticResult.vectorMatchCount > 0) {\n return semanticResult.hits;\n }\n warnings.push(\n `search_${effectiveMode}_degraded:no_vector_matches:results_are_lexical`,\n );\n return effectiveMode === \"semantic\" ? keywordHits : semanticResult.hits;\n}\n\nasync function prepareBuiltInSemanticSearch(\n runtime: SearchRuntimeContext,\n effectiveMode: Exclude<SearchMode, \"keyword\">,\n filteredDocuments: ItemDocument[],\n warnings: string[],\n modeWasExplicit: boolean,\n): Promise<void> {\n const builtInSemanticWillRun =\n !runtime.extensionSearchProvider &&\n runtime.providerResolution.active !== null &&\n (runtime.vectorResolution.active !== null ||\n runtime.extensionVectorAdapter !== null);\n if (modeWasExplicit && builtInSemanticWillRun) {\n await maybeEmitVectorIndexStaleWarning(\n runtime.pmRoot,\n filteredDocuments,\n warnings,\n );\n }\n if (!runtime.extensionSearchProvider) {\n requireSemanticDependencies(\n effectiveMode,\n runtime.providerResolution,\n runtime.vectorResolution,\n runtime.extensionVectorAdapter !== null,\n );\n }\n}\n\nasync function executeSemanticSearch(\n input: SearchModeExecutionInput,\n): Promise<SearchModeExecutionResult> {\n const {\n prepared,\n runtime,\n filteredDocuments,\n keywordHits,\n warnings,\n modeWasExplicit,\n } = input;\n let hits = keywordHits;\n const bm25Hits = await executeBuiltInBm25Search(\n prepared,\n runtime,\n filteredDocuments,\n keywordHits,\n warnings,\n );\n const semanticMode = runtime.effectiveMode;\n if (bm25Hits !== null || semanticMode === \"keyword\") {\n return { effectiveMode: runtime.effectiveMode, hits: bm25Hits ?? hits };\n }\n try {\n await prepareBuiltInSemanticSearch(\n runtime,\n semanticMode,\n filteredDocuments,\n warnings,\n modeWasExplicit,\n );\n if (filteredDocuments.length === 0 || prepared.limit === 0) {\n return { effectiveMode: runtime.effectiveMode, hits: [] };\n }\n const filteredById = new Map(\n filteredDocuments.map((document) => [document.metadata.id, document]),\n );\n hits =\n (await executeExtensionSearchProvider(\n prepared,\n runtime,\n filteredDocuments,\n filteredById,\n )) ?? hits;\n if (hits === keywordHits) {\n const { provider, vectorStore } = requireSemanticDependencies(\n semanticMode,\n runtime.providerResolution,\n runtime.vectorResolution,\n runtime.extensionVectorAdapter !== null,\n );\n const semanticResult = await computeSemanticOrHybridHits({\n requestedMode: semanticMode,\n query: prepared.query,\n filteredDocuments,\n keywordHits,\n hybridSemanticWeight: runtime.hybridSemanticWeight,\n limit: prepared.limit,\n maxResults: runtime.maxResults,\n provider,\n vectorStore,\n extensionVectorAdapter: runtime.extensionVectorAdapter,\n queryExpansion: runtime.queryExpansion,\n queryExpansionExtension: runtime.queryExpansionExtension,\n rerank: runtime.rerank,\n rerankExtension: runtime.rerankExtension,\n warnings,\n settings: runtime.settings,\n });\n hits = maybeApplyNoVectorFallback(\n semanticMode,\n semanticResult,\n keywordHits,\n warnings,\n );\n }\n return { effectiveMode: runtime.effectiveMode, hits };\n } catch (error: unknown) {\n warnings.push(\n buildExplicitSemanticFallbackWarning(runtime.effectiveMode, error),\n );\n return { effectiveMode: \"keyword\", hits: keywordHits };\n }\n}\n\nfunction buildCountOnlySearchResult(\n response: SearchResponseContext,\n total: number,\n): SearchResult {\n if (\n response.projection.mode === \"compact\" &&\n response.options.compact === true\n ) {\n return withSearchWarnings(\n {\n query: response.query.trim(),\n mode: response.effectiveMode,\n items: [],\n count: total,\n total,\n count_only: true,\n filters: buildCompactSearchFilterSummary({\n mode: response.effectiveMode,\n matchMode: response.matchMode,\n options: response.options,\n includeLinked: response.includeLinked,\n titleExact: response.titleExact,\n phraseExact: response.phraseExact,\n scoreThreshold: response.scoreThreshold,\n hybridSemanticWeight: response.hybridSemanticWeight,\n runtimeFieldFilters: response.runtimeFieldFilters,\n }),\n },\n response.warnings,\n );\n }\n const projectionFields =\n response.projection.mode === \"full\"\n ? null\n : [...response.projection.fields];\n return withSearchWarnings(\n {\n query: response.query.trim(),\n mode: response.effectiveMode,\n items: [],\n count: total,\n total,\n count_only: true,\n filters: buildVerboseSearchFilters({\n effectiveMode: response.effectiveMode,\n matchMode: response.matchMode,\n options: response.options,\n includeLinked: response.includeLinked,\n titleExact: response.titleExact,\n phraseExact: response.phraseExact,\n scoreThreshold: response.scoreThreshold,\n hybridSemanticWeight: response.hybridSemanticWeight,\n queryExpansion: response.queryExpansion,\n rerank: response.rerank,\n runtimeFieldFilters: response.runtimeFieldFilters,\n }),\n projection: {\n mode: response.projection.mode,\n fields: projectionFields,\n },\n now: nowIso(),\n },\n response.warnings,\n );\n}\n\nfunction withSearchWarnings(\n result: SearchResult,\n warnings: string[],\n): SearchResult {\n if (warnings.length === 0) {\n return result;\n }\n return { ...result, warnings };\n}\n\nfunction attachSearchHighlights(\n prepared: PreparedSearchInput,\n filteredDocuments: ItemDocument[],\n limited: SearchHit[],\n): { hits: SearchHit[]; projection: SearchProjectionConfig } {\n if (!prepared.highlight) {\n return { hits: limited, projection: prepared.projection };\n }\n const documentById = new Map(\n filteredDocuments.map((document) => [document.metadata.id, document]),\n );\n const hits = limited.map((hit) => ({\n ...hit,\n highlights: buildHitHighlights(\n documentById.get(hit.item.id)!,\n hit.matched_fields,\n prepared.tokens,\n ),\n }));\n if (\n prepared.projection.mode === \"full\" ||\n prepared.projection.fields.includes(\"highlights\")\n ) {\n return { hits, projection: prepared.projection };\n }\n return {\n hits,\n projection: {\n mode: prepared.projection.mode,\n fields: [...prepared.projection.fields, \"highlights\"],\n },\n };\n}\n\nfunction buildSearchResultForHits(\n response: SearchResponseContext,\n projectedItems: SearchResultItem[],\n total: number,\n limitedCount: number,\n effectiveProjection: SearchProjectionConfig,\n pageExtras: {\n has_more?: boolean;\n next_cursor?: string;\n applied_limit: number;\n truncated?: true;\n },\n): SearchResult {\n const truncationExtras = limitedCount < total ? { total } : {};\n if (\n response.projection.mode === \"compact\" &&\n response.options.compact === true\n ) {\n return withSearchWarnings(\n {\n query: response.query.trim(),\n mode: response.effectiveMode,\n items: projectedItems,\n count: projectedItems.length,\n ...truncationExtras,\n ...pageExtras,\n filters: buildCompactSearchFilterSummary({\n mode: response.effectiveMode,\n matchMode: response.matchMode,\n options: response.options,\n includeLinked: response.includeLinked,\n titleExact: response.titleExact,\n phraseExact: response.phraseExact,\n scoreThreshold: response.scoreThreshold,\n hybridSemanticWeight: response.hybridSemanticWeight,\n runtimeFieldFilters: response.runtimeFieldFilters,\n }),\n },\n response.warnings,\n );\n }\n const finalProjectionFields =\n effectiveProjection.mode === \"full\"\n ? null\n : [...effectiveProjection.fields];\n return {\n query: response.query.trim(),\n mode: response.effectiveMode,\n items: projectedItems,\n count: projectedItems.length,\n ...truncationExtras,\n ...pageExtras,\n filters: buildVerboseSearchFilters({\n effectiveMode: response.effectiveMode,\n matchMode: response.matchMode,\n options: response.options,\n includeLinked: response.includeLinked,\n titleExact: response.titleExact,\n phraseExact: response.phraseExact,\n scoreThreshold: response.scoreThreshold,\n hybridSemanticWeight: response.hybridSemanticWeight,\n queryExpansion: response.queryExpansion,\n rerank: response.rerank,\n runtimeFieldFilters: response.runtimeFieldFilters,\n }),\n projection: {\n mode: effectiveProjection.mode,\n fields: finalProjectionFields,\n },\n now: nowIso(),\n ...(response.warnings.length > 0 ? { warnings: response.warnings } : {}),\n };\n}\n\nfunction assertSearchPagingOptions(options: SearchOptions): void {\n if (options.after !== undefined && options.count === true) {\n throw new PmCliError(\n \"Search --after cannot be combined with --count.\",\n EXIT_CODE.USAGE,\n );\n }\n}\n\n/** Implements run search for the public runtime surface of this module. */\nexport async function runSearch(\n rawQuery: string,\n rawOptions: SearchOptions,\n global: GlobalOptions,\n): Promise<SearchResult> {\n assertSearchPagingOptions(rawOptions);\n const prepared = prepareSearchInput(rawQuery, rawOptions);\n const runtime = await resolveSearchRuntimeContext(prepared, global);\n const corpus = await loadFilteredSearchCorpus(prepared, runtime);\n const warnings = corpus.warnings;\n warnings.push(...prepared.inlineWarnings);\n if (\n runtime.effectiveMode === \"hybrid\" &&\n runtime.semanticWeightProvided &&\n runtime.semanticWeightOverride === undefined\n ) {\n warnings.push(\n \"search_hybrid_semantic_weight_override_invalid:using_settings_default\",\n );\n }\n const responseBase = {\n query: prepared.query,\n matchMode: prepared.matchMode,\n options: prepared.options,\n includeLinked: prepared.includeLinked,\n titleExact: prepared.titleExact,\n phraseExact: prepared.phraseExact,\n scoreThreshold: runtime.scoreThreshold,\n hybridSemanticWeight: runtime.hybridSemanticWeight,\n queryExpansion: runtime.queryExpansion,\n rerank: runtime.rerank,\n projection: prepared.projection,\n warnings,\n runtimeFieldFilters: runtime.runtimeFieldFilters,\n };\n if (\n runtime.effectiveMode === \"keyword\" &&\n (corpus.filteredDocuments.length === 0 ||\n (prepared.limit === 0 && !prepared.countOnly))\n ) {\n return buildEmptySearchResultFromContext(\n { ...responseBase, effectiveMode: runtime.effectiveMode },\n prepared.countOnly,\n );\n }\n const keywordHits = await computeKeywordSearchHits(\n prepared,\n runtime,\n corpus.filteredDocuments,\n );\n const modeResult = await executeSemanticSearch({\n prepared,\n runtime,\n filteredDocuments: corpus.filteredDocuments,\n keywordHits,\n warnings,\n modeWasExplicit: prepared.modeWasExplicit,\n });\n if (\n modeResult.effectiveMode !== \"keyword\" &&\n modeResult.hits.length === 0 &&\n (corpus.filteredDocuments.length === 0 ||\n (prepared.limit === 0 && !prepared.countOnly))\n ) {\n return buildEmptySearchResultFromContext(\n { ...responseBase, effectiveMode: modeResult.effectiveMode },\n prepared.countOnly,\n );\n }\n const thresholded = modeResult.hits.filter(\n (entry) =>\n entry.exact_id_match === true || entry.score >= runtime.scoreThreshold,\n );\n const sorted = sortHits(thresholded, runtime.statusRegistry);\n const total = sorted.length;\n const page = resolveSearchPage({\n sorted,\n query: prepared.query,\n mode: modeResult.effectiveMode,\n searchOptions: prepared.options,\n limit: prepared.limit ?? runtime.maxResults,\n });\n const response = { ...responseBase, effectiveMode: modeResult.effectiveMode };\n if (prepared.countOnly) {\n return buildCountOnlySearchResult(response, total);\n }\n const { hits: projectedHits, projection: effectiveProjection } =\n attachSearchHighlights(prepared, corpus.filteredDocuments, page.limited);\n const projectedItems = projectSearchHits(projectedHits, effectiveProjection);\n return buildSearchResultForHits(\n response,\n projectedItems,\n total,\n page.limited.length,\n effectiveProjection,\n page.pageExtras,\n );\n}\n","/**\n * @module core/shared/text-normalization\n *\n * Provides shared primitives and utilities for Text Normalization.\n */\n/** Normalizes text to lowercase whitespace-collapsed form for stable matching and comparison. */\nexport function normalizeLowercaseWhitespace(value: string): string {\n return value.trim().toLowerCase().replace(/\\s+/g, \" \");\n}\n\n/** Implements tokenize alpha numeric for the public runtime surface of this module. */\nexport function tokenizeAlphaNumeric(value: string): string[] {\n return normalizeLowercaseWhitespace(value)\n .split(/[^a-z0-9]+/)\n .filter((token) => token.length > 0);\n}\n\n/** Implements jaccard similarity for the public runtime surface of this module. */\nexport function jaccardSimilarity(\n leftTokens: string[],\n rightTokens: string[],\n): number {\n if (leftTokens.length === 0 && rightTokens.length === 0) {\n return 1;\n }\n if (leftTokens.length === 0 || rightTokens.length === 0) {\n return 0;\n }\n const leftSet = new Set(leftTokens);\n const rightSet = new Set(rightTokens);\n let intersection = 0;\n for (const token of leftSet) {\n if (rightSet.has(token)) {\n intersection += 1;\n }\n }\n // Both token sets are non-empty here (guarded above), so union is always >= 1.\n const union = new Set([...leftSet, ...rightSet]).size;\n return intersection / union;\n}\n","/**\n * @module core/search/relevance\n *\n * Powers search, embeddings, and semantic retrieval behavior for Relevance.\n */\nimport type { PmSettings } from \"../../types.js\";\nimport {\n coercePositiveInteger,\n toNonEmptyString,\n} from \"../shared/primitives.js\";\nimport { tokenizeAlphaNumeric } from \"../shared/text-normalization.js\";\nimport {\n executeEmbeddingRequest,\n type EmbeddingProviderConfig,\n} from \"./providers.js\";\n\n/** Fallback query expansion max queries used when callers do not provide an override. */\nexport const DEFAULT_QUERY_EXPANSION_MAX_QUERIES = 4;\n/** Fallback rerank top k used when callers do not provide an override. */\nexport const DEFAULT_RERANK_TOP_K = 20;\nconst MAX_RERANK_TOP_K = 200;\n\nconst QUERY_EXPANSION_STOP_WORDS = new Set([\n \"a\",\n \"an\",\n \"and\",\n \"for\",\n \"from\",\n \"in\",\n \"into\",\n \"of\",\n \"on\",\n \"or\",\n \"the\",\n \"to\",\n \"with\",\n]);\n\n/** Documents the query expansion config payload exchanged by command, SDK, and package integrations. */\nexport interface QueryExpansionConfig {\n /** Whether enabled applies to this operation. */\n enabled: boolean;\n /** Value that configures or reports provider for this contract. */\n provider: string | null;\n /** Value that configures or reports max queries for this contract. */\n max_queries: number;\n}\n\n/** Documents the rerank config payload exchanged by command, SDK, and package integrations. */\nexport interface RerankConfig {\n /** Whether enabled applies to this operation. */\n enabled: boolean;\n /** Value that configures or reports model for this contract. */\n model: string;\n /** Value that configures or reports top k for this contract. */\n top_k: number;\n}\n\n/** Documents the rerank candidate payload exchanged by command, SDK, and package integrations. */\nexport interface RerankCandidate {\n /** Stable identifier used to reference this record across commands and storage. */\n id: string;\n /** Value that configures or reports text for this contract. */\n text: string;\n}\n\n/** Documents the rerank scored hit payload exchanged by command, SDK, and package integrations. */\nexport interface RerankScoredHit {\n /** Stable identifier used to reference this record across commands and storage. */\n id: string;\n /** Value that configures or reports score for this contract. */\n score: number;\n}\n\nfunction dedupeQueries(values: string[], limit: number): string[] {\n const deduped: string[] = [];\n const seen = new Set<string>();\n for (const entry of values) {\n const normalized = entry.trim().replaceAll(/\\s+/g, \" \");\n if (normalized.length === 0) {\n continue;\n }\n const dedupeKey = normalized.toLowerCase();\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n deduped.push(normalized);\n if (deduped.length >= limit) {\n break;\n }\n }\n return deduped;\n}\n\nfunction singularizeSimple(token: string): string {\n const normalizedToken = token.toLowerCase();\n if (normalizedToken.length > 4 && normalizedToken.endsWith(\"ies\")) {\n return `${normalizedToken.slice(0, -3)}y`;\n }\n if (\n normalizedToken.length > 4 &&\n (normalizedToken.endsWith(\"ches\") ||\n normalizedToken.endsWith(\"shes\") ||\n normalizedToken.endsWith(\"xes\") ||\n normalizedToken.endsWith(\"zes\") ||\n normalizedToken.endsWith(\"sses\"))\n ) {\n return normalizedToken.slice(0, -2);\n }\n if (\n normalizedToken.length > 3 &&\n normalizedToken.endsWith(\"s\") &&\n !normalizedToken.endsWith(\"ss\") &&\n !normalizedToken.endsWith(\"us\") &&\n !normalizedToken.endsWith(\"is\") &&\n !normalizedToken.endsWith(\"as\")\n ) {\n return normalizedToken.slice(0, -1);\n }\n return normalizedToken;\n}\n\nfunction pluralizeSimple(token: string): string {\n const normalizedToken = token.toLowerCase();\n if (\n normalizedToken.length > 2 &&\n (!normalizedToken.endsWith(\"s\") || normalizedToken.endsWith(\"ss\"))\n ) {\n if (normalizedToken.endsWith(\"y\") && !/[aeiou]y$/u.test(normalizedToken)) {\n return `${normalizedToken.slice(0, -1)}ies`;\n }\n if (\n normalizedToken.endsWith(\"ch\") ||\n normalizedToken.endsWith(\"sh\") ||\n normalizedToken.endsWith(\"x\") ||\n normalizedToken.endsWith(\"z\") ||\n normalizedToken.endsWith(\"ss\")\n ) {\n return `${normalizedToken}es`;\n }\n return `${normalizedToken}s`;\n }\n return normalizedToken;\n}\n\n/** Implements build deterministic query expansions for the public runtime surface of this module. */\nexport function buildDeterministicQueryExpansions(\n query: string,\n maxQueries = DEFAULT_QUERY_EXPANSION_MAX_QUERIES,\n): string[] {\n const normalizedQuery = query.trim().replaceAll(/\\s+/g, \" \");\n if (normalizedQuery.length === 0) {\n return [];\n }\n const tokens = tokenizeAlphaNumeric(normalizedQuery);\n if (tokens.length === 0) {\n return [normalizedQuery];\n }\n const contentTokens = tokens.filter(\n (token) => !QUERY_EXPANSION_STOP_WORDS.has(token.toLowerCase()),\n );\n const singularized = tokens.map((token) => singularizeSimple(token));\n const pluralized = contentTokens.map((token) => pluralizeSimple(token));\n return dedupeQueries(\n [\n normalizedQuery,\n tokens.join(\" \"),\n contentTokens.join(\" \"),\n singularized.join(\" \"),\n pluralized.join(\" \"),\n ],\n Math.max(1, maxQueries),\n );\n}\n\n/** Implements normalize query expansion output for the public runtime surface of this module. */\nexport function normalizeQueryExpansionOutput(raw: unknown): string[] {\n const rawQueries = Array.isArray(raw)\n ? raw\n : (raw as { queries?: unknown } | null | undefined)?.queries;\n if (!Array.isArray(rawQueries)) {\n return [];\n }\n return dedupeQueries(\n rawQueries.filter((entry): entry is string => typeof entry === \"string\"),\n DEFAULT_QUERY_EXPANSION_MAX_QUERIES,\n );\n}\n\n/** Implements merge query expansions for the public runtime surface of this module. */\nexport function mergeQueryExpansions(\n base: string[],\n extra: string[],\n maxQueries: number,\n): string[] {\n return dedupeQueries([...base, ...extra], Math.max(1, maxQueries));\n}\n\n/** Implements resolve query expansion config for the public runtime surface of this module. */\nexport function resolveQueryExpansionConfig(\n settings: PmSettings,\n fallbackProviderName: string | null,\n): QueryExpansionConfig {\n const search = (\n settings as {\n search?: { query_expansion?: { enabled?: unknown; provider?: unknown } };\n }\n ).search;\n const queryExpansion = search?.query_expansion;\n const configuredProvider = toNonEmptyString(queryExpansion?.provider);\n return {\n enabled: queryExpansion?.enabled === true,\n provider: configuredProvider ?? fallbackProviderName,\n max_queries: DEFAULT_QUERY_EXPANSION_MAX_QUERIES,\n };\n}\n\n/** Implements resolve rerank config for the public runtime surface of this module. */\nexport function resolveRerankConfig(\n settings: PmSettings,\n fallbackModel: string,\n): RerankConfig {\n const search = (\n settings as {\n search?: {\n rerank?: { enabled?: unknown; model?: unknown; top_k?: unknown };\n };\n }\n ).search;\n const rerank = search?.rerank;\n const configuredModel = toNonEmptyString(rerank?.model);\n const configuredTopK = coercePositiveInteger(rerank?.top_k);\n const normalizedTopK = configuredTopK ?? DEFAULT_RERANK_TOP_K;\n return {\n enabled: rerank?.enabled === true,\n model: configuredModel ?? fallbackModel,\n top_k: Math.min(MAX_RERANK_TOP_K, normalizedTopK),\n };\n}\n\n/** Implements normalize rerank output for the public runtime surface of this module. */\nexport function normalizeRerankOutput(raw: unknown): RerankScoredHit[] {\n const rawHits = Array.isArray(raw)\n ? raw\n : (raw as { hits?: unknown } | null | undefined)?.hits;\n if (!Array.isArray(rawHits)) {\n return [];\n }\n const bestById = new Map<string, number>();\n for (const entry of rawHits) {\n if (typeof entry !== \"object\" || entry === null) {\n continue;\n }\n const id = toNonEmptyString((entry as { id?: unknown }).id);\n const score = (entry as { score?: unknown }).score;\n if (!id || typeof score !== \"number\" || !Number.isFinite(score)) {\n continue;\n }\n const existing = bestById.get(id);\n if (existing === undefined || score > existing) {\n bestById.set(id, score);\n }\n }\n const normalized = [...bestById.entries()].map(([id, score]) => ({\n id,\n score,\n }));\n normalized.sort((left, right) => {\n if (left.score !== right.score) {\n return right.score - left.score;\n }\n return left.id.localeCompare(right.id);\n });\n return normalized;\n}\n\nfunction dotProduct(left: number[], right: number[]): number {\n const size = left.length;\n let result = 0;\n for (let index = 0; index < size; index += 1) {\n result += left[index] * right[index];\n }\n return result;\n}\n\nfunction l2Norm(vector: number[]): number {\n let sumSquares = 0;\n for (let index = 0; index < vector.length; index += 1) {\n sumSquares += vector[index] * vector[index];\n }\n return Math.sqrt(sumSquares);\n}\n\nfunction cosineSimilarityWithKnownLeftNorm(\n left: number[] | null | undefined,\n right: number[] | null | undefined,\n leftNorm: number,\n): number {\n if (\n !left ||\n !right ||\n left.length === 0 ||\n right.length === 0 ||\n left.length !== right.length\n ) {\n return 0;\n }\n const numerator = dotProduct(left, right);\n const rightNorm = l2Norm(right);\n const denominator = leftNorm * rightNorm;\n if (\n !Number.isFinite(numerator) ||\n !Number.isFinite(leftNorm) ||\n !Number.isFinite(rightNorm) ||\n !Number.isFinite(denominator) ||\n denominator === 0\n ) {\n return 0;\n }\n return Math.max(-1, Math.min(1, numerator / denominator));\n}\n\n/** Implements rerank candidates with embeddings for the public runtime surface of this module. */\nexport async function rerankCandidatesWithEmbeddings(\n provider: EmbeddingProviderConfig,\n model: string,\n query: string,\n candidates: RerankCandidate[],\n timeoutMs?: number,\n): Promise<Map<string, number>> {\n if (candidates.length === 0) {\n return new Map();\n }\n const effectiveModel = toNonEmptyString(model) ?? provider.model;\n const rerankProvider: EmbeddingProviderConfig =\n effectiveModel === provider.model\n ? provider\n : { ...provider, model: effectiveModel };\n const payload = [query.trim(), ...candidates.map((entry) => entry.text)];\n const vectors = await executeEmbeddingRequest(\n rerankProvider,\n payload,\n timeoutMs ? { timeout_ms: timeoutMs } : {},\n );\n const queryVector = vectors[0];\n if (!queryVector) {\n return new Map();\n }\n const queryNorm = l2Norm(queryVector);\n const scoreById = new Map<string, number>();\n for (let index = 0; index < candidates.length; index += 1) {\n const candidate = candidates[index];\n const candidateVector = vectors[index + 1];\n if (!candidateVector) {\n continue;\n }\n const similarity = cosineSimilarityWithKnownLeftNorm(\n queryVector,\n candidateVector,\n queryNorm,\n );\n scoreById.set(candidate.id, Math.max(0, Math.min(1, (similarity + 1) / 2)));\n }\n return scoreById;\n}\n","/**\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/** Default Okapi BM25 term-frequency saturation parameter. `1.2` is the widely used Lucene/Elasticsearch default: higher values reduce the diminishing returns of repeated terms more slowly (terms keep accruing weight), lower values saturate sooner. */\nexport const DEFAULT_BM25_K1 = 1.2;\n\n/** Default Okapi BM25 length-normalization parameter. `0.75` is the Lucene default: `0` disables length normalization entirely, `1` fully normalizes a document's score by its length relative to the corpus average. */\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 /** Stable identifier used to reference this record across commands and storage. */\n id: string;\n /** Value that configures or reports text for this contract. */\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 /** Value that configures or reports documents for this contract. */\n documents: Bm25DocumentStats[];\n /** Value that configures or reports document frequency for this contract. */\n documentFrequency: Map<string, number>;\n /** Number of document entries represented by this result. */\n documentCount: number;\n /** Value that configures or reports average document length for this contract. */\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/** Count occurrences of each token in a token list. */\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/** Inverse document frequency for one term using the BM25 \"plus-one\" variant (`ln(1 + (N - n + 0.5) / (n + 0.5))`) used by Lucene. The `1 +` inside the logarithm keeps the IDF strictly non-negative even for a term that appears in every document, so a common term can never subtract from a document's score. */\nfunction inverseDocumentFrequency(\n documentCount: number,\n termDocumentFrequency: number,\n): number {\n return Math.log(\n 1 +\n (documentCount - termDocumentFrequency + 0.5) /\n (termDocumentFrequency + 0.5),\n );\n}\n\n/** Score every document in the index against a query and return an id → score map containing only documents with a strictly positive score (a document that matches no query term is omitted, mirroring the lexical scorer's \"no match → no hit\" contract). Query tokens are de-duplicated so a token repeated in the query does not multiply its own contribution. Returns an empty map for an empty index, an empty query, or a query whose terms appear in no document. */\nexport function scoreBm25Query(\n index: Bm25Index,\n queryTokens: string[],\n params: Bm25Params,\n): 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 = [\n ...new Set(queryTokens.filter((token) => token.length > 0)),\n ];\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(\n term,\n inverseDocumentFrequency(index.documentCount, termDocumentFrequency),\n );\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 -\n params.b +\n (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/** Coerce one persisted BM25 parameter to a finite number within `[min, max]`. A finite number is clamped to the range (preserving user intent — e.g. `k1=5000` becomes `1000` rather than being silently ignored); any non-number or non-finite value (string, `NaN`, `Infinity`, missing) falls back to `fallback` so a malformed `settings.json` can never crash or skew scoring. */\nfunction resolveClampedParam(\n candidate: unknown,\n fallback: number,\n min: number,\n max: number,\n): 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/** Flatten a structured search-corpus record (the shape produced by `buildSearchCorpus`) into a single whitespace-joined string of its *values* only — field names/object keys are deliberately excluded so corpus-wide keys (`title`, `description`, …) never enter the BM25 vocabulary and skew IDF. Strings and numbers contribute their text; arrays and nested objects (tags, dependencies, the plan corpus) are walked recursively; everything else is dropped. */\nexport function flattenSearchCorpusText(\n corpus: Record<string, unknown>,\n): 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(\n settings: Pick<PmSettings, \"search\"> | undefined,\n): Bm25Params {\n const bm25 = (\n settings?.search as { bm25?: { k1?: unknown; b?: unknown } } | undefined\n )?.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","/**\n * @module sdk/query/search-rendering\n *\n * Builds stable compact and verbose filter projections for search responses.\n */\nimport {\n applyFilterValueEcho,\n buildContentFilterEcho,\n buildGovernanceMissingFilterEcho,\n} from \"./list.js\";\nimport type { SearchMatchMode, SearchOptions } from \"./search.js\";\n\n/** Search execution modes represented in response metadata. */\nexport type SearchMode = \"keyword\" | \"semantic\" | \"hybrid\";\n\ninterface SearchRenderingQueryExpansion {\n enabled: boolean;\n provider: string | null;\n}\n\ninterface SearchRenderingRerank {\n enabled: boolean;\n model: string;\n top_k: number;\n}\n\nfunction isAllStatuses(value: unknown): boolean {\n if (typeof value !== \"string\") return false;\n const tokens = value\n .split(\",\")\n .map((entry) => entry.trim().toLowerCase())\n .filter(Boolean);\n return tokens.length === 1 && tokens[0] === \"all\";\n}\n\nconst COMPACT_SEARCH_VALUE_FILTER_ECHO_ENTRIES = [\n {\n optionKey: \"status\",\n summaryKey: \"status\",\n normalize: (value: unknown) => (isAllStatuses(value) ? \"all\" : value),\n },\n { optionKey: \"type\", summaryKey: \"type\" },\n { optionKey: \"tag\", summaryKey: \"tag\" },\n { optionKey: \"priority\", summaryKey: \"priority\" },\n { optionKey: \"deadlineBefore\", summaryKey: \"deadline_before\" },\n { optionKey: \"deadlineAfter\", summaryKey: \"deadline_after\" },\n { optionKey: \"updatedAfter\", summaryKey: \"updated_after\" },\n { optionKey: \"updatedBefore\", summaryKey: \"updated_before\" },\n { optionKey: \"createdAfter\", summaryKey: \"created_after\" },\n { optionKey: \"createdBefore\", summaryKey: \"created_before\" },\n { optionKey: \"assignee\", summaryKey: \"assignee\" },\n { optionKey: \"sprint\", summaryKey: \"sprint\" },\n { optionKey: \"release\", summaryKey: \"release\" },\n { optionKey: \"parent\", summaryKey: \"parent\" },\n] as const;\n\n/** Builds the token-efficient filter echo used by compact search results. */\nexport function buildCompactSearchFilterSummary(params: {\n mode: SearchMode;\n matchMode: SearchMatchMode;\n options: SearchOptions;\n includeLinked: boolean;\n titleExact: boolean;\n phraseExact: boolean;\n scoreThreshold: number;\n hybridSemanticWeight: number;\n runtimeFieldFilters?: Record<string, unknown>;\n}): Record<string, unknown> {\n const { mode, matchMode, options, includeLinked, titleExact, phraseExact, scoreThreshold, hybridSemanticWeight, runtimeFieldFilters } = params;\n const filters: Record<string, unknown> = {};\n applyFilterValueEcho(filters, options, COMPACT_SEARCH_VALUE_FILTER_ECHO_ENTRIES);\n Object.assign(filters, buildGovernanceMissingFilterEcho(options as Record<string, unknown>));\n Object.assign(filters, buildContentFilterEcho(options as Record<string, unknown>));\n if (matchMode !== \"or\") filters.match_mode = matchMode;\n if (includeLinked) filters.include_linked = true;\n if (titleExact) filters.title_exact = true;\n if (phraseExact) filters.phrase_exact = true;\n if (scoreThreshold > 0) filters.score_threshold = scoreThreshold;\n if (mode === \"hybrid\" && options.semanticWeight !== undefined) {\n filters.hybrid_semantic_weight = hybridSemanticWeight;\n }\n if (options.limit !== undefined) filters.limit = options.limit;\n if (runtimeFieldFilters && Object.keys(runtimeFieldFilters).length > 0) {\n filters.runtime_filters = runtimeFieldFilters;\n }\n return filters;\n}\n\n/** Builds the complete filter echo shared by verbose search response paths. */\nexport function buildVerboseSearchFilters(params: {\n effectiveMode: SearchMode;\n matchMode: SearchMatchMode;\n options: SearchOptions;\n includeLinked: boolean;\n titleExact: boolean;\n phraseExact: boolean;\n scoreThreshold: number;\n hybridSemanticWeight: number;\n queryExpansion: SearchRenderingQueryExpansion;\n rerank: SearchRenderingRerank;\n runtimeFieldFilters: Record<string, unknown>;\n}): Record<string, unknown> {\n const { effectiveMode, matchMode, options, includeLinked, titleExact, phraseExact, scoreThreshold, hybridSemanticWeight, queryExpansion, rerank, runtimeFieldFilters } = params;\n const valueOrNull = (value: unknown): unknown => value ?? null;\n return {\n mode: effectiveMode,\n match_mode: matchMode,\n status: isAllStatuses(options.status) ? \"all\" : valueOrNull(options.status),\n type: valueOrNull(options.type),\n tag: valueOrNull(options.tag),\n priority: valueOrNull(options.priority),\n deadline_before: valueOrNull(options.deadlineBefore),\n deadline_after: valueOrNull(options.deadlineAfter),\n updated_after: valueOrNull(options.updatedAfter),\n updated_before: valueOrNull(options.updatedBefore),\n created_after: valueOrNull(options.createdAfter),\n created_before: valueOrNull(options.createdBefore),\n assignee: valueOrNull(options.assignee),\n sprint: valueOrNull(options.sprint),\n release: valueOrNull(options.release),\n parent: valueOrNull(options.parent),\n ...buildGovernanceMissingFilterEcho(options as Record<string, unknown>),\n ...buildContentFilterEcho(options as Record<string, unknown>),\n include_linked: includeLinked,\n title_exact: titleExact,\n phrase_exact: phraseExact,\n score_threshold: scoreThreshold,\n hybrid_semantic_weight: effectiveMode === \"hybrid\" ? hybridSemanticWeight : null,\n query_expansion_enabled: queryExpansion.enabled,\n query_expansion_provider: queryExpansion.provider,\n rerank_enabled: rerank.enabled,\n rerank_model: rerank.model,\n rerank_top_k: rerank.top_k,\n limit: valueOrNull(options.limit),\n runtime_filters: runtimeFieldFilters,\n };\n}\n","/**\n * @module sdk/query/search-pagination\n *\n * Applies the shared SDK cursor contract to ranked search results.\n */\nimport {\n createQueryFingerprint,\n paginateQueryRows,\n} from \"../pagination.js\";\nimport type { SearchHit, SearchOptions } from \"./search.js\";\nimport type { SearchMode } from \"./search-rendering.js\";\n\n/** Build the query-only fingerprint shared by search retrieval and paging. */\nexport function createSearchCursorFingerprint(options: {\n query: string;\n mode: SearchMode;\n searchOptions: SearchOptions;\n}): string {\n const normalizedOptions: Record<string, unknown> = {\n ...options.searchOptions,\n };\n delete normalizedOptions.after;\n delete normalizedOptions.limit;\n delete normalizedOptions.compact;\n delete normalizedOptions.full;\n delete normalizedOptions.fields;\n delete normalizedOptions.highlight;\n delete normalizedOptions.format;\n return createQueryFingerprint(\"search\", {\n query: options.query.trim(),\n mode: options.mode,\n options: normalizedOptions,\n });\n}\n\n/** Page ranked search hits without coupling cursor mechanics to search scoring. */\nexport function resolveSearchPage(options: {\n sorted: SearchHit[];\n query: string;\n mode: SearchMode;\n searchOptions: SearchOptions;\n limit: number;\n}): {\n limited: SearchHit[];\n pageExtras: {\n has_more?: boolean;\n next_cursor?: string;\n applied_limit: number;\n truncated?: true;\n };\n} {\n const page = paginateQueryRows(options.sorted, {\n cursor: options.searchOptions.after,\n fingerprint: createSearchCursorFingerprint(options),\n limit: options.limit,\n readId: (hit) => hit.item.id,\n });\n return {\n limited: page.rows,\n pageExtras: {\n applied_limit: options.limit,\n ...(page.has_more ? { has_more: true, truncated: true } : {}),\n ...(page.next_cursor ? { next_cursor: page.next_cursor } : {}),\n },\n };\n}\n","/**\n * @module sdk/eval\n *\n * Implements the `pm eval` command surface (pm-u8n5): a search-relevance\n * evaluation runner that scores a human-curated golden-query set against the\n * live retrieval path and reports nDCG@k, MRR@k, precision@k, and recall@k per\n * query plus the macro average. With `--fail-under` it doubles as a CI gate so\n * relevance regressions — from corpus changes, hybrid-weight changes, or\n * provider swaps (including the offline BM25 provider, pm-75k9) — fail the build\n * instead of silently degrading retrieval quality.\n */\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n aggregateEvalMetrics,\n DEFAULT_EVAL_K,\n evaluateRanking,\n parseEvalQuerySet,\n type EvalSearchMode,\n type QueryEvalMetrics,\n} from \"../core/search/eval.js\";\nimport { EXIT_CODE } from \"../core/shared/constants.js\";\nimport type { GlobalOptions } from \"../core/shared/command-types.js\";\nimport { PmCliError } from \"../core/shared/errors.js\";\nimport { coercePositiveInteger } from \"../core/shared/primitives.js\";\nimport { pathExists } from \"../core/fs/fs-utils.js\";\nimport { getSettingsPath, resolvePmRoot } from \"../core/store/paths.js\";\nimport { runSearch } from \"./query/search.js\";\n\n/** Relative location (under the pm root) of the default golden-query set. A git-tracked, human-curated file so relevance ground truth lives alongside the tracker it evaluates. */\nexport const DEFAULT_EVAL_QUERIES_RELATIVE_PATH = path.join(\n \"search\",\n \"eval-queries.json\",\n);\n\n/** Documents the eval command options payload exchanged by command, SDK, and package integrations. */\nexport interface EvalOptions {\n /** Default retrieval mode for queries that do not set their own (keyword|semantic|hybrid). */\n mode?: string;\n /** Metric cutoff (`@k`); positive integer, defaults to {@link DEFAULT_EVAL_K}. */\n k?: string | number;\n /** Gate threshold: exit non-zero when the aggregate nDCG@k falls below this `[0,1]` value. */\n failUnder?: string | number;\n /** Override path to the golden-query JSON file (defaults to `<pmRoot>/search/eval-queries.json`). */\n queries?: string;\n /** Output format override: json|toon. */\n format?: string;\n}\n\n/** Per-query relevance report row emitted by {@link runEval}. */\nexport interface EvalQueryReport {\n /** Value that configures or reports query for this contract. */\n query: string;\n /** Value that configures or reports mode for this contract. */\n mode: EvalSearchMode;\n /** Value that configures or reports relevant total for this contract. */\n relevant_total: number;\n /** Value that configures or reports retrieved relevant for this contract. */\n retrieved_relevant: number;\n /** Value that configures or reports ndcg for this contract. */\n ndcg: number;\n /** Value that configures or reports mrr for this contract. */\n mrr: number;\n /** Value that configures or reports precision for this contract. */\n precision: number;\n /** Value that configures or reports recall for this contract. */\n recall: number;\n}\n\n/** Documents the eval result payload exchanged by command, SDK, and package integrations. */\nexport interface EvalResult {\n /** Value that configures or reports k for this contract. */\n k: number;\n /** Number of query entries represented by this result. */\n query_count: number;\n /** Value that configures or reports aggregate for this contract. */\n aggregate: {\n ndcg: number;\n mrr: number;\n precision: number;\n recall: number;\n };\n /** Value that configures or reports queries for this contract. */\n queries: EvalQueryReport[];\n /** Present only when `--fail-under` was supplied. */\n fail_under?: number;\n /** Whether the aggregate nDCG met the gate (always true when no gate is set). */\n passed: boolean;\n}\n\nconst VALID_EVAL_MODES: ReadonlySet<string> = new Set<EvalSearchMode>([\n \"keyword\",\n \"semantic\",\n \"hybrid\",\n]);\n\ntype EvalQuery = ReturnType<typeof parseEvalQuerySet>[\"queries\"][number];\n\n/** Resolves and validates the default retrieval mode for an evaluation run. */\nconst parseEvalMode = (raw: string | undefined): EvalSearchMode => {\n if (raw === undefined) {\n return \"keyword\";\n }\n const normalized = raw.trim().toLowerCase();\n if (!VALID_EVAL_MODES.has(normalized)) {\n throw new PmCliError(\n \"Eval --mode must be one of keyword|semantic|hybrid\",\n EXIT_CODE.USAGE,\n );\n }\n return normalized as EvalSearchMode;\n};\n\n/** Resolves and validates the positive ranking cutoff for an evaluation run. */\nconst parseEvalK = (raw: string | number | undefined): number => {\n if (raw === undefined || raw === \"\") {\n return DEFAULT_EVAL_K;\n }\n const parsed = coercePositiveInteger(raw);\n if (parsed === null) {\n throw new PmCliError(\n \"Eval --k must be a positive integer\",\n EXIT_CODE.USAGE,\n );\n }\n return parsed;\n};\n\n/** Resolves and validates an optional normalized nDCG gate threshold. */\nconst parseFailUnder = (\n raw: string | number | undefined,\n): number | undefined => {\n if (raw === undefined || raw === \"\") {\n return undefined;\n }\n const normalized = String(raw).trim();\n const parsed = Number(normalized);\n if (\n [\n normalized.length === 0,\n !Number.isFinite(parsed),\n parsed < 0,\n parsed > 1,\n ].includes(true)\n ) {\n throw new PmCliError(\n \"Eval --fail-under must be a number in the range [0, 1]\",\n EXIT_CODE.USAGE,\n );\n }\n return parsed;\n};\n\n/** Round a metric to four decimals to keep the JSON output compact and stable. */\nconst roundMetric = (value: number): number =>\n Math.round(value * 10_000) / 10_000;\n\n/** Reads a golden-query file and translates missing-file failures to CLI guidance. */\nconst readEvalQuerySetFile = async (queriesPath: string): Promise<string> => {\n try {\n return await fs.readFile(queriesPath, \"utf8\");\n } catch {\n throw new PmCliError(\n `Eval query set not found at ${queriesPath}`,\n EXIT_CODE.NOT_FOUND,\n {\n examples: [\n `echo '[{\"query\":\"offline search\",\"relevant_ids\":[\"pm-75k9\"]}]' > ${queriesPath}`,\n \"pm eval --queries ./my-eval.json\",\n ],\n nextSteps: [\n \"Create a git-tracked golden-query JSON file (an array of {query, relevant_ids, mode?} objects), then re-run pm eval.\",\n ],\n },\n );\n }\n};\n\n/** Parses golden-query JSON while preserving a path-specific usage diagnostic. */\nconst parseEvalQuerySetJson = (raw: string, queriesPath: string): unknown => {\n try {\n return JSON.parse(raw);\n } catch (error: unknown) {\n throw new PmCliError(\n /* c8 ignore next -- JSON.parse throws Error instances; String fallback protects nonstandard hosts. */\n `Eval query set at ${queriesPath} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n EXIT_CODE.USAGE,\n );\n }\n};\n\n/** Applies the structured golden-query contract and preserves its diagnostics. */\nconst validateEvalQuerySet = (\n parsed: unknown,\n): ReturnType<typeof parseEvalQuerySet> => {\n try {\n return parseEvalQuerySet(parsed);\n } catch (error: unknown) {\n throw new PmCliError(\n /* c8 ignore next -- parseEvalQuerySet throws Error instances; String fallback protects nonstandard hosts. */\n error instanceof Error ? error.message : String(error),\n EXIT_CODE.USAGE,\n );\n }\n};\n\n/** Loads and validates a golden-query set from one resolved filesystem path. */\nconst loadEvalQuerySet = async (\n queriesPath: string,\n): Promise<ReturnType<typeof parseEvalQuerySet>> =>\n validateEvalQuerySet(\n parseEvalQuerySetJson(await readEvalQuerySetFile(queriesPath), queriesPath),\n );\n\n/** Resolves the caller override or tracker-owned default golden-query path. */\nconst resolveEvalQueriesPath = (\n pmRoot: string,\n queries: string | undefined,\n): string =>\n queries\n ? path.resolve(process.cwd(), queries)\n : path.join(pmRoot, DEFAULT_EVAL_QUERIES_RELATIVE_PATH);\n\n/** Executes and scores one golden query without rounding its aggregate input. */\nconst evaluateEvalQuery = async (\n evalQuery: EvalQuery,\n defaultMode: EvalSearchMode,\n k: number,\n global: GlobalOptions,\n): Promise<{ report: EvalQueryReport; metrics: QueryEvalMetrics }> => {\n const mode = evalQuery.mode ?? defaultMode;\n const searchResult = await runSearch(\n evalQuery.query,\n { mode, limit: String(k), fields: \"id\" },\n global,\n );\n const rankedIds = searchResult.items\n .map((item) => (item as { id?: unknown }).id)\n .filter((id): id is string => typeof id === \"string\");\n const metrics = evaluateRanking(\n rankedIds,\n new Set(evalQuery.relevant_ids),\n k,\n );\n return {\n metrics,\n report: {\n query: evalQuery.query,\n mode,\n relevant_total: metrics.relevant_total,\n retrieved_relevant: metrics.retrieved_relevant,\n ndcg: roundMetric(metrics.ndcg),\n mrr: roundMetric(metrics.mrr),\n precision: roundMetric(metrics.precision),\n recall: roundMetric(metrics.recall),\n },\n };\n};\n\n/** Shapes rounded aggregate metrics and the optional gate result. */\nconst buildEvalResult = (\n k: number,\n reports: EvalQueryReport[],\n rawMetrics: QueryEvalMetrics[],\n failUnder: number | undefined,\n): EvalResult => {\n const aggregate = aggregateEvalMetrics(rawMetrics);\n return {\n k,\n query_count: reports.length,\n aggregate: {\n ndcg: roundMetric(aggregate.ndcg),\n mrr: roundMetric(aggregate.mrr),\n precision: roundMetric(aggregate.precision),\n recall: roundMetric(aggregate.recall),\n },\n queries: reports,\n ...(failUnder !== undefined ? { fail_under: failUnder } : {}),\n passed: failUnder === undefined || aggregate.ndcg >= failUnder,\n };\n};\n\n/**\n * Run the search-relevance evaluation (pm-u8n5). Loads the golden-query set\n * (default `<pmRoot>/search/eval-queries.json`, overridable via `--queries`),\n * runs each query through {@link runSearch} at the resolved mode, scores the\n * returned ranking with the nDCG/MRR/precision/recall metrics, and macro-averages\n * across queries. When `--fail-under` is supplied, `passed` reflects whether the\n * aggregate nDCG@k cleared the threshold; the CLI layer maps a failed gate to a\n * non-zero exit code.\n */\nexport const runEval = async (\n options: EvalOptions,\n global: GlobalOptions,\n): Promise<EvalResult> => {\n const pmRoot = resolvePmRoot(process.cwd(), global.path);\n if (!(await pathExists(getSettingsPath(pmRoot)))) {\n throw new PmCliError(\n `Tracker is not initialized at ${pmRoot}. Run pm init first.`,\n EXIT_CODE.NOT_FOUND,\n );\n }\n const k = parseEvalK(options.k);\n const defaultMode = parseEvalMode(options.mode);\n const failUnder = parseFailUnder(options.failUnder);\n const queriesPath = resolveEvalQueriesPath(pmRoot, options.queries);\n const querySet = await loadEvalQuerySet(queriesPath);\n\n const reports: EvalQueryReport[] = [];\n // Aggregate and gate on the UNROUNDED metrics; rounding is applied only to the\n // emitted report values so display precision never flips a --fail-under decision.\n const rawMetrics: QueryEvalMetrics[] = [];\n for (const evalQuery of querySet.queries) {\n const { report, metrics } = await evaluateEvalQuery(\n evalQuery,\n defaultMode,\n k,\n global,\n );\n rawMetrics.push(metrics);\n reports.push(report);\n }\n return buildEvalResult(k, reports, rawMetrics, failUnder);\n};\n","/**\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/** Retrieval mode a golden query is evaluated under. Mirrors the `pm search` mode surface; omitting it on a query defers to the eval run's default mode. */\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/** One curated golden query: the query text, the set of item ids considered relevant, an optional per-query retrieval mode override, and an optional human-readable description of the relevance intent. */\nexport interface EvalQuery {\n /** Value that configures or reports query for this contract. */\n query: string;\n /** Value that configures or reports relevant ids for this contract. */\n relevant_ids: string[];\n /** Value that configures or reports mode for this contract. */\n mode?: EvalSearchMode;\n /** Value that configures or reports description for this contract. */\n description?: string;\n}\n\n/** A parsed, validated golden-query set. */\nexport interface EvalQuerySet {\n /** Value that configures or reports queries for this contract. */\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>([\n \"keyword\",\n \"semantic\",\n \"hybrid\",\n]);\n\n/** Compute Discounted Cumulative Gain at cutoff `k` for an ordered list of binary relevance gains (`1` relevant, `0` not). Position `i` (1-based) contributes `gain / log2(i + 1)`, so a relevant hit ranked first is worth `1` and later hits are progressively discounted. Gains beyond `k` are ignored. */\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/** Normalized DCG at cutoff `k`: the ranking's DCG divided by the DCG of the ideal ranking (all relevant ids first). Returns `0` when the query has no relevant ids (the ideal DCG is `0` and the score is undefined), giving a stable lower bound for aggregation. Result is in `[0, 1]`. */\nexport function ndcgAtK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): 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(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): 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/** Count relevant ids within the top `k` results (shared by precision and recall). */\nfunction countRelevantInTopK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): 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/** Precision at cutoff `k`: relevant ids retrieved in the top `k` divided by `k`. Returns `0` for a non-positive `k`. */\nexport function precisionAtK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): number {\n if (k <= 0) {\n return 0;\n }\n return countRelevantInTopK(rankedIds, relevantIds, k) / k;\n}\n\n/** Recall at cutoff `k`: relevant ids retrieved in the top `k` divided by the total number of relevant ids. Returns `0` when the query has no relevant ids. */\nexport function recallAtK(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): 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 /** Value that configures or reports ndcg for this contract. */\n ndcg: number;\n /** Value that configures or reports mrr for this contract. */\n mrr: number;\n /** Value that configures or reports precision for this contract. */\n precision: number;\n /** Value that configures or reports recall for this contract. */\n recall: number;\n /** Value that configures or reports relevant total for this contract. */\n relevant_total: number;\n /** Value that configures or reports retrieved relevant for this contract. */\n retrieved_relevant: number;\n}\n\n/** Evaluate one ranking against its relevant-id set at cutoff `k`, returning all four metrics together so callers compute the document ranking once and read every score off the result. */\nexport function evaluateRanking(\n rankedIds: string[],\n relevantIds: ReadonlySet<string>,\n k: number,\n): 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 /** Value that configures or reports ndcg for this contract. */\n ndcg: number;\n /** Value that configures or reports mrr for this contract. */\n mrr: number;\n /** Value that configures or reports precision for this contract. */\n precision: number;\n /** Value that configures or reports recall for this contract. */\n recall: number;\n /** Number of query entries represented by this result. */\n query_count: number;\n}\n\n/** Macro-average per-query metrics (each query weighted equally). Returns all zeros with `query_count: 0` for an empty input so the gate path has a stable shape to compare against. */\nexport function aggregateEvalMetrics(\n perQuery: QueryEvalMetrics[],\n): 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(\n `Eval query at index ${index} must be an object`,\n );\n }\n const entry = raw as {\n query?: unknown;\n relevant_ids?: unknown;\n mode?: unknown;\n description?: unknown;\n };\n const query = typeof entry.query === \"string\" ? entry.query.trim() : \"\";\n if (query.length === 0) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} must have a non-empty \"query\" string`,\n );\n }\n if (!Array.isArray(entry.relevant_ids)) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} must have a \"relevant_ids\" array`,\n );\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(\n `Eval query at index ${index} must have a \"relevant_ids\" array of strings`,\n );\n }\n const relevantIds = [\n ...new Set(\n (entry.relevant_ids as string[])\n .map((value) => value.trim())\n .filter((value) => value.length > 0),\n ),\n ];\n if (relevantIds.length === 0) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} must list at least one relevant id`,\n );\n }\n if (\n entry.mode !== undefined &&\n (typeof entry.mode !== \"string\" || !VALID_EVAL_MODES.has(entry.mode))\n ) {\n throw new EvalQuerySetError(\n `Eval query at index ${index} has an invalid mode (expected keyword|semantic|hybrid)`,\n );\n }\n return {\n query,\n relevant_ids: relevantIds,\n ...(entry.mode !== undefined ? { mode: entry.mode as EvalSearchMode } : {}),\n ...(typeof entry.description === \"string\" &&\n 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(\n 'Eval query set must be an array of queries or an object with a \"queries\" array',\n );\n }\n if (rawQueries.length === 0) {\n throw new EvalQuerySetError(\n \"Eval query set must contain at least one query\",\n );\n }\n return {\n queries: rawQueries.map((entry, index) =>\n parseEvalQueryEntry(entry, index),\n ),\n };\n}\n"],"names":["path","itemRecord","fs","path","path","VALID_EVAL_MODES","fs"],"mappings":"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","debugId":"4c8b3841-40b8-5707-9154-ff020ed23bfd"}
|