agentic-qe 3.12.3 → 3.13.1
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/.agents/skills/aqe-plan-quality/SKILL.md +25 -0
- package/.agents/skills/aqe-plan-quality/agents/openai.yaml +4 -0
- package/.agents/skills/aqe-plan-quality/references/qe-routing.md +22 -0
- package/.agents/skills/aqe-review-quality/SKILL.md +24 -0
- package/.agents/skills/aqe-review-quality/agents/openai.yaml +4 -0
- package/.agents/skills/aqe-review-quality/references/quality-gates.md +20 -0
- package/.agents/skills/aqe-test-change/SKILL.md +26 -0
- package/.agents/skills/aqe-test-change/agents/openai.yaml +4 -0
- package/.agents/skills/aqe-test-change/references/test-specialties.md +23 -0
- package/.claude/helpers/.helpers-version +1 -1
- package/.claude/helpers/auto-memory-hook.mjs +430 -430
- package/.claude/helpers/helpers.manifest.json +6 -5
- package/.claude/helpers/hook-handler.cjs +565 -311
- package/.claude/helpers/intelligence.cjs +1058 -1058
- package/.claude/helpers/ruflo-hook.cjs +5 -1
- package/.claude/helpers/statusline.cjs +995 -682
- package/.claude/skills/qe-court/SKILL.md +186 -0
- package/.claude/skills/qe-court/config.json +27 -0
- package/.claude/skills/qe-court/evals/fixtures/seeded-mutant-delivery/README.md +38 -0
- package/.claude/skills/qe-court/evals/fixtures/seeded-mutant-delivery/budget.test.ts +21 -0
- package/.claude/skills/qe-court/evals/fixtures/seeded-mutant-delivery/budget.ts +25 -0
- package/.claude/skills/qe-court/evals/qe-court.yaml +70 -0
- package/.claude/skills/qe-court/schemas/output.json +92 -0
- package/.claude/skills/qe-court/scripts/validate-config.json +30 -0
- package/.claude/skills/skills-manifest.json +9 -8
- package/.codex/hooks/aqe-codex-hook.cjs +69 -0
- package/.codex/hooks/ruflo-codex-hook.cjs +94 -0
- package/.codex/hooks.json +169 -0
- package/CHANGELOG.md +159 -0
- package/README.md +3 -3
- package/assets/skills/qe-court/SKILL.md +186 -0
- package/assets/skills/qe-court/config.json +27 -0
- package/assets/skills/qe-court/evals/fixtures/seeded-mutant-delivery/README.md +38 -0
- package/assets/skills/qe-court/evals/fixtures/seeded-mutant-delivery/budget.test.ts +21 -0
- package/assets/skills/qe-court/evals/fixtures/seeded-mutant-delivery/budget.ts +25 -0
- package/assets/skills/qe-court/evals/qe-court.yaml +70 -0
- package/assets/skills/qe-court/schemas/output.json +92 -0
- package/assets/skills/qe-court/scripts/validate-config.json +30 -0
- package/assets/skills/skills-manifest.json +9 -8
- package/dist/cli/bundle.js +5 -5
- package/dist/cli/chunks/adapter-VRZNL53W.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-XFAQATTH.js → agent-booster-wasm-4VM3DE42.js} +2 -2
- package/dist/cli/chunks/{agent-handler-2ZV4CA3U.js → agent-handler-ZDLMZQQX.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-6WGP7F5T.js → agent-memory-branch-P72MDHHV.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-XCNMNERX.js +2 -0
- package/dist/cli/chunks/{arena-FWX7XZAE.js → arena-55FZGKEV.js} +4 -4
- package/dist/cli/chunks/{arena-KJUNQK4N.js → arena-GCRBQ26R.js} +2 -2
- package/dist/cli/chunks/{audit-YFUDEOKN.js → audit-VYAYVLIV.js} +3 -3
- package/dist/cli/chunks/base-VZZNR4UR.js +2 -0
- package/dist/cli/chunks/{hnswlib-node-SKTT5KIH.js → better-sqlite3-JDDFYVCX.js} +2 -2
- package/dist/cli/chunks/{brain-handler-ZCK4WTPK.js → brain-handler-IUKMRGWO.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-HTVINRYG.js → branch-enumerator-TUI3RWLX.js} +2 -2
- package/dist/cli/chunks/{browser-WUL2B77M.js → browser-NBQTZYX2.js} +2 -2
- package/dist/cli/chunks/browser-workflow-5DZNIFUY.js +2 -0
- package/dist/cli/chunks/{chunk-IWQHQLT6.js → chunk-23MT7OBY.js} +2 -2
- package/dist/cli/chunks/{chunk-KE3RK35K.js → chunk-2CQAWYYE.js} +1 -1
- package/dist/cli/chunks/{chunk-ADQFQBFJ.js → chunk-2D2XFUKI.js} +2 -2
- package/dist/cli/chunks/{chunk-2YDZXFO2.js → chunk-2G2QWV7B.js} +2 -2
- package/dist/cli/chunks/{chunk-HGJQSTQD.js → chunk-2ISLQU3G.js} +1 -1
- package/dist/cli/chunks/{chunk-6E47R27C.js → chunk-2OM3TDC4.js} +1 -1
- package/dist/cli/chunks/{chunk-WQASUQ5P.js → chunk-2XZ4BHWS.js} +1 -1
- package/dist/cli/chunks/{chunk-E2U3LTGM.js → chunk-3F4XH4ZA.js} +1 -1
- package/dist/cli/chunks/{chunk-YUDGQZJN.js → chunk-3K4YC3GC.js} +2 -2
- package/dist/cli/chunks/chunk-3KGCBAUH.js +2 -0
- package/dist/cli/chunks/{chunk-PXCJDB7J.js → chunk-3Y6CHW67.js} +1 -1
- package/dist/cli/chunks/{chunk-MOX25RZQ.js → chunk-4QMWWYNU.js} +2 -2
- package/dist/cli/chunks/{chunk-XZGOXLZH.js → chunk-4WGSMODQ.js} +1 -1
- package/dist/cli/chunks/{chunk-2CPJCXV6.js → chunk-55WDVSCM.js} +2 -2
- package/dist/cli/chunks/{chunk-EHO52NKU.js → chunk-5BB5DUL4.js} +2 -2
- package/dist/cli/chunks/{chunk-BEPP57C2.js → chunk-6C3MZLYW.js} +2 -2
- package/dist/cli/chunks/{chunk-DTZFZ5M7.js → chunk-6QKQFHS7.js} +2 -2
- package/dist/cli/chunks/{chunk-KXKACV3E.js → chunk-6XZXMEK4.js} +3 -3
- package/dist/cli/chunks/{chunk-L6GZGEFQ.js → chunk-7D7XFZZI.js} +2 -2
- package/dist/cli/chunks/{chunk-NLDLUHOF.js → chunk-7WEHZCSK.js} +2 -2
- package/dist/cli/chunks/{chunk-TXLPOXAN.js → chunk-A2MG3YXO.js} +1 -1
- package/dist/cli/chunks/{chunk-HJ2LG5IH.js → chunk-AHTOWWSE.js} +1 -1
- package/dist/cli/chunks/{chunk-GV2BS5NC.js → chunk-AOMXMFDH.js} +2 -2
- package/dist/cli/chunks/{chunk-EH7TSJPS.js → chunk-ARTLSAXO.js} +2 -2
- package/dist/cli/chunks/{chunk-CXMOIE7D.js → chunk-AY7S7AWN.js} +2 -2
- package/dist/cli/chunks/{chunk-2LNDU7AW.js → chunk-AYYDO52G.js} +2 -2
- package/dist/cli/chunks/chunk-BBLWZT5I.js +2 -0
- package/dist/cli/chunks/{chunk-KRS4KGX5.js → chunk-BF5BKSDU.js} +2 -2
- package/dist/cli/chunks/{chunk-BQ2K4BPD.js → chunk-BOCEOLLJ.js} +2 -2
- package/dist/cli/chunks/{chunk-KKOFH26C.js → chunk-CE6LYEHT.js} +1 -1
- package/dist/cli/chunks/{chunk-GS6G7AVS.js → chunk-CWP4RMOM.js} +2 -2
- package/dist/cli/chunks/{chunk-DCYBV6HV.js → chunk-CWXDL7AH.js} +1 -1
- package/dist/cli/chunks/{chunk-KGHSKDC7.js → chunk-DTRFZD7N.js} +2 -2
- package/dist/cli/chunks/{chunk-CYSBM52D.js → chunk-DVPGQG4W.js} +2 -2
- package/dist/cli/chunks/{chunk-MSDIIRLM.js → chunk-E4D47QTF.js} +2 -2
- package/dist/cli/chunks/{chunk-MB7TZQW3.js → chunk-EAKHU5YX.js} +3 -3
- package/dist/cli/chunks/{chunk-TP3UAWMB.js → chunk-EGMGOWCE.js} +2 -2
- package/dist/cli/chunks/{chunk-4EHW4TNA.js → chunk-ELMUHNXN.js} +2 -2
- package/dist/cli/chunks/chunk-EVDYFGVH.js +2 -0
- package/dist/cli/chunks/{chunk-D4GMAUTP.js → chunk-FDUSWM6O.js} +98 -88
- package/dist/cli/chunks/{chunk-YEC55GO5.js → chunk-FM272B4O.js} +2 -2
- package/dist/cli/chunks/{chunk-DMD6WVJ2.js → chunk-FQUUMC57.js} +2 -2
- package/dist/cli/chunks/{chunk-Y625LP6K.js → chunk-FQXQJMSF.js} +2 -2
- package/dist/cli/chunks/{chunk-Z3SXMYVI.js → chunk-FRAGSKXQ.js} +3 -3
- package/dist/cli/chunks/{chunk-MOXKKY5Q.js → chunk-GASOBSNB.js} +4 -4
- package/dist/cli/chunks/{chunk-PTPN6HQ7.js → chunk-GJEEPKAT.js} +2 -2
- package/dist/cli/chunks/{chunk-WFPGIP4N.js → chunk-GOV2MHLV.js} +2 -2
- package/dist/cli/chunks/{chunk-NKTLKMUB.js → chunk-GTPZVLL6.js} +1 -1
- package/dist/cli/chunks/chunk-H7YZ2YF2.js +3 -0
- package/dist/cli/chunks/{chunk-WKE6WL5C.js → chunk-HFI5PHG5.js} +3 -3
- package/dist/cli/chunks/chunk-HUMQU4ES.js +153 -0
- package/dist/cli/chunks/{chunk-5FAWIIWF.js → chunk-HYIRFJDB.js} +2 -2
- package/dist/cli/chunks/{chunk-DZ775UGW.js → chunk-IBSBOHUX.js} +2 -2
- package/dist/cli/chunks/{chunk-NAMJGRGC.js → chunk-IJA4WS7B.js} +2 -2
- package/dist/cli/chunks/{chunk-XUUVAAHV.js → chunk-IJP42OGW.js} +2 -2
- package/dist/cli/chunks/{chunk-UZ7FXVH5.js → chunk-IMQKEFW6.js} +1 -1
- package/dist/cli/chunks/{chunk-MZ7SIO6R.js → chunk-INYS35DV.js} +2 -2
- package/dist/cli/chunks/{chunk-MS6VOSPY.js → chunk-IV2VCR75.js} +5 -5
- package/dist/cli/chunks/{chunk-UAPUA6OY.js → chunk-IZO6TPGX.js} +2 -2
- package/dist/cli/chunks/{chunk-XBOCRCC6.js → chunk-J45DX3IK.js} +1 -1
- package/dist/cli/chunks/{chunk-RE42RJYR.js → chunk-J4T6D2OQ.js} +2 -2
- package/dist/cli/chunks/{chunk-Y5L37K7X.js → chunk-JAPOMPFD.js} +2 -2
- package/dist/cli/chunks/{chunk-M7W6VJ65.js → chunk-JELNVHBF.js} +1 -1
- package/dist/cli/chunks/{chunk-YDYKFSD2.js → chunk-JOTNKZ7A.js} +87 -87
- package/dist/cli/chunks/{chunk-VUCVSKJC.js → chunk-KNWDXI3I.js} +2 -2
- package/dist/cli/chunks/{chunk-SPI4LUJ6.js → chunk-KW5NBORV.js} +2 -2
- package/dist/cli/chunks/{chunk-2OX74DOO.js → chunk-L7IOTWWY.js} +1 -1
- package/dist/cli/chunks/{chunk-VFYMWDSJ.js → chunk-LJQ27PUE.js} +1 -1
- package/dist/cli/chunks/{chunk-NT66CT73.js → chunk-LSKQUUUN.js} +2 -2
- package/dist/cli/chunks/{chunk-ROFCS47F.js → chunk-LSZZQ7H6.js} +1 -1
- package/dist/cli/chunks/{chunk-Y6XNISHP.js → chunk-LTKNCYMO.js} +2 -2
- package/dist/cli/chunks/{chunk-7WF3TW3G.js → chunk-LTWT4GZD.js} +4 -4
- package/dist/cli/chunks/chunk-LVHMXGDI.js +29 -0
- package/dist/cli/chunks/{chunk-3YC4YUGB.js → chunk-M3T6FB54.js} +2 -2
- package/dist/cli/chunks/{chunk-M32DTUZM.js → chunk-MAYZTGJ2.js} +3 -3
- package/dist/cli/chunks/{chunk-RLBNAB6Y.js → chunk-MCIO7BDK.js} +1 -1
- package/dist/cli/chunks/{chunk-SFS3UHNF.js → chunk-MPD7RR4P.js} +1 -1
- package/dist/cli/chunks/{chunk-DDYP6FBC.js → chunk-MUFYDKVC.js} +2 -2
- package/dist/cli/chunks/{chunk-ZFLE4D4X.js → chunk-MX5ZDKRR.js} +2 -2
- package/dist/cli/chunks/{chunk-WBZNLFTV.js → chunk-MXKHIZVM.js} +5 -5
- package/dist/cli/chunks/chunk-MY47CR27.js +2 -0
- package/dist/cli/chunks/chunk-N7WAZ2Y6.js +2 -0
- package/dist/cli/chunks/{chunk-2HCMRGMO.js → chunk-NHV4PTG6.js} +2 -2
- package/dist/cli/chunks/{chunk-HJ4U64BL.js → chunk-NP4CP3LR.js} +2 -2
- package/dist/cli/chunks/{chunk-UIHZ34SJ.js → chunk-OCKTPTQ7.js} +2 -2
- package/dist/cli/chunks/{chunk-SGMJ277D.js → chunk-OE4B6LDZ.js} +1 -1
- package/dist/cli/chunks/{chunk-SV7J5FDW.js → chunk-OPQY2333.js} +2 -2
- package/dist/cli/chunks/{chunk-FTM562PF.js → chunk-ORDH4VPL.js} +1 -1
- package/dist/cli/chunks/{chunk-YOG5KQZF.js → chunk-P4Y3G6OB.js} +2 -2
- package/dist/cli/chunks/{chunk-LHAUFY4Y.js → chunk-PIOO2M4W.js} +2 -2
- package/dist/cli/chunks/{chunk-UGW23T6S.js → chunk-PKMCZFET.js} +2 -2
- package/dist/cli/chunks/{chunk-OPG2HV2W.js → chunk-QES4QHQW.js} +1 -1
- package/dist/cli/chunks/{chunk-BDGKB2PT.js → chunk-QG6BXSNJ.js} +2 -2
- package/dist/cli/chunks/{chunk-BSNNTOHY.js → chunk-QLOOW23R.js} +3 -3
- package/dist/cli/chunks/{chunk-AIWRYWK2.js → chunk-RSCGBHLM.js} +2 -2
- package/dist/cli/chunks/{chunk-LCM7TY76.js → chunk-RZ6CO3RZ.js} +2 -2
- package/dist/cli/chunks/chunk-S6F3IJMK.js +2 -0
- package/dist/cli/chunks/{chunk-WUE53ZPH.js → chunk-S6VNPKHO.js} +1 -1
- package/dist/cli/chunks/{chunk-L2X3BWMN.js → chunk-SHWXADCI.js} +2 -2
- package/dist/cli/chunks/{chunk-GMFFMJD6.js → chunk-SPJQJWGK.js} +2 -2
- package/dist/cli/chunks/{chunk-KVHCWH4H.js → chunk-SS6K4FBH.js} +2 -2
- package/dist/cli/chunks/{chunk-ZGKQCUPB.js → chunk-SXADKQJN.js} +2 -2
- package/dist/cli/chunks/{chunk-LGYEOYQJ.js → chunk-TBQTGQ75.js} +2 -2
- package/dist/cli/chunks/{chunk-J2RJOJ5Q.js → chunk-TDGE52HJ.js} +1 -1
- package/dist/cli/chunks/chunk-THFLRJT6.js +54 -0
- package/dist/cli/chunks/{chunk-GGTCD4MA.js → chunk-TQ2MA3SR.js} +1 -1
- package/dist/cli/chunks/{chunk-NOSQI2OW.js → chunk-UCQ66N6M.js} +3 -3
- package/dist/cli/chunks/{chunk-CL6SNCFF.js → chunk-UHGMS2PJ.js} +1 -1
- package/dist/cli/chunks/{chunk-XDHGCBTS.js → chunk-UHKXKWMD.js} +2 -2
- package/dist/cli/chunks/{chunk-PEHEANAM.js → chunk-UJ6TMZC6.js} +2 -2
- package/dist/cli/chunks/{chunk-PSDH7CIL.js → chunk-UKBDH27A.js} +1 -1
- package/dist/cli/chunks/{chunk-ZTKCGEB6.js → chunk-UMCEEXQN.js} +1 -1
- package/dist/cli/chunks/{chunk-KA4EAMMQ.js → chunk-USUFTHHT.js} +3 -3
- package/dist/cli/chunks/{chunk-QILF6BZH.js → chunk-V32MDID3.js} +2 -2
- package/dist/cli/chunks/{chunk-6SUSRXXF.js → chunk-VAJT6QWX.js} +1 -1
- package/dist/cli/chunks/{chunk-7Q74K3HZ.js → chunk-VLUJWI56.js} +1 -1
- package/dist/cli/chunks/{chunk-DW7OI5IF.js → chunk-WINA3XUT.js} +2 -2
- package/dist/cli/chunks/{chunk-S47YGWXK.js → chunk-WWCH5SSF.js} +2 -2
- package/dist/cli/chunks/{chunk-FJACKKRL.js → chunk-WWP2VXYJ.js} +2 -2
- package/dist/cli/chunks/{chunk-N4ML23ZG.js → chunk-WZROSTQZ.js} +1 -1
- package/dist/cli/chunks/{chunk-FXOOOJQD.js → chunk-XFUF654L.js} +1 -1
- package/dist/cli/chunks/{chunk-PDX7IYTJ.js → chunk-XN2CD5S6.js} +2 -2
- package/dist/cli/chunks/{chunk-DHUZHT5D.js → chunk-XOQQGZFY.js} +1 -1
- package/dist/cli/chunks/{chunk-4HP7N6SP.js → chunk-XSCOEY4C.js} +2 -2
- package/dist/cli/chunks/{chunk-KNWBRMLL.js → chunk-Y734CWHJ.js} +2 -2
- package/dist/cli/chunks/{chunk-NJDLJ3KD.js → chunk-YBPCBFEE.js} +2 -2
- package/dist/cli/chunks/{chunk-67BCEHU5.js → chunk-YLAEIS6F.js} +1 -1
- package/dist/cli/chunks/{chunk-E53UR2EW.js → chunk-YMMVCOPF.js} +3 -3
- package/dist/cli/chunks/{chunk-VSD6JE2H.js → chunk-YQCAXYBF.js} +2 -2
- package/dist/cli/chunks/{chunk-32L7DKNQ.js → chunk-YRVUYM62.js} +2 -2
- package/dist/cli/chunks/{chunk-LNIHLNW4.js → chunk-YVKMHXQK.js} +3 -3
- package/dist/cli/chunks/{chunk-CHFTHSMM.js → chunk-ZCLFAOVT.js} +2 -2
- package/dist/cli/chunks/{chunk-AZ24ONMX.js → chunk-ZH6ZBDVV.js} +1 -1
- package/dist/cli/chunks/{chunk-R6WMGSEK.js → chunk-ZHEKGB4A.js} +2 -2
- package/dist/cli/chunks/{chunk-EOUJ6X5H.js → chunk-ZIBW7CB4.js} +1 -1
- package/dist/cli/chunks/{chunk-OBL6W4Z5.js → chunk-ZLCATRXI.js} +2 -2
- package/dist/cli/chunks/{chunk-UGXHMQ6P.js → chunk-ZXX2VFMA.js} +2 -2
- package/dist/cli/chunks/{chunk-72QQDR3Y.js → chunk-ZYPESQ4M.js} +2 -2
- package/dist/cli/chunks/{ci-MMLUV6L6.js → ci-HHL5WQXQ.js} +2 -2
- package/dist/cli/chunks/{ci-output-25GS6RXR.js → ci-output-HVOJC2KN.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-4OWAN6R6.js → circuit-breaker-HRXMIY2G.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-LR3SRBX6.js → claude-flow-setup-3I7WVMZN.js} +2 -2
- package/dist/cli/chunks/client-EY2IYQDL.js +2 -0
- package/dist/cli/chunks/{cline-installer-YSZWRZUI.js → cline-installer-NBREL4QT.js} +2 -2
- package/dist/cli/chunks/{code-UUWUIXI7.js → code-TX4E2RWU.js} +2 -2
- package/dist/cli/chunks/{code-index-extractor-2LSPQORU.js → code-index-extractor-YELOFLSL.js} +2 -2
- package/dist/cli/chunks/codex-installer-HEX3KFRB.js +10 -0
- package/dist/cli/chunks/{completions-YKXBKZSO.js → completions-72GGFRGG.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-HNT2QRWB.js → complexity-analyzer-WRAKDYUK.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-AW5VCB66.js → continuedev-installer-UGYKSKTI.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-B6SVZXQT.js → copilot-installer-RPCRUKIJ.js} +2 -2
- package/dist/cli/chunks/core-handlers-G4GLA4DT.js +2 -0
- package/dist/cli/chunks/{cost-tracker-POZMBN2V.js → cost-tracker-CNHJ7G4M.js} +2 -2
- package/dist/cli/chunks/{coverage-V5BGPN5Q.js → coverage-RHIQ4XEX.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-P3K4IH5H.js +2 -0
- package/dist/cli/chunks/{cursor-installer-EYBI4QVK.js → cursor-installer-KSRVA4V2.js} +2 -2
- package/dist/cli/chunks/{daemon-CF6ENQB2.js → daemon-IT4AAFBW.js} +3 -3
- package/dist/cli/chunks/{daemon-HKARXY2W.js → daemon-QBXSJABV.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-XIL5IAP7.js → dag-attention-scheduler-F7WCQTLY.js} +2 -2
- package/dist/cli/chunks/{detect-RRX2U2KK.js → detect-2IYU332U.js} +2 -2
- package/dist/cli/chunks/{dist-node-DOANNRCS.js → dist-node-CIYNYCYN.js} +2 -2
- package/dist/cli/chunks/{domain-handler-QMTJV5OR.js → domain-handler-QRYQO2QK.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-FSNH75XW.js → domain-transfer-2OQDOD3G.js} +2 -2
- package/dist/cli/chunks/dream-IT4ZQGEO.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-NI7PGONV.js → embed-and-insert-pattern-P2IFC7JL.js} +2 -2
- package/dist/cli/chunks/{eval-6ZAF2RY3.js → eval-SBPK37IB.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-JMXR7N5G.js → experience-capture-middleware-3GMFND3F.js} +3 -3
- package/dist/cli/chunks/{fast-paths-YB7XZZ76.js → fast-paths-4OYYII2F.js} +2 -2
- package/dist/cli/chunks/{feature-flags-2RC4GFC4.js → feature-flags-BM6QTMMC.js} +2 -2
- package/dist/cli/chunks/{feature-flags-KJSP7KR6.js → feature-flags-NFCAYUWO.js} +2 -2
- package/dist/cli/chunks/{file-discovery-SUPBXFYI.js → file-discovery-2M3ZUAGC.js} +2 -2
- package/dist/cli/chunks/{fleet-KSXFOLFW.js → fleet-QMGGVIDV.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-DFZ5KPPK.js → gnn-wrapper-WGMAGZMO.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-G3EADK2H.js → heartbeat-handler-5RSMEZGG.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-UUWSPHF2.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-YUJVSFPD.js +2 -0
- package/dist/cli/chunks/hnsw-index-FQZ47RSJ.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-MA676GER.js → hnsw-legacy-bridge-TYPQ2T6P.js} +2 -2
- package/dist/cli/chunks/{better-sqlite3-FE55OGYB.js → hnswlib-node-GMRPPMDM.js} +2 -2
- package/dist/cli/chunks/{hooks-HTCPMZNZ.js → hooks-NUC5P3OJ.js} +10 -10
- package/dist/cli/chunks/hybrid-router-T5MF73NF.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-QPB3IH4A.js → hypergraph-engine-OIB7WK54.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-GBFSVD7N.js → hypergraph-handler-XX2N75QC.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-AEGELYMD.js +2 -0
- package/dist/cli/chunks/{init-handler-XYBTBCPD.js → init-handler-AKSTJMZY.js} +6 -6
- package/dist/cli/chunks/init-wizard-WKX3OGWM.js +2 -0
- package/dist/cli/chunks/kernel-5CVWFIGR.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-LY6JOBFY.js → kilocode-installer-375V5ZZB.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-JF6NXTJL.js → kiro-installer-GKY5GB5Q.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-EGPMNDMT.js +2 -0
- package/dist/cli/chunks/{learning-BIISN67N.js → learning-2CQE3QP6.js} +3 -3
- package/dist/cli/chunks/{llm-router-YZUNVZQE.js → llm-router-FTQNRF45.js} +5 -5
- package/dist/cli/chunks/llm-router-service-H4LXOARB.js +2 -0
- package/dist/cli/chunks/{load-MTWNBNLL.js → load-3DBAO5ZG.js} +2 -2
- package/dist/cli/chunks/load-test-OOOGITSN.js +2 -0
- package/dist/cli/chunks/{mcp-37PYMNHQ.js → mcp-AWR6TDXM.js} +2 -2
- package/dist/cli/chunks/{memory-IXUUDCI3.js → memory-GI4LCNXY.js} +5 -5
- package/dist/cli/chunks/memory-backend-O2YOT4LW.js +2 -0
- package/dist/cli/chunks/{memory-handlers-RM2VOFJX.js → memory-handlers-MALKG7GP.js} +2 -2
- package/dist/cli/chunks/{multi-model-executor-RKKS5XYG.js → multi-model-executor-SWFT5U72.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-3VXI5MTR.js → opencode-installer-EYXGYJX5.js} +2 -2
- package/dist/cli/chunks/{orchestrator-UO3ZOGFZ.js → orchestrator-MP3EAZVC.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-WBOHE2XL.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-YJKRL2GI.js → pattern-usage-recorder-25P3R3W7.js} +2 -2
- package/dist/cli/chunks/{pipeline-GJQJKXWX.js → pipeline-LSAFL25D.js} +2 -2
- package/dist/cli/chunks/{platform-RHVCZK6C.js → platform-IJ6DJ2PG.js} +2 -2
- package/dist/cli/chunks/{plugin-ZKAIW7O6.js → plugin-OXOZRZW2.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-4X3DSKQV.js → prime-radiant-advanced-wasm-HJNJQQ3R.js} +2 -2
- package/dist/cli/chunks/protocol-executor-JCNTPW5J.js +2 -0
- package/dist/cli/chunks/{protocol-handler-KKYQZMB2.js → protocol-handler-TCMUH2HL.js} +2 -2
- package/dist/cli/chunks/{prove-OD6RPKWX.js → prove-ADXQ2GOX.js} +2 -2
- package/dist/cli/chunks/provider-manager-LPGQ5GOO.js +2 -0
- package/dist/cli/chunks/qe-reasoning-bank-FWVYVSPP.js +2 -0
- package/dist/cli/chunks/{quality-ZRWBXCKO.js → quality-EWP36ORX.js} +2 -2
- package/dist/cli/chunks/{quality-gate-Y6BWQV7J.js → quality-gate-3BIG7PVU.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-UXNALRVD.js +2 -0
- package/dist/cli/chunks/{real-embeddings-YYEUO4P2.js → real-embeddings-D4NBT7W5.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-JBCPS3FK.js → roocode-installer-DOPWH6YV.js} +2 -2
- package/dist/cli/chunks/router-C6LUIQYY.js +2 -0
- package/dist/cli/chunks/routing-feedback-KMSGGDVD.js +2 -0
- package/dist/cli/chunks/{routing-handler-KTPJOSBJ.js → routing-handler-5ADEFOHS.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-SCZZVRE7.js → ruvector-commands-PLMEIHSN.js} +2 -2
- package/dist/cli/chunks/{rvf-dual-writer-IP7GELQJ.js → rvf-dual-writer-EQWKVNQB.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-adapter-WLFTDARU.js → rvf-migration-adapter-2OWFUUCG.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-coordinator-MGFDQ5WD.js → rvf-migration-coordinator-URAETAPU.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-K54BELUE.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-OTOAGT5W.js → rvf-store-integrity-4AWPW4TF.js} +2 -2
- package/dist/cli/chunks/safe-db-NGOZWF2D.js +2 -0
- package/dist/cli/chunks/schedule-B3Y5P64E.js +2 -0
- package/dist/cli/chunks/scheduler-Z6QVRMTB.js +2 -0
- package/dist/cli/chunks/{security-B2CLZKRB.js → security-HDLZVM62.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-2PMFAQMN.js → shared-rvf-adapter-YQT7PF7X.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-B6P732AV.js → shared-rvf-dual-writer-N5D3NSJ7.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-PLOUGATS.js +2 -0
- package/dist/cli/chunks/{status-handler-M6SN2W2D.js → status-handler-KLYRJ2MR.js} +2 -2
- package/dist/cli/chunks/{structural-health-YCCTGI3K.js → structural-health-6LKVRP6Y.js} +2 -2
- package/dist/cli/chunks/sync-7VMFPBVB.js +2 -0
- package/dist/cli/chunks/{sync-KSRF77ID.js → sync-YYOW6L6W.js} +2 -2
- package/dist/cli/chunks/{task-handler-MIKRB2SL.js → task-handler-RKQDGFN2.js} +2 -2
- package/dist/cli/chunks/{task-handlers-YXKRUBQ4.js → task-handlers-6YJ4QTEP.js} +3 -3
- package/dist/cli/chunks/{test-MLOLQCB7.js → test-ASPUIUJH.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-3KXESUZS.js → test-scheduling-I7ABQBBU.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-6V2PMDBJ.js → token-bootstrap-2XZBTODN.js} +2 -2
- package/dist/cli/chunks/{token-usage-DP6THJ3I.js → token-usage-TMUE6PTF.js} +2 -2
- package/dist/cli/chunks/transformers-FDHHH4SL.js +2 -0
- package/dist/cli/chunks/{tree-sitter-wasm-parser-COK2XERS.js → tree-sitter-wasm-parser-G7PGZA5C.js} +2 -2
- package/dist/cli/chunks/{types-PYHUCVOZ.js → types-JGT57UFP.js} +2 -2
- package/dist/cli/chunks/unified-memory-P5YVLMFI.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-7HI43A2O.js +2 -0
- package/dist/cli/chunks/unified-persistence-U26YP3N3.js +2 -0
- package/dist/cli/chunks/{upgrade-ONP2HNGL.js → upgrade-V6UQODJF.js} +2 -2
- package/dist/cli/chunks/{validate-NWSICDAY.js → validate-UBZAE5RW.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-KXS5P3U7.js → validate-swarm-TSO2MI5X.js} +2 -2
- package/dist/cli/chunks/{vibium-TZSGZRCQ.js → vibium-7G3VYSQA.js} +2 -2
- package/dist/cli/chunks/visual-security-6FCDY5FF.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-V2FADNRA.js → web-tree-sitter-MIYJSF2L.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-GQM7KWDC.js → windsurf-installer-5TLZSQIJ.js} +2 -2
- package/dist/cli/chunks/witness-chain-I3K3WQID.js +2 -0
- package/dist/cli/chunks/{witness-chain-GTITDIA2.js → witness-chain-LTV7H2HM.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-AHRM2M52.js → witness-key-manager-PAJ2J4AL.js} +2 -2
- package/dist/cli/chunks/{workflow-XCGHEL3I.js → workflow-DL3ESR2H.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-MAALP4WA.js +2 -0
- package/dist/cli/chunks/{wrappers-VGO2GO4J.js → wrappers-5HSU665E.js} +2 -2
- package/dist/cli/commands/llm-router.js +1 -0
- package/dist/cli/handlers/init-handler.js +1 -1
- package/dist/coordination/handlers/coverage-collection.d.ts +161 -0
- package/dist/coordination/handlers/coverage-collection.js +639 -0
- package/dist/coordination/handlers/coverage-handlers.js +199 -146
- package/dist/coordination/handlers/handler-types.d.ts +6 -1
- package/dist/coordination/handlers/handler-utils.js +10 -3
- package/dist/coordination/handlers/security-handlers.js +17 -2
- package/dist/coordination/handlers/test-execution-handlers.js +16 -1
- package/dist/coordination/result-saver.js +119 -97
- package/dist/coordination/task-executor.d.ts +26 -1
- package/dist/coordination/task-executor.js +52 -4
- package/dist/domains/code-intelligence/services/knowledge-graph.js +8 -0
- package/dist/domains/coverage-analysis/services/coverage-analyzer.js +4 -0
- package/dist/domains/coverage-analysis/services/gap-detector.js +4 -0
- package/dist/domains/defect-intelligence/services/defect-predictor.js +4 -0
- package/dist/domains/defect-intelligence/services/root-cause-analyzer.js +4 -0
- package/dist/domains/quality-assessment/services/deployment-advisor.js +4 -0
- package/dist/domains/quality-assessment/services/quality-analyzer.js +4 -0
- package/dist/domains/security-compliance/services/scanners/sast-scanner.js +4 -0
- package/dist/domains/test-generation/index.js +17 -2
- package/dist/domains/test-generation/services/test-generator.js +31 -9
- package/dist/init/codex-installer.d.ts +13 -0
- package/dist/init/codex-installer.js +122 -1
- package/dist/init/phases/09-assets.js +4 -0
- package/dist/init/phases/phase-interface.d.ts +1 -1
- package/dist/init/skills-installer.js +1 -0
- package/dist/integrations/embeddings/base/EmbeddingGenerator.js +13 -1
- package/dist/kernel/unified-memory.js +4 -0
- package/dist/learning/qe-flywheel/corpus-scorer.js +10 -7
- package/dist/learning/qe-flywheel/generation.d.ts +7 -0
- package/dist/learning/qe-flywheel/generation.js +5 -0
- package/dist/learning/qe-flywheel/witness-verify.d.ts +86 -0
- package/dist/learning/qe-flywheel/witness-verify.js +156 -0
- package/dist/learning/real-embeddings.js +15 -1
- package/dist/mcp/bundle.js +455 -434
- package/dist/mcp/handlers/domain-handler-configs.js +79 -14
- package/dist/mcp/types.d.ts +42 -4
- package/dist/optimization/session-cache.d.ts +13 -1
- package/dist/optimization/session-cache.js +27 -2
- package/dist/shared/db-recovery.d.ts +55 -0
- package/dist/shared/db-recovery.js +184 -0
- package/dist/shared/llm/billing-modes.js +5 -2
- package/dist/shared/llm/cost-tracker.js +1 -0
- package/dist/shared/llm/interfaces.d.ts +14 -1
- package/dist/shared/llm/llm-router-service.js +59 -4
- package/dist/shared/llm/provider-manager.d.ts +1 -1
- package/dist/shared/llm/provider-manager.js +7 -3
- package/dist/shared/llm/providers/claude-code.js +12 -3
- package/dist/shared/llm/providers/codex.d.ts +58 -0
- package/dist/shared/llm/providers/codex.js +305 -0
- package/dist/shared/llm/providers/index.d.ts +1 -0
- package/dist/shared/llm/providers/index.js +1 -0
- package/dist/shared/llm/router/agent-router-config.d.ts +46 -2
- package/dist/shared/llm/router/agent-router-config.js +124 -2
- package/dist/shared/llm/router/config-store.d.ts +17 -1
- package/dist/shared/llm/router/config-store.js +108 -0
- package/dist/shared/llm/router/hybrid-router.js +2 -2
- package/dist/shared/llm/router/index.d.ts +2 -2
- package/dist/shared/llm/router/index.js +2 -0
- package/dist/shared/llm/router/types.d.ts +44 -0
- package/dist/shared/llm/router/types.js +1 -0
- package/dist/shared/llm/spend-ledger.d.ts +24 -0
- package/dist/shared/llm/spend-ledger.js +86 -15
- package/dist/shared/llm/translation/message-formatter.js +1 -0
- package/dist/shared/safe-db.d.ts +10 -0
- package/dist/shared/safe-db.js +17 -0
- package/dist/skills/qe-court/referee.d.ts +62 -0
- package/dist/skills/qe-court/referee.js +78 -0
- package/dist/validation/gate-reexecute.d.ts +9 -0
- package/dist/validation/gate-reexecute.js +61 -0
- package/dist/validation/paired-bootstrap.d.ts +36 -0
- package/dist/validation/paired-bootstrap.js +58 -0
- package/package.json +9 -2
- package/dist/cli/chunks/adapter-D657MKZY.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-AFR6OZJK.js +0 -2
- package/dist/cli/chunks/base-K5QRGZWE.js +0 -2
- package/dist/cli/chunks/browser-workflow-ZMMKCGYW.js +0 -2
- package/dist/cli/chunks/chunk-6HQDPDN5.js +0 -2
- package/dist/cli/chunks/chunk-6SQ72FG7.js +0 -2
- package/dist/cli/chunks/chunk-7XUM4LBC.js +0 -2
- package/dist/cli/chunks/chunk-FHHCH7WL.js +0 -2
- package/dist/cli/chunks/chunk-G5OGKVLO.js +0 -2
- package/dist/cli/chunks/chunk-ILRKO6A5.js +0 -43
- package/dist/cli/chunks/chunk-NX522PRH.js +0 -153
- package/dist/cli/chunks/chunk-PPUDKQ4X.js +0 -29
- package/dist/cli/chunks/chunk-RSZOCQOL.js +0 -2
- package/dist/cli/chunks/chunk-ULQCEM7K.js +0 -2
- package/dist/cli/chunks/chunk-XQ5JT7KM.js +0 -3
- package/dist/cli/chunks/client-WI7RRUZO.js +0 -2
- package/dist/cli/chunks/codex-installer-E5BVXZVA.js +0 -8
- package/dist/cli/chunks/core-handlers-T6URR57V.js +0 -2
- package/dist/cli/chunks/cross-domain-router-WHTTKHWM.js +0 -2
- package/dist/cli/chunks/dream-QUL6SURC.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-VZNKE33K.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-LGWLDZLC.js +0 -2
- package/dist/cli/chunks/hnsw-index-66FOOI7U.js +0 -2
- package/dist/cli/chunks/hybrid-router-I5MEVQDF.js +0 -2
- package/dist/cli/chunks/impact-analyzer-K6ANYIY3.js +0 -2
- package/dist/cli/chunks/init-wizard-URHGXJ32.js +0 -2
- package/dist/cli/chunks/kernel-OKI5ZY5P.js +0 -2
- package/dist/cli/chunks/knowledge-graph-VQQSK7T5.js +0 -2
- package/dist/cli/chunks/llm-router-service-TISH33SY.js +0 -2
- package/dist/cli/chunks/load-test-KWKWC4Q7.js +0 -2
- package/dist/cli/chunks/memory-backend-JSQQMXVS.js +0 -2
- package/dist/cli/chunks/pattern-null-store-SXBIUKE5.js +0 -2
- package/dist/cli/chunks/protocol-executor-D3Q5P3WY.js +0 -2
- package/dist/cli/chunks/provider-manager-2EIX7E5Q.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-ITOW2ZHC.js +0 -2
- package/dist/cli/chunks/queen-coordinator-TO5X2EXL.js +0 -2
- package/dist/cli/chunks/router-GZJQEJU3.js +0 -2
- package/dist/cli/chunks/routing-feedback-CRXSKFNS.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-WHADT5HX.js +0 -2
- package/dist/cli/chunks/safe-db-MIZ2OFWC.js +0 -2
- package/dist/cli/chunks/schedule-XFILYTYC.js +0 -2
- package/dist/cli/chunks/scheduler-EIPJ777A.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-PFU3GSRD.js +0 -2
- package/dist/cli/chunks/sync-3SDMVAIU.js +0 -2
- package/dist/cli/chunks/transformers-QFOBOP2Y.js +0 -2
- package/dist/cli/chunks/unified-memory-OUVCMFGK.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-YGQPOHXB.js +0 -2
- package/dist/cli/chunks/unified-persistence-GFRZVDOW.js +0 -2
- package/dist/cli/chunks/visual-security-LVOOYQ64.js +0 -2
- package/dist/cli/chunks/witness-chain-QNFPV4UL.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-MIVBCALG.js +0 -2
|
@@ -108,6 +108,9 @@ export const testGenerateConfig = {
|
|
|
108
108
|
const domainTests = data.tests;
|
|
109
109
|
const hasRealTests = Array.isArray(domainTests) && domainTests.length > 0
|
|
110
110
|
&& domainTests[0].testCode;
|
|
111
|
+
// #567: did the ADR-051 LLM branch actually run? Report it instead of
|
|
112
|
+
// asserting `aiGenerated: true` unconditionally.
|
|
113
|
+
const llmEnhanced = data.llmEnhanced === true;
|
|
111
114
|
const tests = hasRealTests
|
|
112
115
|
? domainTests.map((t, i) => ({
|
|
113
116
|
id: generateTestId(),
|
|
@@ -119,7 +122,7 @@ export const testGenerateConfig = {
|
|
|
119
122
|
: [`test assertion ${i}`],
|
|
120
123
|
expectedResult: null,
|
|
121
124
|
estimatedDuration: t.type === 'integration' ? 2000 : 1000,
|
|
122
|
-
aiGenerated:
|
|
125
|
+
aiGenerated: llmEnhanced,
|
|
123
126
|
testCode: t.testCode,
|
|
124
127
|
sourceFile: t.sourceFile,
|
|
125
128
|
testFile: t.testFile || t.file,
|
|
@@ -133,7 +136,9 @@ export const testGenerateConfig = {
|
|
|
133
136
|
aiInsights,
|
|
134
137
|
coverage: {
|
|
135
138
|
predicted: data.coverageEstimate || params?.coverageGoal || 80,
|
|
136
|
-
|
|
139
|
+
// #567: a template scaffold's coverage prediction is a guess, not a
|
|
140
|
+
// 0.9-confidence estimate. Don't dress it up as one.
|
|
141
|
+
confidence: llmEnhanced ? 0.9 : 0.3,
|
|
137
142
|
achievable: true,
|
|
138
143
|
},
|
|
139
144
|
properties: tests.filter(t => t.type === 'property').map(t => ({
|
|
@@ -151,6 +156,10 @@ export const testGenerateConfig = {
|
|
|
151
156
|
patternsUsed: data.patternsUsed || ['assertion-patterns', 'mock-generation', 'edge-case-detection'],
|
|
152
157
|
duration,
|
|
153
158
|
savedFiles,
|
|
159
|
+
// #567: propagate the LLM-enhancement signal to the MCP caller.
|
|
160
|
+
llmEnhanced,
|
|
161
|
+
...(data.generationMode ? { generationMode: data.generationMode } : {}),
|
|
162
|
+
...(data.note ? { note: data.note } : {}),
|
|
154
163
|
};
|
|
155
164
|
},
|
|
156
165
|
};
|
|
@@ -253,12 +262,40 @@ export const coverageAnalyzeConfig = {
|
|
|
253
262
|
// The domain returns CoverageReport { summary: { line, branch, function, statement, files }, ... }
|
|
254
263
|
// Map from both nested (domain) and flat (legacy) field shapes.
|
|
255
264
|
const summary = data.summary;
|
|
256
|
-
const lineCoverage = summary?.line ?? data.lineCoverage ?? 0;
|
|
257
|
-
const branchCoverage = summary?.branch ?? data.branchCoverage ?? 0;
|
|
258
|
-
const functionCoverage = summary?.function ?? data.functionCoverage ?? 0;
|
|
259
|
-
const statementCoverage = summary?.statement ?? data.statementCoverage ?? lineCoverage;
|
|
260
265
|
const totalFiles = summary?.files ?? data.totalFiles ?? 0;
|
|
261
266
|
const gaps = data.gaps || [];
|
|
267
|
+
// #569/ADR-126: an ABSENT provenance flag means "unknown", never "collected".
|
|
268
|
+
//
|
|
269
|
+
// Defaulting these to `true` (`!== false`) meant any producer that supplies
|
|
270
|
+
// no provenance at all — notably the coverage-analysis domain plugin, whose
|
|
271
|
+
// handler returns a nested-`summary` CoverageReport — surfaced the exact
|
|
272
|
+
// impossible pair from the issue: 100% branch coverage alongside 0% function
|
|
273
|
+
// coverage, labelled `measured: true` with `confidence: 0.7` on its gaps.
|
|
274
|
+
// Requiring an explicit `true` makes an unprovenanced result honest (`null`)
|
|
275
|
+
// instead of confidently wrong.
|
|
276
|
+
const branchDataCollected = data.branchDataCollected === true;
|
|
277
|
+
const functionDataCollected = data.functionDataCollected === true;
|
|
278
|
+
const branchCoverage = branchDataCollected
|
|
279
|
+
? (summary?.branch ?? data.branchCoverage ?? null)
|
|
280
|
+
: null;
|
|
281
|
+
const functionCoverage = functionDataCollected
|
|
282
|
+
? (summary?.function ?? data.functionCoverage ?? null)
|
|
283
|
+
: null;
|
|
284
|
+
// #569: is this a measurement or a static estimate? Everything downstream —
|
|
285
|
+
// gap confidence, AI insights, risk assessment — must be qualified by it.
|
|
286
|
+
const estimated = data.estimated === true;
|
|
287
|
+
// #569/ADR-126: `measured` is NOT the complement of `estimated` — there is a
|
|
288
|
+
// third state where nothing was collected at all. Deriving it as `!estimated`
|
|
289
|
+
// reported an empty project (no sources, no coverage report, nothing run) as
|
|
290
|
+
// `lineCoverage: 0, measured: true` — "we measured 0%" when the truth is "we
|
|
291
|
+
// measured nothing". Trust only an explicit claim from the producer.
|
|
292
|
+
const measured = data.measured === true;
|
|
293
|
+
// Likewise, a `null` line/statement figure must survive as `null`. `?? 0`
|
|
294
|
+
// turns "no data" into a plottable 0%.
|
|
295
|
+
const rawLine = summary?.line ?? data.lineCoverage;
|
|
296
|
+
const lineCoverage = rawLine ?? null;
|
|
297
|
+
const rawStatement = summary?.statement ?? data.statementCoverage;
|
|
298
|
+
const statementCoverage = rawStatement ?? lineCoverage;
|
|
262
299
|
const learning = generateV2LearningFeedback('coverage-analyzer');
|
|
263
300
|
// Map gap analysis from real data — never fabricate file paths
|
|
264
301
|
const detailedGaps = gaps.map((gap, i) => {
|
|
@@ -278,7 +315,12 @@ export const coverageAnalyzeConfig = {
|
|
|
278
315
|
suggestion: g.suggestedTest || 'Add test coverage',
|
|
279
316
|
suggestedTest: g.suggestedTest || 'Add test coverage',
|
|
280
317
|
riskScore: g.riskScore || 0.5,
|
|
281
|
-
|
|
318
|
+
// #569: the 0.7 default confidence is only defensible for a gap derived
|
|
319
|
+
// from a real measurement. An estimated gap carries its own low
|
|
320
|
+
// confidence from the handler; a gap with no provenance at all is not
|
|
321
|
+
// known to be measured either, so it gets the cautious value too.
|
|
322
|
+
confidence: g.confidence ?? (measured ? 0.7 : 0.2),
|
|
323
|
+
estimated: g.estimated === true || estimated,
|
|
282
324
|
};
|
|
283
325
|
}).filter((g) => g !== null);
|
|
284
326
|
// Use real file data from the analyzer if available, never fabricate file paths
|
|
@@ -287,8 +329,9 @@ export const coverageAnalyzeConfig = {
|
|
|
287
329
|
? coverageByFileData.map(f => ({
|
|
288
330
|
file: f.file,
|
|
289
331
|
lineCoverage: f.lineCoverage || 0,
|
|
290
|
-
|
|
291
|
-
|
|
332
|
+
// #569: preserve null (metric not collected) instead of collapsing to 0.
|
|
333
|
+
branchCoverage: f.branchCoverage ?? null,
|
|
334
|
+
functionCoverage: f.functionCoverage ?? null,
|
|
292
335
|
}))
|
|
293
336
|
: [];
|
|
294
337
|
return {
|
|
@@ -305,11 +348,25 @@ export const coverageAnalyzeConfig = {
|
|
|
305
348
|
weeklyChange: 0,
|
|
306
349
|
},
|
|
307
350
|
aiInsights: totalFiles > 0 ? {
|
|
308
|
-
recommendations:
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
351
|
+
recommendations: estimated
|
|
352
|
+
// #569: the reported insights ("Coverage is 15.9% below threshold",
|
|
353
|
+
// "Function coverage is below 70%") were all derived from estimated
|
|
354
|
+
// numbers and presented as findings. Lead with the caveat.
|
|
355
|
+
? [
|
|
356
|
+
'ESTIMATED RESULT — no instrumentation ran. The figures below are a ' +
|
|
357
|
+
'static guess from source shape, not measured coverage. Do not act on ' +
|
|
358
|
+
'individual gaps without running real instrumentation first.',
|
|
359
|
+
...(data.recommendations || []),
|
|
360
|
+
]
|
|
361
|
+
: (data.recommendations || [
|
|
362
|
+
'Run tests with coverage enabled to get accurate metrics',
|
|
363
|
+
]),
|
|
364
|
+
// #569: risk can only be graded off a real number. `null < 70` is
|
|
365
|
+
// `false` in JS, which would have silently graded "no data" as 'low'.
|
|
366
|
+
riskAssessment: (estimated || !measured || lineCoverage === null)
|
|
367
|
+
? 'unknown'
|
|
368
|
+
: (lineCoverage < 70 ? 'high' : lineCoverage < 85 ? 'medium' : 'low'),
|
|
369
|
+
confidence: estimated ? 0.2 : (measured ? 0.88 : 0),
|
|
313
370
|
} : {
|
|
314
371
|
recommendations: [
|
|
315
372
|
'No coverage data found. Run tests with coverage first (e.g., npm test -- --coverage, or pytest --cov)',
|
|
@@ -329,6 +386,14 @@ export const coverageAnalyzeConfig = {
|
|
|
329
386
|
gaps: detailedGaps,
|
|
330
387
|
duration,
|
|
331
388
|
savedFiles,
|
|
389
|
+
// #569: provenance travels with the numbers so a caller can never mistake
|
|
390
|
+
// a static estimate for a measurement.
|
|
391
|
+
estimated,
|
|
392
|
+
measured,
|
|
393
|
+
coverageMethod: data.coverageMethod ?? 'unknown',
|
|
394
|
+
branchDataCollected,
|
|
395
|
+
functionDataCollected,
|
|
396
|
+
...(data.warning ? { warning: data.warning } : {}),
|
|
332
397
|
};
|
|
333
398
|
},
|
|
334
399
|
};
|
package/dist/mcp/types.d.ts
CHANGED
|
@@ -446,6 +446,15 @@ export interface TestGenerateResult {
|
|
|
446
446
|
suggestions?: string[];
|
|
447
447
|
savedFiles?: string[];
|
|
448
448
|
patternsUsed?: string[];
|
|
449
|
+
/**
|
|
450
|
+
* #567: true when the ADR-051 LLM branch actually ran. When false the tests
|
|
451
|
+
* are deterministic template scaffolding — see `generationMode`/`note`.
|
|
452
|
+
*/
|
|
453
|
+
llmEnhanced?: boolean;
|
|
454
|
+
/** #567: set to 'deterministic-template' when no LLM enhancement was applied. */
|
|
455
|
+
generationMode?: string;
|
|
456
|
+
/** #567: human-readable reason the LLM branch did not run. */
|
|
457
|
+
note?: string;
|
|
449
458
|
tests?: unknown[];
|
|
450
459
|
antiPatterns?: unknown[];
|
|
451
460
|
aiInsights?: Record<string, unknown>;
|
|
@@ -462,19 +471,46 @@ export interface CoverageAnalyzeResult {
|
|
|
462
471
|
taskId: string;
|
|
463
472
|
status: string;
|
|
464
473
|
duration: number;
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
474
|
+
/**
|
|
475
|
+
* #569: `null` when no coverage figure was produced at all (no report, no
|
|
476
|
+
* instrumentation run, nothing to estimate from). `0` means a measured zero;
|
|
477
|
+
* `null` means "we don't know" — the two must not be conflated.
|
|
478
|
+
*/
|
|
479
|
+
lineCoverage: number | null;
|
|
480
|
+
/**
|
|
481
|
+
* #569: `null` when branch data was not collected. Never report a branch
|
|
482
|
+
* percentage — least of all 100% — that no instrumentation produced.
|
|
483
|
+
*/
|
|
484
|
+
branchCoverage: number | null;
|
|
485
|
+
/** #569: `null` when function-level data was not collected. */
|
|
486
|
+
functionCoverage: number | null;
|
|
468
487
|
gaps?: CoverageGap[];
|
|
469
488
|
riskScore?: number;
|
|
470
489
|
savedFiles?: string[];
|
|
471
|
-
|
|
490
|
+
/** #569: `null` when no figure was produced — see `lineCoverage`. */
|
|
491
|
+
statementCoverage?: number | null;
|
|
472
492
|
totalFiles?: number;
|
|
473
493
|
coverageByFile?: unknown[];
|
|
474
494
|
gapAnalysis?: Record<string, unknown>;
|
|
475
495
|
trends?: Record<string, unknown>;
|
|
476
496
|
aiInsights?: Record<string, unknown>;
|
|
477
497
|
learning?: Record<string, unknown>;
|
|
498
|
+
/**
|
|
499
|
+
* #569 provenance. `true` means the figures are a STATIC ESTIMATE derived
|
|
500
|
+
* from source shape, not measured coverage. Callers must not present an
|
|
501
|
+
* estimated result as a measurement.
|
|
502
|
+
*/
|
|
503
|
+
estimated?: boolean;
|
|
504
|
+
/** Inverse of `estimated`: real instrumentation produced these numbers. */
|
|
505
|
+
measured?: boolean;
|
|
506
|
+
/** How the numbers were obtained: instrumented-report | cargo-llvm-cov | static-estimation | none. */
|
|
507
|
+
coverageMethod?: string;
|
|
508
|
+
/** Whether branch data was actually collected. */
|
|
509
|
+
branchDataCollected?: boolean;
|
|
510
|
+
/** Whether function-level data was actually collected. */
|
|
511
|
+
functionDataCollected?: boolean;
|
|
512
|
+
/** Caveats the caller should surface (e.g. "no instrumentation ran"). */
|
|
513
|
+
warning?: string;
|
|
478
514
|
}
|
|
479
515
|
/**
|
|
480
516
|
* Coverage gap
|
|
@@ -492,6 +528,8 @@ export interface CoverageGap {
|
|
|
492
528
|
priority?: string;
|
|
493
529
|
suggestedTest?: string;
|
|
494
530
|
riskScore?: number;
|
|
531
|
+
/** #569: true when this gap came from a static estimate, not a measurement. */
|
|
532
|
+
estimated?: boolean;
|
|
495
533
|
}
|
|
496
534
|
/**
|
|
497
535
|
* Memory store result
|
|
@@ -47,8 +47,20 @@ export declare class SessionOperationCache {
|
|
|
47
47
|
private misses;
|
|
48
48
|
constructor(config?: Partial<SessionCacheConfig>);
|
|
49
49
|
/**
|
|
50
|
-
* Compute a deterministic fingerprint from domain + action + input.
|
|
50
|
+
* Compute a deterministic fingerprint from build + domain + action + input.
|
|
51
51
|
* Uses SHA-256 of the canonicalized JSON (recursively sorted keys), truncated to 16 hex chars.
|
|
52
|
+
*
|
|
53
|
+
* The build identity is part of the key on purpose. Entries are persisted to
|
|
54
|
+
* `kv_store` and survive process restarts *and package upgrades*, so a
|
|
55
|
+
* fingerprint over inputs alone means an upgraded install keeps replaying the
|
|
56
|
+
* previous version's answers until the TTL lapses — the fix looks like it did
|
|
57
|
+
* not work. That is exactly what happened while verifying issue #569: a
|
|
58
|
+
* project analyzed before the fix kept returning the old fabricated coverage
|
|
59
|
+
* numbers (`lineCoverage: 0, measured: true`) from cache, while an untouched
|
|
60
|
+
* project returned the corrected result.
|
|
61
|
+
*
|
|
62
|
+
* Including the version means an upgrade misses cleanly rather than serving
|
|
63
|
+
* stale answers; entries from the old build simply age out.
|
|
52
64
|
*/
|
|
53
65
|
computeFingerprint(domain: string, action: string, input: Record<string, unknown>): string;
|
|
54
66
|
/**
|
|
@@ -13,6 +13,19 @@
|
|
|
13
13
|
* - TTL-based expiry, LRU-ish eviction at capacity
|
|
14
14
|
*/
|
|
15
15
|
import { createHash } from 'crypto';
|
|
16
|
+
/**
|
|
17
|
+
* Build identity mixed into every cache fingerprint so persisted entries never
|
|
18
|
+
* outlive the code that produced them. `__CLI_VERSION__` is substituted at bundle
|
|
19
|
+
* time; in source/test runs it is undefined and we fall back to a dev marker.
|
|
20
|
+
*
|
|
21
|
+
* `AQE_SESSION_CACHE_SALT` lets an operator force a cold cache without deleting
|
|
22
|
+
* anything (e.g. after a local rebuild that keeps the same version string).
|
|
23
|
+
*/
|
|
24
|
+
function getBuildIdentity() {
|
|
25
|
+
const version = typeof __CLI_VERSION__ !== 'undefined' ? __CLI_VERSION__ : 'dev';
|
|
26
|
+
const salt = (process.env.AQE_SESSION_CACHE_SALT ?? '').trim();
|
|
27
|
+
return salt ? `${version}+${salt}` : version;
|
|
28
|
+
}
|
|
16
29
|
export const DEFAULT_SESSION_CACHE_CONFIG = {
|
|
17
30
|
enabled: true,
|
|
18
31
|
maxEntries: 500,
|
|
@@ -51,11 +64,23 @@ export class SessionOperationCache {
|
|
|
51
64
|
this.config = { ...DEFAULT_SESSION_CACHE_CONFIG, ...config };
|
|
52
65
|
}
|
|
53
66
|
/**
|
|
54
|
-
* Compute a deterministic fingerprint from domain + action + input.
|
|
67
|
+
* Compute a deterministic fingerprint from build + domain + action + input.
|
|
55
68
|
* Uses SHA-256 of the canonicalized JSON (recursively sorted keys), truncated to 16 hex chars.
|
|
69
|
+
*
|
|
70
|
+
* The build identity is part of the key on purpose. Entries are persisted to
|
|
71
|
+
* `kv_store` and survive process restarts *and package upgrades*, so a
|
|
72
|
+
* fingerprint over inputs alone means an upgraded install keeps replaying the
|
|
73
|
+
* previous version's answers until the TTL lapses — the fix looks like it did
|
|
74
|
+
* not work. That is exactly what happened while verifying issue #569: a
|
|
75
|
+
* project analyzed before the fix kept returning the old fabricated coverage
|
|
76
|
+
* numbers (`lineCoverage: 0, measured: true`) from cache, while an untouched
|
|
77
|
+
* project returned the corrected result.
|
|
78
|
+
*
|
|
79
|
+
* Including the version means an upgrade misses cleanly rather than serving
|
|
80
|
+
* stale answers; entries from the old build simply age out.
|
|
56
81
|
*/
|
|
57
82
|
computeFingerprint(domain, action, input) {
|
|
58
|
-
const canonical = canonicalStringify({ action, domain, input });
|
|
83
|
+
const canonical = canonicalStringify({ action, build: getBuildIdentity(), domain, input });
|
|
59
84
|
return createHash('sha256').update(canonical).digest('hex').slice(0, 16);
|
|
60
85
|
}
|
|
61
86
|
/**
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-restore for the unified `memory.db` (M3.2, inspired by ruflo v3.25.2's
|
|
3
|
+
* backup-auto-restore, adapted to better-sqlite3).
|
|
4
|
+
*
|
|
5
|
+
* Hardened after a qe-court review (ADR-124) surfaced three data-loss risks in
|
|
6
|
+
* the first cut:
|
|
7
|
+
* F3 — `isDbHealthy` via a readonly open + integrity_check FALSE-NEGATIVES a
|
|
8
|
+
* HEALTHY WAL db when `-shm` is zeroed/inaccessible over virtiofs (the
|
|
9
|
+
* exact documented failure mode), which would have parked a good DB and
|
|
10
|
+
* reverted to an older backup. FIX: the live-corruption signal is now the
|
|
11
|
+
* SQLite HEADER — a `-wal`/`-shm` problem does not corrupt the main file,
|
|
12
|
+
* so we only treat a missing/garbage header (zeroed/not-a-db) as corrupt.
|
|
13
|
+
* F2 — non-atomic `copyFileSync` + no lock let concurrent hook processes tear
|
|
14
|
+
* the restored image. FIX: copy to a temp in the same dir → atomic rename,
|
|
15
|
+
* under a best-effort exclusive lock so only one process restores.
|
|
16
|
+
* backup trust — a backup we are about to promote to the LIVE db still gets a
|
|
17
|
+
* FULL `integrity_check` (it is a static file, safe to open readonly).
|
|
18
|
+
*
|
|
19
|
+
* DATA-PROTECTION INVARIANTS (this file must never make things worse):
|
|
20
|
+
* - The corrupt original is RENAMED to `<db>.corrupt-<ts>`, NEVER deleted.
|
|
21
|
+
* - A header-valid main file is treated as HEALTHY — we never park a DB that
|
|
22
|
+
* might just have a transient `-wal`/`-shm` issue (a writable open rebuilds
|
|
23
|
+
* `-shm`). We prefer "manual restore" over "auto-destroy a healthy DB".
|
|
24
|
+
* - A backup is used only if it passes `PRAGMA integrity_check`.
|
|
25
|
+
* - If no verified backup exists, we do NOTHING (leave the DB for inspection).
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* True if the main DB file is structurally a database (or absent/empty = a fresh
|
|
29
|
+
* DB the caller will create). LIVE-corruption signal only: it deliberately does
|
|
30
|
+
* NOT open the DB or run integrity_check, because a `-wal`/`-shm` fault over
|
|
31
|
+
* virtiofs makes a HEALTHY db unreadable and we must not mistake that for
|
|
32
|
+
* corruption (F3). Only a missing/garbage header — the zeroed/not-a-db case —
|
|
33
|
+
* is "corrupt". A header-valid-but-page-corrupt file is left for MANUAL restore
|
|
34
|
+
* rather than risk auto-parking a healthy DB.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isDbHealthy(dbPath: string): boolean;
|
|
37
|
+
export interface RestoreResult {
|
|
38
|
+
restored: boolean;
|
|
39
|
+
reason: 'healthy' | 'no-verified-backup' | 'restored-from-backup' | 'restore-in-progress' | 'park-failed' | 'copy-failed';
|
|
40
|
+
backupUsed?: string;
|
|
41
|
+
parkedTo?: string;
|
|
42
|
+
}
|
|
43
|
+
/** Default verified-backup directory (matches `scripts/aqe-db-backup.sh`). */
|
|
44
|
+
export declare function defaultBackupDir(dbPath: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* If `dbPath`'s main file is unambiguously corrupt (bad SQLite header), park it
|
|
47
|
+
* and atomically restore the newest verified backup. No-op (and non-destructive)
|
|
48
|
+
* when the DB is healthy, when no good backup exists, or when another process is
|
|
49
|
+
* already restoring.
|
|
50
|
+
*/
|
|
51
|
+
export declare function attemptAutoRestore(dbPath: string, opts?: {
|
|
52
|
+
backupDir?: string;
|
|
53
|
+
now?: number;
|
|
54
|
+
}): RestoreResult;
|
|
55
|
+
//# sourceMappingURL=db-recovery.d.ts.map
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-restore for the unified `memory.db` (M3.2, inspired by ruflo v3.25.2's
|
|
3
|
+
* backup-auto-restore, adapted to better-sqlite3).
|
|
4
|
+
*
|
|
5
|
+
* Hardened after a qe-court review (ADR-124) surfaced three data-loss risks in
|
|
6
|
+
* the first cut:
|
|
7
|
+
* F3 — `isDbHealthy` via a readonly open + integrity_check FALSE-NEGATIVES a
|
|
8
|
+
* HEALTHY WAL db when `-shm` is zeroed/inaccessible over virtiofs (the
|
|
9
|
+
* exact documented failure mode), which would have parked a good DB and
|
|
10
|
+
* reverted to an older backup. FIX: the live-corruption signal is now the
|
|
11
|
+
* SQLite HEADER — a `-wal`/`-shm` problem does not corrupt the main file,
|
|
12
|
+
* so we only treat a missing/garbage header (zeroed/not-a-db) as corrupt.
|
|
13
|
+
* F2 — non-atomic `copyFileSync` + no lock let concurrent hook processes tear
|
|
14
|
+
* the restored image. FIX: copy to a temp in the same dir → atomic rename,
|
|
15
|
+
* under a best-effort exclusive lock so only one process restores.
|
|
16
|
+
* backup trust — a backup we are about to promote to the LIVE db still gets a
|
|
17
|
+
* FULL `integrity_check` (it is a static file, safe to open readonly).
|
|
18
|
+
*
|
|
19
|
+
* DATA-PROTECTION INVARIANTS (this file must never make things worse):
|
|
20
|
+
* - The corrupt original is RENAMED to `<db>.corrupt-<ts>`, NEVER deleted.
|
|
21
|
+
* - A header-valid main file is treated as HEALTHY — we never park a DB that
|
|
22
|
+
* might just have a transient `-wal`/`-shm` issue (a writable open rebuilds
|
|
23
|
+
* `-shm`). We prefer "manual restore" over "auto-destroy a healthy DB".
|
|
24
|
+
* - A backup is used only if it passes `PRAGMA integrity_check`.
|
|
25
|
+
* - If no verified backup exists, we do NOTHING (leave the DB for inspection).
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, renameSync, copyFileSync, readdirSync, statSync, openSync, readSync, closeSync, writeFileSync, rmSync, } from 'node:fs';
|
|
28
|
+
import { join, dirname } from 'node:path';
|
|
29
|
+
import Database from 'better-sqlite3';
|
|
30
|
+
/** The 16-byte magic every valid SQLite database file starts with. */
|
|
31
|
+
const SQLITE_MAGIC = Buffer.concat([Buffer.from('SQLite format 3', 'latin1'), Buffer.from([0])]);
|
|
32
|
+
/**
|
|
33
|
+
* True if the main DB file is structurally a database (or absent/empty = a fresh
|
|
34
|
+
* DB the caller will create). LIVE-corruption signal only: it deliberately does
|
|
35
|
+
* NOT open the DB or run integrity_check, because a `-wal`/`-shm` fault over
|
|
36
|
+
* virtiofs makes a HEALTHY db unreadable and we must not mistake that for
|
|
37
|
+
* corruption (F3). Only a missing/garbage header — the zeroed/not-a-db case —
|
|
38
|
+
* is "corrupt". A header-valid-but-page-corrupt file is left for MANUAL restore
|
|
39
|
+
* rather than risk auto-parking a healthy DB.
|
|
40
|
+
*/
|
|
41
|
+
export function isDbHealthy(dbPath) {
|
|
42
|
+
if (!existsSync(dbPath))
|
|
43
|
+
return true;
|
|
44
|
+
let size;
|
|
45
|
+
try {
|
|
46
|
+
size = statSync(dbPath).size;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (size === 0)
|
|
52
|
+
return true; // freshly-created, not yet written — not corrupt
|
|
53
|
+
if (size < SQLITE_MAGIC.length)
|
|
54
|
+
return false; // too small to be a real db
|
|
55
|
+
let fd;
|
|
56
|
+
try {
|
|
57
|
+
fd = openSync(dbPath, 'r');
|
|
58
|
+
const header = Buffer.alloc(SQLITE_MAGIC.length);
|
|
59
|
+
readSync(fd, header, 0, SQLITE_MAGIC.length, 0);
|
|
60
|
+
return header.equals(SQLITE_MAGIC);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
if (fd !== undefined) {
|
|
67
|
+
try {
|
|
68
|
+
closeSync(fd);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
/* ignore */
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Full integrity check for a backup we are about to promote to the live DB. */
|
|
77
|
+
function backupIsRestorable(path) {
|
|
78
|
+
let db;
|
|
79
|
+
try {
|
|
80
|
+
db = new Database(path, { readonly: true, fileMustExist: true });
|
|
81
|
+
return db.pragma('integrity_check', { simple: true }) === 'ok';
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
try {
|
|
88
|
+
db?.close();
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
/* ignore */
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Default verified-backup directory (matches `scripts/aqe-db-backup.sh`). */
|
|
96
|
+
export function defaultBackupDir(dbPath) {
|
|
97
|
+
return join(dirname(dbPath), 'backups', 'verified');
|
|
98
|
+
}
|
|
99
|
+
/** Newest `memory-*.db` in the backup dir that passes a full integrity_check, or null. */
|
|
100
|
+
function newestVerifiedBackup(backupDir) {
|
|
101
|
+
if (!existsSync(backupDir))
|
|
102
|
+
return null;
|
|
103
|
+
const candidates = readdirSync(backupDir)
|
|
104
|
+
.filter((f) => f.startsWith('memory-') && f.endsWith('.db'))
|
|
105
|
+
.map((f) => {
|
|
106
|
+
const path = join(backupDir, f);
|
|
107
|
+
return { path, mtime: statSync(path).mtimeMs };
|
|
108
|
+
})
|
|
109
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
110
|
+
for (const c of candidates) {
|
|
111
|
+
if (backupIsRestorable(c.path))
|
|
112
|
+
return c.path;
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* If `dbPath`'s main file is unambiguously corrupt (bad SQLite header), park it
|
|
118
|
+
* and atomically restore the newest verified backup. No-op (and non-destructive)
|
|
119
|
+
* when the DB is healthy, when no good backup exists, or when another process is
|
|
120
|
+
* already restoring.
|
|
121
|
+
*/
|
|
122
|
+
export function attemptAutoRestore(dbPath, opts) {
|
|
123
|
+
if (isDbHealthy(dbPath))
|
|
124
|
+
return { restored: false, reason: 'healthy' };
|
|
125
|
+
const backupDir = opts?.backupDir ?? defaultBackupDir(dbPath);
|
|
126
|
+
const good = newestVerifiedBackup(backupDir);
|
|
127
|
+
if (!good)
|
|
128
|
+
return { restored: false, reason: 'no-verified-backup' };
|
|
129
|
+
// F2: best-effort exclusive lock so concurrent processes don't both restore.
|
|
130
|
+
const lockPath = `${dbPath}.restore.lock`;
|
|
131
|
+
try {
|
|
132
|
+
writeFileSync(lockPath, String(process.pid), { flag: 'wx' });
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return { restored: false, reason: 'restore-in-progress' };
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
// Re-check under the lock: a peer may have just restored a healthy DB.
|
|
139
|
+
if (isDbHealthy(dbPath))
|
|
140
|
+
return { restored: false, reason: 'healthy' };
|
|
141
|
+
const ts = opts?.now ?? Date.now();
|
|
142
|
+
const parked = `${dbPath}.corrupt-${ts}`;
|
|
143
|
+
// Park the corrupt original + any stale WAL/shm. NEVER delete.
|
|
144
|
+
try {
|
|
145
|
+
if (existsSync(dbPath))
|
|
146
|
+
renameSync(dbPath, parked);
|
|
147
|
+
for (const suffix of ['-wal', '-shm']) {
|
|
148
|
+
if (existsSync(dbPath + suffix))
|
|
149
|
+
renameSync(dbPath + suffix, parked + suffix);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return { restored: false, reason: 'park-failed' };
|
|
154
|
+
}
|
|
155
|
+
// F2: restore atomically — copy to a temp on the same filesystem, then rename.
|
|
156
|
+
const tmp = `${dbPath}.restoring-${ts}`;
|
|
157
|
+
try {
|
|
158
|
+
copyFileSync(good, tmp);
|
|
159
|
+
renameSync(tmp, dbPath); // atomic on the same fs
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
try {
|
|
163
|
+
if (existsSync(tmp))
|
|
164
|
+
rmSync(tmp, { force: true });
|
|
165
|
+
if (!existsSync(dbPath) && existsSync(parked))
|
|
166
|
+
renameSync(parked, dbPath);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
/* leave parked copy for manual recovery */
|
|
170
|
+
}
|
|
171
|
+
return { restored: false, reason: 'copy-failed' };
|
|
172
|
+
}
|
|
173
|
+
return { restored: true, reason: 'restored-from-backup', backupUsed: good, parkedTo: parked };
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
try {
|
|
177
|
+
rmSync(lockPath, { force: true });
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
/* ignore */
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=db-recovery.js.map
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
const BILLING_MODE_BY_TYPE = {
|
|
11
11
|
claude: 'metered-api',
|
|
12
12
|
'claude-code': 'subscription',
|
|
13
|
+
codex: 'subscription',
|
|
13
14
|
openai: 'metered-api',
|
|
14
15
|
openrouter: 'metered-api',
|
|
15
16
|
gemini: 'metered-api',
|
|
@@ -45,10 +46,12 @@ export function billingNotice(provider, mode) {
|
|
|
45
46
|
case 'metered-capped':
|
|
46
47
|
return (`ℹ️ LLM provider "${provider}" bills per-token but enforces a server-side ` +
|
|
47
48
|
`hard spend cap; it will pause at the cap rather than overspend.`);
|
|
48
|
-
case 'subscription':
|
|
49
|
-
|
|
49
|
+
case 'subscription': {
|
|
50
|
+
const sub = provider === 'codex' ? 'ChatGPT' : 'Claude Code';
|
|
51
|
+
return (`ℹ️ LLM provider "${provider}" runs on your ${sub} subscription ` +
|
|
50
52
|
`(shared plan usage). Worst case is hitting your plan's rate limit and pausing — ` +
|
|
51
53
|
`no per-token API charges.`);
|
|
54
|
+
}
|
|
52
55
|
case 'local':
|
|
53
56
|
return undefined;
|
|
54
57
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
/**
|
|
12
12
|
* Supported LLM provider types
|
|
13
13
|
*/
|
|
14
|
-
export type LLMProviderType = 'claude' | 'claude-code' | 'openai' | 'ollama' | 'openrouter' | 'bedrock' | 'azure-openai' | 'gemini' | 'cognitum';
|
|
14
|
+
export type LLMProviderType = 'claude' | 'claude-code' | 'codex' | 'openai' | 'ollama' | 'openrouter' | 'bedrock' | 'azure-openai' | 'gemini' | 'cognitum';
|
|
15
15
|
/**
|
|
16
16
|
* Message role in a conversation
|
|
17
17
|
*/
|
|
@@ -273,6 +273,18 @@ export interface ClaudeCodeConfig extends LLMConfig {
|
|
|
273
273
|
/** Tools to disallow in the headless session (safety). */
|
|
274
274
|
disallowedTools?: string[];
|
|
275
275
|
}
|
|
276
|
+
/**
|
|
277
|
+
* Codex CLI (subscription) provider configuration (ADR-123 / ADR-124 M3.5).
|
|
278
|
+
* Runs on the user's ChatGPT subscription by shelling out to `codex exec`,
|
|
279
|
+
* mirroring the claude-code provider. Gives AQE a cross-vendor (GPT-family)
|
|
280
|
+
* engine for provider fallback and qe-court prosecutor/juror diversity.
|
|
281
|
+
*/
|
|
282
|
+
export interface CodexConfig extends LLMConfig {
|
|
283
|
+
/** Path to the `codex` binary (default: 'codex' on PATH). */
|
|
284
|
+
binaryPath?: string;
|
|
285
|
+
/** Max concurrent `codex exec` subprocesses. */
|
|
286
|
+
maxConcurrency?: number;
|
|
287
|
+
}
|
|
276
288
|
/**
|
|
277
289
|
* Cognitum provider configuration (ADR-123). OpenAI-compatible gateway with
|
|
278
290
|
* per-request cost receipts and a server-side hard spend cap.
|
|
@@ -294,6 +306,7 @@ export interface ProviderManagerConfig {
|
|
|
294
306
|
providers: {
|
|
295
307
|
claude?: ClaudeConfig;
|
|
296
308
|
'claude-code'?: ClaudeCodeConfig;
|
|
309
|
+
codex?: CodexConfig;
|
|
297
310
|
openai?: OpenAIConfig;
|
|
298
311
|
ollama?: OllamaConfig;
|
|
299
312
|
openrouter?: OpenRouterConfig;
|