agentic-qe 3.15.17 → 3.15.18
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/helpers/brain-checkpoint.cjs +107 -10
- package/.claude/skills/agentic-quality-engineering/SKILL.md +67 -44
- package/.claude/skills/brutal-honesty-review/SKILL.md +12 -7
- package/.claude/skills/brutal-honesty-review/evals/brutal-honesty-review.yaml +120 -0
- package/.claude/skills/brutal-honesty-review/schemas/output.json +9 -3
- package/.claude/skills/code-review-quality/SKILL.md +2 -2
- package/.claude/skills/holistic-testing-pact/SKILL.md +11 -11
- package/.claude/skills/sherlock-review/SKILL.md +4 -2
- package/.claude/skills/sherlock-review/evals/sherlock-review.yaml +124 -0
- package/.claude/skills/skills-manifest.json +1 -1
- package/.claude/skills/technical-writing/SKILL.md +12 -6
- package/.claude/skills/technical-writing/evals/technical-writing.yaml +96 -0
- package/.opencode/skills/qe-agentic-quality-engineering.yaml +2 -2
- package/.opencode/skills/qe-holistic-testing-pact.yaml +2 -2
- package/CHANGELOG.md +123 -0
- package/assets/skills/agentic-quality-engineering/SKILL.md +67 -44
- package/assets/skills/brutal-honesty-review/SKILL.md +12 -8
- package/assets/skills/brutal-honesty-review/evals/brutal-honesty-review.yaml +120 -0
- package/assets/skills/brutal-honesty-review/schemas/output.json +9 -3
- package/assets/skills/code-review-quality/SKILL.md +2 -2
- package/assets/skills/holistic-testing-pact/SKILL.md +11 -11
- package/assets/skills/sherlock-review/SKILL.md +4 -3
- package/assets/skills/sherlock-review/evals/sherlock-review.yaml +124 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/assets/skills/technical-writing/SKILL.md +12 -6
- package/assets/skills/technical-writing/evals/technical-writing.yaml +96 -0
- package/dist/cli/brain-commands.d.ts +5 -0
- package/dist/cli/brain-commands.js +4 -0
- package/dist/cli/bundle.js +6 -6
- package/dist/cli/chunks/adapter-WRSDXLOT.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-6BUOFQZA.js → agent-booster-wasm-UFNJNF3M.js} +2 -2
- package/dist/cli/chunks/{agent-handler-HPDK3JI3.js → agent-handler-EAYVRJXN.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-5QKUTWK5.js → agent-memory-branch-M65C6WAQ.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-O6NJBCCM.js +2 -0
- package/dist/cli/chunks/{arena-HZ35LESR.js → arena-2GDICP6R.js} +4 -4
- package/dist/cli/chunks/{arena-7OKPMNHD.js → arena-CG3X67OE.js} +2 -2
- package/dist/cli/chunks/{audit-XI575SVK.js → audit-F4FSPJPL.js} +3 -3
- package/dist/cli/chunks/base-J2FXOE77.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-YO5X7ZJS.js → better-sqlite3-2MCFXW4J.js} +2 -2
- package/dist/cli/chunks/brain-handler-WGTJNYNB.js +95 -0
- package/dist/cli/chunks/{branch-enumerator-N6G44UU2.js → branch-enumerator-KL7C535H.js} +2 -2
- package/dist/cli/chunks/{browser-EVKPTLOI.js → browser-SJEXDVHS.js} +2 -2
- package/dist/cli/chunks/browser-workflow-LXGER6ZD.js +2 -0
- package/dist/cli/chunks/{chunk-VLTDW7XJ.js → chunk-244RKAEP.js} +2 -2
- package/dist/cli/chunks/{chunk-CVPXHDQU.js → chunk-27TUMXPD.js} +1 -1
- package/dist/cli/chunks/{chunk-FBBPRVNF.js → chunk-2MBYDPCP.js} +2 -2
- package/dist/cli/chunks/{chunk-P3D7SEHW.js → chunk-2Q6DTBMT.js} +1 -1
- package/dist/cli/chunks/{chunk-NE3LRUNC.js → chunk-355MI7RV.js} +13 -13
- package/dist/cli/chunks/{chunk-YCVLKU6H.js → chunk-3LX5OKBD.js} +2 -2
- package/dist/cli/chunks/{chunk-74MDUIAZ.js → chunk-3RPDKJGV.js} +1 -1
- package/dist/cli/chunks/{chunk-OWIQR6N2.js → chunk-3YMIT73A.js} +2 -2
- package/dist/cli/chunks/{chunk-VKREKVFI.js → chunk-43KUVBSU.js} +2 -2
- package/dist/cli/chunks/chunk-477FKXSS.js +2 -0
- package/dist/cli/chunks/{chunk-XPTCQKVE.js → chunk-4BIMTRRX.js} +1 -1
- package/dist/cli/chunks/{chunk-HD6W6PHV.js → chunk-4CVNVBX5.js} +2 -2
- package/dist/cli/chunks/{chunk-CQER6IJ5.js → chunk-4HL3SD4A.js} +1 -1
- package/dist/cli/chunks/{chunk-ZNXM6WVL.js → chunk-4PEG4DU2.js} +2 -2
- package/dist/cli/chunks/{chunk-BSIWI4ES.js → chunk-4QSQKFED.js} +2 -2
- package/dist/cli/chunks/chunk-53ZBETYR.js +16 -0
- package/dist/cli/chunks/{chunk-BHQ2DLJU.js → chunk-544KDWL4.js} +1 -1
- package/dist/cli/chunks/chunk-54RCGMLB.js +8 -0
- package/dist/cli/chunks/{chunk-TDZ6N43D.js → chunk-5AGXIZQ5.js} +2 -2
- package/dist/cli/chunks/{chunk-RKCN4B26.js → chunk-5M24X6W7.js} +2 -2
- package/dist/cli/chunks/{chunk-GG7PMTHD.js → chunk-5O5T4LEU.js} +1 -1
- package/dist/cli/chunks/{chunk-OWIZBZLN.js → chunk-5RFXX4IF.js} +2 -2
- package/dist/cli/chunks/{chunk-VQFV2IPV.js → chunk-62MLAQRJ.js} +1 -1
- package/dist/cli/chunks/{chunk-PCL5JRKN.js → chunk-6D6TGL2E.js} +2 -2
- package/dist/cli/chunks/{chunk-WBDWHHKP.js → chunk-6IHZDSDL.js} +2 -2
- package/dist/cli/chunks/{chunk-UOVCTK5L.js → chunk-6P3Y45QL.js} +2 -2
- package/dist/cli/chunks/{chunk-45223KK6.js → chunk-6TEVM3X3.js} +10 -10
- package/dist/cli/chunks/{chunk-K7WAI662.js → chunk-7XTUKKRA.js} +1 -1
- package/dist/cli/chunks/chunk-A3GDX6UF.js +2 -0
- package/dist/cli/chunks/{chunk-GN6OE3JT.js → chunk-A5YTKKNA.js} +1 -1
- package/dist/cli/chunks/{chunk-KR2TAAF6.js → chunk-ADNGZAT2.js} +1 -1
- package/dist/cli/chunks/{chunk-J7Q5TXFZ.js → chunk-AWQAE3SW.js} +2 -2
- package/dist/cli/chunks/{chunk-ZN35XSKF.js → chunk-AXDBQFR4.js} +2 -2
- package/dist/cli/chunks/{chunk-ND72UDVH.js → chunk-AXVD7O3F.js} +2 -2
- package/dist/cli/chunks/{chunk-SAEECT23.js → chunk-B52ULNYO.js} +2 -2
- package/dist/cli/chunks/chunk-B6S4FC7M.js +3 -0
- package/dist/cli/chunks/{chunk-Z7SKUC6P.js → chunk-BDVFSMOQ.js} +1 -1
- package/dist/cli/chunks/{chunk-CXCMATZ6.js → chunk-BGXXMX3Y.js} +2 -2
- package/dist/cli/chunks/{chunk-R3KBOQ3O.js → chunk-BKMQQY5T.js} +2 -2
- package/dist/cli/chunks/{chunk-SAZ4PJBR.js → chunk-BN2FROBQ.js} +2 -2
- package/dist/cli/chunks/{chunk-G2X3OLMN.js → chunk-BO6EQNOC.js} +2 -2
- package/dist/cli/chunks/{chunk-776K4ZLE.js → chunk-BOVAKCDC.js} +2 -2
- package/dist/cli/chunks/{chunk-QSQNXBD2.js → chunk-BSXKZDKO.js} +2 -2
- package/dist/cli/chunks/{chunk-MGZ6XZHU.js → chunk-C5QVJ5XQ.js} +1 -1
- package/dist/cli/chunks/{chunk-LOLSZG5J.js → chunk-CFQLLF3D.js} +2 -2
- package/dist/cli/chunks/{chunk-J6QRNQJF.js → chunk-DUCVLT3F.js} +7 -7
- package/dist/cli/chunks/{chunk-QTQDX4TZ.js → chunk-E4RMJCGA.js} +3 -3
- package/dist/cli/chunks/{chunk-MLMD3I75.js → chunk-EONDCWY4.js} +1 -1
- package/dist/cli/chunks/{chunk-7BSOO3CY.js → chunk-F4AGNKL2.js} +2 -2
- package/dist/cli/chunks/{chunk-IKB3M7OF.js → chunk-F6YD3BOW.js} +1 -1
- package/dist/cli/chunks/{chunk-LIF6UWHV.js → chunk-FQRS7WVA.js} +2 -2
- package/dist/cli/chunks/{chunk-QJSSUBO3.js → chunk-FT24SSDG.js} +2 -2
- package/dist/cli/chunks/chunk-FV4YNSAJ.js +5 -0
- package/dist/cli/chunks/{chunk-VITV7AEC.js → chunk-FVDM3X42.js} +2 -2
- package/dist/cli/chunks/{chunk-LN7NKE3N.js → chunk-FVH7TXWU.js} +2 -2
- package/dist/cli/chunks/{chunk-FBSBXCZS.js → chunk-FWR5QY37.js} +2 -2
- package/dist/cli/chunks/{chunk-X2DWHGCC.js → chunk-FYINK2B7.js} +2 -2
- package/dist/cli/chunks/{chunk-ECKHDHR2.js → chunk-GGISVPOZ.js} +2 -2
- package/dist/cli/chunks/{chunk-SRBCBVSI.js → chunk-GPIJIZJQ.js} +2 -2
- package/dist/cli/chunks/{chunk-YR5QBUHZ.js → chunk-GXEVOT5F.js} +2 -2
- package/dist/cli/chunks/{chunk-ZTP3DQ5M.js → chunk-GZ4VB5RI.js} +1 -1
- package/dist/cli/chunks/{chunk-HWQPMUSN.js → chunk-HBDSCYSK.js} +2 -2
- package/dist/cli/chunks/{chunk-XBTGEYED.js → chunk-HGG4HR7C.js} +2 -2
- package/dist/cli/chunks/{chunk-YD2C6EPN.js → chunk-HSCKWWO2.js} +2 -2
- package/dist/cli/chunks/{chunk-LOMT4UC2.js → chunk-HSQ3GUYJ.js} +2 -2
- package/dist/cli/chunks/{chunk-ZC3KDNJW.js → chunk-HZQBW5EM.js} +3 -3
- package/dist/cli/chunks/{chunk-SUAZ5Z47.js → chunk-IGIYANVT.js} +2 -2
- package/dist/cli/chunks/{chunk-IHQGNDMX.js → chunk-IPWMSXBF.js} +2 -2
- package/dist/cli/chunks/{chunk-6V6BD6PH.js → chunk-IWVNC7VY.js} +1 -1
- package/dist/cli/chunks/{chunk-M2YI5YUR.js → chunk-IZODXKZD.js} +2 -2
- package/dist/cli/chunks/{chunk-LG5PPJT7.js → chunk-J2MT2OJV.js} +1 -1
- package/dist/cli/chunks/{chunk-6LSZCEW2.js → chunk-JKIJVVSP.js} +1 -1
- package/dist/cli/chunks/{chunk-REY52O7J.js → chunk-JMRDT2XK.js} +1 -1
- package/dist/cli/chunks/{chunk-XEYFZLIT.js → chunk-JR2UMTKG.js} +1 -1
- package/dist/cli/chunks/{chunk-DJDVD6RM.js → chunk-K6CH4CFF.js} +2 -2
- package/dist/cli/chunks/{chunk-2PCEMDIX.js → chunk-K7KW5QB5.js} +78 -87
- package/dist/cli/chunks/{chunk-EPVPXHL7.js → chunk-KFCQP434.js} +2 -2
- package/dist/cli/chunks/{chunk-TWBZONKT.js → chunk-KH4T6STG.js} +2 -2
- package/dist/cli/chunks/{chunk-JI33PMPZ.js → chunk-KJBYZO57.js} +1 -1
- package/dist/cli/chunks/{chunk-PK34KJH7.js → chunk-KP4OKOKV.js} +2 -2
- package/dist/cli/chunks/chunk-L2MBKVSE.js +2 -0
- package/dist/cli/chunks/{chunk-JVWZAE2H.js → chunk-L3IPUIT3.js} +2 -2
- package/dist/cli/chunks/{chunk-KT2QCXO6.js → chunk-L7PSU2YN.js} +2 -2
- package/dist/cli/chunks/{chunk-HAQJFUAQ.js → chunk-LA3JPGQA.js} +2 -2
- package/dist/cli/chunks/{chunk-LV7UIK4Q.js → chunk-LC2QRN7V.js} +14 -13
- package/dist/cli/chunks/{chunk-KTORRIX3.js → chunk-LHY7TMTM.js} +2 -2
- package/dist/cli/chunks/{chunk-IJSROBM6.js → chunk-LLQ2UMF6.js} +3 -3
- package/dist/cli/chunks/{chunk-NKUHMA4T.js → chunk-LOJ7OO6W.js} +2 -2
- package/dist/cli/chunks/{chunk-OJIUIEI4.js → chunk-LPUSH3VF.js} +1 -1
- package/dist/cli/chunks/{chunk-WAOEQA3W.js → chunk-LSEC2BU7.js} +2 -2
- package/dist/cli/chunks/{chunk-YMUY3TES.js → chunk-LTGB7OIU.js} +2 -2
- package/dist/cli/chunks/{chunk-CVYPMGUM.js → chunk-LUG7YNVZ.js} +2 -2
- package/dist/cli/chunks/{chunk-YAJOBZE5.js → chunk-LWAFRYKE.js} +2 -2
- package/dist/cli/chunks/{chunk-ZP5AWQRO.js → chunk-M24ZAZ4U.js} +2 -2
- package/dist/cli/chunks/{chunk-HFZD5KLR.js → chunk-MKRKRXTX.js} +1 -1
- package/dist/cli/chunks/{chunk-4YM45Z5B.js → chunk-MNNLONAD.js} +1 -1
- package/dist/cli/chunks/{chunk-CMN7PU2H.js → chunk-MQM37KAR.js} +2 -2
- package/dist/cli/chunks/{chunk-COTQ44YO.js → chunk-MSX2OHYT.js} +2 -2
- package/dist/cli/chunks/{chunk-4UKTIQDT.js → chunk-MVYQRVLP.js} +2 -2
- package/dist/cli/chunks/{chunk-HRUHHHVR.js → chunk-MZC5WM2P.js} +2 -2
- package/dist/cli/chunks/{chunk-YKRLUTK7.js → chunk-MZRBNBB3.js} +2 -2
- package/dist/cli/chunks/{chunk-XEMCHGAJ.js → chunk-N3KQU4UC.js} +2 -2
- package/dist/cli/chunks/{chunk-DS5IFRY6.js → chunk-NKU3FFM4.js} +2 -2
- package/dist/cli/chunks/chunk-O5EWFR76.js +2 -0
- package/dist/cli/chunks/{chunk-J3QFJI2Y.js → chunk-O5RDHD5T.js} +2 -2
- package/dist/cli/chunks/chunk-O6UWIXME.js +3 -0
- package/dist/cli/chunks/{chunk-Q6F3DYZN.js → chunk-OA4EQDC4.js} +2 -2
- package/dist/cli/chunks/{chunk-NQFDJ6BT.js → chunk-OBCXCRXK.js} +1 -1
- package/dist/cli/chunks/{chunk-S3TBOKAZ.js → chunk-OHU5P25N.js} +4 -4
- package/dist/cli/chunks/{chunk-DNVRTJKB.js → chunk-OOSV2RIA.js} +2 -2
- package/dist/cli/chunks/{chunk-NZJVDOUN.js → chunk-OW23N2Y5.js} +2 -2
- package/dist/cli/chunks/{chunk-ZWUF27P4.js → chunk-OXOO3YDL.js} +2 -2
- package/dist/cli/chunks/{chunk-4L6WX5KC.js → chunk-OYGKSSSI.js} +1 -1
- package/dist/cli/chunks/{chunk-DCDSN67A.js → chunk-PGO46IIW.js} +1 -1
- package/dist/cli/chunks/{chunk-C7QLLMYI.js → chunk-PZOYQHWS.js} +1 -1
- package/dist/cli/chunks/{chunk-BKHEQIRZ.js → chunk-Q2BZSG7Z.js} +2 -2
- package/dist/cli/chunks/{chunk-5FSPELOG.js → chunk-Q7V722K5.js} +2 -2
- package/dist/cli/chunks/{chunk-2EQK7B5L.js → chunk-QZU6M5IO.js} +2 -2
- package/dist/cli/chunks/{chunk-HVT7RMGV.js → chunk-R55Y76SJ.js} +1 -1
- package/dist/cli/chunks/{chunk-POPSZDI2.js → chunk-RMEQYJPU.js} +4 -4
- package/dist/cli/chunks/{chunk-H2LHWZRE.js → chunk-RTYXFXTI.js} +2 -2
- package/dist/cli/chunks/{chunk-QN7HP2UW.js → chunk-SJF3O4FX.js} +236 -236
- package/dist/cli/chunks/{chunk-2YWYW7NU.js → chunk-SOUS7Z2H.js} +2 -2
- package/dist/cli/chunks/{chunk-U5SMBJ6F.js → chunk-SRVNR3R3.js} +2 -2
- package/dist/cli/chunks/{chunk-ZAQMRFBB.js → chunk-SU3SXMVG.js} +2 -2
- package/dist/cli/chunks/chunk-SWGPLXWW.js +32 -0
- package/dist/cli/chunks/{chunk-S3DT5TPR.js → chunk-TRB3EVH3.js} +2 -2
- package/dist/cli/chunks/{chunk-IJZFJPHS.js → chunk-TVBDUMKT.js} +2 -2
- package/dist/cli/chunks/{chunk-7SNSI4VY.js → chunk-TWTXPSFU.js} +1 -1
- package/dist/cli/chunks/{chunk-ORQ2YBRR.js → chunk-ULYUVUL2.js} +2 -2
- package/dist/cli/chunks/{chunk-MVVVGQJ6.js → chunk-UNTBVJ5X.js} +2 -2
- package/dist/cli/chunks/{chunk-5WATBVU6.js → chunk-UQAA4PHU.js} +2 -2
- package/dist/cli/chunks/{chunk-5WYZVSL2.js → chunk-UWSJVKTE.js} +1 -1
- package/dist/cli/chunks/{chunk-JHKKIJT2.js → chunk-V2LJ54KP.js} +2 -2
- package/dist/cli/chunks/{chunk-2UUZCQSD.js → chunk-VCCTTKP3.js} +2 -2
- package/dist/cli/chunks/{chunk-P4OB6WDJ.js → chunk-VEGUYUVS.js} +1 -1
- package/dist/cli/chunks/{chunk-WX4PO65Q.js → chunk-VUQPVWNK.js} +2 -2
- package/dist/cli/chunks/{chunk-IQL6XRF5.js → chunk-VVGUE2T2.js} +2 -2
- package/dist/cli/chunks/{chunk-HZ5O7G2P.js → chunk-W5ASDHJQ.js} +1 -1
- package/dist/cli/chunks/{chunk-U4S74IIZ.js → chunk-WGXT5NWQ.js} +1 -1
- package/dist/cli/chunks/chunk-WJN3V7QB.js +7 -0
- package/dist/cli/chunks/chunk-WPCRQIIF.js +29 -0
- package/dist/cli/chunks/{chunk-AGCS5GSO.js → chunk-WQNLXUWA.js} +6 -6
- package/dist/cli/chunks/{chunk-LRY6UIRI.js → chunk-WZVRMKG2.js} +2 -2
- package/dist/cli/chunks/{chunk-KPIPVSIP.js → chunk-X27IUWTD.js} +2 -2
- package/dist/cli/chunks/{chunk-VDEKVIP5.js → chunk-X4B345B6.js} +2 -2
- package/dist/cli/chunks/{chunk-ERYADKMZ.js → chunk-X5I2Y4VO.js} +2 -2
- package/dist/cli/chunks/{chunk-EUWG2JG4.js → chunk-X7IQIFTS.js} +2 -2
- package/dist/cli/chunks/chunk-XJN3RKUD.js +3 -0
- package/dist/cli/chunks/{chunk-JRIJM4LE.js → chunk-XQMGXTHJ.js} +3 -3
- package/dist/cli/chunks/{chunk-VYPVU3JF.js → chunk-XTSAMB2Q.js} +2 -2
- package/dist/cli/chunks/{chunk-4NKZU2JZ.js → chunk-XZLIF4O2.js} +2 -2
- package/dist/cli/chunks/{chunk-XFTX3KLE.js → chunk-Y4LSEOZ3.js} +1 -1
- package/dist/cli/chunks/{chunk-ZVMSSCTH.js → chunk-Y4YN2RXR.js} +2 -2
- package/dist/cli/chunks/{chunk-X5QD76IU.js → chunk-YDI56L35.js} +2 -2
- package/dist/cli/chunks/{chunk-LRKLATSH.js → chunk-YFILS5D5.js} +2 -2
- package/dist/cli/chunks/{chunk-AVHYJ3XP.js → chunk-YISDX6WB.js} +2 -2
- package/dist/cli/chunks/{chunk-GPPTRKEM.js → chunk-YP2GHQSV.js} +2 -2
- package/dist/cli/chunks/{chunk-OO2M2QUV.js → chunk-YSX756AM.js} +4 -4
- package/dist/cli/chunks/{chunk-E7XIMOKW.js → chunk-YWANOASW.js} +2 -2
- package/dist/cli/chunks/{chunk-UHJVZEQA.js → chunk-YYIJLG7S.js} +2 -2
- package/dist/cli/chunks/{chunk-LCWEQRZI.js → chunk-Z7SD7LXM.js} +2 -2
- package/dist/cli/chunks/{chunk-TM75GAXG.js → chunk-ZDWD73UF.js} +2 -2
- package/dist/cli/chunks/{chunk-IRHXGCQR.js → chunk-ZFT3RLA4.js} +2 -2
- package/dist/cli/chunks/{chunk-ZGV7L4MW.js → chunk-ZNTHX5G3.js} +1 -1
- package/dist/cli/chunks/{chunk-D75GLKEL.js → chunk-ZS27R7VL.js} +2 -2
- package/dist/cli/chunks/{chunk-INI3Q4CN.js → chunk-ZXHHHR7K.js} +1 -1
- package/dist/cli/chunks/{ci-3RTTTS2D.js → ci-N5MOMNXH.js} +2 -2
- package/dist/cli/chunks/{ci-config-XRUR3I4K.js → ci-config-6L2ROQCW.js} +2 -2
- package/dist/cli/chunks/{ci-output-E5IAMU2U.js → ci-output-DSRBYEIK.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-SHR2P44P.js → circuit-breaker-VRPTNBL7.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-ZDDILFMF.js → claude-flow-setup-4YFG3FU5.js} +2 -2
- package/dist/cli/chunks/client-I3L6BKRQ.js +2 -0
- package/dist/cli/chunks/{cline-installer-BGYVUM6G.js → cline-installer-7RGYJWGN.js} +2 -2
- package/dist/cli/chunks/{code-PJ4MC3MC.js → code-ISC6NW2K.js} +3 -3
- package/dist/cli/chunks/{code-index-extractor-IW2P22YG.js → code-index-extractor-2FID75YV.js} +2 -2
- package/dist/cli/chunks/{codex-installer-A7WZ6OGL.js → codex-installer-DZ7OG6KM.js} +2 -2
- package/dist/cli/chunks/{completions-KS23WD5J.js → completions-SM3LICWK.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-Q7GLSR2E.js → complexity-analyzer-ZWD2CTAD.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-SK55BFW2.js → continuedev-installer-AGASOA26.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-3N5J3WTM.js → copilot-installer-CLPZYTQC.js} +2 -2
- package/dist/cli/chunks/core-handlers-5EFOJ37H.js +2 -0
- package/dist/cli/chunks/{cost-tracker-NENVSO4A.js → cost-tracker-7PIGQYDV.js} +2 -2
- package/dist/cli/chunks/{coverage-5L7UQWDH.js → coverage-T2GEBTYS.js} +9 -9
- package/dist/cli/chunks/cross-domain-router-65WJAKVD.js +2 -0
- package/dist/cli/chunks/{cursor-installer-XXBO2ZE6.js → cursor-installer-KXBID4MB.js} +2 -2
- package/dist/cli/chunks/daemon-43MXIVH3.js +18 -0
- package/dist/cli/chunks/{daemon-CDCQU3LR.js → daemon-VAMJLQJ5.js} +3 -3
- package/dist/cli/chunks/{dag-attention-scheduler-HOMMF7FA.js → dag-attention-scheduler-UBP4VHTA.js} +2 -2
- package/dist/cli/chunks/{detect-FXCOUG6X.js → detect-QWFIQRKI.js} +2 -2
- package/dist/cli/chunks/{dist-node-GXQ7FMTY.js → dist-node-I2GICS3W.js} +2 -2
- package/dist/cli/chunks/{domain-handler-TI3JBAPC.js → domain-handler-Z66ISB2A.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-R7LTUM32.js → domain-plugins-KHMD3FKT.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-LBIAFHIQ.js → domain-transfer-JWGNNA6K.js} +2 -2
- package/dist/cli/chunks/dream-VQ2PZCVR.js +2 -0
- package/dist/cli/chunks/embed-and-insert-pattern-F5P5B6JX.js +3 -0
- package/dist/cli/chunks/{embedding-space-HHLWTBF5.js → embedding-space-KHG6TITM.js} +2 -2
- package/dist/cli/chunks/{eval-KDOZMAXJ.js → eval-43OHU7EI.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-X45PECQN.js → experience-capture-middleware-KXD47H6P.js} +3 -3
- package/dist/cli/chunks/{fast-paths-462V6UUB.js → fast-paths-6D75D5KD.js} +2 -2
- package/dist/cli/chunks/{feature-flags-NIRQ4YDM.js → feature-flags-IE35Y55N.js} +2 -2
- package/dist/cli/chunks/{feature-flags-G66OT3AS.js → feature-flags-OYYHY7LS.js} +2 -2
- package/dist/cli/chunks/file-discovery-LGBTY3ID.js +2 -0
- package/dist/cli/chunks/{fleet-PXWGB7CU.js → fleet-AGVJMFGD.js} +16 -16
- package/dist/cli/chunks/{gnn-wrapper-7MUW3M5M.js → gnn-wrapper-5L66A7LW.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-5237PB35.js → heartbeat-handler-2BY6YYOT.js} +5 -5
- package/dist/cli/chunks/heartbeat-scheduler-3DU3M5AT.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-N2IMSRPV.js +2 -0
- package/dist/cli/chunks/hnsw-index-DVU7TTJE.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-OSQPW7JP.js → hnsw-legacy-bridge-RYMWFNAH.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-GX6WG2GB.js → hnswlib-node-GG47HP2P.js} +2 -2
- package/dist/cli/chunks/{hooks-GUWHL7VC.js → hooks-FQNACS24.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-AS2PNHOD.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-SRWLLCU3.js → hypergraph-engine-6BYNJQEP.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-AVOPRHHO.js → hypergraph-handler-CYTAXZKJ.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-Y4OONLFP.js +2 -0
- package/dist/cli/chunks/{init-guard-P4N6EVZS.js → init-guard-METTAV5O.js} +2 -2
- package/dist/cli/chunks/{init-handler-LRGWOJMD.js → init-handler-GFT74U5Y.js} +6 -6
- package/dist/cli/chunks/init-wizard-HLNUBJQN.js +2 -0
- package/dist/cli/chunks/kernel-XKFWCL7Y.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-7R2EPOQ6.js → kilocode-installer-GZV2D3FF.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-QNM7DPOB.js → kiro-installer-Q4ZXUFC7.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-CNL77CSZ.js +2 -0
- package/dist/cli/chunks/{learning-7OIZBPXZ.js → learning-WA2QEYL7.js} +35 -34
- package/dist/cli/chunks/{llm-router-SIDXES23.js → llm-router-GRTCHWH7.js} +4 -4
- package/dist/cli/chunks/llm-router-service-UIYTYKP6.js +2 -0
- package/dist/cli/chunks/{load-EI2E2C3S.js → load-WXN3Q7Y5.js} +2 -2
- package/dist/cli/chunks/load-test-PXLW4A5B.js +2 -0
- package/dist/cli/chunks/{mcp-IOE5WOCS.js → mcp-LIQCPSJN.js} +2 -2
- package/dist/cli/chunks/{memory-DLYGJAP7.js → memory-OP6CHRFH.js} +5 -5
- package/dist/cli/chunks/memory-backend-XYOSO73Q.js +2 -0
- package/dist/cli/chunks/memory-handlers-PQFYVNVG.js +2 -0
- package/dist/cli/chunks/{multi-model-executor-WHH4YCHM.js → multi-model-executor-H54DEVRZ.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-63FDZAMS.js → opencode-installer-BSQV6UAT.js} +2 -2
- package/dist/cli/chunks/{orchestrator-3LA776KK.js → orchestrator-TJDPQ4VL.js} +122 -35
- package/dist/cli/chunks/pattern-null-store-BKGTQFNF.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-NW54QUGI.js → pattern-usage-recorder-FOVS4M5L.js} +2 -2
- package/dist/cli/chunks/{pipeline-P3TYX6J6.js → pipeline-4AY2ZIC6.js} +2 -2
- package/dist/cli/chunks/{platform-FNA2WLI6.js → platform-FCSITYMR.js} +2 -2
- package/dist/cli/chunks/{plugin-NJS7BC2S.js → plugin-E56TV5S2.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-NIAVL2OT.js → prime-radiant-advanced-wasm-ACOPC533.js} +2 -2
- package/dist/cli/chunks/project-root-MPX7CN2C.js +2 -0
- package/dist/cli/chunks/protocol-executor-CRQOCC4A.js +2 -0
- package/dist/cli/chunks/{protocol-handler-JU5C4JHY.js → protocol-handler-KRVXF4LS.js} +2 -2
- package/dist/cli/chunks/{prove-35VOSLYP.js → prove-KMFPSKGD.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-UEGQ3O7F.js +2 -0
- package/dist/cli/chunks/{quality-ET74X7HN.js → quality-6DBI3HLB.js} +2 -2
- package/dist/cli/chunks/{quality-gate-FEDQISNB.js → quality-gate-3ROZMEIL.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-32574XSG.js +2 -0
- package/dist/cli/chunks/real-embeddings-MIGZNKK3.js +2 -0
- package/dist/cli/chunks/{ref-validation-DTBPYCEB.js → ref-validation-EYIP7DHW.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-LYQEMR4J.js → roocode-installer-IGGZHR2Y.js} +2 -2
- package/dist/cli/chunks/router-CZJY5WX6.js +2 -0
- package/dist/cli/chunks/routing-feedback-RC3UBNFX.js +2 -0
- package/dist/cli/chunks/{routing-handler-DJOJFPII.js → routing-handler-BWNHBYDC.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-VXYGJDPW.js → ruvector-commands-PXIHF432.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-OG7OV2AK.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-THYMW7ZO.js +2 -0
- package/dist/cli/chunks/rvf-migration-coordinator-3H6CLFU7.js +2 -0
- package/dist/cli/chunks/rvf-native-adapter-6JQJIKKW.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-GA2ZYOEG.js → rvf-store-integrity-CVB3NMSL.js} +2 -2
- package/dist/cli/chunks/safe-db-QFKCVTIJ.js +2 -0
- package/dist/cli/chunks/schedule-6JLVMMYB.js +2 -0
- package/dist/cli/chunks/scheduler-3MPZRMJD.js +2 -0
- package/dist/cli/chunks/{security-MM6YOECX.js → security-DCRGOTWU.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-6AHPA3V5.js → shared-rvf-adapter-GKD74QUB.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-EYAVY2GZ.js → shared-rvf-dual-writer-HVAAVEOH.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-LGTIKAEX.js +2 -0
- package/dist/cli/chunks/{standalone-memory-A3PLB4CZ.js → standalone-memory-O7O2U5N4.js} +2 -2
- package/dist/cli/chunks/{status-handler-OSSFAP4Z.js → status-handler-BQTPJJTL.js} +2 -2
- package/dist/cli/chunks/{structural-health-PGY5XUNO.js → structural-health-4H6J4OHK.js} +2 -2
- package/dist/cli/chunks/sync-DJ4TF6QX.js +2 -0
- package/dist/cli/chunks/{sync-CWEHYGNN.js → sync-WW5TAVYW.js} +2 -2
- package/dist/cli/chunks/{task-handler-LHMQ75W4.js → task-handler-HEM4IEOW.js} +2 -2
- package/dist/cli/chunks/{task-handlers-S2TX5FTR.js → task-handlers-JRA3NXIR.js} +3 -3
- package/dist/cli/chunks/{test-4EGZZ6NJ.js → test-772ZXVG2.js} +4 -4
- package/dist/cli/chunks/test-runner-process-XGF2U3NG.js +2 -0
- package/dist/cli/chunks/{test-scheduling-YJQHH3XE.js → test-scheduling-4TRB7LZ7.js} +3 -3
- package/dist/cli/chunks/token-bootstrap-CICBIJ7T.js +2 -0
- package/dist/cli/chunks/{token-usage-WPNOJR6H.js → token-usage-B7PEKE2G.js} +2 -2
- package/dist/cli/chunks/{transformers-4MRPXCPU.js → transformers-V7X7BDZX.js} +2 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-OXPFKFZS.js +2 -0
- package/dist/cli/chunks/{types-6P5FB4EB.js → types-AHHTUY3I.js} +2 -2
- package/dist/cli/chunks/unified-memory-GUR3IUI6.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-NJP2F2RY.js +2 -0
- package/dist/cli/chunks/unified-persistence-NILBWXDP.js +2 -0
- package/dist/cli/chunks/{upgrade-4ICTN63Y.js → upgrade-DZ4DLUQ5.js} +2 -2
- package/dist/cli/chunks/{validate-HQF5GZ7L.js → validate-4DTLIDJE.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-45JYG7VW.js → validate-swarm-A26UFVIS.js} +2 -2
- package/dist/cli/chunks/visual-security-YECYZ27X.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-UOTWZLNH.js → web-tree-sitter-F2C7QRYT.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-WDWSBXGN.js → windsurf-installer-OOBTDA6W.js} +2 -2
- package/dist/cli/chunks/{witness-chain-DOYMNPC7.js → witness-chain-KGFZJP32.js} +2 -2
- package/dist/cli/chunks/witness-chain-LYBXFLJB.js +2 -0
- package/dist/cli/chunks/witness-chain-repair-CNTXOGPN.js +2 -0
- package/dist/cli/chunks/{witness-chain-verifier-JB42X62J.js → witness-chain-verifier-OB7ZZOI3.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-LXXO6L2G.js → witness-key-manager-YCKGKGQI.js} +2 -2
- package/dist/cli/chunks/{workflow-6ARK47NF.js → workflow-PRERHWKY.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-UIBGWCU3.js +2 -0
- package/dist/cli/chunks/wrappers-L4UY4V63.js +2 -0
- package/dist/cli/commands/coverage.js +4 -1
- package/dist/cli/commands/learning-prune.js +9 -1
- package/dist/cli/handlers/brain-handler.js +32 -2
- package/dist/cli/handlers/heartbeat-handler.js +3 -1
- package/dist/cli/utils/coverage-data.js +5 -1
- package/dist/cli/utils/coverage-verdict.d.ts +10 -2
- package/dist/cli/utils/coverage-verdict.js +23 -8
- package/dist/cli/utils/fleet-operation.js +9 -3
- package/dist/coordination/handlers/code-intelligence-handlers.js +17 -3
- package/dist/coordination/handlers/coverage-handlers.js +22 -9
- package/dist/coordination/handlers/coverage-target.d.ts +22 -2
- package/dist/coordination/handlers/coverage-target.js +45 -9
- package/dist/coordination/handlers/handler-utils.d.ts +19 -0
- package/dist/coordination/handlers/handler-utils.js +22 -8
- package/dist/coordination/protocols/code-intelligence-index.js +6 -3
- package/dist/coordination/protocols/learning-consolidation-archive.d.ts +6 -3
- package/dist/coordination/protocols/learning-consolidation-archive.js +4 -3
- package/dist/coordination/workflow-builtin.js +1 -0
- package/dist/domains/defect-intelligence/interfaces.d.ts +2 -0
- package/dist/domains/defect-intelligence/prediction-history.d.ts +15 -1
- package/dist/domains/defect-intelligence/prediction-history.js +63 -7
- package/dist/domains/defect-intelligence/services/defect-predictor.d.ts +1 -0
- package/dist/domains/defect-intelligence/services/defect-predictor.js +33 -13
- package/dist/domains/learning-optimization/coordinator.js +17 -10
- package/dist/domains/learning-optimization/domain-ranking.d.ts +26 -0
- package/dist/domains/learning-optimization/domain-ranking.js +28 -0
- package/dist/domains/learning-optimization/interfaces.d.ts +5 -0
- package/dist/domains/learning-optimization/pattern-archive.d.ts +55 -8
- package/dist/domains/learning-optimization/pattern-archive.js +90 -17
- package/dist/domains/learning-optimization/pattern-consolidation.js +18 -2
- package/dist/domains/learning-optimization/pattern-merge.d.ts +26 -0
- package/dist/domains/learning-optimization/pattern-merge.js +127 -0
- package/dist/domains/learning-optimization/services/learning-coordinator.js +21 -35
- package/dist/domains/test-execution/services/test-executor.js +6 -2
- package/dist/init/init-wizard-steps.js +3 -1
- package/dist/init/phases/07-hooks.js +97 -10
- package/dist/integrations/embeddings/cache/EmbeddingCache.js +1 -1
- package/dist/integrations/ruvector/brain-rvf-exporter.d.ts +16 -1
- package/dist/integrations/ruvector/brain-rvf-exporter.js +18 -32
- package/dist/integrations/ruvector/brain-rvf-richness.d.ts +75 -0
- package/dist/integrations/ruvector/brain-rvf-richness.js +127 -0
- package/dist/kernel/unified-memory-migration.js +1 -1
- package/dist/learning/checkpoint-shrink-ack.d.ts +25 -0
- package/dist/learning/checkpoint-shrink-ack.js +57 -0
- package/dist/learning/dream/dream-engine.d.ts +44 -3
- package/dist/learning/dream/dream-engine.js +6 -2
- package/dist/learning/embedder-identity-store.js +3 -1
- package/dist/learning/embedding-space-legacy-adoption.d.ts +53 -0
- package/dist/learning/embedding-space-legacy-adoption.js +115 -0
- package/dist/learning/embedding-space-registry.d.ts +15 -0
- package/dist/learning/embedding-space-registry.js +50 -11
- package/dist/learning/experience-capture.d.ts +3 -1
- package/dist/learning/experience-capture.js +15 -5
- package/dist/learning/experience-space-verification.d.ts +2 -0
- package/dist/learning/experience-space-verification.js +3 -2
- package/dist/learning/learning-retention.js +4 -0
- package/dist/learning/pattern-promotion.d.ts +7 -0
- package/dist/learning/pattern-promotion.js +64 -12
- package/dist/learning/real-embeddings.js +31 -7
- package/dist/learning/rvf-pattern-store.js +6 -1
- package/dist/mcp/bundle.js +570 -558
- package/dist/mcp/handlers/domain-handler-configs.d.ts +3 -0
- package/dist/mcp/handlers/domain-handler-configs.js +1 -0
- package/dist/mcp/handlers/heartbeat-handlers.d.ts +4 -2
- package/dist/mcp/tools/learning-optimization/optimize.d.ts +6 -1
- package/dist/mcp/tools/learning-optimization/optimize.js +20 -11
- package/dist/planning/goap-planner.js +4 -0
- package/dist/planning/plan-executor.js +6 -2
- package/dist/shared/git/git-analyzer.d.ts +30 -11
- package/dist/shared/git/git-analyzer.js +95 -48
- package/dist/shared/io/confined-read.d.ts +32 -7
- package/dist/shared/io/confined-read.js +58 -25
- package/dist/shared/io/file-reader.js +4 -1
- package/dist/shared/safe-db.d.ts +1 -1
- package/dist/shared/safe-db.js +20 -5
- package/dist/shared/sqlite-journal-mode.d.ts +39 -0
- package/dist/shared/sqlite-journal-mode.js +53 -0
- package/dist/sync/claude-flow-bridge.js +1 -1
- package/dist/sync/readers/sqlite-reader.js +3 -4
- package/dist/sync/writers/sqlite-writer.js +1 -1
- package/dist/workers/interfaces.d.ts +2 -2
- package/dist/workers/quality-daemon/git-watcher.d.ts +8 -0
- package/dist/workers/quality-daemon/git-watcher.js +54 -12
- package/dist/workers/quality-daemon/index.js +1 -1
- package/dist/workers/quality-daemon/priority-queue.d.ts +2 -1
- package/dist/workers/workers/defect-predictor.d.ts +9 -4
- package/dist/workers/workers/defect-predictor.js +98 -37
- package/package.json +1 -1
- package/dist/cli/chunks/adapter-OMILP6KH.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-OXH5CCOS.js +0 -2
- package/dist/cli/chunks/base-MAK2BLTG.js +0 -2
- package/dist/cli/chunks/brain-handler-GCQZFZGQ.js +0 -95
- package/dist/cli/chunks/browser-workflow-IR3VF2TL.js +0 -2
- package/dist/cli/chunks/chunk-4EJLHNER.js +0 -12
- package/dist/cli/chunks/chunk-A4BVDYIL.js +0 -2
- package/dist/cli/chunks/chunk-BE7ZHM34.js +0 -3
- package/dist/cli/chunks/chunk-DHKSPOUQ.js +0 -16
- package/dist/cli/chunks/chunk-FAQ24UHB.js +0 -29
- package/dist/cli/chunks/chunk-IOWEBPXJ.js +0 -5
- package/dist/cli/chunks/chunk-KB34MTFZ.js +0 -3
- package/dist/cli/chunks/chunk-MCXW3DKE.js +0 -8
- package/dist/cli/chunks/chunk-O7VJ3VKD.js +0 -2
- package/dist/cli/chunks/chunk-PIWGKGWP.js +0 -3
- package/dist/cli/chunks/chunk-SFITYZLV.js +0 -7
- package/dist/cli/chunks/chunk-TIVKDIF7.js +0 -2
- package/dist/cli/chunks/client-NO5FOWT4.js +0 -2
- package/dist/cli/chunks/core-handlers-JNAZPXE2.js +0 -2
- package/dist/cli/chunks/cross-domain-router-HEBM767Z.js +0 -2
- package/dist/cli/chunks/daemon-JEBJGEUK.js +0 -18
- package/dist/cli/chunks/dream-GQDCEJMS.js +0 -2
- package/dist/cli/chunks/embed-and-insert-pattern-33KLHDD5.js +0 -3
- package/dist/cli/chunks/file-discovery-33USPLB5.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-LIXLC5IH.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-62D5UH27.js +0 -2
- package/dist/cli/chunks/hnsw-index-GSGUMQQC.js +0 -2
- package/dist/cli/chunks/hybrid-backend-FRWP4BOY.js +0 -2
- package/dist/cli/chunks/impact-analyzer-7KF3AQXV.js +0 -2
- package/dist/cli/chunks/init-wizard-XWWAXY25.js +0 -2
- package/dist/cli/chunks/kernel-ZEJPNDBW.js +0 -2
- package/dist/cli/chunks/knowledge-graph-RRZQS7KY.js +0 -2
- package/dist/cli/chunks/llm-router-service-3OSW67LC.js +0 -2
- package/dist/cli/chunks/load-test-7TRIH2WJ.js +0 -2
- package/dist/cli/chunks/memory-backend-G7ZW6Q2B.js +0 -2
- package/dist/cli/chunks/memory-handlers-TPF3KCO5.js +0 -2
- package/dist/cli/chunks/pattern-null-store-OU3ZC3NR.js +0 -2
- package/dist/cli/chunks/project-root-GMOFJEKD.js +0 -2
- package/dist/cli/chunks/protocol-executor-AD345XRO.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-NLTP26RC.js +0 -2
- package/dist/cli/chunks/queen-coordinator-2TB4FWS6.js +0 -2
- package/dist/cli/chunks/real-embeddings-II6CXTCI.js +0 -2
- package/dist/cli/chunks/router-PLM3MWME.js +0 -2
- package/dist/cli/chunks/routing-feedback-I7VOX2HU.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-GQZHFWO2.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-3TVKBCAM.js +0 -2
- package/dist/cli/chunks/rvf-migration-coordinator-XUHKLMT6.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-5GUTYOWS.js +0 -2
- package/dist/cli/chunks/safe-db-RZPQGLGQ.js +0 -2
- package/dist/cli/chunks/schedule-G7JMQDUX.js +0 -2
- package/dist/cli/chunks/scheduler-4SEGPCKD.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-IVE4SQXR.js +0 -2
- package/dist/cli/chunks/sync-PM6D7EQF.js +0 -2
- package/dist/cli/chunks/test-runner-process-72YACW6M.js +0 -2
- package/dist/cli/chunks/token-bootstrap-DJNETMVW.js +0 -2
- package/dist/cli/chunks/tree-sitter-wasm-parser-UVWSDXFR.js +0 -2
- package/dist/cli/chunks/unified-memory-2VMGSGQL.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-3KULVD3N.js +0 -2
- package/dist/cli/chunks/unified-persistence-QCSLU2SV.js +0 -2
- package/dist/cli/chunks/visual-security-ZYP2KPH7.js +0 -2
- package/dist/cli/chunks/witness-chain-5QRT7EMX.js +0 -2
- package/dist/cli/chunks/witness-chain-repair-CUF2AFQB.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-RYDDWIXN.js +0 -2
- package/dist/cli/chunks/wrappers-CYQBOMPL.js +0 -2
|
@@ -195,6 +195,9 @@ export interface DefectPredictResult {
|
|
|
195
195
|
scanStatus?: 'partial' | 'complete';
|
|
196
196
|
predictionMethod?: 'static-code-indicators';
|
|
197
197
|
estimated?: boolean;
|
|
198
|
+
/** #1137: the run was stored, but pruning older runs failed. */
|
|
199
|
+
retention?: 'failed';
|
|
200
|
+
retentionError?: string;
|
|
198
201
|
taskId: string;
|
|
199
202
|
status: string;
|
|
200
203
|
predictedDefects: Array<{
|
|
@@ -770,6 +770,7 @@ export const defectPredictConfig = {
|
|
|
770
770
|
filesAnalyzed: data.filesAnalyzed, filesSkipped: data.filesSkipped,
|
|
771
771
|
scanStatus: data.scanStatus,
|
|
772
772
|
} : {}),
|
|
773
|
+
...(data.retention === 'failed' ? { retention: 'failed', retentionError: String(data.retentionError ?? '') } : {}),
|
|
773
774
|
predictedDefects: data.predictedDefects || [],
|
|
774
775
|
riskScore: data.riskScore || 0,
|
|
775
776
|
recommendations: data.recommendations || [],
|
|
@@ -20,7 +20,8 @@ export interface HeartbeatStatusResult {
|
|
|
20
20
|
lastResult: {
|
|
21
21
|
success: boolean;
|
|
22
22
|
durationMs: number;
|
|
23
|
-
|
|
23
|
+
/** `null` when the run measured nothing (#1137). */
|
|
24
|
+
healthScore: number | null;
|
|
24
25
|
trend: string;
|
|
25
26
|
domainMetrics: Record<string, number | string>;
|
|
26
27
|
} | null;
|
|
@@ -32,7 +33,8 @@ export interface HeartbeatTriggerParams {
|
|
|
32
33
|
export interface HeartbeatTriggerResult {
|
|
33
34
|
success: boolean;
|
|
34
35
|
durationMs: number;
|
|
35
|
-
|
|
36
|
+
/** `null` when the run measured nothing (#1137). */
|
|
37
|
+
healthScore: number | null;
|
|
36
38
|
trend: string;
|
|
37
39
|
promoted: number;
|
|
38
40
|
deprecated: number;
|
|
@@ -48,6 +48,8 @@ export interface LearnResult {
|
|
|
48
48
|
experienceIdsNotFound?: number;
|
|
49
49
|
evidenceStatus?: 'insufficient-evidence';
|
|
50
50
|
patternsLearned: number;
|
|
51
|
+
/** #1147: why nothing was learned from the requested experiences. */
|
|
52
|
+
noPatternReason?: string;
|
|
51
53
|
newPatterns: LearnedPattern[];
|
|
52
54
|
/** No baseline is recorded to compare against, so improvement is not measured (#1109). */
|
|
53
55
|
improvement: number | null;
|
|
@@ -128,7 +130,10 @@ export interface DashboardResult {
|
|
|
128
130
|
assignedPatternsExcluded?: number;
|
|
129
131
|
/** #1121: untagged patterns mined before #1120 (rate selected over successes), excluded likewise. */
|
|
130
132
|
legacyPatternsExcluded?: number;
|
|
131
|
-
/**
|
|
133
|
+
/**
|
|
134
|
+
* Ranked by measured success rate (#1147): domains with no measured outcome,
|
|
135
|
+
* or with 0% measured success, are left out.
|
|
136
|
+
*/
|
|
132
137
|
topPerformingDomains: DomainName[];
|
|
133
138
|
evidenceStatus?: 'insufficient-evidence';
|
|
134
139
|
unmeasured?: string[];
|
|
@@ -15,6 +15,7 @@ import { MetricsOptimizerService } from '../../../domains/learning-optimization/
|
|
|
15
15
|
import { TransferSpecialistService } from '../../../domains/learning-optimization/services/transfer-specialist.js';
|
|
16
16
|
import { toErrorMessage } from '../../../shared/error-utils.js';
|
|
17
17
|
import { partitionByRewardSource } from '../../../domains/learning-optimization/reward-source.js';
|
|
18
|
+
import { rankTopPerformingDomains } from '../../../domains/learning-optimization/domain-ranking.js';
|
|
18
19
|
// ============================================================================
|
|
19
20
|
// Tool Implementation
|
|
20
21
|
// ============================================================================
|
|
@@ -174,8 +175,21 @@ export class LearningOptimizeTool extends MCPToolBase {
|
|
|
174
175
|
if (!readResult.success)
|
|
175
176
|
throw readResult.error;
|
|
176
177
|
const read = readResult.value;
|
|
178
|
+
const requested = new Set(experienceIds).size;
|
|
177
179
|
const { measured, assignedExcluded } = partitionByRewardSource(read);
|
|
178
180
|
const learned = measured.length > 0 ? await learningCoordinator.learnPattern(read) : null;
|
|
181
|
+
// #1147: say why nothing was learned instead of returning a bare 0.
|
|
182
|
+
let noPatternReason;
|
|
183
|
+
if (read.length === 0) {
|
|
184
|
+
noPatternReason = `None of the ${requested} requested experience ID(s) were found.`;
|
|
185
|
+
}
|
|
186
|
+
else if (measured.length === 0) {
|
|
187
|
+
noPatternReason = `None of the ${read.length} experience(s) read has a measured outcome` +
|
|
188
|
+
(assignedExcluded > 0 ? ` (${assignedExcluded} with an assigned reward excluded).` : '.');
|
|
189
|
+
}
|
|
190
|
+
else if (learned && !learned.success) {
|
|
191
|
+
noPatternReason = learned.error.message;
|
|
192
|
+
}
|
|
179
193
|
const newPatterns = learned?.success
|
|
180
194
|
? [{
|
|
181
195
|
id: learned.value.id,
|
|
@@ -190,11 +204,12 @@ export class LearningOptimizeTool extends MCPToolBase {
|
|
|
190
204
|
this.markAsRealData();
|
|
191
205
|
return {
|
|
192
206
|
experiencesProcessed: read.length,
|
|
193
|
-
experienceIdsNotFound:
|
|
207
|
+
experienceIdsNotFound: requested - read.length,
|
|
194
208
|
measuredExperiences: measured.length,
|
|
195
209
|
assignedRewardsExcluded: assignedExcluded,
|
|
196
210
|
...(measured.length === 0 ? { evidenceStatus: 'insufficient-evidence' } : {}),
|
|
197
211
|
patternsLearned: newPatterns.length,
|
|
212
|
+
...(noPatternReason ? { noPatternReason } : {}),
|
|
198
213
|
newPatterns,
|
|
199
214
|
improvement: null,
|
|
200
215
|
unmeasured: ['improvement'],
|
|
@@ -464,17 +479,11 @@ export class LearningOptimizeTool extends MCPToolBase {
|
|
|
464
479
|
experiencesLast24h += mineResult.value.experienceCount;
|
|
465
480
|
assignedRewardsExcluded += mineResult.value.assignedRewardsExcluded ?? 0;
|
|
466
481
|
// #1109: only a measured success rate can rank a domain.
|
|
467
|
-
|
|
468
|
-
if (successRate !== null) {
|
|
469
|
-
domainPerformance.push({ domain, successRate });
|
|
470
|
-
}
|
|
482
|
+
domainPerformance.push({ domain, successRate: mineResult.value.successRate });
|
|
471
483
|
}
|
|
472
484
|
}
|
|
473
|
-
//
|
|
474
|
-
|
|
475
|
-
const topPerformingDomains = domainPerformance
|
|
476
|
-
.slice(0, 3)
|
|
477
|
-
.map(d => d.domain);
|
|
485
|
+
// #1147: rank by measured success; a domain at 0% is not top-performing.
|
|
486
|
+
const { topPerformingDomains, measuredDomains } = rankTopPerformingDomains(domainPerformance);
|
|
478
487
|
// Calculate overall learning rate from pattern stats
|
|
479
488
|
// getPatternStats already leaves out patterns learned from assigned rewards.
|
|
480
489
|
const totalPatterns = statsResult.success ? statsResult.value.totalPatterns : 0;
|
|
@@ -528,7 +537,7 @@ export class LearningOptimizeTool extends MCPToolBase {
|
|
|
528
537
|
const unmeasured = [];
|
|
529
538
|
if (overallLearningRate === null)
|
|
530
539
|
unmeasured.push('overallLearningRate');
|
|
531
|
-
if (
|
|
540
|
+
if (measuredDomains === 0)
|
|
532
541
|
unmeasured.push('topPerformingDomains');
|
|
533
542
|
return {
|
|
534
543
|
overallLearningRate,
|
|
@@ -656,6 +656,10 @@ export class GOAPPlanner {
|
|
|
656
656
|
}
|
|
657
657
|
// #1157: goal and condition keys can come from callers; an inherited
|
|
658
658
|
// member such as `constructor` is not part of the world state.
|
|
659
|
+
// #1186: deliberately, a key resolves only through own properties of
|
|
660
|
+
// objects. An array's own `length` resolves (`items.length`), but a
|
|
661
|
+
// primitive has no world-state members, so `name.length` on a string
|
|
662
|
+
// is undefined and a condition on it is unmet.
|
|
659
663
|
if (typeof current !== 'object' || !Object.hasOwn(current, part)) {
|
|
660
664
|
return undefined;
|
|
661
665
|
}
|
|
@@ -123,8 +123,8 @@ export class PlanExecutor {
|
|
|
123
123
|
// This allows async unified storage initialization
|
|
124
124
|
if (!this.config.useUnified) {
|
|
125
125
|
// Legacy mode: create separate database immediately
|
|
126
|
-
|
|
127
|
-
this.db
|
|
126
|
+
// #1164: openDatabase() set the journal mode (retrying contention, honouring AQE_DISABLE_WAL).
|
|
127
|
+
this.db = openDatabase(dbPath ?? ':memory:');
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
// ==========================================================================
|
|
@@ -911,6 +911,10 @@ export class PlanExecutor {
|
|
|
911
911
|
}
|
|
912
912
|
// #1157: goal and condition keys can come from callers; an inherited
|
|
913
913
|
// member such as `constructor` is not part of the world state.
|
|
914
|
+
// #1186: deliberately, a key resolves only through own properties of
|
|
915
|
+
// objects. An array's own `length` resolves (`items.length`), but a
|
|
916
|
+
// primitive has no world-state members, so `name.length` on a string
|
|
917
|
+
// is undefined and a condition on it is unmet.
|
|
914
918
|
if (typeof current !== 'object' || !Object.hasOwn(current, part)) {
|
|
915
919
|
return undefined;
|
|
916
920
|
}
|
|
@@ -71,23 +71,28 @@ export declare class GitAnalyzer {
|
|
|
71
71
|
private isGitRepo;
|
|
72
72
|
/** After a rev-parse timeout, when to ask git again (until then: "timeout"). */
|
|
73
73
|
private repoRetryAt;
|
|
74
|
+
/** Files whose git data came back incomplete outside any withFileDeadline() call. */
|
|
74
75
|
private readonly timedOutFiles;
|
|
75
|
-
/**
|
|
76
|
-
private readonly
|
|
76
|
+
/** The withFileDeadline() call each async context runs in, so concurrent calls on one file stay apart (#1165). */
|
|
77
|
+
private readonly fileScopes;
|
|
77
78
|
constructor(config?: GitAnalyzerConfig);
|
|
78
79
|
/**
|
|
79
80
|
* Check if current directory is a git repository
|
|
80
81
|
*/
|
|
81
82
|
isGitRepository(): Promise<boolean>;
|
|
82
83
|
/**
|
|
83
|
-
* True when git timed out
|
|
84
|
-
* the analysis returned its "git
|
|
84
|
+
* True when git timed out, or its output overflowed, while analysing
|
|
85
|
+
* `filePath` since the last call, so the analysis returned its "git
|
|
86
|
+
* unavailable" default rather than a result. Inside withFileDeadline() it
|
|
87
|
+
* reports only that call's analyses, not another caller's on the same file (#1165).
|
|
85
88
|
*/
|
|
86
89
|
consumeTimeout(filePath: string): boolean;
|
|
87
90
|
/**
|
|
88
91
|
* Run `work`, during which every analysis of `filePath` also stops at one
|
|
89
92
|
* shared `fileTimeoutMs` deadline. One file's analyses then wait for git at
|
|
90
|
-
* most that long together, rather than `gitTimeoutMs` each (#1115).
|
|
93
|
+
* most that long together, rather than `gitTimeoutMs` each (#1115). Each
|
|
94
|
+
* call has its own deadline and timeout flag, even when calls on the same
|
|
95
|
+
* file overlap (#1165); call consumeTimeout() inside `work` to read the flag.
|
|
91
96
|
*/
|
|
92
97
|
withFileDeadline<T>(filePath: string, work: () => Promise<T>): Promise<T>;
|
|
93
98
|
/**
|
|
@@ -112,13 +117,16 @@ export declare class GitAnalyzer {
|
|
|
112
117
|
getBugHistory(filePath: string): Promise<number>;
|
|
113
118
|
/**
|
|
114
119
|
* Get comprehensive file history analysis
|
|
120
|
+
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs`, and
|
|
121
|
+
* an ENOBUFS error when its output overflows; zero history would be a false answer (#1165)
|
|
115
122
|
*/
|
|
116
123
|
getFileHistory(filePath: string): Promise<FileHistory>;
|
|
117
124
|
/**
|
|
118
125
|
* Get files changed since a specific date
|
|
119
126
|
* @param since - Date to check changes from (default: 24 hours ago)
|
|
120
127
|
* @returns Array of changed file paths relative to repo root
|
|
121
|
-
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs
|
|
128
|
+
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs`, and
|
|
129
|
+
* an Error when git fails; neither means "no changes" (#1165)
|
|
122
130
|
*/
|
|
123
131
|
getChangedFiles(since?: Date): Promise<string[]>;
|
|
124
132
|
/**
|
|
@@ -128,13 +136,15 @@ export declare class GitAnalyzer {
|
|
|
128
136
|
* @throws Error when `commitHash` is option-shaped (starts with "-") or otherwise
|
|
129
137
|
* not a safe revision argument; git would otherwise parse it as an option
|
|
130
138
|
* (e.g. `--output=<path>` writes an arbitrary file). See issue #960.
|
|
131
|
-
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs
|
|
139
|
+
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs`, and
|
|
140
|
+
* an Error when git fails, e.g. on an unknown revision (#1165)
|
|
132
141
|
*/
|
|
133
142
|
getCommitFiles(commitHash?: string): Promise<string[]>;
|
|
134
143
|
/**
|
|
135
144
|
* Get files with uncommitted changes (staged + unstaged)
|
|
136
145
|
* @returns Array of modified file paths relative to repo root
|
|
137
|
-
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs
|
|
146
|
+
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs`, and
|
|
147
|
+
* an Error when git fails (#1165)
|
|
138
148
|
*/
|
|
139
149
|
getUncommittedFiles(): Promise<string[]>;
|
|
140
150
|
/**
|
|
@@ -143,13 +153,22 @@ export declare class GitAnalyzer {
|
|
|
143
153
|
* never reach a shell.
|
|
144
154
|
*/
|
|
145
155
|
private countBugFixCommits;
|
|
156
|
+
/**
|
|
157
|
+
* `query`'s paths, or none when the repository has no commit yet, which
|
|
158
|
+
* `git log` and `git diff HEAD` report as an error.
|
|
159
|
+
*/
|
|
160
|
+
private unlessUnborn;
|
|
146
161
|
/**
|
|
147
162
|
* Run one file's analysis with every git call sharing one `gitTimeoutMs`
|
|
148
|
-
* deadline (#1115). When git is unavailable or
|
|
149
|
-
*
|
|
150
|
-
*
|
|
163
|
+
* deadline (#1115). When git is unavailable or fails, the analysis returns
|
|
164
|
+
* its default, which callers treat as "no git data", never a measured 0
|
|
165
|
+
* (#1165). A timeout or an output overflow is recorded for consumeTimeout(),
|
|
166
|
+
* or, with `strict`, rejects.
|
|
151
167
|
*/
|
|
152
168
|
private analyze;
|
|
169
|
+
/** The withFileDeadline() call on `filePath` that the current async context runs in. */
|
|
170
|
+
private scopeFor;
|
|
171
|
+
private markIncomplete;
|
|
153
172
|
/**
|
|
154
173
|
* Whether the repo root is a git work tree. A timeout is not an answer: it
|
|
155
174
|
* is remembered for `cacheTtl` so a hung git is not waited on for every
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* - Bug history from commit messages
|
|
10
10
|
*/
|
|
11
11
|
import * as path from 'path';
|
|
12
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
12
13
|
import { assertSafeGitRef } from './ref-validation.js';
|
|
13
14
|
import { GitTimeoutError, runGit } from './git-process.js';
|
|
14
15
|
/**
|
|
@@ -35,6 +36,10 @@ const DEFAULT_CONFIG = {
|
|
|
35
36
|
};
|
|
36
37
|
/** Room for `git blame --line-porcelain` on large files (execFileSync allowed 1 MiB). */
|
|
37
38
|
const GIT_MAX_BUFFER = 64 * 1024 * 1024;
|
|
39
|
+
/** Git had an answer that was not read: it timed out or overflowed the output limit. */
|
|
40
|
+
function isIncompleteRead(error) {
|
|
41
|
+
return error instanceof GitTimeoutError || error?.code === 'ENOBUFS';
|
|
42
|
+
}
|
|
38
43
|
/**
|
|
39
44
|
* Git Analyzer for defect prediction metrics
|
|
40
45
|
*/
|
|
@@ -44,9 +49,10 @@ export class GitAnalyzer {
|
|
|
44
49
|
isGitRepo = null;
|
|
45
50
|
/** After a rev-parse timeout, when to ask git again (until then: "timeout"). */
|
|
46
51
|
repoRetryAt = 0;
|
|
52
|
+
/** Files whose git data came back incomplete outside any withFileDeadline() call. */
|
|
47
53
|
timedOutFiles = new Set();
|
|
48
|
-
/**
|
|
49
|
-
|
|
54
|
+
/** The withFileDeadline() call each async context runs in, so concurrent calls on one file stay apart (#1165). */
|
|
55
|
+
fileScopes = new AsyncLocalStorage();
|
|
50
56
|
constructor(config = {}) {
|
|
51
57
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
52
58
|
}
|
|
@@ -57,27 +63,31 @@ export class GitAnalyzer {
|
|
|
57
63
|
return (await this.repoState()) === true;
|
|
58
64
|
}
|
|
59
65
|
/**
|
|
60
|
-
* True when git timed out
|
|
61
|
-
* the analysis returned its "git
|
|
66
|
+
* True when git timed out, or its output overflowed, while analysing
|
|
67
|
+
* `filePath` since the last call, so the analysis returned its "git
|
|
68
|
+
* unavailable" default rather than a result. Inside withFileDeadline() it
|
|
69
|
+
* reports only that call's analyses, not another caller's on the same file (#1165).
|
|
62
70
|
*/
|
|
63
71
|
consumeTimeout(filePath) {
|
|
64
|
-
|
|
72
|
+
const scope = this.scopeFor(filePath);
|
|
73
|
+
if (!scope)
|
|
74
|
+
return this.timedOutFiles.delete(filePath);
|
|
75
|
+
const incomplete = scope.incomplete;
|
|
76
|
+
scope.incomplete = false;
|
|
77
|
+
return incomplete;
|
|
65
78
|
}
|
|
66
79
|
/**
|
|
67
80
|
* Run `work`, during which every analysis of `filePath` also stops at one
|
|
68
81
|
* shared `fileTimeoutMs` deadline. One file's analyses then wait for git at
|
|
69
|
-
* most that long together, rather than `gitTimeoutMs` each (#1115).
|
|
82
|
+
* most that long together, rather than `gitTimeoutMs` each (#1115). Each
|
|
83
|
+
* call has its own deadline and timeout flag, even when calls on the same
|
|
84
|
+
* file overlap (#1165); call consumeTimeout() inside `work` to read the flag.
|
|
70
85
|
*/
|
|
71
86
|
async withFileDeadline(filePath, work) {
|
|
72
|
-
if (this.
|
|
87
|
+
if (this.scopeFor(filePath))
|
|
73
88
|
return work();
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return await work();
|
|
77
|
-
}
|
|
78
|
-
finally {
|
|
79
|
-
this.fileDeadlines.delete(filePath);
|
|
80
|
-
}
|
|
89
|
+
const scope = { filePath, deadline: Date.now() + this.config.fileTimeoutMs, incomplete: false };
|
|
90
|
+
return this.fileScopes.run(scope, work);
|
|
81
91
|
}
|
|
82
92
|
/**
|
|
83
93
|
* Get file change frequency (commits in last 90 days / 3)
|
|
@@ -88,7 +98,7 @@ export class GitAnalyzer {
|
|
|
88
98
|
const cached = this.getFromCache(cacheKey);
|
|
89
99
|
if (cached !== undefined)
|
|
90
100
|
return cached;
|
|
91
|
-
return this.analyze(filePath, 0.4, async (git, relativePath) => {
|
|
101
|
+
return this.analyze(filePath, 0.4, {}, async (git, relativePath) => {
|
|
92
102
|
// Literal pathspecs preserve route filenames such as app/[id].tsx.
|
|
93
103
|
// Arguments go to git directly, without shell interpretation.
|
|
94
104
|
const output = (await git.text(['--literal-pathspecs', 'log', '--oneline', '--since=90 days ago', '--', relativePath])).trim();
|
|
@@ -107,7 +117,7 @@ export class GitAnalyzer {
|
|
|
107
117
|
const cached = this.getFromCache(cacheKey);
|
|
108
118
|
if (cached !== undefined)
|
|
109
119
|
return cached;
|
|
110
|
-
return this.analyze(filePath, 0.5, async (git, relativePath) => {
|
|
120
|
+
return this.analyze(filePath, 0.5, {}, async (git, relativePath) => {
|
|
111
121
|
const blameOutput = await git.text(['--literal-pathspecs', 'blame', '--line-porcelain', '--', relativePath]);
|
|
112
122
|
// Parse blame output - count authors manually instead of piping through shell
|
|
113
123
|
const authorCounts = new Map();
|
|
@@ -135,7 +145,7 @@ export class GitAnalyzer {
|
|
|
135
145
|
const cached = this.getFromCache(cacheKey);
|
|
136
146
|
if (cached !== undefined)
|
|
137
147
|
return cached;
|
|
138
|
-
return this.analyze(filePath, 0.4, async (git, relativePath) => {
|
|
148
|
+
return this.analyze(filePath, 0.4, {}, async (git, relativePath) => {
|
|
139
149
|
// First commit: the last line (oldest) of the commits that added the file
|
|
140
150
|
const added = await git.lines(['--literal-pathspecs', 'log', '--format=%at', '--follow', '--diff-filter=A', '--', relativePath]);
|
|
141
151
|
const firstCommitTimestamp = parseInt(added[added.length - 1] ?? '', 10);
|
|
@@ -172,7 +182,7 @@ export class GitAnalyzer {
|
|
|
172
182
|
const cached = this.getFromCache(cacheKey);
|
|
173
183
|
if (cached !== undefined)
|
|
174
184
|
return cached;
|
|
175
|
-
return this.analyze(filePath, 0.2, async (git, relativePath) => {
|
|
185
|
+
return this.analyze(filePath, 0.2, {}, async (git, relativePath) => {
|
|
176
186
|
const bugCommits = await this.countBugFixCommits(git, relativePath);
|
|
177
187
|
const riskScore = Math.min(1, bugCommits / 10); // Normalize: 10+ bug fixes = 1.0
|
|
178
188
|
this.setCache(cacheKey, riskScore);
|
|
@@ -181,14 +191,16 @@ export class GitAnalyzer {
|
|
|
181
191
|
}
|
|
182
192
|
/**
|
|
183
193
|
* Get comprehensive file history analysis
|
|
194
|
+
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs`, and
|
|
195
|
+
* an ENOBUFS error when its output overflows; zero history would be a false answer (#1165)
|
|
184
196
|
*/
|
|
185
197
|
async getFileHistory(filePath) {
|
|
186
198
|
const cacheKey = `history:${filePath}`;
|
|
187
199
|
const cached = this.getFromCache(cacheKey);
|
|
188
200
|
if (cached)
|
|
189
201
|
return cached;
|
|
190
|
-
return this.analyze(filePath, this.getDefaultFileHistory(filePath), async (git, relativePath) => {
|
|
191
|
-
//
|
|
202
|
+
return this.analyze(filePath, this.getDefaultFileHistory(filePath), { strict: true }, async (git, relativePath) => {
|
|
203
|
+
// `git log` yields no lines when the file is not in git
|
|
192
204
|
const totalCommits = (await git.lines(['--literal-pathspecs', 'log', '--oneline', '--', relativePath])).length;
|
|
193
205
|
// Parse authors here instead of piping through sort/wc
|
|
194
206
|
const uniqueAuthors = new Set(await git.lines(['--literal-pathspecs', 'log', '--format=%ae', '--', relativePath])).size;
|
|
@@ -224,14 +236,16 @@ export class GitAnalyzer {
|
|
|
224
236
|
* Get files changed since a specific date
|
|
225
237
|
* @param since - Date to check changes from (default: 24 hours ago)
|
|
226
238
|
* @returns Array of changed file paths relative to repo root
|
|
227
|
-
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs
|
|
239
|
+
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs`, and
|
|
240
|
+
* an Error when git fails; neither means "no changes" (#1165)
|
|
228
241
|
*/
|
|
229
242
|
async getChangedFiles(since) {
|
|
230
243
|
if (!(await this.isGitRepository())) {
|
|
231
244
|
return [];
|
|
232
245
|
}
|
|
233
246
|
const sinceDate = since || new Date(Date.now() - 24 * 60 * 60 * 1000);
|
|
234
|
-
const
|
|
247
|
+
const git = this.query();
|
|
248
|
+
const files = await this.unlessUnborn(git, git.paths(['log', `--since=${sinceDate.toISOString()}`, '--name-only', '-z', '--format=']));
|
|
235
249
|
return Array.from(new Set(files));
|
|
236
250
|
}
|
|
237
251
|
/**
|
|
@@ -241,7 +255,8 @@ export class GitAnalyzer {
|
|
|
241
255
|
* @throws Error when `commitHash` is option-shaped (starts with "-") or otherwise
|
|
242
256
|
* not a safe revision argument; git would otherwise parse it as an option
|
|
243
257
|
* (e.g. `--output=<path>` writes an arbitrary file). See issue #960.
|
|
244
|
-
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs
|
|
258
|
+
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs`, and
|
|
259
|
+
* an Error when git fails, e.g. on an unknown revision (#1165)
|
|
245
260
|
*/
|
|
246
261
|
async getCommitFiles(commitHash = 'HEAD') {
|
|
247
262
|
// Validate before touching git: there is no shell, so stripping
|
|
@@ -255,7 +270,8 @@ export class GitAnalyzer {
|
|
|
255
270
|
/**
|
|
256
271
|
* Get files with uncommitted changes (staged + unstaged)
|
|
257
272
|
* @returns Array of modified file paths relative to repo root
|
|
258
|
-
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs
|
|
273
|
+
* @throws GitTimeoutError when git does not answer within `gitTimeoutMs`, and
|
|
274
|
+
* an Error when git fails (#1165)
|
|
259
275
|
*/
|
|
260
276
|
async getUncommittedFiles() {
|
|
261
277
|
if (!(await this.isGitRepository())) {
|
|
@@ -263,7 +279,7 @@ export class GitAnalyzer {
|
|
|
263
279
|
}
|
|
264
280
|
// `diff HEAD` fails before the first commit; `--cached` still lists staged files.
|
|
265
281
|
const git = this.query();
|
|
266
|
-
const unstaged = await git.paths(['diff', '--name-only', '-z', 'HEAD']);
|
|
282
|
+
const unstaged = await this.unlessUnborn(git, git.paths(['diff', '--name-only', '-z', 'HEAD']));
|
|
267
283
|
const staged = await git.paths(['diff', '--name-only', '-z', '--cached']);
|
|
268
284
|
return Array.from(new Set([...unstaged, ...staged]));
|
|
269
285
|
}
|
|
@@ -279,28 +295,69 @@ export class GitAnalyzer {
|
|
|
279
295
|
const lines = await git.lines(['--literal-pathspecs', 'log', '--oneline', '-i', ...greps, '--', relativePath]);
|
|
280
296
|
return new Set(lines.map((line) => line.split(' ')[0]).filter(Boolean)).size;
|
|
281
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* `query`'s paths, or none when the repository has no commit yet, which
|
|
300
|
+
* `git log` and `git diff HEAD` report as an error.
|
|
301
|
+
*/
|
|
302
|
+
async unlessUnborn(git, query) {
|
|
303
|
+
try {
|
|
304
|
+
return await query;
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
if (error instanceof GitTimeoutError)
|
|
308
|
+
throw error;
|
|
309
|
+
try {
|
|
310
|
+
await git.text(['rev-parse', '--verify', '-q', 'HEAD']);
|
|
311
|
+
}
|
|
312
|
+
catch (headError) {
|
|
313
|
+
if (headError instanceof GitTimeoutError)
|
|
314
|
+
throw headError;
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
282
320
|
/**
|
|
283
321
|
* Run one file's analysis with every git call sharing one `gitTimeoutMs`
|
|
284
|
-
* deadline (#1115). When git is unavailable or
|
|
285
|
-
*
|
|
286
|
-
*
|
|
322
|
+
* deadline (#1115). When git is unavailable or fails, the analysis returns
|
|
323
|
+
* its default, which callers treat as "no git data", never a measured 0
|
|
324
|
+
* (#1165). A timeout or an output overflow is recorded for consumeTimeout(),
|
|
325
|
+
* or, with `strict`, rejects.
|
|
287
326
|
*/
|
|
288
|
-
async analyze(filePath, fallback, work) {
|
|
327
|
+
async analyze(filePath, fallback, options, work) {
|
|
328
|
+
const scope = this.scopeFor(filePath);
|
|
289
329
|
const repo = await this.repoState();
|
|
290
|
-
if (repo
|
|
291
|
-
if (
|
|
292
|
-
this.
|
|
293
|
-
|
|
330
|
+
if (repo === 'timeout') {
|
|
331
|
+
if (options.strict)
|
|
332
|
+
throw new GitTimeoutError(['rev-parse', '--is-inside-work-tree'], this.config.gitTimeoutMs);
|
|
333
|
+
this.markIncomplete(filePath, scope);
|
|
294
334
|
}
|
|
335
|
+
if (repo !== true)
|
|
336
|
+
return fallback;
|
|
295
337
|
try {
|
|
296
|
-
return await work(this.query(
|
|
338
|
+
return await work(this.query(scope?.deadline), this.getRelativePath(filePath));
|
|
297
339
|
}
|
|
298
340
|
catch (error) {
|
|
299
|
-
|
|
300
|
-
|
|
341
|
+
// Any other failure is git's answer for this file, e.g. `blame` of an untracked file.
|
|
342
|
+
if (!isIncompleteRead(error))
|
|
343
|
+
return fallback;
|
|
344
|
+
if (options.strict)
|
|
345
|
+
throw error;
|
|
346
|
+
this.markIncomplete(filePath, scope);
|
|
301
347
|
return fallback;
|
|
302
348
|
}
|
|
303
349
|
}
|
|
350
|
+
/** The withFileDeadline() call on `filePath` that the current async context runs in. */
|
|
351
|
+
scopeFor(filePath) {
|
|
352
|
+
const scope = this.fileScopes.getStore();
|
|
353
|
+
return scope?.filePath === filePath ? scope : undefined;
|
|
354
|
+
}
|
|
355
|
+
markIncomplete(filePath, scope) {
|
|
356
|
+
if (scope)
|
|
357
|
+
scope.incomplete = true;
|
|
358
|
+
else
|
|
359
|
+
this.timedOutFiles.add(filePath);
|
|
360
|
+
}
|
|
304
361
|
/**
|
|
305
362
|
* Whether the repo root is a git work tree. A timeout is not an answer: it
|
|
306
363
|
* is remembered for `cacheTtl` so a hung git is not waited on for every
|
|
@@ -335,20 +392,10 @@ export class GitAnalyzer {
|
|
|
335
392
|
const text = (args) => runGit(args, {
|
|
336
393
|
cwd: this.config.repoRoot, timeout: deadline - Date.now(), maxBuffer: GIT_MAX_BUFFER,
|
|
337
394
|
});
|
|
338
|
-
const orNothing = async (args, separator) => {
|
|
339
|
-
try {
|
|
340
|
-
return (await text(args)).split(separator);
|
|
341
|
-
}
|
|
342
|
-
catch (error) {
|
|
343
|
-
if (error instanceof GitTimeoutError)
|
|
344
|
-
throw error;
|
|
345
|
-
return [];
|
|
346
|
-
}
|
|
347
|
-
};
|
|
348
395
|
return {
|
|
349
396
|
text,
|
|
350
|
-
lines: async (args) => (await
|
|
351
|
-
paths: async (args) => (await
|
|
397
|
+
lines: async (args) => (await text(args)).split('\n').map((line) => line.trim()).filter(Boolean),
|
|
398
|
+
paths: async (args) => (await text(args)).split('\0').filter(Boolean),
|
|
352
399
|
};
|
|
353
400
|
}
|
|
354
401
|
/**
|
|
@@ -5,24 +5,41 @@
|
|
|
5
5
|
* it again later, so a file or symlink swapped in between could be read
|
|
6
6
|
* unchecked. These readers OPEN first and validate what was opened:
|
|
7
7
|
*
|
|
8
|
-
* - the path
|
|
9
|
-
*
|
|
8
|
+
* - the path is resolved the kernel's way (a symlink is followed before a
|
|
9
|
+
* later `..` is applied, as the payload guard does), and that realpath is
|
|
10
|
+
* opened with O_NOFOLLOW (a symlink swapped onto the final name fails the
|
|
11
|
+
* open) and O_NONBLOCK (a FIFO cannot hang the open);
|
|
10
12
|
* - the descriptor must be a regular file within the size limit (fstat);
|
|
11
13
|
* - the descriptor's real location (/proc/self/fd/N on Linux; elsewhere the
|
|
12
14
|
* re-resolved realpath, which must be the same inode) must lie inside the
|
|
13
15
|
* project root, so a directory component swapped for a symlink is caught;
|
|
16
|
+
* a file that was replaced or unlinked after the open is refused as
|
|
17
|
+
* 'changed-during-read';
|
|
14
18
|
* - the content is read from that same descriptor, and never past the limit,
|
|
15
19
|
* even if the file grows after the fstat.
|
|
16
20
|
*
|
|
17
21
|
* A path spelled outside the root is refused before any filesystem call,
|
|
18
22
|
* unless the caller opts into `outsideRoot: 'allow'` for paths it accepts
|
|
19
23
|
* from a trusted source (the other checks still apply).
|
|
24
|
+
*
|
|
25
|
+
* Hardlinks (#1186): no path check can see a hardlink, because every name of
|
|
26
|
+
* a hardlinked file is equally real and the kernel offers no way to list the
|
|
27
|
+
* other names. `hardlinks: 'refuse'` refuses any file with more than one link
|
|
28
|
+
* (st_nlink > 1), which also refuses a hardlink whose other name is inside
|
|
29
|
+
* the project (pnpm stores, `cp -al` snapshots). A file whose outside name
|
|
30
|
+
* was removed has one link and is read. The policy trusts the link count the
|
|
31
|
+
* filesystem reports: one that reports 1 for every file (FAT, some network
|
|
32
|
+
* shares) hides a hardlink from it. Verified on Linux only.
|
|
20
33
|
*/
|
|
21
34
|
import { type Stats } from 'node:fs';
|
|
22
35
|
import { CallerInputError } from '../error-utils.js';
|
|
23
36
|
/** Default upper bound for a confined read when the caller names none. */
|
|
24
37
|
export declare const DEFAULT_MAX_CONFINED_READ_BYTES: number;
|
|
25
|
-
export type ConfinedReadReason = 'not-found' | 'not-a-file' | 'outside-project-root' | 'unreadable' | 'too-large'
|
|
38
|
+
export type ConfinedReadReason = 'not-found' | 'not-a-file' | 'outside-project-root' | 'unreadable' | 'too-large'
|
|
39
|
+
/** The opened file is no longer at the checked path (replaced or unlinked). */
|
|
40
|
+
| 'changed-during-read'
|
|
41
|
+
/** `hardlinks: 'refuse'` and the file has more than one link. */
|
|
42
|
+
| 'hardlinked';
|
|
26
43
|
export interface ConfinedReadOptions {
|
|
27
44
|
/** Project root; defaults to findProjectRoot(). */
|
|
28
45
|
projectRoot?: string;
|
|
@@ -34,6 +51,11 @@ export interface ConfinedReadOptions {
|
|
|
34
51
|
* trusts it. Paths spelled inside the root are always held to the root.
|
|
35
52
|
*/
|
|
36
53
|
outsideRoot?: 'refuse' | 'allow';
|
|
54
|
+
/**
|
|
55
|
+
* 'refuse' refuses a file with more than one hardlink, which a path check
|
|
56
|
+
* cannot confine (see the module comment). Default 'allow'.
|
|
57
|
+
*/
|
|
58
|
+
hardlinks?: 'allow' | 'refuse';
|
|
37
59
|
}
|
|
38
60
|
/**
|
|
39
61
|
* A confined read that was refused; `reason` matches the payload guard's.
|
|
@@ -52,10 +74,13 @@ export declare const CONFINED_OPEN_FLAGS: number;
|
|
|
52
74
|
/** True when `candidate` is `root` or lies beneath it (both absolute). */
|
|
53
75
|
export declare function isWithinRoot(root: string, candidate: string): boolean;
|
|
54
76
|
/**
|
|
55
|
-
* Where an OPEN descriptor really points. On Linux, /proc/self/fd/N
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
77
|
+
* Where an OPEN descriptor really points. On Linux, /proc/self/fd/N names the
|
|
78
|
+
* opened file itself; when /proc answers, its answer is final (#1186): a file
|
|
79
|
+
* unlinked or replaced since the open reads as "<path> (deleted)" or names
|
|
80
|
+
* another inode, and is not re-resolved by name. Without /proc (macOS,
|
|
81
|
+
* Windows, /proc not mounted), re-resolve the path and accept it only if it
|
|
82
|
+
* is the same inode as the descriptor, so a swap after the open is detected.
|
|
83
|
+
* Returns null when the opened file is no longer where it was checked.
|
|
59
84
|
*/
|
|
60
85
|
export declare function openedLocation(fd: number, lexical: string, opened: Stats): Promise<string | null>;
|
|
61
86
|
/** Synchronous openedLocation, for callers that read synchronously. */
|