@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
|
@@ -1,58 +1,19 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
-
import {
|
|
4
|
-
runDocs
|
|
5
|
-
} from "./chunk-X2MGQMZO.js";
|
|
6
|
-
import {
|
|
7
|
-
scanHistoryDrift
|
|
8
|
-
} from "./chunk-NVZ6NVHJ.js";
|
|
9
|
-
import {
|
|
10
|
-
runFiles
|
|
11
|
-
} from "./chunk-AFGKSHAM.js";
|
|
12
|
-
import {
|
|
13
|
-
isRemoteLinkedArtifactReference
|
|
14
|
-
} from "./chunk-H5IOT54C.js";
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b111adf0-7ac6-5083-9fb7-c9a093abf43b")}catch(e){}}();
|
|
15
3
|
import {
|
|
16
4
|
runUpdate
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import {
|
|
19
|
-
wrapOwnershipConflict
|
|
20
|
-
} from "./chunk-ILVOOAT4.js";
|
|
21
|
-
import {
|
|
22
|
-
PM_TELEMETRY_SOURCE_CONTEXT_VALUES,
|
|
23
|
-
TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS,
|
|
24
|
-
TELEMETRY_SCHEMA_VERSION,
|
|
25
|
-
flushTelemetryQueueNow
|
|
26
|
-
} from "./chunk-EY7ZE3TG.js";
|
|
5
|
+
} from "./chunk-MRXAHR4B.js";
|
|
27
6
|
import {
|
|
28
7
|
buildCapabilityContractMetadata,
|
|
29
8
|
buildRegistrationCollisionRemediation,
|
|
30
9
|
collectUnknownCapabilityGuidance,
|
|
31
10
|
readManagedExtensionState,
|
|
32
11
|
runInit
|
|
33
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MI3346YW.js";
|
|
34
13
|
import {
|
|
35
14
|
collectStaleVectorizationIds,
|
|
36
15
|
runNext
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import {
|
|
39
|
-
collectDanglingDependencyReferences,
|
|
40
|
-
createRelationshipKindRegistry
|
|
41
|
-
} from "./chunk-L5BTTDU5.js";
|
|
42
|
-
import {
|
|
43
|
-
computeContentFieldUtilization
|
|
44
|
-
} from "./chunk-NCVT6XEL.js";
|
|
45
|
-
import {
|
|
46
|
-
computeMetadataCoverage,
|
|
47
|
-
groupItemsByDimension,
|
|
48
|
-
lifecycleClassifierFromStatusRegistry
|
|
49
|
-
} from "./chunk-CKX4WOPC.js";
|
|
50
|
-
import {
|
|
51
|
-
parseLimit
|
|
52
|
-
} from "./chunk-PT7MCCGD.js";
|
|
53
|
-
import {
|
|
54
|
-
resolveAuthor
|
|
55
|
-
} from "./chunk-CUFW7ITY.js";
|
|
16
|
+
} from "./chunk-CZA2DXCV.js";
|
|
56
17
|
import {
|
|
57
18
|
buildVectorizationEmbeddingIdentity,
|
|
58
19
|
hasVectorizationEmbeddingIdentityChanged,
|
|
@@ -62,7 +23,10 @@ import {
|
|
|
62
23
|
resolveProviderConfigSource,
|
|
63
24
|
resolveSettingsWithSemanticRuntimeDefaults,
|
|
64
25
|
resolveVectorStores
|
|
65
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-UE7LK3RE.js";
|
|
27
|
+
import {
|
|
28
|
+
scanHistoryDrift
|
|
29
|
+
} from "./chunk-XXWDEQ6O.js";
|
|
66
30
|
import {
|
|
67
31
|
ACTIVITY_COMMANDER_STRING_OPTION_CONTRACTS,
|
|
68
32
|
ACTIVITY_FLAG_CONTRACTS,
|
|
@@ -154,7 +118,10 @@ import {
|
|
|
154
118
|
UPGRADE_FLAG_CONTRACTS,
|
|
155
119
|
VALIDATE_FLAG_CONTRACTS,
|
|
156
120
|
compactFlagAliasContracts
|
|
157
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-JPWUZOMR.js";
|
|
122
|
+
import {
|
|
123
|
+
wrapOwnershipConflict
|
|
124
|
+
} from "./chunk-Y2VSGFT4.js";
|
|
158
125
|
import {
|
|
159
126
|
LINKED_TEST_PM_CONTEXT_MODE_VALUES,
|
|
160
127
|
LINKED_TEST_PROTECTED_ENV_KEYS,
|
|
@@ -171,12 +138,41 @@ import {
|
|
|
171
138
|
parseLinkedTestRegexList,
|
|
172
139
|
parseLinkedTestStringList,
|
|
173
140
|
runCreate
|
|
174
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-BDC4TW4B.js";
|
|
142
|
+
import {
|
|
143
|
+
collectDanglingDependencyReferences
|
|
144
|
+
} from "./chunk-77XFQRTD.js";
|
|
145
|
+
import {
|
|
146
|
+
runDocs
|
|
147
|
+
} from "./chunk-LT5UWU7H.js";
|
|
148
|
+
import {
|
|
149
|
+
runFiles
|
|
150
|
+
} from "./chunk-YGEA4CLH.js";
|
|
151
|
+
import {
|
|
152
|
+
isRemoteLinkedArtifactReference
|
|
153
|
+
} from "./chunk-VSQE43NO.js";
|
|
175
154
|
import {
|
|
176
155
|
createStdinTokenResolver,
|
|
177
156
|
parseCsvKv,
|
|
178
157
|
parseOptionalNumber
|
|
179
|
-
} from "./chunk-
|
|
158
|
+
} from "./chunk-SVAWG7EE.js";
|
|
159
|
+
import {
|
|
160
|
+
computeContentFieldUtilization
|
|
161
|
+
} from "./chunk-YG56M3NE.js";
|
|
162
|
+
import {
|
|
163
|
+
computeMetadataCoverage,
|
|
164
|
+
groupItemsByDimension,
|
|
165
|
+
lifecycleClassifierFromStatusRegistry
|
|
166
|
+
} from "./chunk-XKVHL3MB.js";
|
|
167
|
+
import {
|
|
168
|
+
parseLimit
|
|
169
|
+
} from "./chunk-FIUTBFC6.js";
|
|
170
|
+
import {
|
|
171
|
+
readHistoryEntries
|
|
172
|
+
} from "./chunk-M4B4RK4J.js";
|
|
173
|
+
import {
|
|
174
|
+
resolveAuthor
|
|
175
|
+
} from "./chunk-CUFW7ITY.js";
|
|
180
176
|
import {
|
|
181
177
|
CURRENT_ITEM_FORMAT_VERSION,
|
|
182
178
|
compareTimestampStrings,
|
|
@@ -203,7 +199,7 @@ import {
|
|
|
203
199
|
stableValueEquals,
|
|
204
200
|
toItemRecord,
|
|
205
201
|
writeSettings
|
|
206
|
-
} from "./chunk-
|
|
202
|
+
} from "./chunk-QFG4MB7P.js";
|
|
207
203
|
import {
|
|
208
204
|
DEFAULT_VALIDATE_CLOSURE_LIKE_METADATA_FIELD_PATTERNS,
|
|
209
205
|
DEFAULT_VALIDATE_STALE_BLOCKER_REASON_PATTERNS,
|
|
@@ -218,9 +214,12 @@ import {
|
|
|
218
214
|
SCOPE_VALUES,
|
|
219
215
|
SETTINGS_DEFAULTS,
|
|
220
216
|
activateExtensions,
|
|
217
|
+
appendLineAtomic,
|
|
221
218
|
collectRegisteredItemFieldNames,
|
|
222
219
|
commandOptionFlagLabel,
|
|
220
|
+
createRelationshipKindRegistry,
|
|
223
221
|
ensureDir,
|
|
222
|
+
getHistoryPath,
|
|
224
223
|
getItemFormatFromPath,
|
|
225
224
|
getSettingsPath,
|
|
226
225
|
getTestRunRecordPath,
|
|
@@ -239,17 +238,1821 @@ import {
|
|
|
239
238
|
resolveCommandOptionPolicyState,
|
|
240
239
|
resolveGlobalPmRoot,
|
|
241
240
|
resolveItemTypeRegistry,
|
|
241
|
+
resolvePmPackageRootFromModule,
|
|
242
242
|
resolvePmRoot,
|
|
243
243
|
resolveRuntimeFieldRegistry,
|
|
244
244
|
resolveRuntimeStatusRegistry,
|
|
245
|
+
resolveTelemetryErrorCategory,
|
|
245
246
|
statusIsTerminal,
|
|
246
247
|
toNonEmptyStringOrUndefined,
|
|
247
248
|
writeFileAtomic
|
|
248
|
-
} from "./chunk-
|
|
249
|
+
} from "./chunk-D35WYXWC.js";
|
|
250
|
+
|
|
251
|
+
// dist/core/telemetry/observability.js
|
|
252
|
+
var SETUP_ROOT_COMMANDS = /* @__PURE__ */ new Set([
|
|
253
|
+
"init",
|
|
254
|
+
"config",
|
|
255
|
+
"completion",
|
|
256
|
+
"completion-statuses",
|
|
257
|
+
"completion-tags",
|
|
258
|
+
"completion-types"
|
|
259
|
+
]);
|
|
260
|
+
var QUERY_ROOT_COMMANDS = /* @__PURE__ */ new Set([
|
|
261
|
+
"list",
|
|
262
|
+
"list-all",
|
|
263
|
+
"list-open",
|
|
264
|
+
"list-in-progress",
|
|
265
|
+
"list-blocked",
|
|
266
|
+
"list-closed",
|
|
267
|
+
"list-canceled",
|
|
268
|
+
"list-draft",
|
|
269
|
+
"search",
|
|
270
|
+
"get",
|
|
271
|
+
"context",
|
|
272
|
+
"calendar",
|
|
273
|
+
"history",
|
|
274
|
+
"activity",
|
|
275
|
+
"aggregate",
|
|
276
|
+
"deps",
|
|
277
|
+
"contracts",
|
|
278
|
+
"stats"
|
|
279
|
+
]);
|
|
280
|
+
var MUTATION_ROOT_COMMANDS = /* @__PURE__ */ new Set([
|
|
281
|
+
"create",
|
|
282
|
+
"update",
|
|
283
|
+
"update-many",
|
|
284
|
+
"close-many",
|
|
285
|
+
"append",
|
|
286
|
+
"close",
|
|
287
|
+
"delete",
|
|
288
|
+
"restore",
|
|
289
|
+
"claim",
|
|
290
|
+
"release",
|
|
291
|
+
"comments",
|
|
292
|
+
"notes",
|
|
293
|
+
"learnings",
|
|
294
|
+
"files",
|
|
295
|
+
"docs",
|
|
296
|
+
"start-task",
|
|
297
|
+
"pause-task",
|
|
298
|
+
"close-task"
|
|
299
|
+
]);
|
|
300
|
+
var TESTING_ROOT_COMMANDS = /* @__PURE__ */ new Set([
|
|
301
|
+
"test",
|
|
302
|
+
"test-all",
|
|
303
|
+
"test-runs",
|
|
304
|
+
"test-verify",
|
|
305
|
+
"trace-test",
|
|
306
|
+
"test-ping"
|
|
307
|
+
]);
|
|
308
|
+
var DIAGNOSTICS_ROOT_COMMANDS = /* @__PURE__ */ new Set([
|
|
309
|
+
"health",
|
|
310
|
+
"validate",
|
|
311
|
+
"normalize",
|
|
312
|
+
"reindex",
|
|
313
|
+
"gc",
|
|
314
|
+
"telemetry",
|
|
315
|
+
"extension-doctor"
|
|
316
|
+
]);
|
|
317
|
+
function normalizeCommandPath(commandPath) {
|
|
318
|
+
return commandPath.trim().replaceAll(/\s+/g, " ").toLowerCase();
|
|
319
|
+
}
|
|
320
|
+
function normalizeErrorCode(errorCode2) {
|
|
321
|
+
const normalized = errorCode2?.trim().toLowerCase();
|
|
322
|
+
return normalized && normalized.length > 0 ? normalized : void 0;
|
|
323
|
+
}
|
|
324
|
+
var TELEMETRY_ERROR_MESSAGE_CLASSIFIERS = [
|
|
325
|
+
{
|
|
326
|
+
code: "unknown_command",
|
|
327
|
+
matches: (message) => message.includes("unknown command")
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
code: "unknown_option",
|
|
331
|
+
matches: (message) => message.includes("unknown option")
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
code: "missing_required_option",
|
|
335
|
+
matches: (message) => message.includes("missing required options") || message.includes("missing required option")
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
code: "missing_required_argument",
|
|
339
|
+
matches: (message) => message.includes("missing required argument")
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
code: "no_update_fields",
|
|
343
|
+
matches: (message) => message.includes("no update flags provided")
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
code: "ownership_conflict",
|
|
347
|
+
matches: (message) => message.includes("is assigned to") && message.includes("use --force")
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
code: "lock_conflict",
|
|
351
|
+
matches: (message) => message.includes("is locked")
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
code: "terminal_state_conflict",
|
|
355
|
+
matches: (message) => message.includes("already terminal") && message.includes("use --force")
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
code: "tracker_not_initialized",
|
|
359
|
+
matches: (message) => message.includes("tracker is not initialized")
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
code: "item_not_found",
|
|
363
|
+
matches: (message) => message.includes(" not found")
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
code: "close_through_update",
|
|
367
|
+
matches: (message) => message.includes('use "pm close <id> <text>" to close an item') || message.includes("invalid --status value") && message.includes('"closed"')
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
code: "invalid_argument_value",
|
|
371
|
+
matches: (message) => message.startsWith("invalid ") || message.includes(" must be ") || message.includes(" requires ")
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
code: "invalid_command_usage",
|
|
375
|
+
matches: (message) => message.includes("either as positional") && message.includes("not both")
|
|
376
|
+
}
|
|
377
|
+
];
|
|
378
|
+
var TELEMETRY_EXIT_CODE_FALLBACKS = /* @__PURE__ */ new Map([
|
|
379
|
+
[EXIT_CODE.USAGE, "invalid_command_usage"],
|
|
380
|
+
[EXIT_CODE.NOT_FOUND, "item_not_found"],
|
|
381
|
+
[EXIT_CODE.CONFLICT, "lock_conflict"],
|
|
382
|
+
[EXIT_CODE.DEPENDENCY_FAILED, "dependency_failed"]
|
|
383
|
+
]);
|
|
384
|
+
function deriveTelemetryCommandTaxonomy(commandPath) {
|
|
385
|
+
const normalizedPath = normalizeCommandPath(commandPath);
|
|
386
|
+
const tokens = normalizedPath.length > 0 ? normalizedPath.split(" ") : ["<unknown>"];
|
|
387
|
+
const root = tokens[0];
|
|
388
|
+
const leaf = tokens[tokens.length - 1];
|
|
389
|
+
let family = "other";
|
|
390
|
+
if (SETUP_ROOT_COMMANDS.has(root)) {
|
|
391
|
+
family = "setup";
|
|
392
|
+
} else if (QUERY_ROOT_COMMANDS.has(root)) {
|
|
393
|
+
family = "query";
|
|
394
|
+
} else if (MUTATION_ROOT_COMMANDS.has(root)) {
|
|
395
|
+
family = "mutation";
|
|
396
|
+
} else if (TESTING_ROOT_COMMANDS.has(root)) {
|
|
397
|
+
family = "testing";
|
|
398
|
+
} else if (root === "extension") {
|
|
399
|
+
family = "extension";
|
|
400
|
+
} else if (DIAGNOSTICS_ROOT_COMMANDS.has(root)) {
|
|
401
|
+
family = "diagnostics";
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
command_path: normalizedPath.length > 0 ? normalizedPath : "<unknown>",
|
|
405
|
+
command_root: root,
|
|
406
|
+
command_leaf: leaf,
|
|
407
|
+
command_depth: tokens.length,
|
|
408
|
+
command_family: family
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
function inferTelemetryErrorCode(params) {
|
|
412
|
+
if (params.ok) {
|
|
413
|
+
return void 0;
|
|
414
|
+
}
|
|
415
|
+
const explicit = normalizeErrorCode(params.errorCode);
|
|
416
|
+
if (explicit) {
|
|
417
|
+
return explicit;
|
|
418
|
+
}
|
|
419
|
+
const message = (params.errorMessage ?? "").trim().toLowerCase();
|
|
420
|
+
for (const classifier of TELEMETRY_ERROR_MESSAGE_CLASSIFIERS) {
|
|
421
|
+
if (classifier.matches(message)) {
|
|
422
|
+
return classifier.code;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
const exitCode = Number.isFinite(params.exitCode) ? Math.max(0, Math.trunc(params.exitCode)) : void 0;
|
|
426
|
+
if (exitCode !== void 0) {
|
|
427
|
+
return TELEMETRY_EXIT_CODE_FALLBACKS.get(exitCode) ?? "command_failed";
|
|
428
|
+
}
|
|
429
|
+
return "command_failed";
|
|
430
|
+
}
|
|
431
|
+
function deriveTelemetryCommandResolution(params) {
|
|
432
|
+
if (params.ok) {
|
|
433
|
+
return "success";
|
|
434
|
+
}
|
|
435
|
+
const normalizedCode = normalizeErrorCode(params.errorCode);
|
|
436
|
+
if (normalizedCode === "unknown_command") {
|
|
437
|
+
return "nonexistent_command";
|
|
438
|
+
}
|
|
439
|
+
if (normalizedCode === "unknown_option") {
|
|
440
|
+
return "invalid_option";
|
|
441
|
+
}
|
|
442
|
+
if (normalizedCode === "missing_required_option") {
|
|
443
|
+
return "missing_required_option";
|
|
444
|
+
}
|
|
445
|
+
if (normalizedCode === "missing_required_argument") {
|
|
446
|
+
return "missing_required_argument";
|
|
447
|
+
}
|
|
448
|
+
if (normalizedCode === "health_findings") {
|
|
449
|
+
return "health_findings";
|
|
450
|
+
}
|
|
451
|
+
if (normalizedCode === "validation_findings") {
|
|
452
|
+
return "validation_findings";
|
|
453
|
+
}
|
|
454
|
+
if (params.errorCategory === "usage") {
|
|
455
|
+
return "invalid_usage";
|
|
456
|
+
}
|
|
457
|
+
if (params.errorCategory === "validation") {
|
|
458
|
+
return "validation_failed";
|
|
459
|
+
}
|
|
460
|
+
if (params.errorCategory === "conflict") {
|
|
461
|
+
return "conflict";
|
|
462
|
+
}
|
|
463
|
+
if (params.errorCategory === "runtime") {
|
|
464
|
+
return "runtime_failed";
|
|
465
|
+
}
|
|
466
|
+
return "unknown_failed";
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// dist/core/telemetry/runtime.js
|
|
470
|
+
import crypto from "node:crypto";
|
|
471
|
+
import { spawn } from "node:child_process";
|
|
472
|
+
import { mkdirSync, rmSync, statSync } from "node:fs";
|
|
473
|
+
import { mkdir, readdir, rm, stat } from "node:fs/promises";
|
|
474
|
+
import os from "node:os";
|
|
475
|
+
import path from "node:path";
|
|
476
|
+
var TELEMETRY_QUEUE_RELATIVE_PATH = path.join("runtime", "telemetry", "events.jsonl");
|
|
477
|
+
var TELEMETRY_STATE_RELATIVE_PATH = path.join("runtime", "telemetry", "state.json");
|
|
478
|
+
var TELEMETRY_OTEL_SPANS_RELATIVE_PATH = path.join("runtime", "telemetry", "otel-spans.jsonl");
|
|
479
|
+
var TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE = 8;
|
|
480
|
+
var TELEMETRY_OTEL_SPANS_MAX_PENDING = 500;
|
|
481
|
+
var TELEMETRY_SCHEMA_VERSION = 1;
|
|
482
|
+
var TELEMETRY_CLIENT_SCHEMA_VERSION = 1;
|
|
483
|
+
var TELEMETRY_FLUSH_BATCH_SIZE = 100;
|
|
484
|
+
var TELEMETRY_MAX_RETRY_DELAY_MS = 36e5;
|
|
485
|
+
var TELEMETRY_RETRY_BASE_DELAY_MS = 3e4;
|
|
486
|
+
var TELEMETRY_HTTP_TIMEOUT_MS = 5e3;
|
|
487
|
+
var MILLISECONDS_PER_DAY = 864e5;
|
|
488
|
+
var TELEMETRY_MAX_EVENT_BYTES = 65536;
|
|
489
|
+
var TELEMETRY_SANITIZE_MAX_DEPTH = 6;
|
|
490
|
+
var TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS = 20;
|
|
491
|
+
var TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS = 15;
|
|
492
|
+
var TELEMETRY_RESULT_PREVIEW_MAX_BYTES = 8192;
|
|
493
|
+
var TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS = [25, 50, 100, 200];
|
|
494
|
+
var TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
495
|
+
var TELEMETRY_FLUSH_LOCK_STALE_MS = 6e4;
|
|
496
|
+
var TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS = 6e4;
|
|
497
|
+
var OTEL_TRACES_ENDPOINT_ENV = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";
|
|
498
|
+
var OTEL_BASE_ENDPOINT_ENV = "OTEL_EXPORTER_OTLP_ENDPOINT";
|
|
499
|
+
var OTEL_SERVICE_NAME_ENV = "OTEL_SERVICE_NAME";
|
|
500
|
+
var PM_TELEMETRY_DISABLED_ENV = "PM_TELEMETRY_DISABLED";
|
|
501
|
+
var PM_NO_TELEMETRY_ENV = "PM_NO_TELEMETRY";
|
|
502
|
+
var PM_TELEMETRY_DISABLED_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
503
|
+
var PM_TELEMETRY_OTEL_DISABLED_ENV = "PM_TELEMETRY_OTEL_DISABLED";
|
|
504
|
+
var PM_TELEMETRY_OTEL_DISABLED_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
505
|
+
var PM_TELEMETRY_INLINE_FLUSH_ENV = "PM_TELEMETRY_INLINE_FLUSH";
|
|
506
|
+
var PM_TELEMETRY_FLUSH_CHILD_ENV = "PM_TELEMETRY_FLUSH_CHILD";
|
|
507
|
+
var PM_TELEMETRY_SOURCE_CONTEXT_ENV = "PM_TELEMETRY_SOURCE_CONTEXT";
|
|
508
|
+
var PM_AUTHOR_ENV = "PM_AUTHOR";
|
|
509
|
+
var PM_TELEMETRY_SOURCE_CONTEXT_VALUES = [
|
|
510
|
+
"user",
|
|
511
|
+
"automation",
|
|
512
|
+
"test",
|
|
513
|
+
"dogfood"
|
|
514
|
+
];
|
|
515
|
+
var _lastFlushPromise = Promise.resolve();
|
|
516
|
+
var _queueMutationPromise = Promise.resolve();
|
|
517
|
+
var PM_TELEMETRY_SOURCE_CONTEXT_SET = new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES);
|
|
518
|
+
var BOOLEAN_TRUE_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
519
|
+
var PROCESS_SESSION_ID = crypto.randomUUID();
|
|
520
|
+
var SENSITIVE_KEYWORDS = [
|
|
521
|
+
"token",
|
|
522
|
+
"secret",
|
|
523
|
+
"password",
|
|
524
|
+
"passwd",
|
|
525
|
+
"api_key",
|
|
526
|
+
"apikey",
|
|
527
|
+
"authorization",
|
|
528
|
+
"cookie",
|
|
529
|
+
"session",
|
|
530
|
+
"credentials",
|
|
531
|
+
"bearer"
|
|
532
|
+
];
|
|
533
|
+
var SENSITIVE_INLINE_KEY_PATTERN = "(?:token|secret|password|passwd|api[_-]?key|apikey|authorization|cookie|session|credentials|bearer)";
|
|
534
|
+
var INLINE_SENSITIVE_ASSIGNMENT_PATTERN = new RegExp(`\\b(${SENSITIVE_INLINE_KEY_PATTERN})\\s*([:=])\\s*([^\\s,;]+)`, "giu");
|
|
535
|
+
var INLINE_SENSITIVE_FLAG_PATTERN = new RegExp(`(--${SENSITIVE_INLINE_KEY_PATTERN})(=|\\s+)([^\\s,;]+)`, "giu");
|
|
536
|
+
var ABSOLUTE_PATH_TOKEN_PATTERN = /(^|[\s"'`(=])\/(?:[^\s"'`),;]+)/g;
|
|
537
|
+
var BEARER_TOKEN_PATTERN = /bearer\s+[a-z0-9._=-]+/giu;
|
|
538
|
+
var PRIVATE_IP_PATTERN = /\b(?:10\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|172\.(?:1[6-9]|2\d|3[01])\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.(?:25[0-5]|2[0-4]\d|[01]?\d?\d))\b/g;
|
|
539
|
+
function queuePath(globalPmRoot) {
|
|
540
|
+
return path.join(globalPmRoot, TELEMETRY_QUEUE_RELATIVE_PATH);
|
|
541
|
+
}
|
|
542
|
+
function otelSpansQueuePath(globalPmRoot) {
|
|
543
|
+
return path.join(globalPmRoot, TELEMETRY_OTEL_SPANS_RELATIVE_PATH);
|
|
544
|
+
}
|
|
545
|
+
function telemetryRuntimeDirectory(globalPmRoot) {
|
|
546
|
+
return path.dirname(queuePath(globalPmRoot));
|
|
547
|
+
}
|
|
548
|
+
function runtimeStatePath(globalPmRoot) {
|
|
549
|
+
return path.join(globalPmRoot, TELEMETRY_STATE_RELATIVE_PATH);
|
|
550
|
+
}
|
|
551
|
+
function flushLockPath(globalPmRoot) {
|
|
552
|
+
return path.join(globalPmRoot, "runtime", "telemetry", "flush.lock");
|
|
553
|
+
}
|
|
554
|
+
function flushSpawnLockPath(globalPmRoot) {
|
|
555
|
+
return path.join(globalPmRoot, "runtime", "telemetry", "flush.spawn.lock");
|
|
556
|
+
}
|
|
557
|
+
function telemetryFlushRunnerPath() {
|
|
558
|
+
return path.join(resolvePmPackageRootFromModule(import.meta.url, ["../../.."]), "dist", "cli", "telemetry-flush.js");
|
|
559
|
+
}
|
|
560
|
+
function shouldFlushInline() {
|
|
561
|
+
if (parseBooleanTrueLike(process.env[PM_TELEMETRY_INLINE_FLUSH_ENV])) {
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
if (parseBooleanTrueLike(process.env[PM_TELEMETRY_FLUSH_CHILD_ENV])) {
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
const nodeEnv = (process.env.NODE_ENV ?? "").trim().toLowerCase();
|
|
568
|
+
return typeof process.env.VITEST === "string" || typeof process.env.VITEST_WORKER_ID === "string" || nodeEnv === "test";
|
|
569
|
+
}
|
|
570
|
+
async function readRuntimeState(globalPmRoot) {
|
|
571
|
+
const raw = await readFileIfExists(runtimeStatePath(globalPmRoot));
|
|
572
|
+
if (!raw || raw.trim().length === 0) {
|
|
573
|
+
return {};
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
const parsed = JSON.parse(raw);
|
|
577
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
578
|
+
return {};
|
|
579
|
+
}
|
|
580
|
+
return parsed;
|
|
581
|
+
} catch {
|
|
582
|
+
return {};
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
async function writeRuntimeState(globalPmRoot, patch) {
|
|
586
|
+
try {
|
|
587
|
+
const current = await readRuntimeState(globalPmRoot);
|
|
588
|
+
const next = {
|
|
589
|
+
...current,
|
|
590
|
+
...patch
|
|
591
|
+
};
|
|
592
|
+
const normalized = Object.fromEntries(Object.entries(next).filter(([, value]) => value !== void 0).sort((left, right) => left[0].localeCompare(right[0])));
|
|
593
|
+
await writeFileAtomic(runtimeStatePath(globalPmRoot), `${JSON.stringify(normalized, null, 2)}
|
|
594
|
+
`);
|
|
595
|
+
} catch {
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
function isSensitiveKey(key) {
|
|
599
|
+
const normalized = key.trim().toLowerCase().replaceAll("-", "_").replaceAll(/[^a-z0-9_]+/g, "_");
|
|
600
|
+
const tokens = normalized.split("_").filter((token) => token.length > 0);
|
|
601
|
+
return SENSITIVE_KEYWORDS.some((keyword) => normalized === keyword || normalized.endsWith(`_${keyword}`) || tokens.includes(keyword));
|
|
602
|
+
}
|
|
603
|
+
function redactInlineSensitiveAssignments(input) {
|
|
604
|
+
const withoutAssignments = input.replaceAll(INLINE_SENSITIVE_ASSIGNMENT_PATTERN, (_match, key, delimiter) => `${key}${delimiter}[redacted]`);
|
|
605
|
+
return withoutAssignments.replaceAll(INLINE_SENSITIVE_FLAG_PATTERN, (_match, flag, delimiter) => `${flag}${delimiter}[redacted]`);
|
|
606
|
+
}
|
|
607
|
+
function redactAbsolutePathTokens(input) {
|
|
608
|
+
return input.replaceAll(ABSOLUTE_PATH_TOKEN_PATTERN, (_match, prefix) => `${prefix}[redacted_path]`);
|
|
609
|
+
}
|
|
610
|
+
function isAsciiLetterOrDigitCode(code) {
|
|
611
|
+
const isUpper = code >= 65 && code <= 90;
|
|
612
|
+
const isLower = code >= 97 && code <= 122;
|
|
613
|
+
const isDigit = code >= 48 && code <= 57;
|
|
614
|
+
return isUpper || isLower || isDigit;
|
|
615
|
+
}
|
|
616
|
+
function isEmailLocalCharacter(character) {
|
|
617
|
+
if (!character) {
|
|
618
|
+
return false;
|
|
619
|
+
}
|
|
620
|
+
const code = character.charCodeAt(0);
|
|
621
|
+
if (isAsciiLetterOrDigitCode(code)) {
|
|
622
|
+
return true;
|
|
623
|
+
}
|
|
624
|
+
return character === "." || character === "_" || character === "%" || character === "+" || character === "-";
|
|
625
|
+
}
|
|
626
|
+
function isEmailDomainCharacter(character) {
|
|
627
|
+
if (!character) {
|
|
628
|
+
return false;
|
|
629
|
+
}
|
|
630
|
+
const code = character.charCodeAt(0);
|
|
631
|
+
if (isAsciiLetterOrDigitCode(code)) {
|
|
632
|
+
return true;
|
|
633
|
+
}
|
|
634
|
+
return character === "." || character === "-";
|
|
635
|
+
}
|
|
636
|
+
function looksLikeEmailToken(token) {
|
|
637
|
+
const atIndex = token.indexOf("@");
|
|
638
|
+
if (atIndex <= 0 || atIndex !== token.lastIndexOf("@") || atIndex === token.length - 1) {
|
|
639
|
+
return false;
|
|
640
|
+
}
|
|
641
|
+
const localPart = token.slice(0, atIndex);
|
|
642
|
+
const domainPart = token.slice(atIndex + 1);
|
|
643
|
+
const lastDot = domainPart.lastIndexOf(".");
|
|
644
|
+
if (lastDot <= 0 || lastDot === domainPart.length - 1) {
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
if (domainPart.length - (lastDot + 1) < 2) {
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
for (const character of localPart) {
|
|
651
|
+
if (!isEmailLocalCharacter(character)) {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
for (const character of domainPart) {
|
|
656
|
+
if (!isEmailDomainCharacter(character)) {
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
function redactEmailTokens(input) {
|
|
663
|
+
let redacted = "";
|
|
664
|
+
let cursor = 0;
|
|
665
|
+
while (cursor < input.length) {
|
|
666
|
+
const atIndex = input.indexOf("@", cursor);
|
|
667
|
+
if (atIndex < 0) {
|
|
668
|
+
redacted += input.slice(cursor);
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
let start = atIndex - 1;
|
|
672
|
+
while (start >= cursor && isEmailLocalCharacter(input[start])) {
|
|
673
|
+
start -= 1;
|
|
674
|
+
}
|
|
675
|
+
start += 1;
|
|
676
|
+
let end = atIndex + 1;
|
|
677
|
+
while (end < input.length && isEmailDomainCharacter(input[end])) {
|
|
678
|
+
end += 1;
|
|
679
|
+
}
|
|
680
|
+
const candidate = input.slice(start, end);
|
|
681
|
+
if (looksLikeEmailToken(candidate)) {
|
|
682
|
+
redacted += input.slice(cursor, start);
|
|
683
|
+
redacted += "[redacted_email]";
|
|
684
|
+
cursor = end;
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
redacted += input.slice(cursor, atIndex + 1);
|
|
688
|
+
cursor = atIndex + 1;
|
|
689
|
+
}
|
|
690
|
+
return redacted;
|
|
691
|
+
}
|
|
692
|
+
function sanitizeCommonSensitiveTokens(input) {
|
|
693
|
+
const withoutEmails = redactEmailTokens(input);
|
|
694
|
+
const withoutBearer = withoutEmails.replaceAll(BEARER_TOKEN_PATTERN, "bearer [redacted_token]");
|
|
695
|
+
return withoutBearer.replaceAll(PRIVATE_IP_PATTERN, "[redacted_ip]");
|
|
696
|
+
}
|
|
697
|
+
function sanitizeStringRedacted(input) {
|
|
698
|
+
const withoutCommonSensitiveTokens = sanitizeCommonSensitiveTokens(input);
|
|
699
|
+
const withoutInlineSecrets = redactInlineSensitiveAssignments(withoutCommonSensitiveTokens);
|
|
700
|
+
const withoutAbsolutePaths = redactAbsolutePathTokens(withoutInlineSecrets);
|
|
701
|
+
const trimmed = withoutAbsolutePaths.trim();
|
|
702
|
+
if (trimmed.startsWith("/") && trimmed.length > 1) {
|
|
703
|
+
return "[redacted_path]";
|
|
704
|
+
}
|
|
705
|
+
if (withoutAbsolutePaths.length > 512) {
|
|
706
|
+
return `${withoutAbsolutePaths.slice(0, 509)}...`;
|
|
707
|
+
}
|
|
708
|
+
return withoutAbsolutePaths;
|
|
709
|
+
}
|
|
710
|
+
function sanitizeStringMax(input) {
|
|
711
|
+
const withoutCommonSensitiveTokens = sanitizeCommonSensitiveTokens(input);
|
|
712
|
+
const withoutInlineSecrets = redactInlineSensitiveAssignments(withoutCommonSensitiveTokens);
|
|
713
|
+
const withoutAbsolutePaths = redactAbsolutePathTokens(withoutInlineSecrets);
|
|
714
|
+
const trimmed = withoutAbsolutePaths.trim();
|
|
715
|
+
if (trimmed.startsWith("/") && trimmed.length > 1) {
|
|
716
|
+
return "[redacted_path]";
|
|
717
|
+
}
|
|
718
|
+
if (withoutAbsolutePaths.length > 2048) {
|
|
719
|
+
return `${withoutAbsolutePaths.slice(0, 2045)}...`;
|
|
720
|
+
}
|
|
721
|
+
return withoutAbsolutePaths;
|
|
722
|
+
}
|
|
723
|
+
function sanitizeString(input, captureLevel = "redacted") {
|
|
724
|
+
if (captureLevel === "max") {
|
|
725
|
+
return sanitizeStringMax(input);
|
|
726
|
+
}
|
|
727
|
+
return sanitizeStringRedacted(input);
|
|
728
|
+
}
|
|
729
|
+
function sanitizeValue(value, keyHint, captureLevel = "redacted", depth = 0) {
|
|
730
|
+
if (keyHint && isSensitiveKey(keyHint)) {
|
|
731
|
+
return "[redacted]";
|
|
732
|
+
}
|
|
733
|
+
if (value === null || value === void 0) {
|
|
734
|
+
return value;
|
|
735
|
+
}
|
|
736
|
+
if (typeof value === "string") {
|
|
737
|
+
return sanitizeString(value, captureLevel);
|
|
738
|
+
}
|
|
739
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
740
|
+
return value;
|
|
741
|
+
}
|
|
742
|
+
if (depth >= TELEMETRY_SANITIZE_MAX_DEPTH) {
|
|
743
|
+
return "[depth_truncated]";
|
|
744
|
+
}
|
|
745
|
+
if (Array.isArray(value)) {
|
|
746
|
+
return value.slice(0, TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS).map((entry) => sanitizeValue(entry, void 0, captureLevel, depth + 1));
|
|
747
|
+
}
|
|
748
|
+
if (typeof value === "object") {
|
|
749
|
+
const record = value;
|
|
750
|
+
const sanitized = {};
|
|
751
|
+
for (const [key, nested] of Object.entries(record)) {
|
|
752
|
+
sanitized[key] = sanitizeValue(nested, key, captureLevel, depth + 1);
|
|
753
|
+
}
|
|
754
|
+
return sanitized;
|
|
755
|
+
}
|
|
756
|
+
return String(value);
|
|
757
|
+
}
|
|
758
|
+
function sanitizeCommandArgs(args, captureLevel = "redacted") {
|
|
759
|
+
const sanitized = [];
|
|
760
|
+
let nextIsSensitiveValue = false;
|
|
761
|
+
for (const rawArg of args) {
|
|
762
|
+
const arg = sanitizeString(rawArg, captureLevel);
|
|
763
|
+
if (nextIsSensitiveValue) {
|
|
764
|
+
sanitized.push("[redacted]");
|
|
765
|
+
nextIsSensitiveValue = false;
|
|
766
|
+
continue;
|
|
767
|
+
}
|
|
768
|
+
if (arg.startsWith("--")) {
|
|
769
|
+
const withoutPrefix = arg.slice(2);
|
|
770
|
+
const delimiterIndex = withoutPrefix.indexOf("=");
|
|
771
|
+
if (delimiterIndex >= 0) {
|
|
772
|
+
const key = withoutPrefix.slice(0, delimiterIndex);
|
|
773
|
+
const value = withoutPrefix.slice(delimiterIndex + 1);
|
|
774
|
+
if (isSensitiveKey(key)) {
|
|
775
|
+
sanitized.push(`--${key}=[redacted]`);
|
|
776
|
+
} else {
|
|
777
|
+
sanitized.push(`--${key}=${sanitizeString(value, captureLevel)}`);
|
|
778
|
+
}
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (isSensitiveKey(withoutPrefix)) {
|
|
782
|
+
sanitized.push(`--${withoutPrefix}`);
|
|
783
|
+
nextIsSensitiveValue = true;
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
sanitized.push(arg);
|
|
788
|
+
}
|
|
789
|
+
return sanitized;
|
|
790
|
+
}
|
|
791
|
+
function normalizeCaptureLevel(value) {
|
|
792
|
+
const normalized = value?.trim().toLowerCase();
|
|
793
|
+
if (normalized === "minimal" || normalized === "redacted" || normalized === "max") {
|
|
794
|
+
return normalized;
|
|
795
|
+
}
|
|
796
|
+
return "redacted";
|
|
797
|
+
}
|
|
798
|
+
function parseBooleanTrueLike(value) {
|
|
799
|
+
return BOOLEAN_TRUE_VALUES.has((value ?? "").trim().toLowerCase());
|
|
800
|
+
}
|
|
801
|
+
function normalizePmVersion(value) {
|
|
802
|
+
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
803
|
+
return trimmed.length > 0 ? trimmed : "0.0.0";
|
|
804
|
+
}
|
|
805
|
+
function normalizeTelemetryErrorCode(value) {
|
|
806
|
+
const normalized = value?.trim();
|
|
807
|
+
return normalized && normalized.length > 0 ? normalized : void 0;
|
|
808
|
+
}
|
|
809
|
+
function normalizeTelemetryExitCode(exitCode, ok) {
|
|
810
|
+
if (Number.isFinite(exitCode)) {
|
|
811
|
+
return Math.max(0, Math.trunc(exitCode));
|
|
812
|
+
}
|
|
813
|
+
return ok ? 0 : 1;
|
|
814
|
+
}
|
|
815
|
+
function normalizeTelemetryErrorCategory(params) {
|
|
816
|
+
if (params.ok) {
|
|
817
|
+
return void 0;
|
|
818
|
+
}
|
|
819
|
+
if (typeof params.errorCategory === "string" && params.errorCategory.trim().length > 0) {
|
|
820
|
+
return params.errorCategory;
|
|
821
|
+
}
|
|
822
|
+
if (typeof params.errorCode === "string" && params.errorCode.trim().length > 0) {
|
|
823
|
+
return resolveTelemetryErrorCategory(params.errorCode);
|
|
824
|
+
}
|
|
825
|
+
return "unknown";
|
|
826
|
+
}
|
|
827
|
+
function resolveTelemetrySourceContext(globalOptions) {
|
|
828
|
+
const override = (process.env[PM_TELEMETRY_SOURCE_CONTEXT_ENV] ?? "").trim().toLowerCase();
|
|
829
|
+
if (PM_TELEMETRY_SOURCE_CONTEXT_SET.has(override)) {
|
|
830
|
+
return {
|
|
831
|
+
source_context: override,
|
|
832
|
+
source_context_source: "env_override"
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
const nodeEnv = (process.env.NODE_ENV ?? "").trim().toLowerCase();
|
|
836
|
+
if (typeof process.env.VITEST === "string" || typeof process.env.VITEST_WORKER_ID === "string" || nodeEnv === "test") {
|
|
837
|
+
return {
|
|
838
|
+
source_context: "test",
|
|
839
|
+
source_context_source: "inferred"
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
const nonTty = process.stdin.isTTY !== true || process.stdout.isTTY !== true;
|
|
843
|
+
const ci = parseBooleanTrueLike(process.env.CI);
|
|
844
|
+
const scriptLikeMode = globalOptions.json === true || globalOptions.quiet === true;
|
|
845
|
+
if (nonTty || ci || scriptLikeMode) {
|
|
846
|
+
return {
|
|
847
|
+
source_context: "automation",
|
|
848
|
+
source_context_source: "inferred"
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
return {
|
|
852
|
+
source_context: "user",
|
|
853
|
+
source_context_source: "inferred"
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
function hashWithInstallationId(installationId, value) {
|
|
857
|
+
return crypto.createHash("sha256").update(`${installationId}:${value}`).digest("hex");
|
|
858
|
+
}
|
|
859
|
+
function buildAuthorContextPayloadFields(captureLevel, installationId) {
|
|
860
|
+
const author = (process.env[PM_AUTHOR_ENV] ?? "").trim();
|
|
861
|
+
if (captureLevel === "minimal") {
|
|
862
|
+
return { has_author_context: author.length > 0 };
|
|
863
|
+
}
|
|
864
|
+
return author.length > 0 ? { author_context_hash: hashWithInstallationId(installationId, author) } : {};
|
|
865
|
+
}
|
|
866
|
+
function normalizeForHash(value, depth = 0) {
|
|
867
|
+
if (value === null || value === void 0) {
|
|
868
|
+
return value;
|
|
869
|
+
}
|
|
870
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
871
|
+
return value;
|
|
872
|
+
}
|
|
873
|
+
if (depth >= TELEMETRY_SANITIZE_MAX_DEPTH) {
|
|
874
|
+
return "[depth_truncated]";
|
|
875
|
+
}
|
|
876
|
+
if (Array.isArray(value)) {
|
|
877
|
+
return value.slice(0, TELEMETRY_SANITIZE_MAX_ARRAY_ITEMS).map((entry) => normalizeForHash(entry, depth + 1));
|
|
878
|
+
}
|
|
879
|
+
if (typeof value === "object") {
|
|
880
|
+
const record = value;
|
|
881
|
+
const normalized = {};
|
|
882
|
+
const sortedKeys = Object.keys(record).sort((left, right) => left.localeCompare(right));
|
|
883
|
+
for (const key of sortedKeys) {
|
|
884
|
+
normalized[key] = normalizeForHash(record[key], depth + 1);
|
|
885
|
+
}
|
|
886
|
+
return normalized;
|
|
887
|
+
}
|
|
888
|
+
return String(value);
|
|
889
|
+
}
|
|
890
|
+
function hashTelemetryValue(installationId, value) {
|
|
891
|
+
return hashWithInstallationId(installationId, JSON.stringify(normalizeForHash(value)));
|
|
892
|
+
}
|
|
893
|
+
function hashCommandArgs(installationId, args) {
|
|
894
|
+
return {
|
|
895
|
+
hashes: args.map((arg) => hashWithInstallationId(installationId, arg)),
|
|
896
|
+
digest: hashWithInstallationId(installationId, args.join("\0"))
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
function hashTelemetryErrorFingerprint(installationId, command, errorCode2, errorMessage) {
|
|
900
|
+
const normalizedMessage = sanitizeString(typeof errorMessage === "string" ? errorMessage : "", "redacted");
|
|
901
|
+
const normalizedCode = typeof errorCode2 === "string" && errorCode2.length > 0 ? errorCode2 : "unknown_error";
|
|
902
|
+
const fingerprintSource = `${command}\0${normalizedCode}\0${normalizedMessage}`;
|
|
903
|
+
return hashWithInstallationId(installationId, fingerprintSource);
|
|
904
|
+
}
|
|
905
|
+
function telemetryDisabledByEnvironment() {
|
|
906
|
+
return PM_TELEMETRY_DISABLED_VALUES.has((process.env[PM_TELEMETRY_DISABLED_ENV] ?? "").trim().toLowerCase()) || PM_TELEMETRY_DISABLED_VALUES.has((process.env[PM_NO_TELEMETRY_ENV] ?? "").trim().toLowerCase());
|
|
907
|
+
}
|
|
908
|
+
function resolveOtelTracesEndpoint() {
|
|
909
|
+
if (PM_TELEMETRY_OTEL_DISABLED_VALUES.has((process.env[PM_TELEMETRY_OTEL_DISABLED_ENV] ?? "").trim().toLowerCase())) {
|
|
910
|
+
return null;
|
|
911
|
+
}
|
|
912
|
+
const directEndpoint = (process.env[OTEL_TRACES_ENDPOINT_ENV] ?? "").trim();
|
|
913
|
+
if (directEndpoint.length > 0) {
|
|
914
|
+
try {
|
|
915
|
+
return new URL(directEndpoint).toString();
|
|
916
|
+
} catch {
|
|
917
|
+
return null;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
const baseEndpoint = (process.env[OTEL_BASE_ENDPOINT_ENV] ?? "").trim();
|
|
921
|
+
if (baseEndpoint.length === 0) {
|
|
922
|
+
return null;
|
|
923
|
+
}
|
|
924
|
+
try {
|
|
925
|
+
const url = new URL(baseEndpoint);
|
|
926
|
+
const normalizedPath = url.pathname.replace(/\/+$/, "");
|
|
927
|
+
if (!normalizedPath.endsWith("/v1/traces")) {
|
|
928
|
+
url.pathname = `${normalizedPath.length === 0 ? "" : normalizedPath}/v1/traces`;
|
|
929
|
+
}
|
|
930
|
+
return url.toString();
|
|
931
|
+
} catch {
|
|
932
|
+
return null;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
function isoToUnixNano(iso) {
|
|
936
|
+
const parsedMs = Date.parse(iso);
|
|
937
|
+
const epochMs = Number.isNaN(parsedMs) ? Date.now() : parsedMs;
|
|
938
|
+
return `${BigInt(epochMs) * 1000000n}`;
|
|
939
|
+
}
|
|
940
|
+
function otlpStringAttribute(key, value) {
|
|
941
|
+
return {
|
|
942
|
+
key,
|
|
943
|
+
value: { stringValue: value }
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
function otlpBoolAttribute(key, value) {
|
|
947
|
+
return {
|
|
948
|
+
key,
|
|
949
|
+
value: { boolValue: value }
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
function otlpIntAttribute(key, value) {
|
|
953
|
+
return {
|
|
954
|
+
key,
|
|
955
|
+
value: { intValue: String(Math.max(0, Math.trunc(value))) }
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
function buildOtelSpanRequest(activeCommand, outcome, finishedAtIso, durationMs) {
|
|
959
|
+
if (typeof activeCommand.otel_traces_endpoint !== "string" || activeCommand.otel_traces_endpoint.trim().length === 0 || typeof activeCommand.otel_trace_id !== "string" || activeCommand.otel_trace_id.length === 0 || typeof activeCommand.otel_span_id !== "string" || activeCommand.otel_span_id.length === 0) {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
const serviceNameCandidate = sanitizeString((process.env[OTEL_SERVICE_NAME_ENV] ?? "").trim());
|
|
963
|
+
const serviceName = serviceNameCandidate.length > 0 ? serviceNameCandidate : "pm-cli";
|
|
964
|
+
const normalizedExitCode = normalizeTelemetryExitCode(outcome.exit_code, outcome.ok);
|
|
965
|
+
const normalizedErrorCode = normalizeTelemetryErrorCode(outcome.error_code);
|
|
966
|
+
const normalizedErrorCategory = normalizeTelemetryErrorCategory({
|
|
967
|
+
ok: outcome.ok,
|
|
968
|
+
errorCode: normalizedErrorCode,
|
|
969
|
+
errorCategory: outcome.error_category
|
|
970
|
+
});
|
|
971
|
+
const attributes = [
|
|
972
|
+
otlpStringAttribute("pm.command", sanitizeString(activeCommand.command)),
|
|
973
|
+
otlpStringAttribute("pm.version", activeCommand.pm_version),
|
|
974
|
+
otlpStringAttribute("pm.source_context", activeCommand.source_context),
|
|
975
|
+
otlpStringAttribute("pm.source_context_source", activeCommand.source_context_source),
|
|
976
|
+
otlpStringAttribute("pm.installation_id", activeCommand.installation_id),
|
|
977
|
+
otlpStringAttribute("pm.session_id", PROCESS_SESSION_ID),
|
|
978
|
+
otlpStringAttribute("pm.pm_root_hash", activeCommand.pm_root_hash),
|
|
979
|
+
otlpStringAttribute("pm.cwd_hash", activeCommand.cwd_hash),
|
|
980
|
+
otlpBoolAttribute("pm.ok", outcome.ok),
|
|
981
|
+
otlpIntAttribute("pm.exit_code", normalizedExitCode),
|
|
982
|
+
otlpIntAttribute("pm.duration_ms", durationMs)
|
|
983
|
+
];
|
|
984
|
+
if (typeof normalizedErrorCode === "string") {
|
|
985
|
+
attributes.push(otlpStringAttribute("pm.error_code", normalizedErrorCode));
|
|
986
|
+
}
|
|
987
|
+
if (typeof normalizedErrorCategory === "string") {
|
|
988
|
+
attributes.push(otlpStringAttribute("pm.error_category", normalizedErrorCategory));
|
|
989
|
+
}
|
|
990
|
+
if (typeof outcome.error === "string" && outcome.error.trim().length > 0) {
|
|
991
|
+
attributes.push(otlpStringAttribute("pm.error", sanitizeString(outcome.error)));
|
|
992
|
+
}
|
|
993
|
+
const payload = {
|
|
994
|
+
resourceSpans: [
|
|
995
|
+
{
|
|
996
|
+
resource: {
|
|
997
|
+
attributes: [otlpStringAttribute("service.name", serviceName)]
|
|
998
|
+
},
|
|
999
|
+
scopeSpans: [
|
|
1000
|
+
{
|
|
1001
|
+
scope: {
|
|
1002
|
+
name: "pm-cli.telemetry",
|
|
1003
|
+
version: "1"
|
|
1004
|
+
},
|
|
1005
|
+
spans: [
|
|
1006
|
+
{
|
|
1007
|
+
traceId: activeCommand.otel_trace_id,
|
|
1008
|
+
spanId: activeCommand.otel_span_id,
|
|
1009
|
+
name: `pm.command.${sanitizeString(activeCommand.command)}`,
|
|
1010
|
+
kind: 1,
|
|
1011
|
+
startTimeUnixNano: isoToUnixNano(activeCommand.started_at),
|
|
1012
|
+
endTimeUnixNano: isoToUnixNano(finishedAtIso),
|
|
1013
|
+
attributes,
|
|
1014
|
+
status: {
|
|
1015
|
+
code: outcome.ok ? 1 : 2,
|
|
1016
|
+
message: outcome.ok ? "" : sanitizeString(typeof outcome.error === "string" ? outcome.error : "command_failed")
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
]
|
|
1020
|
+
}
|
|
1021
|
+
]
|
|
1022
|
+
}
|
|
1023
|
+
]
|
|
1024
|
+
};
|
|
1025
|
+
return { endpoint: activeCommand.otel_traces_endpoint, payload };
|
|
1026
|
+
}
|
|
1027
|
+
function summarizeResult(result, captureLevel = "redacted") {
|
|
1028
|
+
if (result === null || result === void 0) {
|
|
1029
|
+
return { type: "nullish" };
|
|
1030
|
+
}
|
|
1031
|
+
if (typeof result === "string") {
|
|
1032
|
+
return { type: "string", value: sanitizeString(result, captureLevel) };
|
|
1033
|
+
}
|
|
1034
|
+
if (typeof result === "number" || typeof result === "boolean") {
|
|
1035
|
+
return { type: typeof result, value: result };
|
|
1036
|
+
}
|
|
1037
|
+
if (Array.isArray(result)) {
|
|
1038
|
+
return {
|
|
1039
|
+
type: "array",
|
|
1040
|
+
length: result.length,
|
|
1041
|
+
sample: result.slice(0, 5).map((entry) => sanitizeValue(entry, void 0, captureLevel))
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
if (typeof result === "object") {
|
|
1045
|
+
const record = result;
|
|
1046
|
+
const keys = Object.keys(record).sort((left, right) => left.localeCompare(right));
|
|
1047
|
+
const sanitized = {};
|
|
1048
|
+
let previewBytes = 0;
|
|
1049
|
+
for (const key of keys.slice(0, 25)) {
|
|
1050
|
+
const sanitizedValue = sanitizeValue(record[key], key, captureLevel);
|
|
1051
|
+
const entrySize = JSON.stringify(sanitizedValue).length;
|
|
1052
|
+
if (previewBytes + entrySize > TELEMETRY_RESULT_PREVIEW_MAX_BYTES) {
|
|
1053
|
+
sanitized[key] = "[preview_truncated]";
|
|
1054
|
+
break;
|
|
1055
|
+
}
|
|
1056
|
+
previewBytes += entrySize;
|
|
1057
|
+
sanitized[key] = sanitizedValue;
|
|
1058
|
+
}
|
|
1059
|
+
return {
|
|
1060
|
+
type: "object",
|
|
1061
|
+
key_count: keys.length,
|
|
1062
|
+
keys_preview: keys.slice(0, 50),
|
|
1063
|
+
preview: sanitized
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
return { type: typeof result, value: String(result) };
|
|
1067
|
+
}
|
|
1068
|
+
function buildCommandStartPayload(params) {
|
|
1069
|
+
const { captureLevel, context, pmVersion, sourceContext, pmRootHash, cwdHash, installationId } = params;
|
|
1070
|
+
const commandTaxonomy = deriveTelemetryCommandTaxonomy(context.command);
|
|
1071
|
+
const hashedArgs = hashCommandArgs(installationId, context.args);
|
|
1072
|
+
const commandInvocationDigest = hashWithInstallationId(installationId, `${context.command}\0${context.args.join("\0")}`);
|
|
1073
|
+
const commandOptionsDigest = hashTelemetryValue(installationId, context.options);
|
|
1074
|
+
const globalOptionsDigest = hashTelemetryValue(installationId, context.global);
|
|
1075
|
+
const authorContextFields = buildAuthorContextPayloadFields(captureLevel, installationId);
|
|
1076
|
+
if (captureLevel === "minimal") {
|
|
1077
|
+
return {
|
|
1078
|
+
capture_level: captureLevel,
|
|
1079
|
+
pm_version: pmVersion,
|
|
1080
|
+
source_context: sourceContext.source_context,
|
|
1081
|
+
source_context_source: sourceContext.source_context_source,
|
|
1082
|
+
command_taxonomy: commandTaxonomy,
|
|
1083
|
+
command_args_digest: hashedArgs.digest,
|
|
1084
|
+
command_invocation_digest: commandInvocationDigest,
|
|
1085
|
+
command_options_digest: commandOptionsDigest,
|
|
1086
|
+
global_options_digest: globalOptionsDigest,
|
|
1087
|
+
...authorContextFields
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
return {
|
|
1091
|
+
pm_version: pmVersion,
|
|
1092
|
+
source_context: sourceContext.source_context,
|
|
1093
|
+
source_context_source: sourceContext.source_context_source,
|
|
1094
|
+
command_taxonomy: commandTaxonomy,
|
|
1095
|
+
...authorContextFields,
|
|
1096
|
+
command_args: sanitizeCommandArgs(context.args, captureLevel),
|
|
1097
|
+
command_args_hashes: hashedArgs.hashes,
|
|
1098
|
+
command_args_digest: hashedArgs.digest,
|
|
1099
|
+
command_invocation_digest: commandInvocationDigest,
|
|
1100
|
+
command_options: sanitizeValue(context.options, void 0, captureLevel),
|
|
1101
|
+
command_options_digest: commandOptionsDigest,
|
|
1102
|
+
global_options: sanitizeValue(context.global, void 0, captureLevel),
|
|
1103
|
+
global_options_digest: globalOptionsDigest,
|
|
1104
|
+
pm_root_hash: pmRootHash,
|
|
1105
|
+
cwd_hash: cwdHash,
|
|
1106
|
+
capture_level: captureLevel,
|
|
1107
|
+
runtime: {
|
|
1108
|
+
node: process.version,
|
|
1109
|
+
platform: process.platform,
|
|
1110
|
+
arch: process.arch,
|
|
1111
|
+
hostname_hash: hashWithInstallationId(installationId, os.hostname()),
|
|
1112
|
+
stdin_tty: process.stdin.isTTY === true,
|
|
1113
|
+
stdout_tty: process.stdout.isTTY === true
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
function buildCommandFinishPayload(params) {
|
|
1118
|
+
const { captureLevel, pmVersion, sourceContext, outcome, durationMs, startedAt, command, installationId, commandTaxonomy, exitCode, errorCode: errorCode2, errorCategory, commandResolution, resolutionStage } = params;
|
|
1119
|
+
const errorFingerprint = outcome.ok === false ? hashTelemetryErrorFingerprint(installationId, command, errorCode2, outcome.error) : void 0;
|
|
1120
|
+
const authorContextFields = buildAuthorContextPayloadFields(captureLevel, installationId);
|
|
1121
|
+
if (captureLevel === "minimal") {
|
|
1122
|
+
return {
|
|
1123
|
+
capture_level: captureLevel,
|
|
1124
|
+
pm_version: pmVersion,
|
|
1125
|
+
source_context: sourceContext.source_context,
|
|
1126
|
+
source_context_source: sourceContext.source_context_source,
|
|
1127
|
+
command_taxonomy: commandTaxonomy,
|
|
1128
|
+
command_resolution: commandResolution,
|
|
1129
|
+
resolution_stage: resolutionStage,
|
|
1130
|
+
ok: outcome.ok,
|
|
1131
|
+
exit_code: exitCode,
|
|
1132
|
+
error_code: errorCode2,
|
|
1133
|
+
error_category: errorCategory,
|
|
1134
|
+
error: outcome.error ? sanitizeString(outcome.error, "redacted") : void 0,
|
|
1135
|
+
error_fingerprint: errorFingerprint,
|
|
1136
|
+
duration_ms: durationMs,
|
|
1137
|
+
...authorContextFields
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
return {
|
|
1141
|
+
capture_level: captureLevel,
|
|
1142
|
+
pm_version: pmVersion,
|
|
1143
|
+
source_context: sourceContext.source_context,
|
|
1144
|
+
source_context_source: sourceContext.source_context_source,
|
|
1145
|
+
command_taxonomy: commandTaxonomy,
|
|
1146
|
+
command_resolution: commandResolution,
|
|
1147
|
+
resolution_stage: resolutionStage,
|
|
1148
|
+
...authorContextFields,
|
|
1149
|
+
ok: outcome.ok,
|
|
1150
|
+
exit_code: exitCode,
|
|
1151
|
+
error_code: errorCode2,
|
|
1152
|
+
error_category: errorCategory,
|
|
1153
|
+
error: outcome.error ? sanitizeString(outcome.error, captureLevel) : void 0,
|
|
1154
|
+
error_fingerprint: errorFingerprint,
|
|
1155
|
+
duration_ms: durationMs,
|
|
1156
|
+
started_at: startedAt,
|
|
1157
|
+
result_summary: summarizeResult(outcome.result, captureLevel)
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
function buildCommandErrorPayload(params) {
|
|
1161
|
+
const { captureLevel, pmVersion, sourceContext, command, commandTaxonomy, commandResolution, resolutionStage, args, options, pmRootHash, cwdHash, installationId, errorCode: errorCode2, errorMessage, errorCategory, exitCode } = params;
|
|
1162
|
+
const attemptedArgHashes = hashCommandArgs(installationId, args);
|
|
1163
|
+
const attemptedCommandDigest = hashWithInstallationId(installationId, command);
|
|
1164
|
+
const attemptedOptionsDigest = hashTelemetryValue(installationId, options);
|
|
1165
|
+
const errorFingerprint = hashTelemetryErrorFingerprint(installationId, command, errorCode2, errorMessage);
|
|
1166
|
+
if (captureLevel === "minimal") {
|
|
1167
|
+
return {
|
|
1168
|
+
capture_level: captureLevel,
|
|
1169
|
+
pm_version: pmVersion,
|
|
1170
|
+
source_context: sourceContext.source_context,
|
|
1171
|
+
source_context_source: sourceContext.source_context_source,
|
|
1172
|
+
command_taxonomy: commandTaxonomy,
|
|
1173
|
+
command_resolution: commandResolution,
|
|
1174
|
+
resolution_stage: resolutionStage,
|
|
1175
|
+
attempted_command_digest: attemptedCommandDigest,
|
|
1176
|
+
attempted_args_digest: attemptedArgHashes.digest,
|
|
1177
|
+
attempted_options_digest: attemptedOptionsDigest,
|
|
1178
|
+
error_code: errorCode2,
|
|
1179
|
+
error_category: errorCategory,
|
|
1180
|
+
exit_code: exitCode,
|
|
1181
|
+
error: sanitizeString(errorMessage, "redacted"),
|
|
1182
|
+
error_fingerprint: errorFingerprint
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
return {
|
|
1186
|
+
capture_level: captureLevel,
|
|
1187
|
+
pm_version: pmVersion,
|
|
1188
|
+
source_context: sourceContext.source_context,
|
|
1189
|
+
source_context_source: sourceContext.source_context_source,
|
|
1190
|
+
command_taxonomy: commandTaxonomy,
|
|
1191
|
+
command_resolution: commandResolution,
|
|
1192
|
+
resolution_stage: resolutionStage,
|
|
1193
|
+
attempted_command: sanitizeString(command, captureLevel),
|
|
1194
|
+
attempted_command_digest: attemptedCommandDigest,
|
|
1195
|
+
attempted_args: sanitizeCommandArgs(args, captureLevel),
|
|
1196
|
+
attempted_args_hashes: attemptedArgHashes.hashes,
|
|
1197
|
+
attempted_args_digest: attemptedArgHashes.digest,
|
|
1198
|
+
attempted_options: sanitizeValue(options, void 0, captureLevel),
|
|
1199
|
+
attempted_options_digest: attemptedOptionsDigest,
|
|
1200
|
+
error_code: errorCode2,
|
|
1201
|
+
error_category: errorCategory,
|
|
1202
|
+
exit_code: exitCode,
|
|
1203
|
+
error: sanitizeString(errorMessage, captureLevel),
|
|
1204
|
+
error_fingerprint: errorFingerprint,
|
|
1205
|
+
pm_root_hash: pmRootHash,
|
|
1206
|
+
cwd_hash: cwdHash,
|
|
1207
|
+
runtime: {
|
|
1208
|
+
node: process.version,
|
|
1209
|
+
platform: process.platform,
|
|
1210
|
+
arch: process.arch,
|
|
1211
|
+
hostname_hash: hashWithInstallationId(installationId, os.hostname()),
|
|
1212
|
+
stdin_tty: process.stdin.isTTY === true,
|
|
1213
|
+
stdout_tty: process.stdout.isTTY === true
|
|
1214
|
+
}
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
async function ensureInstallationId(globalPmRoot) {
|
|
1218
|
+
const settings = await readSettings(globalPmRoot);
|
|
1219
|
+
let changed = false;
|
|
1220
|
+
if (settings.telemetry.installation_id.trim().length === 0) {
|
|
1221
|
+
settings.telemetry.installation_id = crypto.randomUUID();
|
|
1222
|
+
changed = true;
|
|
1223
|
+
}
|
|
1224
|
+
if (changed) {
|
|
1225
|
+
await writeSettings(globalPmRoot, settings, "telemetry:install_id");
|
|
1226
|
+
}
|
|
1227
|
+
return {
|
|
1228
|
+
installationId: settings.telemetry.installation_id,
|
|
1229
|
+
endpoint: settings.telemetry.endpoint,
|
|
1230
|
+
retentionDays: Math.max(1, Math.trunc(settings.telemetry.retention_days))
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
async function enqueueTelemetryEvent(globalPmRoot, event) {
|
|
1234
|
+
const queued = {
|
|
1235
|
+
client_schema_version: TELEMETRY_CLIENT_SCHEMA_VERSION,
|
|
1236
|
+
event,
|
|
1237
|
+
attempts: 0
|
|
1238
|
+
};
|
|
1239
|
+
let serialized = JSON.stringify(queued);
|
|
1240
|
+
if (serialized.length > TELEMETRY_MAX_EVENT_BYTES) {
|
|
1241
|
+
const trimmed = {
|
|
1242
|
+
...event,
|
|
1243
|
+
payload: {
|
|
1244
|
+
...event.payload,
|
|
1245
|
+
result_summary: {
|
|
1246
|
+
truncated: true,
|
|
1247
|
+
reason: "payload_size_exceeded",
|
|
1248
|
+
original_bytes: serialized.length
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
};
|
|
1252
|
+
const trimmedQueued = {
|
|
1253
|
+
client_schema_version: TELEMETRY_CLIENT_SCHEMA_VERSION,
|
|
1254
|
+
event: trimmed,
|
|
1255
|
+
attempts: 0
|
|
1256
|
+
};
|
|
1257
|
+
serialized = JSON.stringify(trimmedQueued);
|
|
1258
|
+
}
|
|
1259
|
+
await withQueueMutation(async () => {
|
|
1260
|
+
await appendLineAtomic(queuePath(globalPmRoot), serialized);
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
function parseQueueLines(raw) {
|
|
1264
|
+
const entries = [];
|
|
1265
|
+
for (const line of raw.split("\n")) {
|
|
1266
|
+
const trimmed = line.trim();
|
|
1267
|
+
if (trimmed.length === 0) {
|
|
1268
|
+
continue;
|
|
1269
|
+
}
|
|
1270
|
+
try {
|
|
1271
|
+
const parsed = JSON.parse(trimmed);
|
|
1272
|
+
if (parsed && typeof parsed === "object" && parsed.event && typeof parsed.event === "object" && typeof parsed.attempts === "number" && (parsed.client_schema_version === void 0 || typeof parsed.client_schema_version === "number" && Number.isFinite(parsed.client_schema_version))) {
|
|
1273
|
+
entries.push(parsed);
|
|
1274
|
+
}
|
|
1275
|
+
} catch {
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
return entries;
|
|
1279
|
+
}
|
|
1280
|
+
function nextRetryIso(attempts) {
|
|
1281
|
+
const delay = Math.min(TELEMETRY_RETRY_BASE_DELAY_MS * 2 ** Math.max(attempts - 1, 0), TELEMETRY_MAX_RETRY_DELAY_MS);
|
|
1282
|
+
return new Date(Date.now() + delay).toISOString();
|
|
1283
|
+
}
|
|
1284
|
+
function isDueForRetryAt(nextAttemptAfter) {
|
|
1285
|
+
if (typeof nextAttemptAfter !== "string" || nextAttemptAfter.trim().length === 0) {
|
|
1286
|
+
return true;
|
|
1287
|
+
}
|
|
1288
|
+
const dueAtMs = Date.parse(nextAttemptAfter);
|
|
1289
|
+
if (Number.isNaN(dueAtMs)) {
|
|
1290
|
+
return true;
|
|
1291
|
+
}
|
|
1292
|
+
return dueAtMs <= Date.now();
|
|
1293
|
+
}
|
|
1294
|
+
function isDueForRetry(entry) {
|
|
1295
|
+
return isDueForRetryAt(entry.next_attempt_after);
|
|
1296
|
+
}
|
|
1297
|
+
function retentionCutoffMs(retentionDays) {
|
|
1298
|
+
const normalizedDays = Number.isFinite(retentionDays) ? Math.max(1, Math.trunc(retentionDays)) : 1;
|
|
1299
|
+
return Date.now() - normalizedDays * MILLISECONDS_PER_DAY;
|
|
1300
|
+
}
|
|
1301
|
+
function isExpiredQueueEntry(entry, cutoffMs) {
|
|
1302
|
+
const occurredAt = entry.event?.occurred_at;
|
|
1303
|
+
if (typeof occurredAt !== "string" || occurredAt.trim().length === 0) {
|
|
1304
|
+
return false;
|
|
1305
|
+
}
|
|
1306
|
+
const occurredAtMs = Date.parse(occurredAt);
|
|
1307
|
+
if (Number.isNaN(occurredAtMs)) {
|
|
1308
|
+
return false;
|
|
1309
|
+
}
|
|
1310
|
+
return occurredAtMs < cutoffMs;
|
|
1311
|
+
}
|
|
1312
|
+
function pruneExpiredQueueEntries(entries, retentionDays) {
|
|
1313
|
+
const cutoffMs = retentionCutoffMs(retentionDays);
|
|
1314
|
+
const retained = [];
|
|
1315
|
+
let prunedCount = 0;
|
|
1316
|
+
for (const entry of entries) {
|
|
1317
|
+
const serializedSize = JSON.stringify(entry).length;
|
|
1318
|
+
const oversized = serializedSize > TELEMETRY_MAX_EVENT_BYTES;
|
|
1319
|
+
if (oversized || isExpiredQueueEntry(entry, cutoffMs) || entry.attempts >= TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS) {
|
|
1320
|
+
prunedCount += 1;
|
|
1321
|
+
continue;
|
|
1322
|
+
}
|
|
1323
|
+
retained.push(entry);
|
|
1324
|
+
}
|
|
1325
|
+
return { entries: retained, prunedCount };
|
|
1326
|
+
}
|
|
1327
|
+
async function rewriteQueue(globalPmRoot, entries) {
|
|
1328
|
+
const serialized = entries.map((entry) => JSON.stringify(entry)).join("\n");
|
|
1329
|
+
const contents = serialized.length > 0 ? `${serialized}
|
|
1330
|
+
` : "";
|
|
1331
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
1332
|
+
try {
|
|
1333
|
+
await writeFileAtomic(queuePath(globalPmRoot), contents);
|
|
1334
|
+
return;
|
|
1335
|
+
} catch (error) {
|
|
1336
|
+
const retryDelay = TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS[attempt];
|
|
1337
|
+
if (retryDelay === void 0 || !isRetryableQueueRewriteError(error)) {
|
|
1338
|
+
throw error;
|
|
1339
|
+
}
|
|
1340
|
+
await sleep(retryDelay);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
function isRetryableQueueRewriteError(error) {
|
|
1345
|
+
if (typeof error !== "object" || error === null || !("code" in error)) {
|
|
1346
|
+
return false;
|
|
1347
|
+
}
|
|
1348
|
+
const code = error.code;
|
|
1349
|
+
return code === "EACCES" || code === "EBUSY" || code === "EPERM";
|
|
1350
|
+
}
|
|
1351
|
+
function sleep(milliseconds) {
|
|
1352
|
+
return new Promise((resolve) => {
|
|
1353
|
+
setTimeout(resolve, milliseconds);
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
async function enqueuePendingOtelSpan(globalPmRoot, request) {
|
|
1357
|
+
const pending = {
|
|
1358
|
+
id: crypto.randomUUID(),
|
|
1359
|
+
endpoint: request.endpoint,
|
|
1360
|
+
payload: request.payload,
|
|
1361
|
+
enqueued_at: nowIso(),
|
|
1362
|
+
attempts: 0
|
|
1363
|
+
};
|
|
1364
|
+
const serialized = JSON.stringify(pending);
|
|
1365
|
+
if (serialized.length > TELEMETRY_MAX_EVENT_BYTES) {
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
await withQueueMutation(async () => {
|
|
1369
|
+
await appendLineAtomic(otelSpansQueuePath(globalPmRoot), serialized);
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
function backfillPendingOtelSpanId(entry) {
|
|
1373
|
+
const material = JSON.stringify([
|
|
1374
|
+
entry.endpoint,
|
|
1375
|
+
entry.enqueued_at,
|
|
1376
|
+
entry.payload
|
|
1377
|
+
]);
|
|
1378
|
+
return crypto.createHash("sha256").update(material).digest("hex").slice(0, 32);
|
|
1379
|
+
}
|
|
1380
|
+
function parsePendingOtelSpanLines(raw) {
|
|
1381
|
+
const entries = [];
|
|
1382
|
+
for (const line of raw.split("\n")) {
|
|
1383
|
+
const trimmed = line.trim();
|
|
1384
|
+
if (trimmed.length === 0) {
|
|
1385
|
+
continue;
|
|
1386
|
+
}
|
|
1387
|
+
try {
|
|
1388
|
+
const parsed = JSON.parse(trimmed);
|
|
1389
|
+
if (parsed && typeof parsed === "object" && typeof parsed.endpoint === "string" && parsed.endpoint.trim().length > 0 && "payload" in parsed && typeof parsed.attempts === "number" && Number.isFinite(parsed.attempts)) {
|
|
1390
|
+
if (typeof parsed.id !== "string" || parsed.id.length === 0) {
|
|
1391
|
+
parsed.id = backfillPendingOtelSpanId(parsed);
|
|
1392
|
+
}
|
|
1393
|
+
entries.push(parsed);
|
|
1394
|
+
}
|
|
1395
|
+
} catch {
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
return entries;
|
|
1399
|
+
}
|
|
1400
|
+
function isExpiredPendingOtelSpan(entry, cutoffMs) {
|
|
1401
|
+
if (typeof entry.enqueued_at !== "string" || entry.enqueued_at.trim().length === 0) {
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
const enqueuedAtMs = Date.parse(entry.enqueued_at);
|
|
1405
|
+
if (Number.isNaN(enqueuedAtMs)) {
|
|
1406
|
+
return false;
|
|
1407
|
+
}
|
|
1408
|
+
return enqueuedAtMs < cutoffMs;
|
|
1409
|
+
}
|
|
1410
|
+
function prunePendingOtelSpans(entries, retentionDays) {
|
|
1411
|
+
const cutoffMs = retentionCutoffMs(retentionDays);
|
|
1412
|
+
const retained = [];
|
|
1413
|
+
let prunedCount = 0;
|
|
1414
|
+
for (const entry of entries) {
|
|
1415
|
+
const oversized = JSON.stringify(entry).length > TELEMETRY_MAX_EVENT_BYTES;
|
|
1416
|
+
if (oversized || isExpiredPendingOtelSpan(entry, cutoffMs) || entry.attempts >= TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS) {
|
|
1417
|
+
prunedCount += 1;
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1420
|
+
retained.push(entry);
|
|
1421
|
+
}
|
|
1422
|
+
if (retained.length > TELEMETRY_OTEL_SPANS_MAX_PENDING) {
|
|
1423
|
+
const overflow = retained.length - TELEMETRY_OTEL_SPANS_MAX_PENDING;
|
|
1424
|
+
prunedCount += overflow;
|
|
1425
|
+
return { entries: retained.slice(overflow), prunedCount };
|
|
1426
|
+
}
|
|
1427
|
+
return { entries: retained, prunedCount };
|
|
1428
|
+
}
|
|
1429
|
+
async function rewritePendingOtelSpans(globalPmRoot, entries) {
|
|
1430
|
+
const serialized = entries.map((entry) => JSON.stringify(entry)).join("\n");
|
|
1431
|
+
const contents = serialized.length > 0 ? `${serialized}
|
|
1432
|
+
` : "";
|
|
1433
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
1434
|
+
try {
|
|
1435
|
+
await writeFileAtomic(otelSpansQueuePath(globalPmRoot), contents);
|
|
1436
|
+
return;
|
|
1437
|
+
} catch (error) {
|
|
1438
|
+
const retryDelay = TELEMETRY_QUEUE_REWRITE_RETRY_DELAYS_MS[attempt];
|
|
1439
|
+
if (retryDelay === void 0 || !isRetryableQueueRewriteError(error)) {
|
|
1440
|
+
throw error;
|
|
1441
|
+
}
|
|
1442
|
+
await sleep(retryDelay);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
async function reconcilePendingOtelSpansAfterFlush(globalPmRoot, retentionDays, succeededIds, failedUpdates) {
|
|
1447
|
+
return withQueueMutation(async () => {
|
|
1448
|
+
const raw = await readFileIfExists(otelSpansQueuePath(globalPmRoot));
|
|
1449
|
+
const current = raw === null ? [] : parsePendingOtelSpanLines(raw);
|
|
1450
|
+
const reconciled = [];
|
|
1451
|
+
for (const entry of current) {
|
|
1452
|
+
if (succeededIds.has(entry.id)) {
|
|
1453
|
+
continue;
|
|
1454
|
+
}
|
|
1455
|
+
const failure = failedUpdates.get(entry.id);
|
|
1456
|
+
reconciled.push(failure ? {
|
|
1457
|
+
...entry,
|
|
1458
|
+
attempts: failure.attempts,
|
|
1459
|
+
next_attempt_after: failure.next_attempt_after
|
|
1460
|
+
} : entry);
|
|
1461
|
+
}
|
|
1462
|
+
const { entries: retained } = prunePendingOtelSpans(reconciled, retentionDays);
|
|
1463
|
+
await rewritePendingOtelSpans(globalPmRoot, retained);
|
|
1464
|
+
return retained.length;
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
async function flushPendingOtelSpans(globalPmRoot, retentionDays) {
|
|
1468
|
+
const raw = await readFileIfExists(otelSpansQueuePath(globalPmRoot));
|
|
1469
|
+
if (raw === null || raw.trim().length === 0) {
|
|
1470
|
+
await writeRuntimeState(globalPmRoot, { pending_otel_spans: 0 });
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
const entries = parsePendingOtelSpanLines(raw);
|
|
1474
|
+
const { entries: retained, prunedCount } = prunePendingOtelSpans(entries, retentionDays);
|
|
1475
|
+
const due = retained.filter((entry) => isDueForRetryAt(entry.next_attempt_after)).slice(0, TELEMETRY_OTEL_SPANS_FLUSH_BATCH_SIZE);
|
|
1476
|
+
if (due.length === 0) {
|
|
1477
|
+
const remaining2 = prunedCount > 0 ? await reconcilePendingOtelSpansAfterFlush(globalPmRoot, retentionDays, /* @__PURE__ */ new Set(), /* @__PURE__ */ new Map()) : retained.length;
|
|
1478
|
+
await writeRuntimeState(globalPmRoot, { pending_otel_spans: remaining2 });
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1481
|
+
const attemptTime = nowIso();
|
|
1482
|
+
const succeededIds = /* @__PURE__ */ new Set();
|
|
1483
|
+
const failedUpdates = /* @__PURE__ */ new Map();
|
|
1484
|
+
let succeededCount = 0;
|
|
1485
|
+
let lastError;
|
|
1486
|
+
await Promise.all(due.map(async (span) => {
|
|
1487
|
+
try {
|
|
1488
|
+
const response = await fetch(span.endpoint, {
|
|
1489
|
+
method: "POST",
|
|
1490
|
+
headers: { "content-type": "application/json" },
|
|
1491
|
+
body: JSON.stringify(span.payload),
|
|
1492
|
+
signal: AbortSignal.timeout(TELEMETRY_HTTP_TIMEOUT_MS)
|
|
1493
|
+
});
|
|
1494
|
+
if (!response.ok) {
|
|
1495
|
+
throw new Error(`local_otel_export_http_${response.status}`);
|
|
1496
|
+
}
|
|
1497
|
+
succeededIds.add(span.id);
|
|
1498
|
+
succeededCount += 1;
|
|
1499
|
+
} catch (error) {
|
|
1500
|
+
lastError = error instanceof Error ? sanitizeString(error.message, "redacted") : "local_otel_export_failed";
|
|
1501
|
+
const nextAttempts = span.attempts + 1;
|
|
1502
|
+
failedUpdates.set(span.id, {
|
|
1503
|
+
attempts: nextAttempts,
|
|
1504
|
+
next_attempt_after: nextRetryIso(nextAttempts)
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
}));
|
|
1508
|
+
const remaining = await reconcilePendingOtelSpansAfterFlush(globalPmRoot, retentionDays, succeededIds, failedUpdates);
|
|
1509
|
+
const statePatch = {
|
|
1510
|
+
pending_otel_spans: remaining,
|
|
1511
|
+
last_otel_attempt_at: attemptTime
|
|
1512
|
+
};
|
|
1513
|
+
if (succeededCount > 0) {
|
|
1514
|
+
statePatch.last_otel_success_at = attemptTime;
|
|
1515
|
+
}
|
|
1516
|
+
if (lastError !== void 0) {
|
|
1517
|
+
statePatch.last_otel_failure_at = attemptTime;
|
|
1518
|
+
statePatch.last_otel_failure_error = lastError;
|
|
1519
|
+
} else if (remaining === 0) {
|
|
1520
|
+
statePatch.last_otel_failure_at = void 0;
|
|
1521
|
+
statePatch.last_otel_failure_error = void 0;
|
|
1522
|
+
}
|
|
1523
|
+
await writeRuntimeState(globalPmRoot, statePatch);
|
|
1524
|
+
}
|
|
1525
|
+
async function flushTelemetryArtifacts(globalPmRoot, endpoint, retentionDays) {
|
|
1526
|
+
try {
|
|
1527
|
+
await flushQueue(globalPmRoot, endpoint, retentionDays);
|
|
1528
|
+
} catch {
|
|
1529
|
+
}
|
|
1530
|
+
try {
|
|
1531
|
+
await flushPendingOtelSpans(globalPmRoot, retentionDays);
|
|
1532
|
+
} catch {
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
async function cleanupTelemetryQueueTempOrphans(globalPmRoot, maxAgeMs = TELEMETRY_QUEUE_TMP_ORPHAN_MAX_AGE_MS) {
|
|
1536
|
+
try {
|
|
1537
|
+
const dirPath = telemetryRuntimeDirectory(globalPmRoot);
|
|
1538
|
+
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
1539
|
+
const cutoffMs = Date.now() - Math.max(0, maxAgeMs);
|
|
1540
|
+
await Promise.all(entries.filter((entry) => entry.isFile() && /^\.events\.jsonl\.\d+\.\d+\.[a-f0-9]+\.tmp$/.test(entry.name)).map(async (entry) => {
|
|
1541
|
+
const candidate = path.join(dirPath, entry.name);
|
|
1542
|
+
const candidateStats = await stat(candidate);
|
|
1543
|
+
if (candidateStats.mtimeMs < cutoffMs) {
|
|
1544
|
+
await rm(candidate, { force: true });
|
|
1545
|
+
}
|
|
1546
|
+
}));
|
|
1547
|
+
} catch {
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
async function withQueueMutation(operation) {
|
|
1551
|
+
const run = _queueMutationPromise.catch(
|
|
1552
|
+
/* c8 ignore next */
|
|
1553
|
+
() => {
|
|
1554
|
+
}
|
|
1555
|
+
).then(operation);
|
|
1556
|
+
_queueMutationPromise = run.catch(
|
|
1557
|
+
/* c8 ignore next */
|
|
1558
|
+
() => {
|
|
1559
|
+
}
|
|
1560
|
+
);
|
|
1561
|
+
return run;
|
|
1562
|
+
}
|
|
1563
|
+
async function readCurrentQueueEntries(globalPmRoot) {
|
|
1564
|
+
const raw = await readFileIfExists(queuePath(globalPmRoot));
|
|
1565
|
+
if (raw === null || raw.trim().length === 0) {
|
|
1566
|
+
return [];
|
|
1567
|
+
}
|
|
1568
|
+
return parseQueueLines(raw);
|
|
1569
|
+
}
|
|
1570
|
+
async function removeFlushedEntriesFromCurrentQueue(globalPmRoot, flushedIds, retentionDays) {
|
|
1571
|
+
return withQueueMutation(async () => {
|
|
1572
|
+
const currentEntries = await readCurrentQueueEntries(globalPmRoot);
|
|
1573
|
+
const { entries: retainedEntries } = pruneExpiredQueueEntries(currentEntries, retentionDays);
|
|
1574
|
+
const remaining = retainedEntries.filter((entry) => !flushedIds.has(entry.event.event_id));
|
|
1575
|
+
await rewriteQueue(globalPmRoot, remaining);
|
|
1576
|
+
return remaining;
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
async function markFailedEntriesInCurrentQueue(globalPmRoot, failedIds, attemptTime, retentionDays) {
|
|
1580
|
+
return withQueueMutation(async () => {
|
|
1581
|
+
const currentEntries = await readCurrentQueueEntries(globalPmRoot);
|
|
1582
|
+
const { entries: retainedEntries } = pruneExpiredQueueEntries(currentEntries, retentionDays);
|
|
1583
|
+
const retried = retainedEntries.map((entry) => {
|
|
1584
|
+
if (!failedIds.has(entry.event.event_id)) {
|
|
1585
|
+
return entry;
|
|
1586
|
+
}
|
|
1587
|
+
const attempts = entry.attempts + 1;
|
|
1588
|
+
return {
|
|
1589
|
+
...entry,
|
|
1590
|
+
attempts,
|
|
1591
|
+
last_attempt_at: attemptTime,
|
|
1592
|
+
next_attempt_after: nextRetryIso(attempts)
|
|
1593
|
+
};
|
|
1594
|
+
});
|
|
1595
|
+
await rewriteQueue(globalPmRoot, retried);
|
|
1596
|
+
return retried;
|
|
1597
|
+
});
|
|
1598
|
+
}
|
|
1599
|
+
async function flushQueue(globalPmRoot, endpoint, retentionDays) {
|
|
1600
|
+
await cleanupTelemetryQueueTempOrphans(globalPmRoot);
|
|
1601
|
+
const normalizedEndpoint = endpoint.trim();
|
|
1602
|
+
if (normalizedEndpoint.length === 0) {
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
const raw = await readFileIfExists(queuePath(globalPmRoot));
|
|
1606
|
+
if (raw === null || raw.trim().length === 0) {
|
|
1607
|
+
await writeRuntimeState(globalPmRoot, {
|
|
1608
|
+
endpoint: normalizedEndpoint,
|
|
1609
|
+
queue_entries: 0
|
|
1610
|
+
});
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
const queueEntries = parseQueueLines(raw);
|
|
1614
|
+
if (queueEntries.length === 0) {
|
|
1615
|
+
await writeRuntimeState(globalPmRoot, {
|
|
1616
|
+
endpoint: normalizedEndpoint,
|
|
1617
|
+
queue_entries: 0
|
|
1618
|
+
});
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
const { entries: retainedEntries, prunedCount } = pruneExpiredQueueEntries(queueEntries, retentionDays);
|
|
1622
|
+
if (retainedEntries.length === 0) {
|
|
1623
|
+
await rewriteQueue(globalPmRoot, []);
|
|
1624
|
+
await writeRuntimeState(globalPmRoot, {
|
|
1625
|
+
endpoint: normalizedEndpoint,
|
|
1626
|
+
queue_entries: 0
|
|
1627
|
+
});
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
const dueEntries = retainedEntries.filter((entry) => isDueForRetry(entry)).slice(0, TELEMETRY_FLUSH_BATCH_SIZE);
|
|
1631
|
+
if (dueEntries.length === 0) {
|
|
1632
|
+
if (prunedCount > 0) {
|
|
1633
|
+
await rewriteQueue(globalPmRoot, retainedEntries);
|
|
1634
|
+
}
|
|
1635
|
+
await writeRuntimeState(globalPmRoot, {
|
|
1636
|
+
endpoint: normalizedEndpoint,
|
|
1637
|
+
queue_entries: retainedEntries.length
|
|
1638
|
+
});
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
const dueIds = new Set(dueEntries.map((entry) => entry.event.event_id));
|
|
1642
|
+
const attemptTime = nowIso();
|
|
1643
|
+
const requestHeaders = {
|
|
1644
|
+
"content-type": "application/json"
|
|
1645
|
+
};
|
|
1646
|
+
const ingestKey = process.env.PM_TELEMETRY_INGEST_KEY?.trim();
|
|
1647
|
+
if (ingestKey) {
|
|
1648
|
+
requestHeaders["x-pm-telemetry-key"] = ingestKey;
|
|
1649
|
+
}
|
|
1650
|
+
try {
|
|
1651
|
+
const response = await fetch(normalizedEndpoint, {
|
|
1652
|
+
method: "POST",
|
|
1653
|
+
headers: requestHeaders,
|
|
1654
|
+
body: JSON.stringify({
|
|
1655
|
+
schema_version: TELEMETRY_SCHEMA_VERSION,
|
|
1656
|
+
events: dueEntries.map((entry) => entry.event)
|
|
1657
|
+
}),
|
|
1658
|
+
signal: AbortSignal.timeout(TELEMETRY_HTTP_TIMEOUT_MS)
|
|
1659
|
+
});
|
|
1660
|
+
if (!response.ok) {
|
|
1661
|
+
throw new Error(`telemetry_flush_http_${response.status}`);
|
|
1662
|
+
}
|
|
1663
|
+
} catch (error) {
|
|
1664
|
+
const retried = await markFailedEntriesInCurrentQueue(globalPmRoot, dueIds, attemptTime, retentionDays);
|
|
1665
|
+
const errorMessage = (() => {
|
|
1666
|
+
if (error instanceof Error) {
|
|
1667
|
+
return sanitizeString(error.message, "redacted");
|
|
1668
|
+
}
|
|
1669
|
+
return "telemetry_flush_failed";
|
|
1670
|
+
})();
|
|
1671
|
+
await writeRuntimeState(globalPmRoot, {
|
|
1672
|
+
endpoint: normalizedEndpoint,
|
|
1673
|
+
queue_entries: retried.length,
|
|
1674
|
+
last_attempted_flush_at: attemptTime,
|
|
1675
|
+
last_failed_flush_at: attemptTime,
|
|
1676
|
+
last_failed_flush_error: errorMessage
|
|
1677
|
+
});
|
|
1678
|
+
return;
|
|
1679
|
+
}
|
|
1680
|
+
try {
|
|
1681
|
+
const remaining = await removeFlushedEntriesFromCurrentQueue(globalPmRoot, dueIds, retentionDays);
|
|
1682
|
+
await writeRuntimeState(globalPmRoot, {
|
|
1683
|
+
endpoint: normalizedEndpoint,
|
|
1684
|
+
queue_entries: remaining.length,
|
|
1685
|
+
last_attempted_flush_at: attemptTime,
|
|
1686
|
+
last_successful_flush_at: attemptTime,
|
|
1687
|
+
last_failed_flush_at: void 0,
|
|
1688
|
+
last_failed_flush_error: void 0
|
|
1689
|
+
});
|
|
1690
|
+
} catch (error) {
|
|
1691
|
+
const errorMessage = (() => {
|
|
1692
|
+
if (error instanceof Error) {
|
|
1693
|
+
return sanitizeString(error.message, "redacted");
|
|
1694
|
+
}
|
|
1695
|
+
return "telemetry_flush_failed";
|
|
1696
|
+
})();
|
|
1697
|
+
const currentEntries = await readCurrentQueueEntries(globalPmRoot).catch(() => retainedEntries);
|
|
1698
|
+
await writeRuntimeState(globalPmRoot, {
|
|
1699
|
+
endpoint: normalizedEndpoint,
|
|
1700
|
+
queue_entries: currentEntries.length,
|
|
1701
|
+
last_attempted_flush_at: attemptTime,
|
|
1702
|
+
last_failed_flush_at: attemptTime,
|
|
1703
|
+
last_failed_flush_error: errorMessage
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
async function acquireTelemetryFlushLock(globalPmRoot) {
|
|
1708
|
+
const lockPath = flushLockPath(globalPmRoot);
|
|
1709
|
+
await mkdir(path.dirname(lockPath), { recursive: true });
|
|
1710
|
+
try {
|
|
1711
|
+
await mkdir(lockPath);
|
|
1712
|
+
return true;
|
|
1713
|
+
} catch (error) {
|
|
1714
|
+
if (typeof error !== "object" || error === null || !("code" in error) || error.code !== "EEXIST") {
|
|
1715
|
+
throw error;
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
try {
|
|
1719
|
+
const lockStats = await stat(lockPath);
|
|
1720
|
+
if (Date.now() - lockStats.mtimeMs < TELEMETRY_FLUSH_LOCK_STALE_MS) {
|
|
1721
|
+
return false;
|
|
1722
|
+
}
|
|
1723
|
+
await rm(lockPath, { recursive: true, force: true });
|
|
1724
|
+
await mkdir(lockPath);
|
|
1725
|
+
return true;
|
|
1726
|
+
} catch {
|
|
1727
|
+
return false;
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
function isFreshDirectoryLock(lockPath, staleMs) {
|
|
1731
|
+
try {
|
|
1732
|
+
return Date.now() - statSync(lockPath).mtimeMs < staleMs;
|
|
1733
|
+
} catch {
|
|
1734
|
+
return false;
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
function removeDirectoryLockBestEffort(lockPath) {
|
|
1738
|
+
try {
|
|
1739
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
1740
|
+
} catch {
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
function errorCode(error) {
|
|
1744
|
+
if (typeof error !== "object" || error === null || !("code" in error)) {
|
|
1745
|
+
return void 0;
|
|
1746
|
+
}
|
|
1747
|
+
const code = error.code;
|
|
1748
|
+
return typeof code === "string" ? code : void 0;
|
|
1749
|
+
}
|
|
1750
|
+
function createDirectoryLock(lockPath) {
|
|
1751
|
+
try {
|
|
1752
|
+
mkdirSync(lockPath);
|
|
1753
|
+
return true;
|
|
1754
|
+
} catch (error) {
|
|
1755
|
+
const code = errorCode(error);
|
|
1756
|
+
if (code === "EEXIST") {
|
|
1757
|
+
return false;
|
|
1758
|
+
}
|
|
1759
|
+
if (code !== "ENOENT") {
|
|
1760
|
+
return false;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
try {
|
|
1764
|
+
mkdirSync(path.dirname(lockPath), { recursive: true });
|
|
1765
|
+
mkdirSync(lockPath);
|
|
1766
|
+
return true;
|
|
1767
|
+
} catch {
|
|
1768
|
+
return false;
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
function acquireTelemetryFlushSpawnGate(globalPmRoot) {
|
|
1772
|
+
if (isFreshDirectoryLock(flushLockPath(globalPmRoot), TELEMETRY_FLUSH_LOCK_STALE_MS)) {
|
|
1773
|
+
return false;
|
|
1774
|
+
}
|
|
1775
|
+
const lockPath = flushSpawnLockPath(globalPmRoot);
|
|
1776
|
+
try {
|
|
1777
|
+
if (Date.now() - statSync(lockPath).mtimeMs < TELEMETRY_FLUSH_SPAWN_LOCK_STALE_MS) {
|
|
1778
|
+
return false;
|
|
1779
|
+
}
|
|
1780
|
+
removeDirectoryLockBestEffort(lockPath);
|
|
1781
|
+
} catch (error) {
|
|
1782
|
+
if (errorCode(error) !== "ENOENT") {
|
|
1783
|
+
return false;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
return createDirectoryLock(lockPath);
|
|
1787
|
+
}
|
|
1788
|
+
function releaseTelemetryFlushSpawnGate(globalPmRoot) {
|
|
1789
|
+
removeDirectoryLockBestEffort(flushSpawnLockPath(globalPmRoot));
|
|
1790
|
+
}
|
|
1791
|
+
async function flushQueueWithProcessLock(globalPmRoot, endpoint, retentionDays) {
|
|
1792
|
+
const acquired = await acquireTelemetryFlushLock(globalPmRoot);
|
|
1793
|
+
releaseTelemetryFlushSpawnGate(globalPmRoot);
|
|
1794
|
+
if (!acquired) {
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1797
|
+
try {
|
|
1798
|
+
await flushTelemetryArtifacts(globalPmRoot, endpoint, retentionDays);
|
|
1799
|
+
} finally {
|
|
1800
|
+
try {
|
|
1801
|
+
await rm(flushLockPath(globalPmRoot), { recursive: true, force: true });
|
|
1802
|
+
} catch {
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
function scheduleTelemetryFlush(globalPmRoot, endpoint, retentionDays) {
|
|
1807
|
+
if (shouldFlushInline()) {
|
|
1808
|
+
const previousFlush = _lastFlushPromise;
|
|
1809
|
+
const nextFlush = flushTelemetryArtifacts(globalPmRoot, endpoint, retentionDays);
|
|
1810
|
+
_lastFlushPromise = Promise.allSettled([previousFlush, nextFlush]).then(() => {
|
|
1811
|
+
});
|
|
1812
|
+
return;
|
|
1813
|
+
}
|
|
1814
|
+
try {
|
|
1815
|
+
const acquiredSpawnGate = acquireTelemetryFlushSpawnGate(globalPmRoot);
|
|
1816
|
+
if (!acquiredSpawnGate) {
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
const child = spawn(process.execPath, [telemetryFlushRunnerPath()], {
|
|
1820
|
+
detached: true,
|
|
1821
|
+
stdio: "ignore",
|
|
1822
|
+
// Detached workers inherit cwd by default. On Windows that can keep a
|
|
1823
|
+
// disposable project directory locked after the foreground command exits.
|
|
1824
|
+
cwd: os.tmpdir(),
|
|
1825
|
+
env: {
|
|
1826
|
+
...process.env,
|
|
1827
|
+
PM_GLOBAL_PATH: globalPmRoot,
|
|
1828
|
+
[PM_TELEMETRY_FLUSH_CHILD_ENV]: "1"
|
|
1829
|
+
}
|
|
1830
|
+
});
|
|
1831
|
+
child.on("error", () => {
|
|
1832
|
+
releaseTelemetryFlushSpawnGate(globalPmRoot);
|
|
1833
|
+
});
|
|
1834
|
+
child.unref();
|
|
1835
|
+
} catch {
|
|
1836
|
+
releaseTelemetryFlushSpawnGate(globalPmRoot);
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
async function flushTelemetryQueueNow(globalPmRoot = resolveGlobalPmRoot(process.cwd())) {
|
|
1840
|
+
if (telemetryDisabledByEnvironment()) {
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
try {
|
|
1844
|
+
const settings = await readSettings(globalPmRoot);
|
|
1845
|
+
if (!settings.telemetry.enabled) {
|
|
1846
|
+
return;
|
|
1847
|
+
}
|
|
1848
|
+
const { endpoint, retentionDays } = await ensureInstallationId(globalPmRoot);
|
|
1849
|
+
await flushQueueWithProcessLock(globalPmRoot, endpoint, retentionDays);
|
|
1850
|
+
} catch {
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
async function startTelemetryCommand(context) {
|
|
1854
|
+
if (telemetryDisabledByEnvironment()) {
|
|
1855
|
+
return null;
|
|
1856
|
+
}
|
|
1857
|
+
if (context.command === "telemetry" && context.args.some((token) => token.trim().toLowerCase() === "clear")) {
|
|
1858
|
+
return null;
|
|
1859
|
+
}
|
|
1860
|
+
try {
|
|
1861
|
+
const globalPmRoot = resolveGlobalPmRoot(process.cwd());
|
|
1862
|
+
const settings = await readSettings(globalPmRoot);
|
|
1863
|
+
if (!settings.telemetry.enabled) {
|
|
1864
|
+
return null;
|
|
1865
|
+
}
|
|
1866
|
+
const captureLevel = normalizeCaptureLevel(settings.telemetry.capture_level);
|
|
1867
|
+
const { installationId, endpoint, retentionDays } = await ensureInstallationId(globalPmRoot);
|
|
1868
|
+
const pmVersion = normalizePmVersion(context.pm_version);
|
|
1869
|
+
const sourceContext = resolveTelemetrySourceContext(context.global);
|
|
1870
|
+
const pmRootHash = hashWithInstallationId(installationId, context.pm_root);
|
|
1871
|
+
const cwdHash = hashWithInstallationId(installationId, process.cwd());
|
|
1872
|
+
const otelTracesEndpoint = resolveOtelTracesEndpoint();
|
|
1873
|
+
const occurredAt = nowIso();
|
|
1874
|
+
const event = {
|
|
1875
|
+
schema_version: TELEMETRY_SCHEMA_VERSION,
|
|
1876
|
+
event_id: crypto.randomUUID(),
|
|
1877
|
+
event_type: "command_start",
|
|
1878
|
+
occurred_at: occurredAt,
|
|
1879
|
+
installation_id: installationId,
|
|
1880
|
+
session_id: PROCESS_SESSION_ID,
|
|
1881
|
+
command: context.command,
|
|
1882
|
+
payload: buildCommandStartPayload({
|
|
1883
|
+
captureLevel,
|
|
1884
|
+
context,
|
|
1885
|
+
pmVersion,
|
|
1886
|
+
sourceContext,
|
|
1887
|
+
pmRootHash,
|
|
1888
|
+
cwdHash,
|
|
1889
|
+
installationId
|
|
1890
|
+
})
|
|
1891
|
+
};
|
|
1892
|
+
await enqueueTelemetryEvent(globalPmRoot, event);
|
|
1893
|
+
scheduleTelemetryFlush(globalPmRoot, endpoint, retentionDays);
|
|
1894
|
+
const commandTaxonomy = deriveTelemetryCommandTaxonomy(context.command);
|
|
1895
|
+
return {
|
|
1896
|
+
started_at: occurredAt,
|
|
1897
|
+
started_at_ms: Date.now(),
|
|
1898
|
+
command: context.command,
|
|
1899
|
+
command_taxonomy: commandTaxonomy,
|
|
1900
|
+
pm_version: pmVersion,
|
|
1901
|
+
source_context: sourceContext.source_context,
|
|
1902
|
+
source_context_source: sourceContext.source_context_source,
|
|
1903
|
+
installation_id: installationId,
|
|
1904
|
+
pm_root_hash: pmRootHash,
|
|
1905
|
+
cwd_hash: cwdHash,
|
|
1906
|
+
endpoint,
|
|
1907
|
+
retention_days: retentionDays,
|
|
1908
|
+
global_pm_root: globalPmRoot,
|
|
1909
|
+
capture_level: captureLevel,
|
|
1910
|
+
otel_traces_endpoint: otelTracesEndpoint ?? void 0,
|
|
1911
|
+
otel_trace_id: otelTracesEndpoint ? crypto.randomBytes(16).toString("hex") : void 0,
|
|
1912
|
+
otel_span_id: otelTracesEndpoint ? crypto.randomBytes(8).toString("hex") : void 0
|
|
1913
|
+
};
|
|
1914
|
+
} catch {
|
|
1915
|
+
return null;
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
async function finishTelemetryCommand(activeCommand, outcome) {
|
|
1919
|
+
if (!activeCommand) {
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
try {
|
|
1923
|
+
const finishedAt = nowIso();
|
|
1924
|
+
const durationMs = Math.max(0, Date.now() - activeCommand.started_at_ms);
|
|
1925
|
+
const normalizedErrorCode = normalizeTelemetryErrorCode(inferTelemetryErrorCode({
|
|
1926
|
+
ok: outcome.ok,
|
|
1927
|
+
errorCode: outcome.error_code,
|
|
1928
|
+
errorMessage: outcome.error,
|
|
1929
|
+
exitCode: outcome.exit_code
|
|
1930
|
+
}));
|
|
1931
|
+
const normalizedErrorCategory = normalizeTelemetryErrorCategory({
|
|
1932
|
+
ok: outcome.ok,
|
|
1933
|
+
errorCode: normalizedErrorCode,
|
|
1934
|
+
errorCategory: outcome.error_category
|
|
1935
|
+
});
|
|
1936
|
+
const normalizedExitCode = normalizeTelemetryExitCode(outcome.exit_code, outcome.ok);
|
|
1937
|
+
const commandResolution = outcome.command_resolution ?? deriveTelemetryCommandResolution({
|
|
1938
|
+
ok: outcome.ok,
|
|
1939
|
+
errorCode: normalizedErrorCode,
|
|
1940
|
+
errorCategory: normalizedErrorCategory
|
|
1941
|
+
});
|
|
1942
|
+
const resolutionStage = outcome.resolution_stage ?? "execute";
|
|
1943
|
+
const event = {
|
|
1944
|
+
schema_version: TELEMETRY_SCHEMA_VERSION,
|
|
1945
|
+
event_id: crypto.randomUUID(),
|
|
1946
|
+
event_type: "command_finish",
|
|
1947
|
+
occurred_at: finishedAt,
|
|
1948
|
+
installation_id: activeCommand.installation_id,
|
|
1949
|
+
session_id: PROCESS_SESSION_ID,
|
|
1950
|
+
command: activeCommand.command,
|
|
1951
|
+
payload: buildCommandFinishPayload({
|
|
1952
|
+
captureLevel: activeCommand.capture_level,
|
|
1953
|
+
pmVersion: activeCommand.pm_version,
|
|
1954
|
+
sourceContext: {
|
|
1955
|
+
source_context: activeCommand.source_context,
|
|
1956
|
+
source_context_source: activeCommand.source_context_source
|
|
1957
|
+
},
|
|
1958
|
+
outcome,
|
|
1959
|
+
durationMs,
|
|
1960
|
+
startedAt: activeCommand.started_at,
|
|
1961
|
+
command: activeCommand.command,
|
|
1962
|
+
installationId: activeCommand.installation_id,
|
|
1963
|
+
commandTaxonomy: activeCommand.command_taxonomy,
|
|
1964
|
+
exitCode: normalizedExitCode,
|
|
1965
|
+
errorCode: normalizedErrorCode,
|
|
1966
|
+
errorCategory: normalizedErrorCategory,
|
|
1967
|
+
commandResolution,
|
|
1968
|
+
resolutionStage
|
|
1969
|
+
})
|
|
1970
|
+
};
|
|
1971
|
+
await enqueueTelemetryEvent(activeCommand.global_pm_root, event);
|
|
1972
|
+
const otelRequest = buildOtelSpanRequest(activeCommand, {
|
|
1973
|
+
...outcome,
|
|
1974
|
+
exit_code: normalizedExitCode,
|
|
1975
|
+
error_code: normalizedErrorCode,
|
|
1976
|
+
error_category: normalizedErrorCategory
|
|
1977
|
+
}, finishedAt, durationMs);
|
|
1978
|
+
if (otelRequest) {
|
|
1979
|
+
await enqueuePendingOtelSpan(activeCommand.global_pm_root, otelRequest);
|
|
1980
|
+
}
|
|
1981
|
+
scheduleTelemetryFlush(activeCommand.global_pm_root, activeCommand.endpoint, activeCommand.retention_days);
|
|
1982
|
+
} catch {
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
async function emitTelemetryErrorEvent(context) {
|
|
1986
|
+
if (telemetryDisabledByEnvironment()) {
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1989
|
+
try {
|
|
1990
|
+
const globalPmRoot = resolveGlobalPmRoot(process.cwd());
|
|
1991
|
+
const settings = await readSettings(globalPmRoot);
|
|
1992
|
+
if (!settings.telemetry.enabled) {
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
const captureLevel = normalizeCaptureLevel(settings.telemetry.capture_level);
|
|
1996
|
+
const { installationId, endpoint, retentionDays } = await ensureInstallationId(globalPmRoot);
|
|
1997
|
+
const pmVersion = normalizePmVersion(context.pm_version);
|
|
1998
|
+
const sourceContext = resolveTelemetrySourceContext(context.global);
|
|
1999
|
+
const pmRootHash = hashWithInstallationId(installationId, context.pm_root);
|
|
2000
|
+
const cwdHash = hashWithInstallationId(installationId, process.cwd());
|
|
2001
|
+
const occurredAt = nowIso();
|
|
2002
|
+
const normalizedErrorCode = normalizeTelemetryErrorCode(inferTelemetryErrorCode({
|
|
2003
|
+
ok: false,
|
|
2004
|
+
errorCode: context.error_code,
|
|
2005
|
+
errorMessage: context.error_message,
|
|
2006
|
+
exitCode: context.exit_code
|
|
2007
|
+
}));
|
|
2008
|
+
const normalizedErrorCategory = context.error_category ?? resolveTelemetryErrorCategory(normalizedErrorCode);
|
|
2009
|
+
const normalizedExitCode = normalizeTelemetryExitCode(context.exit_code, false);
|
|
2010
|
+
const normalizedCommand = context.command.trim().length > 0 ? context.command : "<unknown>";
|
|
2011
|
+
const commandTaxonomy = deriveTelemetryCommandTaxonomy(normalizedCommand);
|
|
2012
|
+
const commandResolution = context.command_resolution ?? deriveTelemetryCommandResolution({
|
|
2013
|
+
ok: false,
|
|
2014
|
+
errorCode: normalizedErrorCode,
|
|
2015
|
+
errorCategory: normalizedErrorCategory
|
|
2016
|
+
});
|
|
2017
|
+
const resolutionStage = context.resolution_stage ?? "unknown";
|
|
2018
|
+
const event = {
|
|
2019
|
+
schema_version: TELEMETRY_SCHEMA_VERSION,
|
|
2020
|
+
event_id: crypto.randomUUID(),
|
|
2021
|
+
event_type: "command_error",
|
|
2022
|
+
occurred_at: occurredAt,
|
|
2023
|
+
installation_id: installationId,
|
|
2024
|
+
session_id: PROCESS_SESSION_ID,
|
|
2025
|
+
command: sanitizeString(normalizedCommand, "redacted"),
|
|
2026
|
+
payload: buildCommandErrorPayload({
|
|
2027
|
+
captureLevel,
|
|
2028
|
+
pmVersion,
|
|
2029
|
+
sourceContext,
|
|
2030
|
+
command: normalizedCommand,
|
|
2031
|
+
commandTaxonomy,
|
|
2032
|
+
commandResolution,
|
|
2033
|
+
resolutionStage,
|
|
2034
|
+
args: context.args,
|
|
2035
|
+
options: context.options,
|
|
2036
|
+
pmRootHash,
|
|
2037
|
+
cwdHash,
|
|
2038
|
+
installationId,
|
|
2039
|
+
errorCode: normalizedErrorCode,
|
|
2040
|
+
errorCategory: normalizedErrorCategory,
|
|
2041
|
+
exitCode: normalizedExitCode,
|
|
2042
|
+
errorMessage: context.error_message
|
|
2043
|
+
})
|
|
2044
|
+
};
|
|
2045
|
+
await enqueueTelemetryEvent(globalPmRoot, event);
|
|
2046
|
+
scheduleTelemetryFlush(globalPmRoot, endpoint, retentionDays);
|
|
2047
|
+
} catch {
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
249
2050
|
|
|
250
|
-
// dist/sdk/
|
|
251
|
-
function
|
|
252
|
-
|
|
2051
|
+
// dist/sdk/ownership-source.js
|
|
2052
|
+
async function describeItemOwnershipConflict(pmRoot, itemId, assignee) {
|
|
2053
|
+
const history = await readHistoryEntries(getHistoryPath(pmRoot, itemId), itemId).catch(() => []);
|
|
2054
|
+
const latestOwnershipOperation = [...history].reverse().find((entry) => entry.patch.some((operation) => operation.path === "/metadata/assignee"))?.op;
|
|
2055
|
+
return latestOwnershipOperation === "claim" ? `claimed by ${assignee}` : `assigned to ${assignee}`;
|
|
253
2056
|
}
|
|
254
2057
|
|
|
255
2058
|
// dist/cli/commands/claim.js
|
|
@@ -277,7 +2080,7 @@ async function runClaim(id, force, global, options = {}) {
|
|
|
277
2080
|
message: options.message,
|
|
278
2081
|
force,
|
|
279
2082
|
skipNoop: true,
|
|
280
|
-
mutate(document) {
|
|
2083
|
+
async mutate(document) {
|
|
281
2084
|
const currentAssignee = document.metadata.assignee;
|
|
282
2085
|
const currentAssigneeText = typeof currentAssignee === "string" ? currentAssignee : "";
|
|
283
2086
|
previousAssignee = currentAssigneeText.trim().length > 0 ? currentAssigneeText : null;
|
|
@@ -291,7 +2094,8 @@ async function runClaim(id, force, global, options = {}) {
|
|
|
291
2094
|
return { changedFields: [] };
|
|
292
2095
|
}
|
|
293
2096
|
if (heldByOther && !force) {
|
|
294
|
-
|
|
2097
|
+
const ownershipPhrase = await describeItemOwnershipConflict(pmRoot, document.metadata.id, currentAssigneeText);
|
|
2098
|
+
throw new PmCliError(`Item ${document.metadata.id} is already ${ownershipPhrase}. Use --force to take over, or --if-available to skip without failing.`, EXIT_CODE.CONFLICT, {
|
|
295
2099
|
code: "already_claimed_by",
|
|
296
2100
|
why: "Claim is an atomic test-and-set so parallel agents never proceed believing they own the same item.",
|
|
297
2101
|
nextSteps: [
|
|
@@ -1195,22 +2999,22 @@ function packageOwnedActionForCommand(command) {
|
|
|
1195
2999
|
}
|
|
1196
3000
|
function resolveActionCommandPath(action) {
|
|
1197
3001
|
if (PM_CORE_COMMAND_NAMES.includes(action)) {
|
|
1198
|
-
return
|
|
3002
|
+
return normalizeCommandPath2(action);
|
|
1199
3003
|
}
|
|
1200
3004
|
if (action.startsWith("extension-")) {
|
|
1201
|
-
return
|
|
3005
|
+
return normalizeCommandPath2(`extension ${action.slice("extension-".length)}`);
|
|
1202
3006
|
}
|
|
1203
3007
|
if (action.startsWith("package-")) {
|
|
1204
|
-
return
|
|
3008
|
+
return normalizeCommandPath2(`package ${action.slice("package-".length)}`);
|
|
1205
3009
|
}
|
|
1206
3010
|
if (action.startsWith("test-runs-")) {
|
|
1207
|
-
return
|
|
3011
|
+
return normalizeCommandPath2(`test-runs ${action.slice("test-runs-".length)}`);
|
|
1208
3012
|
}
|
|
1209
3013
|
if (action.startsWith("templates-")) {
|
|
1210
|
-
return
|
|
3014
|
+
return normalizeCommandPath2(`templates ${action.slice("templates-".length)}`);
|
|
1211
3015
|
}
|
|
1212
3016
|
if (PACKAGE_OWNED_ACTIONS.has(action)) {
|
|
1213
|
-
return PACKAGE_OWNED_ACTION_COMMAND_PATHS.get(action) ??
|
|
3017
|
+
return PACKAGE_OWNED_ACTION_COMMAND_PATHS.get(action) ?? normalizeCommandPath2(action);
|
|
1214
3018
|
}
|
|
1215
3019
|
return null;
|
|
1216
3020
|
}
|
|
@@ -1226,7 +3030,7 @@ function actionDescriptorMatchesSelectedCommand(descriptor, selectedCommand) {
|
|
|
1226
3030
|
});
|
|
1227
3031
|
}
|
|
1228
3032
|
function splitCommandPathAliases(commandPath) {
|
|
1229
|
-
return commandPath.split("|").map((entry) =>
|
|
3033
|
+
return commandPath.split("|").map((entry) => normalizeCommandPath2(entry)).filter((entry) => entry.length > 0);
|
|
1230
3034
|
}
|
|
1231
3035
|
function resolveScopedCommandsFromActionDescriptors(descriptors, commandCatalog) {
|
|
1232
3036
|
const commandSet = new Set(commandCatalog);
|
|
@@ -1306,7 +3110,7 @@ function filterSchemaByActions(schema, actions) {
|
|
|
1306
3110
|
oneOf: filtered
|
|
1307
3111
|
};
|
|
1308
3112
|
}
|
|
1309
|
-
function
|
|
3113
|
+
function normalizeCommandPath2(value) {
|
|
1310
3114
|
return value.trim().toLowerCase().split(/\s+/).filter((entry) => entry.length > 0).join(" ");
|
|
1311
3115
|
}
|
|
1312
3116
|
function normalizeActionNameFromCommand(commandPath) {
|
|
@@ -1391,7 +3195,7 @@ function toExtensionFlagContract(definition) {
|
|
|
1391
3195
|
function collectExtensionFlagContractsByCommand(registrations) {
|
|
1392
3196
|
const grouped = /* @__PURE__ */ new Map();
|
|
1393
3197
|
for (const registration of registrations) {
|
|
1394
|
-
const commandPath =
|
|
3198
|
+
const commandPath = normalizeCommandPath2(registration.target_command);
|
|
1395
3199
|
if (commandPath.length === 0) {
|
|
1396
3200
|
continue;
|
|
1397
3201
|
}
|
|
@@ -1442,7 +3246,7 @@ function collectExtensionCommandContracts(runtimeProbe) {
|
|
|
1442
3246
|
const flagsByCommand = collectExtensionFlagContractsByCommand(runtimeProbe.flagRegistrations);
|
|
1443
3247
|
const definitionsByCommand = /* @__PURE__ */ new Map();
|
|
1444
3248
|
for (const definition of runtimeProbe.commandDefinitions) {
|
|
1445
|
-
const command =
|
|
3249
|
+
const command = normalizeCommandPath2(definition.command);
|
|
1446
3250
|
if (command.length === 0) {
|
|
1447
3251
|
continue;
|
|
1448
3252
|
}
|
|
@@ -1476,7 +3280,7 @@ function collectExtensionCommandContracts(runtimeProbe) {
|
|
|
1476
3280
|
}
|
|
1477
3281
|
const extensionCommands = /* @__PURE__ */ new Set();
|
|
1478
3282
|
for (const command of runtimeProbe.handlers) {
|
|
1479
|
-
extensionCommands.add(
|
|
3283
|
+
extensionCommands.add(normalizeCommandPath2(command));
|
|
1480
3284
|
}
|
|
1481
3285
|
for (const command of definitionsByCommand.keys()) {
|
|
1482
3286
|
extensionCommands.add(command);
|
|
@@ -1663,7 +3467,7 @@ async function resolveRuntimeExtensionActionProbe(global) {
|
|
|
1663
3467
|
...loadResult,
|
|
1664
3468
|
loaded: loadResult.loaded
|
|
1665
3469
|
});
|
|
1666
|
-
const handlers = new Set(activationResult.commands.handlers.map((entry) =>
|
|
3470
|
+
const handlers = new Set(activationResult.commands.handlers.map((entry) => normalizeCommandPath2(entry.command)));
|
|
1667
3471
|
return {
|
|
1668
3472
|
handlers,
|
|
1669
3473
|
disabledReason: null,
|
|
@@ -1723,7 +3527,7 @@ function collectActionContractDescriptors(extensionContracts, options = {}) {
|
|
|
1723
3527
|
action: contract.action,
|
|
1724
3528
|
provider: "extension",
|
|
1725
3529
|
requires_extension: true,
|
|
1726
|
-
command_path:
|
|
3530
|
+
command_path: normalizeCommandPath2(contract.command)
|
|
1727
3531
|
});
|
|
1728
3532
|
}
|
|
1729
3533
|
return [...descriptors.values()].sort((left, right) => (left.action ?? "").localeCompare(right.action ?? ""));
|
|
@@ -2080,7 +3884,7 @@ function buildContractsCommandCatalog(actionDescriptors, mergedExtensionContract
|
|
|
2080
3884
|
...actionDescriptors.flatMap((entry) => entry.command_path ? splitCommandPathAliases(entry.command_path) : []),
|
|
2081
3885
|
...mergedExtensionContracts.flatMap((entry) => entry.command.split("|"))
|
|
2082
3886
|
])
|
|
2083
|
-
].map((entry) =>
|
|
3887
|
+
].map((entry) => normalizeCommandPath2(entry)).filter((entry) => entry.length > 0).sort((left, right) => left.localeCompare(right));
|
|
2084
3888
|
}
|
|
2085
3889
|
function buildCommandNamespaceError(command, namespaceChildren) {
|
|
2086
3890
|
const displayedNamespaceChildren = namespaceChildren.slice(0, COMMAND_NAMESPACE_DISPLAY_LIMIT);
|
|
@@ -2390,14 +4194,76 @@ async function runContracts(options, global) {
|
|
|
2390
4194
|
return result;
|
|
2391
4195
|
}
|
|
2392
4196
|
|
|
4197
|
+
// dist/cli/commands/scheduling-shortcuts.js
|
|
4198
|
+
var DEFAULT_DURATION = "1h";
|
|
4199
|
+
var DEFAULT_START = "now";
|
|
4200
|
+
var DEFAULT_REMINDER_AT = "+1d";
|
|
4201
|
+
function quoteCsvValue(value) {
|
|
4202
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
4203
|
+
}
|
|
4204
|
+
function appendPair(pairs, key, value) {
|
|
4205
|
+
if (value !== void 0) {
|
|
4206
|
+
pairs.push(`${key}=${quoteCsvValue(value)}`);
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
function buildCommonOptions(type, title, options) {
|
|
4210
|
+
return {
|
|
4211
|
+
type,
|
|
4212
|
+
title,
|
|
4213
|
+
schedulePreset: "lightweight",
|
|
4214
|
+
parent: options.parent,
|
|
4215
|
+
allowMissingParent: options.allowMissingParent,
|
|
4216
|
+
tags: options.tags,
|
|
4217
|
+
priority: options.priority,
|
|
4218
|
+
body: options.body,
|
|
4219
|
+
description: options.description,
|
|
4220
|
+
author: options.author,
|
|
4221
|
+
message: options.message
|
|
4222
|
+
};
|
|
4223
|
+
}
|
|
4224
|
+
function buildEventEntry(options) {
|
|
4225
|
+
const pairs = [];
|
|
4226
|
+
appendPair(pairs, "start", options.start ?? DEFAULT_START);
|
|
4227
|
+
if (options.end !== void 0) {
|
|
4228
|
+
appendPair(pairs, "end", options.end);
|
|
4229
|
+
} else {
|
|
4230
|
+
appendPair(pairs, "duration", options.duration ?? DEFAULT_DURATION);
|
|
4231
|
+
}
|
|
4232
|
+
appendPair(pairs, "location", options.location);
|
|
4233
|
+
appendPair(pairs, "timezone", options.timezone);
|
|
4234
|
+
if (options.allDay === true) {
|
|
4235
|
+
appendPair(pairs, "all_day", "true");
|
|
4236
|
+
}
|
|
4237
|
+
return pairs.join(",");
|
|
4238
|
+
}
|
|
4239
|
+
async function createScheduled(type, title, options, global) {
|
|
4240
|
+
const createOptions = buildCommonOptions(type, title, options);
|
|
4241
|
+
createOptions.event = [buildEventEntry(options)];
|
|
4242
|
+
return runCreate(createOptions, global);
|
|
4243
|
+
}
|
|
4244
|
+
function runMeet(title, options, global) {
|
|
4245
|
+
return createScheduled("Meeting", title, options, global);
|
|
4246
|
+
}
|
|
4247
|
+
function runEvent(title, options, global) {
|
|
4248
|
+
return createScheduled("Event", title, options, global);
|
|
4249
|
+
}
|
|
4250
|
+
function runRemind(title, options, global) {
|
|
4251
|
+
const createOptions = buildCommonOptions("Reminder", title, options);
|
|
4252
|
+
const pairs = [];
|
|
4253
|
+
appendPair(pairs, "at", options.at ?? DEFAULT_REMINDER_AT);
|
|
4254
|
+
appendPair(pairs, "text", options.text ?? title);
|
|
4255
|
+
createOptions.reminder = [pairs.join(",")];
|
|
4256
|
+
return runCreate(createOptions, global);
|
|
4257
|
+
}
|
|
4258
|
+
|
|
2393
4259
|
// dist/sdk/governance/gc.js
|
|
2394
4260
|
import fs3 from "node:fs/promises";
|
|
2395
|
-
import
|
|
4261
|
+
import path4 from "node:path";
|
|
2396
4262
|
|
|
2397
4263
|
// dist/core/checkpoint/checkpoint-gc.js
|
|
2398
4264
|
import fs from "node:fs/promises";
|
|
2399
|
-
import
|
|
2400
|
-
var
|
|
4265
|
+
import path2 from "node:path";
|
|
4266
|
+
var MILLISECONDS_PER_DAY2 = 864e5;
|
|
2401
4267
|
function isErrno(error, code) {
|
|
2402
4268
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
2403
4269
|
}
|
|
@@ -2427,7 +4293,7 @@ async function collectCheckpointFiles(checkpointsDir, warnings) {
|
|
|
2427
4293
|
const files = [];
|
|
2428
4294
|
for (const entry of dirEntries) {
|
|
2429
4295
|
if (entry.isDirectory()) {
|
|
2430
|
-
const subdir =
|
|
4296
|
+
const subdir = path2.join(checkpointsDir, entry.name);
|
|
2431
4297
|
let nested;
|
|
2432
4298
|
try {
|
|
2433
4299
|
nested = await fs.readdir(subdir);
|
|
@@ -2451,8 +4317,8 @@ async function collectCheckpointFiles(checkpointsDir, warnings) {
|
|
|
2451
4317
|
async function runCheckpointGc(pmRoot, options) {
|
|
2452
4318
|
const { dryRun, hooks } = options;
|
|
2453
4319
|
const nowMs2 = options.now ?? Date.now();
|
|
2454
|
-
const retentionMs = Math.max(0, options.retentionDays) *
|
|
2455
|
-
const checkpointsDir =
|
|
4320
|
+
const retentionMs = Math.max(0, options.retentionDays) * MILLISECONDS_PER_DAY2;
|
|
4321
|
+
const checkpointsDir = path2.join(pmRoot, "checkpoints");
|
|
2456
4322
|
const result = {
|
|
2457
4323
|
scanned: 0,
|
|
2458
4324
|
removed: [],
|
|
@@ -2462,7 +4328,7 @@ async function runCheckpointGc(pmRoot, options) {
|
|
|
2462
4328
|
};
|
|
2463
4329
|
const files = await collectCheckpointFiles(checkpointsDir, result.warnings);
|
|
2464
4330
|
for (const relName of files) {
|
|
2465
|
-
const absPath =
|
|
4331
|
+
const absPath = path2.join(checkpointsDir, relName);
|
|
2466
4332
|
const relPath = `checkpoints/${relName}`;
|
|
2467
4333
|
result.scanned += 1;
|
|
2468
4334
|
if (hooks?.onRead) {
|
|
@@ -2537,7 +4403,7 @@ async function runCheckpointGc(pmRoot, options) {
|
|
|
2537
4403
|
|
|
2538
4404
|
// dist/core/lock/lock-gc.js
|
|
2539
4405
|
import fs2 from "node:fs/promises";
|
|
2540
|
-
import
|
|
4406
|
+
import path3 from "node:path";
|
|
2541
4407
|
function parseLock(raw) {
|
|
2542
4408
|
let parsed;
|
|
2543
4409
|
try {
|
|
@@ -2610,7 +4476,7 @@ function classifyLockContent(file, raw, nowMs2) {
|
|
|
2610
4476
|
}
|
|
2611
4477
|
async function scanLockHealth(pmRoot, now) {
|
|
2612
4478
|
const nowMs2 = now ?? Date.now();
|
|
2613
|
-
const locksDir =
|
|
4479
|
+
const locksDir = path3.join(pmRoot, "locks");
|
|
2614
4480
|
const scan = {
|
|
2615
4481
|
scanned: 0,
|
|
2616
4482
|
active_lock_count: 0,
|
|
@@ -2631,7 +4497,7 @@ async function scanLockHealth(pmRoot, now) {
|
|
|
2631
4497
|
for (const file of dirEntries) {
|
|
2632
4498
|
let raw;
|
|
2633
4499
|
try {
|
|
2634
|
-
raw = await fs2.readFile(
|
|
4500
|
+
raw = await fs2.readFile(path3.join(locksDir, file), "utf8");
|
|
2635
4501
|
} catch (readError) {
|
|
2636
4502
|
if (isErrno2(readError, "ENOENT")) {
|
|
2637
4503
|
continue;
|
|
@@ -2655,7 +4521,7 @@ async function scanLockHealth(pmRoot, now) {
|
|
|
2655
4521
|
async function runLockGc(pmRoot, options) {
|
|
2656
4522
|
const { dryRun, hooks } = options;
|
|
2657
4523
|
const nowMs2 = options.now ?? Date.now();
|
|
2658
|
-
const locksDir =
|
|
4524
|
+
const locksDir = path3.join(pmRoot, "locks");
|
|
2659
4525
|
const result = {
|
|
2660
4526
|
scanned: 0,
|
|
2661
4527
|
removed: [],
|
|
@@ -2675,7 +4541,7 @@ async function runLockGc(pmRoot, options) {
|
|
|
2675
4541
|
}
|
|
2676
4542
|
for (const file of dirEntries) {
|
|
2677
4543
|
result.scanned += 1;
|
|
2678
|
-
const absPath =
|
|
4544
|
+
const absPath = path3.join(locksDir, file);
|
|
2679
4545
|
const relPath = `locks/${file}`;
|
|
2680
4546
|
if (hooks?.onRead) {
|
|
2681
4547
|
const hookWarnings = await hooks.onRead(absPath);
|
|
@@ -2803,7 +4669,7 @@ function isErrno3(error, code) {
|
|
|
2803
4669
|
}
|
|
2804
4670
|
async function removeCacheFile(pmRoot, target, dryRun) {
|
|
2805
4671
|
const relativePath = target.relativePath;
|
|
2806
|
-
const absolutePath =
|
|
4672
|
+
const absolutePath = path4.join(pmRoot, relativePath);
|
|
2807
4673
|
const warnings = await runActiveOnReadHooks({
|
|
2808
4674
|
path: absolutePath,
|
|
2809
4675
|
scope: "project"
|
|
@@ -2980,7 +4846,7 @@ async function runGc(global, options = {}) {
|
|
|
2980
4846
|
|
|
2981
4847
|
// dist/sdk/author-attribution.js
|
|
2982
4848
|
import fs4 from "node:fs/promises";
|
|
2983
|
-
import
|
|
4849
|
+
import path5 from "node:path";
|
|
2984
4850
|
var HISTORY_AUTHOR_ATTRIBUTION_BASELINE = "2026-07-15T06:22:12.276Z";
|
|
2985
4851
|
var HISTORY_AUTHOR_ATTRIBUTION_BASELINE_MS = Date.parse(HISTORY_AUTHOR_ATTRIBUTION_BASELINE);
|
|
2986
4852
|
var HISTORY_AUTHOR_EVENT_CLASSIFICATIONS = [
|
|
@@ -3029,7 +4895,7 @@ var inspectHistoryAuthorStream = (itemId, raw, sampleLimit = 20) => {
|
|
|
3029
4895
|
};
|
|
3030
4896
|
};
|
|
3031
4897
|
var scanHistoryAuthorAttribution = async (pmRoot, sampleLimit = 20) => {
|
|
3032
|
-
const historyDirectory =
|
|
4898
|
+
const historyDirectory = path5.join(pmRoot, "history");
|
|
3033
4899
|
let fileNames;
|
|
3034
4900
|
try {
|
|
3035
4901
|
fileNames = (await fs4.readdir(historyDirectory)).filter((fileName) => fileName.endsWith(".jsonl")).sort((left, right) => left.localeCompare(right));
|
|
@@ -3046,7 +4912,7 @@ var scanHistoryAuthorAttribution = async (pmRoot, sampleLimit = 20) => {
|
|
|
3046
4912
|
for (const fileName of fileNames) {
|
|
3047
4913
|
let raw;
|
|
3048
4914
|
try {
|
|
3049
|
-
raw = await fs4.readFile(
|
|
4915
|
+
raw = await fs4.readFile(path5.join(historyDirectory, fileName), "utf8");
|
|
3050
4916
|
} catch {
|
|
3051
4917
|
continue;
|
|
3052
4918
|
}
|
|
@@ -3075,7 +4941,7 @@ var scanHistoryAuthorAttribution = async (pmRoot, sampleLimit = 20) => {
|
|
|
3075
4941
|
|
|
3076
4942
|
// dist/sdk/governance/health.js
|
|
3077
4943
|
import fs5 from "node:fs/promises";
|
|
3078
|
-
import
|
|
4944
|
+
import path6 from "node:path";
|
|
3079
4945
|
|
|
3080
4946
|
// dist/core/diagnostics/remediation.js
|
|
3081
4947
|
var REMEDIATION_REGISTRY = Object.freeze([
|
|
@@ -3447,11 +5313,11 @@ function buildRemediationCommands(warnings) {
|
|
|
3447
5313
|
}
|
|
3448
5314
|
|
|
3449
5315
|
// dist/sdk/governance/health.js
|
|
3450
|
-
var
|
|
5316
|
+
var PM_TELEMETRY_SOURCE_CONTEXT_SET2 = new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES);
|
|
3451
5317
|
var STALE_VECTORIZATION_SUMMARY_LIMIT = 25;
|
|
3452
5318
|
var BRIEF_HEALTH_DETAIL_LIMIT = 8;
|
|
3453
|
-
var
|
|
3454
|
-
var
|
|
5319
|
+
var TELEMETRY_QUEUE_RELATIVE_PATH2 = path6.join("runtime", "telemetry", "events.jsonl");
|
|
5320
|
+
var TELEMETRY_STATE_RELATIVE_PATH2 = path6.join("runtime", "telemetry", "state.json");
|
|
3455
5321
|
var TELEMETRY_ENDPOINT_PROBE_TIMEOUT_MS = 2500;
|
|
3456
5322
|
var TELEMETRY_QUEUE_HIGH_WATER_MARK = 500;
|
|
3457
5323
|
var TELEMETRY_QUEUE_HIGH_RETRY_THRESHOLD = TELEMETRY_MAX_QUEUE_ENTRY_ATTEMPTS - 3;
|
|
@@ -3490,7 +5356,7 @@ async function isDirectory(targetPath) {
|
|
|
3490
5356
|
}
|
|
3491
5357
|
}
|
|
3492
5358
|
async function countHistoryStreams(pmRoot, compactPolicy) {
|
|
3493
|
-
const historyDir =
|
|
5359
|
+
const historyDir = path6.join(pmRoot, "history");
|
|
3494
5360
|
if (!await isDirectory(historyDir)) {
|
|
3495
5361
|
return { count: 0, warnings: [], over_threshold: [], max_entries: null };
|
|
3496
5362
|
}
|
|
@@ -3500,7 +5366,7 @@ async function countHistoryStreams(pmRoot, compactPolicy) {
|
|
|
3500
5366
|
const warnings = [];
|
|
3501
5367
|
const overThreshold = [];
|
|
3502
5368
|
for (const fileName of historyFiles) {
|
|
3503
|
-
const streamPath =
|
|
5369
|
+
const streamPath = path6.join(historyDir, fileName);
|
|
3504
5370
|
warnings.push(...await runActiveOnReadHooks({ path: streamPath, scope: "project" }));
|
|
3505
5371
|
if (!policyActive) {
|
|
3506
5372
|
continue;
|
|
@@ -3527,13 +5393,13 @@ async function countHistoryStreams(pmRoot, compactPolicy) {
|
|
|
3527
5393
|
};
|
|
3528
5394
|
}
|
|
3529
5395
|
function normalizeRelativePath(pmRoot, targetPath) {
|
|
3530
|
-
return
|
|
5396
|
+
return path6.relative(pmRoot, targetPath).replaceAll("\\", "/");
|
|
3531
5397
|
}
|
|
3532
5398
|
async function listItemDocumentPaths(pmRoot, typeToFolder) {
|
|
3533
5399
|
const folders = [...new Set(Object.values(typeToFolder))].sort((left, right) => left.localeCompare(right));
|
|
3534
5400
|
const itemPaths = [];
|
|
3535
5401
|
for (const folder of folders) {
|
|
3536
|
-
const directoryPath =
|
|
5402
|
+
const directoryPath = path6.join(pmRoot, folder);
|
|
3537
5403
|
let entries = [];
|
|
3538
5404
|
try {
|
|
3539
5405
|
entries = await fs5.readdir(directoryPath);
|
|
@@ -3547,7 +5413,7 @@ async function listItemDocumentPaths(pmRoot, typeToFolder) {
|
|
|
3547
5413
|
if (!ITEM_FILE_EXTENSIONS.some((extension) => entry.toLowerCase().endsWith(extension))) {
|
|
3548
5414
|
continue;
|
|
3549
5415
|
}
|
|
3550
|
-
itemPaths.push(
|
|
5416
|
+
itemPaths.push(path6.join(directoryPath, entry));
|
|
3551
5417
|
}
|
|
3552
5418
|
}
|
|
3553
5419
|
itemPaths.sort((left, right) => normalizeRelativePath(pmRoot, left).localeCompare(normalizeRelativePath(pmRoot, right)));
|
|
@@ -3596,7 +5462,7 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema) {
|
|
|
3596
5462
|
}
|
|
3597
5463
|
}
|
|
3598
5464
|
const formatVersionScan = scanItemFormatVersions(formatVersionEntries);
|
|
3599
|
-
const historyDir =
|
|
5465
|
+
const historyDir = path6.join(pmRoot, "history");
|
|
3600
5466
|
const historyUnreadable = [];
|
|
3601
5467
|
const historyConflictMarkers = [];
|
|
3602
5468
|
const historyInvalidJson = [];
|
|
@@ -3610,7 +5476,7 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema) {
|
|
|
3610
5476
|
}
|
|
3611
5477
|
for (const fileName of historyFiles) {
|
|
3612
5478
|
const itemId = fileName.slice(0, -".jsonl".length);
|
|
3613
|
-
const historyPath =
|
|
5479
|
+
const historyPath = path6.join(historyDir, fileName);
|
|
3614
5480
|
let raw = "";
|
|
3615
5481
|
try {
|
|
3616
5482
|
raw = await fs5.readFile(historyPath, "utf8");
|
|
@@ -4221,7 +6087,7 @@ function telemetryEnvFlagEnabled(envKey) {
|
|
|
4221
6087
|
}
|
|
4222
6088
|
function telemetrySourceContextOverride() {
|
|
4223
6089
|
const value = (process.env.PM_TELEMETRY_SOURCE_CONTEXT ?? "").trim().toLowerCase();
|
|
4224
|
-
return
|
|
6090
|
+
return PM_TELEMETRY_SOURCE_CONTEXT_SET2.has(value) ? value : null;
|
|
4225
6091
|
}
|
|
4226
6092
|
function normalizeEndpointForDisplay(rawEndpoint) {
|
|
4227
6093
|
const trimmed = rawEndpoint.trim();
|
|
@@ -4407,9 +6273,9 @@ async function probeTelemetryEndpointHealth(endpoint) {
|
|
|
4407
6273
|
}
|
|
4408
6274
|
async function buildTelemetryCheck(settings, options) {
|
|
4409
6275
|
const globalPmRoot = resolveGlobalPmRoot(process.cwd());
|
|
4410
|
-
const
|
|
4411
|
-
const statePath =
|
|
4412
|
-
const queueRaw = await readFileIfExists(
|
|
6276
|
+
const queuePath2 = path6.join(globalPmRoot, TELEMETRY_QUEUE_RELATIVE_PATH2);
|
|
6277
|
+
const statePath = path6.join(globalPmRoot, TELEMETRY_STATE_RELATIVE_PATH2);
|
|
6278
|
+
const queueRaw = await readFileIfExists(queuePath2);
|
|
4413
6279
|
const queueExists = queueRaw !== null;
|
|
4414
6280
|
const queueSizeBytes = queueRaw ? Buffer.byteLength(queueRaw, "utf8") : 0;
|
|
4415
6281
|
const queueSummary = queueRaw ? parseTelemetryQueue(queueRaw) : emptyTelemetryQueueSummary();
|
|
@@ -4434,7 +6300,7 @@ async function buildTelemetryCheck(settings, options) {
|
|
|
4434
6300
|
capture_level: settings.telemetry.capture_level,
|
|
4435
6301
|
endpoint: endpointDisplay,
|
|
4436
6302
|
global_pm_root: globalPmRoot,
|
|
4437
|
-
queue_path:
|
|
6303
|
+
queue_path: queuePath2,
|
|
4438
6304
|
queue_exists: queueExists,
|
|
4439
6305
|
queue_entries: queueSummary.validEntries,
|
|
4440
6306
|
queue_draining: isTelemetryQueueDraining(queueHasEntries, warnings),
|
|
@@ -4739,7 +6605,7 @@ async function scanHealthDirectories(pmRoot, typeRegistry, strictDirectories) {
|
|
|
4739
6605
|
const missingOptionalDirs = [];
|
|
4740
6606
|
const hookWarnings = [];
|
|
4741
6607
|
for (const relativeDir of [...requiredDirs, ...optionalDirs]) {
|
|
4742
|
-
const directoryPath =
|
|
6608
|
+
const directoryPath = path6.join(pmRoot, relativeDir);
|
|
4743
6609
|
hookWarnings.push(...await runActiveOnReadHooks({
|
|
4744
6610
|
path: directoryPath,
|
|
4745
6611
|
scope: "project"
|
|
@@ -5037,71 +6903,9 @@ var _testOnlyHealthCommand = {
|
|
|
5037
6903
|
warningCode
|
|
5038
6904
|
};
|
|
5039
6905
|
|
|
5040
|
-
// dist/cli/commands/scheduling-shortcuts.js
|
|
5041
|
-
var DEFAULT_DURATION = "1h";
|
|
5042
|
-
var DEFAULT_START = "now";
|
|
5043
|
-
var DEFAULT_REMINDER_AT = "+1d";
|
|
5044
|
-
function quoteCsvValue(value) {
|
|
5045
|
-
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
5046
|
-
}
|
|
5047
|
-
function appendPair(pairs, key, value) {
|
|
5048
|
-
if (value !== void 0) {
|
|
5049
|
-
pairs.push(`${key}=${quoteCsvValue(value)}`);
|
|
5050
|
-
}
|
|
5051
|
-
}
|
|
5052
|
-
function buildCommonOptions(type, title, options) {
|
|
5053
|
-
return {
|
|
5054
|
-
type,
|
|
5055
|
-
title,
|
|
5056
|
-
schedulePreset: "lightweight",
|
|
5057
|
-
parent: options.parent,
|
|
5058
|
-
allowMissingParent: options.allowMissingParent,
|
|
5059
|
-
tags: options.tags,
|
|
5060
|
-
priority: options.priority,
|
|
5061
|
-
body: options.body,
|
|
5062
|
-
description: options.description,
|
|
5063
|
-
author: options.author,
|
|
5064
|
-
message: options.message
|
|
5065
|
-
};
|
|
5066
|
-
}
|
|
5067
|
-
function buildEventEntry(options) {
|
|
5068
|
-
const pairs = [];
|
|
5069
|
-
appendPair(pairs, "start", options.start ?? DEFAULT_START);
|
|
5070
|
-
if (options.end !== void 0) {
|
|
5071
|
-
appendPair(pairs, "end", options.end);
|
|
5072
|
-
} else {
|
|
5073
|
-
appendPair(pairs, "duration", options.duration ?? DEFAULT_DURATION);
|
|
5074
|
-
}
|
|
5075
|
-
appendPair(pairs, "location", options.location);
|
|
5076
|
-
appendPair(pairs, "timezone", options.timezone);
|
|
5077
|
-
if (options.allDay === true) {
|
|
5078
|
-
appendPair(pairs, "all_day", "true");
|
|
5079
|
-
}
|
|
5080
|
-
return pairs.join(",");
|
|
5081
|
-
}
|
|
5082
|
-
async function createScheduled(type, title, options, global) {
|
|
5083
|
-
const createOptions = buildCommonOptions(type, title, options);
|
|
5084
|
-
createOptions.event = [buildEventEntry(options)];
|
|
5085
|
-
return runCreate(createOptions, global);
|
|
5086
|
-
}
|
|
5087
|
-
function runMeet(title, options, global) {
|
|
5088
|
-
return createScheduled("Meeting", title, options, global);
|
|
5089
|
-
}
|
|
5090
|
-
function runEvent(title, options, global) {
|
|
5091
|
-
return createScheduled("Event", title, options, global);
|
|
5092
|
-
}
|
|
5093
|
-
function runRemind(title, options, global) {
|
|
5094
|
-
const createOptions = buildCommonOptions("Reminder", title, options);
|
|
5095
|
-
const pairs = [];
|
|
5096
|
-
appendPair(pairs, "at", options.at ?? DEFAULT_REMINDER_AT);
|
|
5097
|
-
appendPair(pairs, "text", options.text ?? title);
|
|
5098
|
-
createOptions.reminder = [pairs.join(",")];
|
|
5099
|
-
return runCreate(createOptions, global);
|
|
5100
|
-
}
|
|
5101
|
-
|
|
5102
6906
|
// dist/sdk/stats.js
|
|
5103
6907
|
import fs6 from "node:fs/promises";
|
|
5104
|
-
import
|
|
6908
|
+
import path7 from "node:path";
|
|
5105
6909
|
|
|
5106
6910
|
// dist/core/history/history-storage-stats.js
|
|
5107
6911
|
function shouldReplaceExtreme(candidate, current, candidateTieBreaker, currentTieBreaker, direction, tieDirection = "min") {
|
|
@@ -5157,21 +6961,21 @@ function computeHistoryStorageStats(streams, options) {
|
|
|
5157
6961
|
let newestEntry = null;
|
|
5158
6962
|
let globalOldestMs = Number.POSITIVE_INFINITY;
|
|
5159
6963
|
let globalNewestMs = Number.NEGATIVE_INFINITY;
|
|
5160
|
-
for (const
|
|
5161
|
-
totalLines +=
|
|
5162
|
-
totalBytes +=
|
|
5163
|
-
if (
|
|
5164
|
-
const ms = Date.parse(
|
|
5165
|
-
if (shouldReplaceExtreme(ms, globalOldestMs,
|
|
6964
|
+
for (const stat2 of stats) {
|
|
6965
|
+
totalLines += stat2.lines;
|
|
6966
|
+
totalBytes += stat2.bytes;
|
|
6967
|
+
if (stat2.oldest_ts !== null) {
|
|
6968
|
+
const ms = Date.parse(stat2.oldest_ts);
|
|
6969
|
+
if (shouldReplaceExtreme(ms, globalOldestMs, stat2.id, oldestEntry?.id ?? null, "min")) {
|
|
5166
6970
|
globalOldestMs = ms;
|
|
5167
|
-
oldestEntry = { id:
|
|
6971
|
+
oldestEntry = { id: stat2.id, ts: stat2.oldest_ts };
|
|
5168
6972
|
}
|
|
5169
6973
|
}
|
|
5170
|
-
if (
|
|
5171
|
-
const ms = Date.parse(
|
|
5172
|
-
if (shouldReplaceExtreme(ms, globalNewestMs,
|
|
6974
|
+
if (stat2.newest_ts !== null) {
|
|
6975
|
+
const ms = Date.parse(stat2.newest_ts);
|
|
6976
|
+
if (shouldReplaceExtreme(ms, globalNewestMs, stat2.id, newestEntry?.id ?? null, "max")) {
|
|
5173
6977
|
globalNewestMs = ms;
|
|
5174
|
-
newestEntry = { id:
|
|
6978
|
+
newestEntry = { id: stat2.id, ts: stat2.newest_ts };
|
|
5175
6979
|
}
|
|
5176
6980
|
}
|
|
5177
6981
|
}
|
|
@@ -5208,7 +7012,7 @@ function countNonEmptyLines(raw) {
|
|
|
5208
7012
|
return raw.split(/\r?\n/u).filter((line) => line.trim().length > 0).length;
|
|
5209
7013
|
}
|
|
5210
7014
|
async function readHistoryStreamContents(pmRoot) {
|
|
5211
|
-
const historyDir =
|
|
7015
|
+
const historyDir = path7.join(pmRoot, "history");
|
|
5212
7016
|
if (!await pathExists(historyDir)) {
|
|
5213
7017
|
return [];
|
|
5214
7018
|
}
|
|
@@ -5219,7 +7023,7 @@ async function readHistoryStreamContents(pmRoot) {
|
|
|
5219
7023
|
const historyFiles = (await fs6.readdir(historyDir)).filter((entry) => entry.endsWith(".jsonl")).sort((a, b) => a.localeCompare(b));
|
|
5220
7024
|
const streams = [];
|
|
5221
7025
|
for (const file of historyFiles) {
|
|
5222
|
-
const historyPath =
|
|
7026
|
+
const historyPath = path7.join(historyDir, file);
|
|
5223
7027
|
const raw = await readFileIfExists(historyPath);
|
|
5224
7028
|
if (raw === null) {
|
|
5225
7029
|
continue;
|
|
@@ -5293,10 +7097,10 @@ async function runStats(global, options = {}) {
|
|
|
5293
7097
|
|
|
5294
7098
|
// dist/sdk/telemetry.js
|
|
5295
7099
|
import fs7 from "node:fs/promises";
|
|
5296
|
-
import
|
|
5297
|
-
var
|
|
5298
|
-
var
|
|
5299
|
-
var TELEMETRY_RUNTIME_RELATIVE_PATH =
|
|
7100
|
+
import path8 from "node:path";
|
|
7101
|
+
var TELEMETRY_QUEUE_RELATIVE_PATH3 = path8.join("runtime", "telemetry", "events.jsonl");
|
|
7102
|
+
var TELEMETRY_STATE_RELATIVE_PATH3 = path8.join("runtime", "telemetry", "state.json");
|
|
7103
|
+
var TELEMETRY_RUNTIME_RELATIVE_PATH = path8.join("runtime", "telemetry");
|
|
5300
7104
|
var DEFAULT_STATS_LIMIT = 20;
|
|
5301
7105
|
var TELEMETRY_SUBCOMMANDS = [
|
|
5302
7106
|
"status",
|
|
@@ -5513,15 +7317,15 @@ var readTelemetryRuntimeState = async (statePath) => {
|
|
|
5513
7317
|
var nullableTelemetryStateValue = (value) => value ?? null;
|
|
5514
7318
|
var buildTelemetryStatusSummary = async (globalPmRoot) => {
|
|
5515
7319
|
const settings = await readSettings(globalPmRoot);
|
|
5516
|
-
const
|
|
5517
|
-
const statePath =
|
|
5518
|
-
const queueRaw = await readFileIfExists(
|
|
7320
|
+
const queuePath2 = path8.join(globalPmRoot, TELEMETRY_QUEUE_RELATIVE_PATH3);
|
|
7321
|
+
const statePath = path8.join(globalPmRoot, TELEMETRY_STATE_RELATIVE_PATH3);
|
|
7322
|
+
const queueRaw = await readFileIfExists(queuePath2);
|
|
5519
7323
|
const queue = parseTelemetryQueue2(queueRaw);
|
|
5520
7324
|
const runtimeState = await readTelemetryRuntimeState(statePath);
|
|
5521
7325
|
return {
|
|
5522
7326
|
enabled: settings.telemetry.enabled,
|
|
5523
7327
|
endpoint: settings.telemetry.endpoint,
|
|
5524
|
-
queue_path:
|
|
7328
|
+
queue_path: queuePath2,
|
|
5525
7329
|
state_path: statePath,
|
|
5526
7330
|
queue_rows_total: queue.rows_total,
|
|
5527
7331
|
queue_entries: queue.valid_entries,
|
|
@@ -5592,7 +7396,7 @@ var runTelemetryClear = async (_options, context) => {
|
|
|
5592
7396
|
if (settingsChanged) {
|
|
5593
7397
|
await writeSettings(context.globalPmRoot, settings, "telemetry:clear");
|
|
5594
7398
|
}
|
|
5595
|
-
const telemetryRuntimePath =
|
|
7399
|
+
const telemetryRuntimePath = path8.join(context.globalPmRoot, TELEMETRY_RUNTIME_RELATIVE_PATH);
|
|
5596
7400
|
const existed = await pathExists(telemetryRuntimePath);
|
|
5597
7401
|
await fs7.rm(telemetryRuntimePath, { recursive: true, force: true });
|
|
5598
7402
|
return {
|
|
@@ -5618,8 +7422,8 @@ var runTelemetry = async (options, _global) => {
|
|
|
5618
7422
|
const globalPmRoot = resolveGlobalPmRoot(process.cwd());
|
|
5619
7423
|
return TELEMETRY_COMMAND_HANDLERS[subcommand](options, {
|
|
5620
7424
|
globalPmRoot,
|
|
5621
|
-
queuePath:
|
|
5622
|
-
statePath:
|
|
7425
|
+
queuePath: path8.join(globalPmRoot, TELEMETRY_QUEUE_RELATIVE_PATH3),
|
|
7426
|
+
statePath: path8.join(globalPmRoot, TELEMETRY_STATE_RELATIVE_PATH3)
|
|
5623
7427
|
});
|
|
5624
7428
|
};
|
|
5625
7429
|
|
|
@@ -6080,10 +7884,10 @@ function firstPositionalToken(tokens, flagsWithValue = /* @__PURE__ */ new Set()
|
|
|
6080
7884
|
}
|
|
6081
7885
|
|
|
6082
7886
|
// dist/sdk/test/execution.js
|
|
6083
|
-
import { spawn } from "node:child_process";
|
|
6084
|
-
import { cp, mkdir, mkdtemp, readdir, rm } from "node:fs/promises";
|
|
7887
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
7888
|
+
import { cp, mkdir as mkdir2, mkdtemp, readdir as readdir2, rm as rm2 } from "node:fs/promises";
|
|
6085
7889
|
import { tmpdir } from "node:os";
|
|
6086
|
-
import
|
|
7890
|
+
import path9 from "node:path";
|
|
6087
7891
|
|
|
6088
7892
|
// dist/core/test/item-test-run-tracking.js
|
|
6089
7893
|
var DEFAULT_TRACKED_TEST_RUN_HISTORY_LIMIT = 20;
|
|
@@ -6762,7 +8566,7 @@ async function killProcessTree(pid) {
|
|
|
6762
8566
|
}
|
|
6763
8567
|
if (process.platform === "win32") {
|
|
6764
8568
|
await new Promise((resolve) => {
|
|
6765
|
-
const killer =
|
|
8569
|
+
const killer = spawn2("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
6766
8570
|
stdio: "ignore",
|
|
6767
8571
|
windowsHide: true
|
|
6768
8572
|
});
|
|
@@ -6899,7 +8703,7 @@ function waitForLinkedTestChildClose(child) {
|
|
|
6899
8703
|
});
|
|
6900
8704
|
}
|
|
6901
8705
|
function createLinkedTestChild(command, env) {
|
|
6902
|
-
return
|
|
8706
|
+
return spawn2(command, {
|
|
6903
8707
|
cwd: process.cwd(),
|
|
6904
8708
|
env,
|
|
6905
8709
|
shell: true,
|
|
@@ -7071,7 +8875,7 @@ async function copyIntoSandboxIfPresent(sourcePath, targetPath, recursive = fals
|
|
|
7071
8875
|
if (!await pathExists(sourcePath)) {
|
|
7072
8876
|
return;
|
|
7073
8877
|
}
|
|
7074
|
-
await
|
|
8878
|
+
await mkdir2(path9.dirname(targetPath), { recursive: true });
|
|
7075
8879
|
try {
|
|
7076
8880
|
if (recursive) {
|
|
7077
8881
|
await cp(sourcePath, targetPath, { recursive: true, force: true });
|
|
@@ -7087,21 +8891,21 @@ async function copyIntoSandboxIfPresent(sourcePath, targetPath, recursive = fals
|
|
|
7087
8891
|
}
|
|
7088
8892
|
async function seedLinkedTestSandbox(sandboxPmPath, sandboxGlobalPath, sourceRoots) {
|
|
7089
8893
|
await copyIntoSandboxIfPresent(getSettingsPath(sourceRoots.projectPmRoot), getSettingsPath(sandboxPmPath));
|
|
7090
|
-
await copyIntoSandboxIfPresent(
|
|
8894
|
+
await copyIntoSandboxIfPresent(path9.join(sourceRoots.projectPmRoot, "extensions"), path9.join(sandboxPmPath, "extensions"), true);
|
|
7091
8895
|
await copyIntoSandboxIfPresent(getSettingsPath(sourceRoots.globalPmRoot), getSettingsPath(sandboxGlobalPath));
|
|
7092
|
-
await copyIntoSandboxIfPresent(
|
|
8896
|
+
await copyIntoSandboxIfPresent(path9.join(sourceRoots.globalPmRoot, "extensions"), path9.join(sandboxGlobalPath, "extensions"), true);
|
|
7093
8897
|
}
|
|
7094
8898
|
async function seedLinkedTestTrackerData(sourceRoot, sandboxRoot) {
|
|
7095
8899
|
if (!await pathExists(sourceRoot)) {
|
|
7096
8900
|
return;
|
|
7097
8901
|
}
|
|
7098
|
-
const entries = await
|
|
8902
|
+
const entries = await readdir2(sourceRoot, { withFileTypes: true });
|
|
7099
8903
|
for (const entry of entries) {
|
|
7100
8904
|
if (LINKED_TEST_TRACKER_DIRS_TO_SKIP.has(entry.name)) {
|
|
7101
8905
|
continue;
|
|
7102
8906
|
}
|
|
7103
|
-
const sourcePath =
|
|
7104
|
-
const targetPath =
|
|
8907
|
+
const sourcePath = path9.join(sourceRoot, entry.name);
|
|
8908
|
+
const targetPath = path9.join(sandboxRoot, entry.name);
|
|
7105
8909
|
if (entry.isDirectory()) {
|
|
7106
8910
|
await copyIntoSandboxIfPresent(sourcePath, targetPath, true);
|
|
7107
8911
|
continue;
|
|
@@ -7116,15 +8920,15 @@ async function countLinkedTestItemFiles(pmRoot) {
|
|
|
7116
8920
|
return 0;
|
|
7117
8921
|
}
|
|
7118
8922
|
let total = 0;
|
|
7119
|
-
const entries = await
|
|
8923
|
+
const entries = await readdir2(pmRoot, { withFileTypes: true });
|
|
7120
8924
|
for (const entry of entries) {
|
|
7121
8925
|
if (!entry.isDirectory() || LINKED_TEST_ITEM_COUNT_DIRS_TO_SKIP.has(entry.name)) {
|
|
7122
8926
|
continue;
|
|
7123
8927
|
}
|
|
7124
|
-
const folderPath =
|
|
8928
|
+
const folderPath = path9.join(pmRoot, entry.name);
|
|
7125
8929
|
let files;
|
|
7126
8930
|
try {
|
|
7127
|
-
files = await
|
|
8931
|
+
files = await readdir2(folderPath, { withFileTypes: true });
|
|
7128
8932
|
} catch {
|
|
7129
8933
|
continue;
|
|
7130
8934
|
}
|
|
@@ -7316,10 +9120,10 @@ ${stderr}`;
|
|
|
7316
9120
|
function createLinkedTestSandboxLayout(sandboxRoot) {
|
|
7317
9121
|
return {
|
|
7318
9122
|
root: sandboxRoot,
|
|
7319
|
-
schemaProjectPmPath:
|
|
7320
|
-
schemaGlobalPmPath:
|
|
7321
|
-
trackerProjectPmPath:
|
|
7322
|
-
trackerGlobalPmPath:
|
|
9123
|
+
schemaProjectPmPath: path9.join(sandboxRoot, "schema", "project", ".agents", "pm"),
|
|
9124
|
+
schemaGlobalPmPath: path9.join(sandboxRoot, "schema", "global"),
|
|
9125
|
+
trackerProjectPmPath: path9.join(sandboxRoot, "tracker", "project", ".agents", "pm"),
|
|
9126
|
+
trackerGlobalPmPath: path9.join(sandboxRoot, "tracker", "global")
|
|
7323
9127
|
};
|
|
7324
9128
|
}
|
|
7325
9129
|
async function initializeLinkedTestSandboxes(layout) {
|
|
@@ -7519,7 +9323,7 @@ async function runSingleLinkedTest(params) {
|
|
|
7519
9323
|
}
|
|
7520
9324
|
async function runLinkedTests(tests, defaultTimeoutSeconds, options) {
|
|
7521
9325
|
const results = [];
|
|
7522
|
-
const sandboxRoot = await mkdtemp(
|
|
9326
|
+
const sandboxRoot = await mkdtemp(path9.join(tmpdir(), "pm-linked-test-"));
|
|
7523
9327
|
const layout = createLinkedTestSandboxLayout(sandboxRoot);
|
|
7524
9328
|
const runLevelPmContextMode = parsePmContextMode(options?.pmContext);
|
|
7525
9329
|
const progressMode = options?.progress === true ? "always" : "auto";
|
|
@@ -7562,7 +9366,7 @@ async function runLinkedTests(tests, defaultTimeoutSeconds, options) {
|
|
|
7562
9366
|
}));
|
|
7563
9367
|
}
|
|
7564
9368
|
} finally {
|
|
7565
|
-
await
|
|
9369
|
+
await rm2(layout.root, {
|
|
7566
9370
|
recursive: true,
|
|
7567
9371
|
force: true,
|
|
7568
9372
|
maxRetries: 3,
|
|
@@ -8230,13 +10034,13 @@ var runTestAll = async (options, global) => {
|
|
|
8230
10034
|
};
|
|
8231
10035
|
|
|
8232
10036
|
// dist/sdk/test/runs.js
|
|
8233
|
-
import
|
|
10037
|
+
import os2 from "node:os";
|
|
8234
10038
|
|
|
8235
10039
|
// dist/core/test/background-runs.js
|
|
8236
10040
|
import fs8 from "node:fs/promises";
|
|
8237
|
-
import { spawn as
|
|
10041
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
8238
10042
|
import { createHash, randomBytes } from "node:crypto";
|
|
8239
|
-
import
|
|
10043
|
+
import path10 from "node:path";
|
|
8240
10044
|
var BACKGROUND_RUN_ACTIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
8241
10045
|
"queued",
|
|
8242
10046
|
"running"
|
|
@@ -8274,7 +10078,7 @@ function buildBackgroundTestRunFingerprint(kind, commandArgs, pmRoot) {
|
|
|
8274
10078
|
const payload = {
|
|
8275
10079
|
kind,
|
|
8276
10080
|
command: normalizeCommandArgs(commandArgs),
|
|
8277
|
-
pm_root:
|
|
10081
|
+
pm_root: path10.resolve(pmRoot)
|
|
8278
10082
|
};
|
|
8279
10083
|
return createHash("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
8280
10084
|
}
|
|
@@ -8330,7 +10134,7 @@ async function listBackgroundRunRecordPaths(pmRoot) {
|
|
|
8330
10134
|
return [];
|
|
8331
10135
|
}
|
|
8332
10136
|
const entries = await fs8.readdir(recordsRoot, { withFileTypes: true });
|
|
8333
|
-
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) =>
|
|
10137
|
+
return entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => path10.join(recordsRoot, entry.name)).sort((left, right) => right.localeCompare(left));
|
|
8334
10138
|
}
|
|
8335
10139
|
function parseLinuxRssStatus(raw) {
|
|
8336
10140
|
const match = raw.match(/^VmRSS:\s+(\d+)\s+kB$/m);
|
|
@@ -8508,18 +10312,18 @@ function tailLines(value, limit) {
|
|
|
8508
10312
|
async function resolveBackgroundCliEntry(cwd) {
|
|
8509
10313
|
const configured = process.env.PM_BACKGROUND_CLI_ENTRY?.trim();
|
|
8510
10314
|
if (configured && configured.length > 0) {
|
|
8511
|
-
const resolvedConfigured =
|
|
10315
|
+
const resolvedConfigured = path10.resolve(cwd, configured);
|
|
8512
10316
|
if (await pathExists(resolvedConfigured)) {
|
|
8513
10317
|
return resolvedConfigured;
|
|
8514
10318
|
}
|
|
8515
10319
|
}
|
|
8516
|
-
const distEntry =
|
|
10320
|
+
const distEntry = path10.resolve(cwd, "dist", "cli.js");
|
|
8517
10321
|
if (await pathExists(distEntry)) {
|
|
8518
10322
|
return distEntry;
|
|
8519
10323
|
}
|
|
8520
10324
|
const argvEntry = process.argv[1]?.trim();
|
|
8521
10325
|
if (argvEntry && argvEntry.length > 0) {
|
|
8522
|
-
const resolvedArgvEntry =
|
|
10326
|
+
const resolvedArgvEntry = path10.resolve(cwd, argvEntry);
|
|
8523
10327
|
if (await pathExists(resolvedArgvEntry)) {
|
|
8524
10328
|
return resolvedArgvEntry;
|
|
8525
10329
|
}
|
|
@@ -8633,7 +10437,7 @@ async function spawnBackgroundTestRunWorker(options) {
|
|
|
8633
10437
|
PM_BACKGROUND_TEST_RUN_RESUMED_FROM: record.resumed_from ?? "",
|
|
8634
10438
|
FORCE_COLOR: "0"
|
|
8635
10439
|
};
|
|
8636
|
-
const child =
|
|
10440
|
+
const child = spawn3(process.execPath, [cliEntry, ...args], {
|
|
8637
10441
|
cwd: process.cwd(),
|
|
8638
10442
|
env,
|
|
8639
10443
|
detached: true,
|
|
@@ -8815,7 +10619,7 @@ async function runBackgroundTestRunWorker(pmRoot, runId, noExtensions = false) {
|
|
|
8815
10619
|
const env = buildBackgroundWorkerEnv(record);
|
|
8816
10620
|
await writeBackgroundRunRecord(pmRoot, record);
|
|
8817
10621
|
const childArgs = buildBackgroundWorkerChildArgs(record, noExtensions);
|
|
8818
|
-
const child =
|
|
10622
|
+
const child = spawn3(process.execPath, [cliEntry, ...childArgs], {
|
|
8819
10623
|
cwd: process.cwd(),
|
|
8820
10624
|
env,
|
|
8821
10625
|
detached: false,
|
|
@@ -9100,7 +10904,7 @@ function normalizeStream(value) {
|
|
|
9100
10904
|
}
|
|
9101
10905
|
function resolveWhoamiFallback() {
|
|
9102
10906
|
try {
|
|
9103
|
-
const username =
|
|
10907
|
+
const username = os2.userInfo().username.trim();
|
|
9104
10908
|
if (username.length > 0) {
|
|
9105
10909
|
return username;
|
|
9106
10910
|
}
|
|
@@ -9239,7 +11043,7 @@ async function runTestRunsWorker(runId, global) {
|
|
|
9239
11043
|
import fs9 from "node:fs/promises";
|
|
9240
11044
|
import { realpathSync } from "node:fs";
|
|
9241
11045
|
import { execFile } from "node:child_process";
|
|
9242
|
-
import
|
|
11046
|
+
import path11 from "node:path";
|
|
9243
11047
|
import { promisify } from "node:util";
|
|
9244
11048
|
|
|
9245
11049
|
// dist/core/validate/fix-planning.js
|
|
@@ -9545,8 +11349,8 @@ function buildMissingLinkedPathRows(rows, lookup) {
|
|
|
9545
11349
|
});
|
|
9546
11350
|
}
|
|
9547
11351
|
}
|
|
9548
|
-
return [...buckets.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([
|
|
9549
|
-
path:
|
|
11352
|
+
return [...buckets.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([path12, bucket]) => ({
|
|
11353
|
+
path: path12,
|
|
9550
11354
|
classification: bucket.classification,
|
|
9551
11355
|
items: [...bucket.owners.values()].map((owner) => {
|
|
9552
11356
|
const metadata = lookup(owner.item_id);
|
|
@@ -9883,16 +11687,16 @@ function resolveFileScanMode(scanMode) {
|
|
|
9883
11687
|
throw new PmCliError(`Unknown --scan-mode value "${scanMode}". Supported values: ${VALIDATE_FILE_SCAN_MODES.join(", ")}.`, EXIT_CODE.USAGE);
|
|
9884
11688
|
}
|
|
9885
11689
|
function resolveWorkspaceRoot(pmRoot) {
|
|
9886
|
-
const resolvedPmRoot =
|
|
11690
|
+
const resolvedPmRoot = path11.resolve(pmRoot);
|
|
9887
11691
|
const normalizedPmRoot = resolvedPmRoot.replaceAll("\\", "/");
|
|
9888
11692
|
if (normalizedPmRoot.endsWith("/.agents/pm")) {
|
|
9889
|
-
return
|
|
11693
|
+
return path11.dirname(path11.dirname(resolvedPmRoot));
|
|
9890
11694
|
}
|
|
9891
|
-
const resolvedCwd =
|
|
11695
|
+
const resolvedCwd = path11.resolve(process.cwd());
|
|
9892
11696
|
const canonicalPmRoot = realpathForWorkspaceRoot(resolvedPmRoot);
|
|
9893
11697
|
const canonicalCwd = realpathForWorkspaceRoot(resolvedCwd);
|
|
9894
|
-
const relativeFromPmRoot =
|
|
9895
|
-
const cwdInsidePmRoot = relativeFromPmRoot.length === 0 || !relativeFromPmRoot.startsWith("..") && !
|
|
11698
|
+
const relativeFromPmRoot = path11.relative(canonicalPmRoot, canonicalCwd);
|
|
11699
|
+
const cwdInsidePmRoot = relativeFromPmRoot.length === 0 || !relativeFromPmRoot.startsWith("..") && !path11.isAbsolute(relativeFromPmRoot);
|
|
9896
11700
|
if (cwdInsidePmRoot) {
|
|
9897
11701
|
return resolvedPmRoot;
|
|
9898
11702
|
}
|
|
@@ -9902,11 +11706,11 @@ function realpathForWorkspaceRoot(inputPath) {
|
|
|
9902
11706
|
try {
|
|
9903
11707
|
return realpathSync.native(inputPath);
|
|
9904
11708
|
} catch {
|
|
9905
|
-
return
|
|
11709
|
+
return path11.resolve(inputPath);
|
|
9906
11710
|
}
|
|
9907
11711
|
}
|
|
9908
11712
|
async function listFilesRecursive(basePath, relativePath, output) {
|
|
9909
|
-
const targetDirectory = relativePath.length > 0 ?
|
|
11713
|
+
const targetDirectory = relativePath.length > 0 ? path11.join(basePath, relativePath) : basePath;
|
|
9910
11714
|
let entries;
|
|
9911
11715
|
try {
|
|
9912
11716
|
entries = await fs9.readdir(targetDirectory, { withFileTypes: true });
|
|
@@ -9920,7 +11724,7 @@ async function listFilesRecursive(basePath, relativePath, output) {
|
|
|
9920
11724
|
if (entry.name.startsWith(".")) {
|
|
9921
11725
|
continue;
|
|
9922
11726
|
}
|
|
9923
|
-
const childRelative = relativePath.length > 0 ?
|
|
11727
|
+
const childRelative = relativePath.length > 0 ? path11.join(relativePath, entry.name) : entry.name;
|
|
9924
11728
|
if (entry.isDirectory()) {
|
|
9925
11729
|
if (DIRECTORY_IGNORE_SET.has(entry.name)) {
|
|
9926
11730
|
continue;
|
|
@@ -9940,7 +11744,7 @@ async function collectDefaultProjectFileCandidates(workspaceRoot) {
|
|
|
9940
11744
|
await listFilesRecursive(workspaceRoot, directory, discovered);
|
|
9941
11745
|
}
|
|
9942
11746
|
for (const candidate of FILE_SCAN_ROOT_FILES) {
|
|
9943
|
-
const absolute =
|
|
11747
|
+
const absolute = path11.join(workspaceRoot, candidate);
|
|
9944
11748
|
try {
|
|
9945
11749
|
const stats = await fs9.stat(absolute);
|
|
9946
11750
|
if (stats.isFile()) {
|
|
@@ -9972,7 +11776,7 @@ function resolvePmInternalCandidatePrefixes(pmRoot, workspaceRoot) {
|
|
|
9972
11776
|
if (configuredDefault.length > 0) {
|
|
9973
11777
|
prefixes.add(configuredDefault);
|
|
9974
11778
|
}
|
|
9975
|
-
const relativePmRoot = normalizeRelativeDirectoryPath(
|
|
11779
|
+
const relativePmRoot = normalizeRelativeDirectoryPath(path11.relative(workspaceRoot, pmRoot));
|
|
9976
11780
|
if (relativePmRoot.length > 0 && !relativePmRoot.startsWith("..")) {
|
|
9977
11781
|
prefixes.add(relativePmRoot);
|
|
9978
11782
|
}
|
|
@@ -10452,30 +12256,30 @@ function resolveLifecycleDependencyCycleSamplePath(component, graph) {
|
|
|
10452
12256
|
return [start, start];
|
|
10453
12257
|
}
|
|
10454
12258
|
const componentSet = new Set(component);
|
|
10455
|
-
const
|
|
12259
|
+
const path12 = [start];
|
|
10456
12260
|
const visited = /* @__PURE__ */ new Set([start]);
|
|
10457
12261
|
const search = (current) => {
|
|
10458
12262
|
const neighbors = (graph.get(current) ?? []).filter((candidate) => componentSet.has(candidate));
|
|
10459
12263
|
for (const next of neighbors) {
|
|
10460
|
-
if (next === start &&
|
|
10461
|
-
|
|
12264
|
+
if (next === start && path12.length > 1) {
|
|
12265
|
+
path12.push(start);
|
|
10462
12266
|
return true;
|
|
10463
12267
|
}
|
|
10464
12268
|
if (visited.has(next)) {
|
|
10465
12269
|
continue;
|
|
10466
12270
|
}
|
|
10467
12271
|
visited.add(next);
|
|
10468
|
-
|
|
12272
|
+
path12.push(next);
|
|
10469
12273
|
if (search(next)) {
|
|
10470
12274
|
return true;
|
|
10471
12275
|
}
|
|
10472
|
-
|
|
12276
|
+
path12.pop();
|
|
10473
12277
|
visited.delete(next);
|
|
10474
12278
|
}
|
|
10475
12279
|
return false;
|
|
10476
12280
|
};
|
|
10477
12281
|
if (search(start)) {
|
|
10478
|
-
return [...
|
|
12282
|
+
return [...path12];
|
|
10479
12283
|
}
|
|
10480
12284
|
return [...component, start];
|
|
10481
12285
|
}
|
|
@@ -10733,7 +12537,7 @@ function linkedArtifactPathExceedsFilesystemLimits(artifactPath) {
|
|
|
10733
12537
|
return normalized.length > LINKED_ARTIFACT_MAX_PATH_LENGTH || normalized.split(/[\\/]/).some((segment) => segment.length > LINKED_ARTIFACT_MAX_SEGMENT_LENGTH);
|
|
10734
12538
|
}
|
|
10735
12539
|
async function linkedArtifactIsMissing(workspaceRoot, artifactPath) {
|
|
10736
|
-
const absolutePath =
|
|
12540
|
+
const absolutePath = path11.isAbsolute(artifactPath) ? artifactPath : path11.resolve(workspaceRoot, artifactPath);
|
|
10737
12541
|
if (linkedArtifactPathExceedsFilesystemLimits(absolutePath)) {
|
|
10738
12542
|
return false;
|
|
10739
12543
|
}
|
|
@@ -11399,20 +13203,31 @@ var runValidate2 = (options, global) => runValidate(options, global, {
|
|
|
11399
13203
|
runUpdate: (id, updateOptions, updateGlobal) => runUpdate(id, updateOptions, updateGlobal)
|
|
11400
13204
|
});
|
|
11401
13205
|
|
|
13206
|
+
// dist/sdk/start-task-status.js
|
|
13207
|
+
function resolveStartTaskInProgressStatus(statusRegistry) {
|
|
13208
|
+
return normalizeStatusInputWithRegistry("in_progress", statusRegistry) ?? statusRegistry.open_status;
|
|
13209
|
+
}
|
|
13210
|
+
|
|
11402
13211
|
export {
|
|
11403
|
-
|
|
13212
|
+
deriveTelemetryCommandTaxonomy,
|
|
13213
|
+
deriveTelemetryCommandResolution,
|
|
13214
|
+
flushTelemetryQueueNow,
|
|
13215
|
+
startTelemetryCommand,
|
|
13216
|
+
finishTelemetryCommand,
|
|
13217
|
+
emitTelemetryErrorEvent,
|
|
13218
|
+
describeItemOwnershipConflict,
|
|
11404
13219
|
runClaim,
|
|
11405
13220
|
runClaimNext,
|
|
11406
13221
|
runRelease,
|
|
11407
13222
|
runContracts,
|
|
13223
|
+
runMeet,
|
|
13224
|
+
runEvent,
|
|
13225
|
+
runRemind,
|
|
11408
13226
|
runGc,
|
|
11409
13227
|
inspectHistoryAuthorStream,
|
|
11410
13228
|
scanHistoryAuthorAttribution,
|
|
11411
13229
|
runHealth,
|
|
11412
13230
|
_testOnlyHealthCommand,
|
|
11413
|
-
runMeet,
|
|
11414
|
-
runEvent,
|
|
11415
|
-
runRemind,
|
|
11416
13231
|
runStats,
|
|
11417
13232
|
TELEMETRY_SUBCOMMANDS,
|
|
11418
13233
|
runTelemetry,
|
|
@@ -11433,8 +13248,9 @@ export {
|
|
|
11433
13248
|
runTestRunsWorker,
|
|
11434
13249
|
_testOnlyValidateCommand,
|
|
11435
13250
|
runValidate,
|
|
11436
|
-
runValidate2
|
|
13251
|
+
runValidate2,
|
|
13252
|
+
resolveStartTaskInProgressStatus
|
|
11437
13253
|
};
|
|
11438
|
-
//# sourceMappingURL=chunk-
|
|
13254
|
+
//# sourceMappingURL=chunk-ODEIDKGW.js.map
|
|
11439
13255
|
|
|
11440
|
-
//# debugId=
|
|
13256
|
+
//# debugId=b111adf0-7ac6-5083-9fb7-c9a093abf43b
|