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
|
@@ -5,18 +5,31 @@
|
|
|
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 { constants as fsConstants } from 'node:fs';
|
|
22
35
|
import * as fsSync from 'node:fs';
|
|
@@ -52,19 +65,22 @@ export function isWithinRoot(root, candidate) {
|
|
|
52
65
|
return relative === '' || (relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
|
|
53
66
|
}
|
|
54
67
|
/**
|
|
55
|
-
* Where an OPEN descriptor really points. On Linux, /proc/self/fd/N
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
68
|
+
* Where an OPEN descriptor really points. On Linux, /proc/self/fd/N names the
|
|
69
|
+
* opened file itself; when /proc answers, its answer is final (#1186): a file
|
|
70
|
+
* unlinked or replaced since the open reads as "<path> (deleted)" or names
|
|
71
|
+
* another inode, and is not re-resolved by name. Without /proc (macOS,
|
|
72
|
+
* Windows, /proc not mounted), re-resolve the path and accept it only if it
|
|
73
|
+
* is the same inode as the descriptor, so a swap after the open is detected.
|
|
74
|
+
* Returns null when the opened file is no longer where it was checked.
|
|
59
75
|
*/
|
|
60
76
|
export async function openedLocation(fd, lexical, opened) {
|
|
61
77
|
const sameFile = async (candidate) => {
|
|
62
78
|
const st = await fs.stat(candidate).catch(() => null);
|
|
63
79
|
return st !== null && st.dev === opened.dev && st.ino === opened.ino;
|
|
64
80
|
};
|
|
65
|
-
const viaProc = await fs.
|
|
66
|
-
if (viaProc
|
|
67
|
-
return viaProc;
|
|
81
|
+
const viaProc = await fs.readlink(`/proc/self/fd/${fd}`).catch(() => null);
|
|
82
|
+
if (viaProc !== null)
|
|
83
|
+
return path.isAbsolute(viaProc) && await sameFile(viaProc) ? viaProc : null;
|
|
68
84
|
const real = await fs.realpath(lexical).catch(() => null);
|
|
69
85
|
if (real && await sameFile(real))
|
|
70
86
|
return real;
|
|
@@ -81,18 +97,21 @@ export function openedLocationSync(fd, lexical, opened) {
|
|
|
81
97
|
return false;
|
|
82
98
|
}
|
|
83
99
|
};
|
|
84
|
-
const
|
|
100
|
+
const viaProc = (() => {
|
|
85
101
|
try {
|
|
86
|
-
return fsSync.
|
|
102
|
+
return fsSync.readlinkSync(`/proc/self/fd/${fd}`);
|
|
87
103
|
}
|
|
88
104
|
catch {
|
|
89
105
|
return null;
|
|
90
106
|
}
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
107
|
+
})();
|
|
108
|
+
if (viaProc !== null)
|
|
109
|
+
return path.isAbsolute(viaProc) && sameFile(viaProc) ? viaProc : null;
|
|
110
|
+
let real = null;
|
|
111
|
+
try {
|
|
112
|
+
real = fsSync.realpathSync.native(lexical);
|
|
113
|
+
}
|
|
114
|
+
catch { /* not resolvable */ }
|
|
96
115
|
if (real && sameFile(real))
|
|
97
116
|
return real;
|
|
98
117
|
return null;
|
|
@@ -120,14 +139,21 @@ function plan(filePath, rootReal, options) {
|
|
|
120
139
|
// reason cannot reveal whether an outside path exists.
|
|
121
140
|
if (!inRoot && options.outsideRoot !== 'allow')
|
|
122
141
|
throw fail(filePath, 'outside-project-root');
|
|
123
|
-
|
|
142
|
+
const raw = path.isAbsolute(filePath) ? filePath : `${process.cwd()}${path.sep}${filePath}`;
|
|
143
|
+
return {
|
|
144
|
+
lexical, raw, rootReal, inRoot,
|
|
145
|
+
limit: options.maxBytes ?? DEFAULT_MAX_CONFINED_READ_BYTES,
|
|
146
|
+
hardlinks: options.hardlinks ?? 'allow',
|
|
147
|
+
};
|
|
124
148
|
}
|
|
125
149
|
/** Check the opened descriptor's stat before anything is read. */
|
|
126
|
-
function checkOpened(filePath, st,
|
|
150
|
+
function checkOpened(filePath, st, p) {
|
|
127
151
|
if (!st.isFile())
|
|
128
152
|
throw fail(filePath, 'not-a-file');
|
|
129
|
-
if (st.size > limit)
|
|
153
|
+
if (st.size > p.limit)
|
|
130
154
|
throw fail(filePath, 'too-large');
|
|
155
|
+
if (p.hardlinks === 'refuse' && st.nlink > 1)
|
|
156
|
+
throw fail(filePath, 'hardlinked');
|
|
131
157
|
}
|
|
132
158
|
/**
|
|
133
159
|
* Read a file by path, confined to the project root and validated on the
|
|
@@ -139,7 +165,9 @@ export async function readConfinedFile(filePath, options = {}) {
|
|
|
139
165
|
const p = plan(filePath, rootReal, options);
|
|
140
166
|
let real;
|
|
141
167
|
try {
|
|
142
|
-
|
|
168
|
+
// fs.promises.realpath is the native realpath(3): it resolves `..` after
|
|
169
|
+
// following the symlink before it.
|
|
170
|
+
real = await fs.realpath(p.raw);
|
|
143
171
|
}
|
|
144
172
|
catch (error) {
|
|
145
173
|
throw fail(filePath, reasonFor(error), error);
|
|
@@ -155,10 +183,12 @@ export async function readConfinedFile(filePath, options = {}) {
|
|
|
155
183
|
}
|
|
156
184
|
try {
|
|
157
185
|
const st = await handle.stat();
|
|
158
|
-
checkOpened(filePath, st, p
|
|
186
|
+
checkOpened(filePath, st, p);
|
|
159
187
|
if (p.inRoot) {
|
|
160
188
|
const location = await openedLocation(handle.fd, real, st);
|
|
161
|
-
if (!location
|
|
189
|
+
if (!location)
|
|
190
|
+
throw fail(filePath, 'changed-during-read');
|
|
191
|
+
if (!isWithinRoot(p.rootReal, location))
|
|
162
192
|
throw fail(filePath, 'outside-project-root');
|
|
163
193
|
}
|
|
164
194
|
// Read at most limit + 1 bytes from this descriptor: a file that grew
|
|
@@ -201,7 +231,8 @@ export function readConfinedFileSync(filePath, options = {}) {
|
|
|
201
231
|
const p = plan(filePath, rootReal, options);
|
|
202
232
|
let real;
|
|
203
233
|
try {
|
|
204
|
-
|
|
234
|
+
// .native: the JS realpathSync collapses `..` as text before resolving.
|
|
235
|
+
real = fsSync.realpathSync.native(p.raw);
|
|
205
236
|
}
|
|
206
237
|
catch (error) {
|
|
207
238
|
throw fail(filePath, reasonFor(error), error);
|
|
@@ -217,10 +248,12 @@ export function readConfinedFileSync(filePath, options = {}) {
|
|
|
217
248
|
}
|
|
218
249
|
try {
|
|
219
250
|
const st = fsSync.fstatSync(fd);
|
|
220
|
-
checkOpened(filePath, st, p
|
|
251
|
+
checkOpened(filePath, st, p);
|
|
221
252
|
if (p.inRoot) {
|
|
222
253
|
const location = openedLocationSync(fd, real, st);
|
|
223
|
-
if (!location
|
|
254
|
+
if (!location)
|
|
255
|
+
throw fail(filePath, 'changed-during-read');
|
|
256
|
+
if (!isWithinRoot(p.rootReal, location))
|
|
224
257
|
throw fail(filePath, 'outside-project-root');
|
|
225
258
|
}
|
|
226
259
|
const chunks = [];
|
|
@@ -335,7 +335,10 @@ export class FileReader {
|
|
|
335
335
|
try {
|
|
336
336
|
// The lexical root, so a path spelled under a symlinked root still
|
|
337
337
|
// counts as inside; the primitive resolves the root's realpath itself.
|
|
338
|
-
|
|
338
|
+
// #1186: the caller's spelling, not `lexical`, so `link/../x` resolves
|
|
339
|
+
// through the link the way the kernel and the payload guard resolve it.
|
|
340
|
+
const raw = path.isAbsolute(filePath) ? filePath : `${path.resolve(this.basePath)}${path.sep}${filePath}`;
|
|
341
|
+
return ok(await readConfinedText(raw, { projectRoot: this.projectRoot ?? rootReal }));
|
|
339
342
|
}
|
|
340
343
|
catch (error) {
|
|
341
344
|
if (!(error instanceof ConfinedReadError))
|
package/dist/shared/safe-db.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface SafeDbOptions {
|
|
|
16
16
|
fileMustExist?: boolean;
|
|
17
17
|
/** Busy timeout in ms (default: 5000) */
|
|
18
18
|
busyTimeout?: number;
|
|
19
|
-
/** Enable WAL mode (default: true for writable
|
|
19
|
+
/** Enable WAL mode (default: true for writable; always ignored for readonly) */
|
|
20
20
|
walMode?: boolean;
|
|
21
21
|
/**
|
|
22
22
|
* M3.2: on a malformed/corrupt existing DB, auto-restore the newest verified
|
package/dist/shared/safe-db.js
CHANGED
|
@@ -12,6 +12,7 @@ import Database from 'better-sqlite3';
|
|
|
12
12
|
import { basename } from 'node:path';
|
|
13
13
|
import { attemptAutoRestore } from './db-recovery.js';
|
|
14
14
|
import { withNativeModuleRemedy } from './native-module-errors.js';
|
|
15
|
+
import { setJournalModeWithRetry } from './sqlite-journal-mode.js';
|
|
15
16
|
/**
|
|
16
17
|
* Open a SQLite database with safe defaults that prevent corruption.
|
|
17
18
|
*
|
|
@@ -95,8 +96,11 @@ export function openDatabase(dbPath, opts) {
|
|
|
95
96
|
// 2026-07-07), so continuing to write in WAL would trade a loud outage for
|
|
96
97
|
// silent corruption. Availability is not worth that; the message below
|
|
97
98
|
// carries the exact command that finds the real holder.
|
|
99
|
+
//
|
|
100
|
+
// Concurrent openers racing the same one-time switch (#1164) are retried
|
|
101
|
+
// within busyTimeout first; only contention that outlasts it fails closed.
|
|
98
102
|
try {
|
|
99
|
-
db
|
|
103
|
+
setJournalModeWithRetry(db, desired, busyTimeout);
|
|
100
104
|
}
|
|
101
105
|
catch (err) {
|
|
102
106
|
const code = err?.code;
|
|
@@ -135,11 +139,22 @@ export function openDatabase(dbPath, opts) {
|
|
|
135
139
|
}
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
|
-
else if (walMode) {
|
|
142
|
+
else if (walMode && !readonly) {
|
|
139
143
|
// WAL mode for writable connections prevents corruption from concurrent
|
|
140
|
-
// writers. Readonly connections inherit
|
|
141
|
-
//
|
|
142
|
-
|
|
144
|
+
// writers. Readonly connections inherit the file's journal mode and must
|
|
145
|
+
// not switch it: that is a write and fails with SQLITE_READONLY on a
|
|
146
|
+
// rollback-journal file (#1320), so `walMode` is ignored for readonly opens.
|
|
147
|
+
//
|
|
148
|
+
// #1164: switching a rollback-journal file to WAL upgrades a read lock to a
|
|
149
|
+
// write lock, and SQLite returns SQLITE_BUSY for that at once instead of
|
|
150
|
+
// waiting on busy_timeout. Concurrent first opens retry within busyTimeout.
|
|
151
|
+
try {
|
|
152
|
+
setJournalModeWithRetry(db, 'WAL', busyTimeout);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
db.close();
|
|
156
|
+
throw err;
|
|
157
|
+
}
|
|
143
158
|
}
|
|
144
159
|
return db;
|
|
145
160
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Switch a SQLite connection's journal mode, retrying lock contention (#1164).
|
|
3
|
+
*
|
|
4
|
+
* `PRAGMA journal_mode = WAL` on a rollback-journal database reads page 1
|
|
5
|
+
* under a SHARED lock and then upgrades to a write lock to rewrite the header.
|
|
6
|
+
* SQLite does not run the busy handler for that upgrade (an upgrade from a
|
|
7
|
+
* held read lock could deadlock), so when several processes open the same
|
|
8
|
+
* non-WAL database at once, all but one can get SQLITE_BUSY in well under a
|
|
9
|
+
* millisecond even with busy_timeout set. Leaving WAL needs an EXCLUSIVE lock
|
|
10
|
+
* and fails the same way.
|
|
11
|
+
*
|
|
12
|
+
* This retries the switch with a short, growing sleep until `budgetMs` has
|
|
13
|
+
* passed, then throws the last error. Once another process has switched the
|
|
14
|
+
* file, the retry finds the mode already set, which needs no write lock.
|
|
15
|
+
*
|
|
16
|
+
* Dependency-free (no better-sqlite3 import) so optional-dependency callers can
|
|
17
|
+
* use it with a connection they loaded themselves.
|
|
18
|
+
*/
|
|
19
|
+
/** The part of a better-sqlite3 connection this needs. */
|
|
20
|
+
export interface JournalModeConnection {
|
|
21
|
+
pragma(source: string, options?: {
|
|
22
|
+
simple?: boolean;
|
|
23
|
+
}): unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface JournalModeRetryOptions {
|
|
26
|
+
/** Synchronous sleep, injectable for tests. */
|
|
27
|
+
sleep?: (ms: number) => void;
|
|
28
|
+
/** Clock in ms, injectable for tests. */
|
|
29
|
+
now?: () => number;
|
|
30
|
+
}
|
|
31
|
+
/** True for SQLITE_BUSY / SQLITE_LOCKED, including extended codes such as SQLITE_BUSY_RECOVERY. */
|
|
32
|
+
export declare function isJournalLockContention(err: unknown): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Set `journal_mode` to `mode`, retrying SQLITE_BUSY / SQLITE_LOCKED for up to
|
|
35
|
+
* `budgetMs`. Returns the mode SQLite reports afterwards, lower-cased. Any
|
|
36
|
+
* other error is thrown at once.
|
|
37
|
+
*/
|
|
38
|
+
export declare function setJournalModeWithRetry(db: JournalModeConnection, mode: string, budgetMs: number, options?: JournalModeRetryOptions): string;
|
|
39
|
+
//# sourceMappingURL=sqlite-journal-mode.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Switch a SQLite connection's journal mode, retrying lock contention (#1164).
|
|
3
|
+
*
|
|
4
|
+
* `PRAGMA journal_mode = WAL` on a rollback-journal database reads page 1
|
|
5
|
+
* under a SHARED lock and then upgrades to a write lock to rewrite the header.
|
|
6
|
+
* SQLite does not run the busy handler for that upgrade (an upgrade from a
|
|
7
|
+
* held read lock could deadlock), so when several processes open the same
|
|
8
|
+
* non-WAL database at once, all but one can get SQLITE_BUSY in well under a
|
|
9
|
+
* millisecond even with busy_timeout set. Leaving WAL needs an EXCLUSIVE lock
|
|
10
|
+
* and fails the same way.
|
|
11
|
+
*
|
|
12
|
+
* This retries the switch with a short, growing sleep until `budgetMs` has
|
|
13
|
+
* passed, then throws the last error. Once another process has switched the
|
|
14
|
+
* file, the retry finds the mode already set, which needs no write lock.
|
|
15
|
+
*
|
|
16
|
+
* Dependency-free (no better-sqlite3 import) so optional-dependency callers can
|
|
17
|
+
* use it with a connection they loaded themselves.
|
|
18
|
+
*/
|
|
19
|
+
const FIRST_BACKOFF_MS = 2;
|
|
20
|
+
const MAX_BACKOFF_MS = 50;
|
|
21
|
+
/** True for SQLITE_BUSY / SQLITE_LOCKED, including extended codes such as SQLITE_BUSY_RECOVERY. */
|
|
22
|
+
export function isJournalLockContention(err) {
|
|
23
|
+
const code = err?.code;
|
|
24
|
+
return typeof code === 'string' && (code.startsWith('SQLITE_BUSY') || code.startsWith('SQLITE_LOCKED'));
|
|
25
|
+
}
|
|
26
|
+
function sleepSync(ms) {
|
|
27
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Set `journal_mode` to `mode`, retrying SQLITE_BUSY / SQLITE_LOCKED for up to
|
|
31
|
+
* `budgetMs`. Returns the mode SQLite reports afterwards, lower-cased. Any
|
|
32
|
+
* other error is thrown at once.
|
|
33
|
+
*/
|
|
34
|
+
export function setJournalModeWithRetry(db, mode, budgetMs, options = {}) {
|
|
35
|
+
const sleep = options.sleep ?? sleepSync;
|
|
36
|
+
const now = options.now ?? Date.now;
|
|
37
|
+
const deadline = now() + Math.max(0, budgetMs);
|
|
38
|
+
let backoff = FIRST_BACKOFF_MS;
|
|
39
|
+
for (;;) {
|
|
40
|
+
try {
|
|
41
|
+
return String(db.pragma(`journal_mode = ${mode}`, { simple: true }) ?? '').toLowerCase();
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
const remaining = deadline - now();
|
|
45
|
+
if (!isJournalLockContention(err) || remaining <= 0)
|
|
46
|
+
throw err;
|
|
47
|
+
// Jitter so processes that collided do not retry in lockstep.
|
|
48
|
+
sleep(Math.min(remaining, backoff / 2 + Math.random() * backoff / 2));
|
|
49
|
+
backoff = Math.min(backoff * 2, MAX_BACKOFF_MS);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=sqlite-journal-mode.js.map
|
|
@@ -152,8 +152,8 @@ export async function syncClaudeFlowToAQE(options = {}) {
|
|
|
152
152
|
// Import safe database opener
|
|
153
153
|
const { openDatabase } = await import('../shared/safe-db.js');
|
|
154
154
|
const db = openDatabase(aqeDbPath);
|
|
155
|
+
// #1164: openDatabase() set the journal mode (retrying contention, honouring AQE_DISABLE_WAL).
|
|
155
156
|
try {
|
|
156
|
-
db.pragma('journal_mode = WAL');
|
|
157
157
|
// Prepare insert statements
|
|
158
158
|
const insertKv = db.prepare(`
|
|
159
159
|
INSERT OR REPLACE INTO kv_store (key, namespace, value, expires_at, created_at)
|
|
@@ -37,11 +37,10 @@ export class SQLiteReader {
|
|
|
37
37
|
throw new Error(`SQLite database not found: ${this.dbPath}`);
|
|
38
38
|
}
|
|
39
39
|
try {
|
|
40
|
-
// Open read-only
|
|
40
|
+
// Open read-only. Never set journal_mode/synchronous here: switching the
|
|
41
|
+
// journal mode is a write, so it fails with SQLITE_READONLY on a
|
|
42
|
+
// rollback-journal source (#1320). A reader must leave the source as-is.
|
|
41
43
|
this.db = openDatabase(this.dbPath, { readonly: true });
|
|
42
|
-
// Enable performance settings for reads
|
|
43
|
-
this.db.pragma('journal_mode = WAL');
|
|
44
|
-
this.db.pragma('synchronous = NORMAL');
|
|
45
44
|
console.log(`[SQLiteReader:${this.name}] Initialized: ${this.dbPath}`);
|
|
46
45
|
}
|
|
47
46
|
catch (error) {
|
|
@@ -31,8 +31,8 @@ export class SQLiteWriter {
|
|
|
31
31
|
throw new Error(`SQLite database not found: ${this.dbPath}. Run 'aqe init' to create it.`);
|
|
32
32
|
}
|
|
33
33
|
try {
|
|
34
|
+
// #1164: openDatabase() set the journal mode (retrying contention, honouring AQE_DISABLE_WAL).
|
|
34
35
|
this.db = openDatabase(this.dbPath);
|
|
35
|
-
this.db.pragma('journal_mode = WAL');
|
|
36
36
|
this.db.pragma('synchronous = NORMAL');
|
|
37
37
|
logger.debug(`Opened SQLite database: ${this.dbPath}`);
|
|
38
38
|
}
|
|
@@ -55,8 +55,8 @@ export interface WorkerMetrics {
|
|
|
55
55
|
readonly itemsAnalyzed: number;
|
|
56
56
|
/** Number of issues found */
|
|
57
57
|
readonly issuesFound: number;
|
|
58
|
-
/** Health score (0-100) */
|
|
59
|
-
readonly healthScore: number;
|
|
58
|
+
/** Health score (0-100); `null` when nothing was measured (#1137) */
|
|
59
|
+
readonly healthScore: number | null;
|
|
60
60
|
/** Trend direction */
|
|
61
61
|
readonly trend: 'improving' | 'stable' | 'degrading';
|
|
62
62
|
/** Domain-specific metrics */
|
|
@@ -28,6 +28,8 @@ export declare class GitWatcher {
|
|
|
28
28
|
private debounceTimer;
|
|
29
29
|
private _running;
|
|
30
30
|
private _polling;
|
|
31
|
+
/** Ref changes to read again after git timed out on them (fs.watch mode). */
|
|
32
|
+
private readonly retryTimers;
|
|
31
33
|
constructor(queue: PriorityQueue, options?: GitWatcherOptions);
|
|
32
34
|
get running(): boolean;
|
|
33
35
|
/**
|
|
@@ -45,6 +47,12 @@ export declare class GitWatcher {
|
|
|
45
47
|
poll(): Promise<string[]>;
|
|
46
48
|
private handleRefChange;
|
|
47
49
|
private processRefChange;
|
|
50
|
+
/**
|
|
51
|
+
* Enqueue the files changed from `lastHash` (the last head seen) to
|
|
52
|
+
* `commitHash`, or in `commitHash` alone. Returns false when git timed out,
|
|
53
|
+
* so the caller keeps `lastHash` and tries again (#1165). When git fails,
|
|
54
|
+
* the changed files are left unknown rather than reported as none.
|
|
55
|
+
*/
|
|
48
56
|
private enqueueCommitAnalysis;
|
|
49
57
|
private snapshotHeads;
|
|
50
58
|
}
|
|
@@ -9,7 +9,7 @@ import { watch } from 'fs';
|
|
|
9
9
|
import { resolve, join } from 'path';
|
|
10
10
|
import { existsSync, readFileSync } from 'fs';
|
|
11
11
|
import { getGitRefError } from '../../shared/git/ref-validation.js';
|
|
12
|
-
import { runGit } from '../../shared/git/git-process.js';
|
|
12
|
+
import { GitTimeoutError, runGit } from '../../shared/git/git-process.js';
|
|
13
13
|
/** A hung git must not stall the watcher; its process group is stopped (#1115). */
|
|
14
14
|
const GIT_TIMEOUT_MS = 10_000;
|
|
15
15
|
const DEFAULTS = {
|
|
@@ -30,6 +30,8 @@ export class GitWatcher {
|
|
|
30
30
|
debounceTimer;
|
|
31
31
|
_running = false;
|
|
32
32
|
_polling = false;
|
|
33
|
+
/** Ref changes to read again after git timed out on them (fs.watch mode). */
|
|
34
|
+
retryTimers = new Set();
|
|
33
35
|
constructor(queue, options) {
|
|
34
36
|
this.queue = queue;
|
|
35
37
|
this.options = { ...DEFAULTS, ...options };
|
|
@@ -87,6 +89,9 @@ export class GitWatcher {
|
|
|
87
89
|
this.watcher.close();
|
|
88
90
|
this.watcher = undefined;
|
|
89
91
|
}
|
|
92
|
+
for (const timer of this.retryTimers)
|
|
93
|
+
clearTimeout(timer);
|
|
94
|
+
this.retryTimers.clear();
|
|
90
95
|
this._running = false;
|
|
91
96
|
}
|
|
92
97
|
/**
|
|
@@ -111,8 +116,11 @@ export class GitWatcher {
|
|
|
111
116
|
const [branch, hash] = line.split(' ');
|
|
112
117
|
const lastHash = this.lastKnownHeads.get(branch);
|
|
113
118
|
if (lastHash && lastHash !== hash) {
|
|
119
|
+
// #1165: on a git timeout keep the old head, so the next poll
|
|
120
|
+
// covers this commit too.
|
|
121
|
+
if (!(await this.enqueueCommitAnalysis(branch, hash, lastHash)))
|
|
122
|
+
continue;
|
|
114
123
|
changedBranches.push(branch);
|
|
115
|
-
await this.enqueueCommitAnalysis(branch, hash);
|
|
116
124
|
}
|
|
117
125
|
this.lastKnownHeads.set(branch, hash);
|
|
118
126
|
}
|
|
@@ -152,37 +160,70 @@ export class GitWatcher {
|
|
|
152
160
|
const lastHash = this.lastKnownHeads.get(branch);
|
|
153
161
|
if (lastHash === newHash)
|
|
154
162
|
return; // no change
|
|
163
|
+
if (!(await this.enqueueCommitAnalysis(branch, newHash, lastHash))) {
|
|
164
|
+
// #1165: git timed out; keep the old head and read the ref again later.
|
|
165
|
+
const timer = setTimeout(() => {
|
|
166
|
+
this.retryTimers.delete(timer);
|
|
167
|
+
this.processRefChange(filename).catch((err) => {
|
|
168
|
+
console.debug('[GitWatcher] Error processing ref change:', err);
|
|
169
|
+
});
|
|
170
|
+
}, this.options.pollIntervalMs);
|
|
171
|
+
timer.unref?.();
|
|
172
|
+
this.retryTimers.add(timer);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
155
175
|
this.lastKnownHeads.set(branch, newHash);
|
|
156
|
-
await this.enqueueCommitAnalysis(branch, newHash);
|
|
157
176
|
}
|
|
158
|
-
|
|
177
|
+
/**
|
|
178
|
+
* Enqueue the files changed from `lastHash` (the last head seen) to
|
|
179
|
+
* `commitHash`, or in `commitHash` alone. Returns false when git timed out,
|
|
180
|
+
* so the caller keeps `lastHash` and tries again (#1165). When git fails,
|
|
181
|
+
* the changed files are left unknown rather than reported as none.
|
|
182
|
+
*/
|
|
183
|
+
async enqueueCommitAnalysis(branch, commitHash, lastHash) {
|
|
159
184
|
// The hash is read from a ref file; never let an option-shaped value
|
|
160
185
|
// (e.g. `--output=<path>`) reach `git diff-tree` (issue #960).
|
|
161
186
|
if (getGitRefError(commitHash, 'commit hash'))
|
|
162
|
-
return;
|
|
163
|
-
|
|
164
|
-
|
|
187
|
+
return true;
|
|
188
|
+
const since = lastHash && !getGitRefError(lastHash, 'commit hash') ? lastHash : undefined;
|
|
189
|
+
const diffTree = async (revisions) => {
|
|
165
190
|
const stdout = await runGit([
|
|
166
191
|
'diff-tree',
|
|
167
192
|
'--no-commit-id',
|
|
168
193
|
'--name-only',
|
|
169
194
|
'-r',
|
|
170
|
-
|
|
195
|
+
...revisions,
|
|
171
196
|
], { cwd: this.options.repoRoot, timeout: GIT_TIMEOUT_MS });
|
|
172
|
-
|
|
197
|
+
return stdout
|
|
173
198
|
.trim()
|
|
174
199
|
.split('\n')
|
|
175
200
|
.filter(Boolean)
|
|
176
201
|
.slice(0, this.options.maxChangedFiles);
|
|
202
|
+
};
|
|
203
|
+
let changedFiles;
|
|
204
|
+
try {
|
|
205
|
+
// From the last head seen, so commits between two polls are not skipped.
|
|
206
|
+
changedFiles = await diffTree(since ? [since, commitHash] : ['--root', commitHash]);
|
|
177
207
|
}
|
|
178
|
-
catch {
|
|
179
|
-
|
|
208
|
+
catch (error) {
|
|
209
|
+
if (error instanceof GitTimeoutError)
|
|
210
|
+
return false;
|
|
211
|
+
// The last head can be gone after a force-push and gc; fall back to this commit.
|
|
212
|
+
if (since) {
|
|
213
|
+
try {
|
|
214
|
+
changedFiles = await diffTree(['--root', commitHash]);
|
|
215
|
+
}
|
|
216
|
+
catch (fallbackError) {
|
|
217
|
+
if (fallbackError instanceof GitTimeoutError)
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
180
221
|
}
|
|
181
222
|
const payload = {
|
|
182
223
|
type: 'git_commit',
|
|
183
224
|
branch,
|
|
184
225
|
commitHash,
|
|
185
|
-
changedFiles,
|
|
226
|
+
...(changedFiles ? { changedFiles } : {}),
|
|
186
227
|
};
|
|
187
228
|
const item = {
|
|
188
229
|
id: `git-${commitHash}-${Date.now()}`,
|
|
@@ -193,6 +234,7 @@ export class GitWatcher {
|
|
|
193
234
|
ttlMs: 5 * 60 * 1000, // 5 min TTL
|
|
194
235
|
};
|
|
195
236
|
this.queue.enqueue(item);
|
|
237
|
+
return true;
|
|
196
238
|
}
|
|
197
239
|
async snapshotHeads() {
|
|
198
240
|
try {
|
|
@@ -203,7 +203,7 @@ export class QualityDaemon {
|
|
|
203
203
|
});
|
|
204
204
|
}
|
|
205
205
|
if (delta.newGaps.length > 0) {
|
|
206
|
-
const suggestions = await this.testSuggester.suggest(delta.newGaps, payload.changedFiles, memory);
|
|
206
|
+
const suggestions = await this.testSuggester.suggest(delta.newGaps, payload.changedFiles ?? [], memory);
|
|
207
207
|
this._suggestionsGenerated += suggestions.length;
|
|
208
208
|
if (suggestions.length > 0) {
|
|
209
209
|
await this.notificationService.send({
|
|
@@ -23,7 +23,8 @@ export interface GitCommitPayload {
|
|
|
23
23
|
readonly type: 'git_commit';
|
|
24
24
|
readonly branch: string;
|
|
25
25
|
readonly commitHash: string;
|
|
26
|
-
|
|
26
|
+
/** Files changed since the last commit seen; absent when git could not list them (#1165). */
|
|
27
|
+
readonly changedFiles?: string[];
|
|
27
28
|
}
|
|
28
29
|
export interface CoverageDeltaPayload {
|
|
29
30
|
readonly type: 'coverage_delta';
|
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
* A `defect:predictions` record without
|
|
19
19
|
* the measured stamp (the invented one written by <= 3.15.6) is ignored and
|
|
20
20
|
* replaced by the next measured run.
|
|
21
|
+
*
|
|
22
|
+
* #1137: the latest run of every target is reported, so predicting `src/b`
|
|
23
|
+
* after `src/a` keeps `src/a`'s files; a file named by several targets takes
|
|
24
|
+
* its prediction from the newest run that names it.
|
|
21
25
|
*/
|
|
22
26
|
import { BaseWorker } from '../base-worker';
|
|
23
27
|
import { WorkerContext, WorkerResult } from '../interfaces';
|
|
@@ -31,11 +35,12 @@ export declare class DefectPredictorWorker extends BaseWorker {
|
|
|
31
35
|
*/
|
|
32
36
|
private markPreviousStale;
|
|
33
37
|
/**
|
|
34
|
-
* #1043: the most recent prediction
|
|
38
|
+
* #1043: the most recent prediction runs the defect-intelligence predictor
|
|
35
39
|
* recorded, restricted to regular files whose real path is inside the
|
|
36
|
-
* project root.
|
|
37
|
-
*
|
|
38
|
-
*
|
|
40
|
+
* project root. #1137: the latest run of each target contributes, and a
|
|
41
|
+
* file takes its prediction from the newest run naming it. `measured` is
|
|
42
|
+
* `null` when no file qualifies; `unusable` then describes the newest run
|
|
43
|
+
* (or its ambiguous timestamp).
|
|
39
44
|
*/
|
|
40
45
|
private readLatestPrediction;
|
|
41
46
|
private analyzeHighRiskPredictions;
|