agentic-qe 3.12.3 → 3.13.0
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/.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/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/CHANGELOG.md +65 -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-CWIMFWAI.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-XFAQATTH.js → agent-booster-wasm-ACX2DK7Y.js} +2 -2
- package/dist/cli/chunks/{agent-handler-2ZV4CA3U.js → agent-handler-B45WP4ZJ.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-6WGP7F5T.js → agent-memory-branch-QQLZDE56.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-OTXT2DLN.js +2 -0
- package/dist/cli/chunks/{arena-FWX7XZAE.js → arena-G3IKZAG5.js} +4 -4
- package/dist/cli/chunks/{arena-KJUNQK4N.js → arena-SDB7723R.js} +2 -2
- package/dist/cli/chunks/{audit-YFUDEOKN.js → audit-GY46XUZA.js} +3 -3
- package/dist/cli/chunks/base-O3SPSWBA.js +2 -0
- package/dist/cli/chunks/{hnswlib-node-SKTT5KIH.js → better-sqlite3-DUZ6FFAH.js} +2 -2
- package/dist/cli/chunks/{brain-handler-ZCK4WTPK.js → brain-handler-347CYMPN.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-HTVINRYG.js → branch-enumerator-Z3ULBFSM.js} +2 -2
- package/dist/cli/chunks/{browser-WUL2B77M.js → browser-OYEIHD7F.js} +2 -2
- package/dist/cli/chunks/browser-workflow-MXS3ZKY2.js +2 -0
- package/dist/cli/chunks/{chunk-OBL6W4Z5.js → chunk-2DIT5AUU.js} +2 -2
- package/dist/cli/chunks/{chunk-IWQHQLT6.js → chunk-2NRZYQSF.js} +2 -2
- package/dist/cli/chunks/chunk-2VQVEQS4.js +153 -0
- package/dist/cli/chunks/{chunk-E2U3LTGM.js → chunk-32ZGV4Q4.js} +1 -1
- package/dist/cli/chunks/{chunk-VUCVSKJC.js → chunk-34PEINFS.js} +2 -2
- package/dist/cli/chunks/{chunk-XUUVAAHV.js → chunk-3GSYD5SL.js} +2 -2
- package/dist/cli/chunks/{chunk-MOX25RZQ.js → chunk-3JVUWKCO.js} +2 -2
- package/dist/cli/chunks/{chunk-RLBNAB6Y.js → chunk-3K4SF57Q.js} +1 -1
- package/dist/cli/chunks/{chunk-MSDIIRLM.js → chunk-3NOCK6ED.js} +2 -2
- package/dist/cli/chunks/{chunk-3YC4YUGB.js → chunk-3UHEZ5HZ.js} +2 -2
- package/dist/cli/chunks/{chunk-J2RJOJ5Q.js → chunk-4BDLD7V2.js} +1 -1
- package/dist/cli/chunks/{chunk-ZGKQCUPB.js → chunk-4BESADKE.js} +2 -2
- package/dist/cli/chunks/{chunk-PDX7IYTJ.js → chunk-54MFKCLT.js} +2 -2
- package/dist/cli/chunks/{chunk-TP3UAWMB.js → chunk-56WZFXTQ.js} +2 -2
- package/dist/cli/chunks/{chunk-WFPGIP4N.js → chunk-5EIOQCGN.js} +2 -2
- package/dist/cli/chunks/{chunk-32L7DKNQ.js → chunk-5FLTZ3KT.js} +2 -2
- package/dist/cli/chunks/{chunk-Y5L37K7X.js → chunk-5ICQL42E.js} +2 -2
- package/dist/cli/chunks/{chunk-Y625LP6K.js → chunk-5KAT6WBQ.js} +2 -2
- package/dist/cli/chunks/{chunk-UIHZ34SJ.js → chunk-6AOBLBR4.js} +2 -2
- package/dist/cli/chunks/{chunk-7WF3TW3G.js → chunk-6DTOGSDV.js} +4 -4
- package/dist/cli/chunks/{chunk-NAMJGRGC.js → chunk-6SXKCIN5.js} +2 -2
- package/dist/cli/chunks/{chunk-FTM562PF.js → chunk-7DMXCCSD.js} +1 -1
- package/dist/cli/chunks/{chunk-KE3RK35K.js → chunk-7UNY32PU.js} +1 -1
- package/dist/cli/chunks/{chunk-BSNNTOHY.js → chunk-7YXT6BXN.js} +3 -3
- package/dist/cli/chunks/{chunk-DZ775UGW.js → chunk-A4QLGPYO.js} +2 -2
- package/dist/cli/chunks/{chunk-SFS3UHNF.js → chunk-A7GLWWSE.js} +1 -1
- package/dist/cli/chunks/{chunk-WKE6WL5C.js → chunk-ANIDFJCT.js} +3 -3
- package/dist/cli/chunks/{chunk-XDHGCBTS.js → chunk-ANYYTWOQ.js} +2 -2
- package/dist/cli/chunks/{chunk-NLDLUHOF.js → chunk-AO7AHX6K.js} +2 -2
- package/dist/cli/chunks/{chunk-Z3SXMYVI.js → chunk-BCKTBGDM.js} +3 -3
- package/dist/cli/chunks/{chunk-UGW23T6S.js → chunk-BGYLNCL6.js} +2 -2
- package/dist/cli/chunks/{chunk-KVHCWH4H.js → chunk-BOVH6WSM.js} +2 -2
- package/dist/cli/chunks/{chunk-L2X3BWMN.js → chunk-BUGWPTMF.js} +2 -2
- package/dist/cli/chunks/{chunk-DTZFZ5M7.js → chunk-CFVEDUTW.js} +2 -2
- package/dist/cli/chunks/{chunk-CL6SNCFF.js → chunk-CPH5JP4L.js} +1 -1
- package/dist/cli/chunks/{chunk-AIWRYWK2.js → chunk-CQFT7H3F.js} +2 -2
- package/dist/cli/chunks/{chunk-BQ2K4BPD.js → chunk-CWUBOLKY.js} +2 -2
- package/dist/cli/chunks/{chunk-2LNDU7AW.js → chunk-CYL2FV23.js} +2 -2
- package/dist/cli/chunks/{chunk-YEC55GO5.js → chunk-D3MPV5G7.js} +2 -2
- package/dist/cli/chunks/{chunk-DMD6WVJ2.js → chunk-DRIJYTSK.js} +2 -2
- package/dist/cli/chunks/{chunk-PXCJDB7J.js → chunk-DYUC7WFA.js} +1 -1
- package/dist/cli/chunks/{chunk-EOUJ6X5H.js → chunk-E3B5XTXJ.js} +1 -1
- package/dist/cli/chunks/{chunk-PSDH7CIL.js → chunk-EECM5XKY.js} +1 -1
- package/dist/cli/chunks/{chunk-E53UR2EW.js → chunk-EFRESRLB.js} +3 -3
- package/dist/cli/chunks/{chunk-SGMJ277D.js → chunk-ES7WCYOU.js} +1 -1
- package/dist/cli/chunks/{chunk-DDYP6FBC.js → chunk-FAQLI3P5.js} +2 -2
- package/dist/cli/chunks/{chunk-CXMOIE7D.js → chunk-FBBZHATF.js} +2 -2
- package/dist/cli/chunks/{chunk-KKOFH26C.js → chunk-FL3BM54K.js} +1 -1
- package/dist/cli/chunks/{chunk-MB7TZQW3.js → chunk-FQLWQWRU.js} +3 -3
- package/dist/cli/chunks/{chunk-GMFFMJD6.js → chunk-FQY3UTGA.js} +2 -2
- package/dist/cli/chunks/{chunk-SPI4LUJ6.js → chunk-FUU32QY5.js} +2 -2
- package/dist/cli/chunks/{chunk-RSZOCQOL.js → chunk-G4GTE3RJ.js} +2 -2
- package/dist/cli/chunks/{chunk-NOSQI2OW.js → chunk-G5DFYX3J.js} +3 -3
- package/dist/cli/chunks/{chunk-OPG2HV2W.js → chunk-G7FMYFTN.js} +1 -1
- package/dist/cli/chunks/{chunk-N4ML23ZG.js → chunk-GFBLWFRV.js} +1 -1
- package/dist/cli/chunks/{chunk-LNIHLNW4.js → chunk-GJMZR7WU.js} +3 -3
- package/dist/cli/chunks/{chunk-PTPN6HQ7.js → chunk-GTUFX7AR.js} +2 -2
- package/dist/cli/chunks/{chunk-67BCEHU5.js → chunk-GUEZQOHL.js} +1 -1
- package/dist/cli/chunks/{chunk-RE42RJYR.js → chunk-HL2QMM4M.js} +2 -2
- package/dist/cli/chunks/{chunk-QILF6BZH.js → chunk-HOKON5EL.js} +2 -2
- package/dist/cli/chunks/{chunk-YOG5KQZF.js → chunk-HTPM3URI.js} +2 -2
- package/dist/cli/chunks/chunk-HVB2L52I.js +2 -0
- package/dist/cli/chunks/{chunk-DHUZHT5D.js → chunk-IHQTXJAQ.js} +1 -1
- package/dist/cli/chunks/{chunk-SV7J5FDW.js → chunk-IPHLXAMX.js} +2 -2
- package/dist/cli/chunks/{chunk-Y6XNISHP.js → chunk-IYDYJ33J.js} +2 -2
- package/dist/cli/chunks/{chunk-CYSBM52D.js → chunk-IZRLIWFN.js} +2 -2
- package/dist/cli/chunks/{chunk-MS6VOSPY.js → chunk-J3L52EA4.js} +5 -5
- package/dist/cli/chunks/{chunk-WQASUQ5P.js → chunk-JGM6XCCP.js} +1 -1
- package/dist/cli/chunks/chunk-JPIBPKBP.js +54 -0
- package/dist/cli/chunks/{chunk-TXLPOXAN.js → chunk-K5N6SLHO.js} +1 -1
- package/dist/cli/chunks/{chunk-R6WMGSEK.js → chunk-KSYLRM4Q.js} +2 -2
- package/dist/cli/chunks/{chunk-2CPJCXV6.js → chunk-KUA4HHU6.js} +2 -2
- package/dist/cli/chunks/{chunk-WUE53ZPH.js → chunk-KVL63BSU.js} +1 -1
- package/dist/cli/chunks/{chunk-6SUSRXXF.js → chunk-KZTBNDNE.js} +1 -1
- package/dist/cli/chunks/{chunk-M7W6VJ65.js → chunk-L2SFGFE6.js} +1 -1
- package/dist/cli/chunks/{chunk-XZGOXLZH.js → chunk-L4LLA5U7.js} +1 -1
- package/dist/cli/chunks/{chunk-AZ24ONMX.js → chunk-L4S722JD.js} +1 -1
- package/dist/cli/chunks/{chunk-HJ4U64BL.js → chunk-LBE2P6UC.js} +2 -2
- package/dist/cli/chunks/{chunk-KA4EAMMQ.js → chunk-LOXVVMS4.js} +3 -3
- package/dist/cli/chunks/{chunk-UGXHMQ6P.js → chunk-LWYLW7RX.js} +2 -2
- package/dist/cli/chunks/{chunk-HJ2LG5IH.js → chunk-LXPB7H2P.js} +1 -1
- package/dist/cli/chunks/{chunk-WBZNLFTV.js → chunk-MBCGI3M2.js} +3 -3
- package/dist/cli/chunks/{chunk-7XUM4LBC.js → chunk-MVI2QMRW.js} +1 -1
- package/dist/cli/chunks/{chunk-2OX74DOO.js → chunk-N5MMBA35.js} +1 -1
- package/dist/cli/chunks/{chunk-VSD6JE2H.js → chunk-N7VOOI3U.js} +2 -2
- package/dist/cli/chunks/{chunk-ROFCS47F.js → chunk-NETN3OUG.js} +1 -1
- package/dist/cli/chunks/chunk-NQNKKVNO.js +29 -0
- package/dist/cli/chunks/{chunk-NJDLJ3KD.js → chunk-NUQBJGGF.js} +2 -2
- package/dist/cli/chunks/chunk-OETDMOOE.js +2 -0
- package/dist/cli/chunks/{chunk-4EHW4TNA.js → chunk-OXXMVQDF.js} +2 -2
- package/dist/cli/chunks/{chunk-6HQDPDN5.js → chunk-OZR25R7W.js} +2 -2
- package/dist/cli/chunks/{chunk-UZ7FXVH5.js → chunk-PERJO2DY.js} +1 -1
- package/dist/cli/chunks/{chunk-XQ5JT7KM.js → chunk-PP2RYSHT.js} +3 -3
- package/dist/cli/chunks/{chunk-DCYBV6HV.js → chunk-Q7PBGNUD.js} +1 -1
- package/dist/cli/chunks/{chunk-LCM7TY76.js → chunk-QCEW4ZDW.js} +2 -2
- package/dist/cli/chunks/{chunk-NKTLKMUB.js → chunk-QI4CGJNK.js} +1 -1
- package/dist/cli/chunks/{chunk-NT66CT73.js → chunk-QQB55ZJJ.js} +2 -2
- package/dist/cli/chunks/{chunk-KRS4KGX5.js → chunk-QTU3CVOB.js} +2 -2
- package/dist/cli/chunks/{chunk-DW7OI5IF.js → chunk-QWYISZTN.js} +2 -2
- package/dist/cli/chunks/{chunk-KNWBRMLL.js → chunk-R3GEXYO4.js} +2 -2
- package/dist/cli/chunks/{chunk-YUDGQZJN.js → chunk-RDU4WTV2.js} +2 -2
- package/dist/cli/chunks/{chunk-VFYMWDSJ.js → chunk-RJZRWVL4.js} +1 -1
- package/dist/cli/chunks/{chunk-D4GMAUTP.js → chunk-RLCWR7TS.js} +10 -10
- package/dist/cli/chunks/{chunk-YDYKFSD2.js → chunk-RSFIOR2I.js} +10 -10
- package/dist/cli/chunks/{chunk-EHO52NKU.js → chunk-RVJPWRV6.js} +2 -2
- package/dist/cli/chunks/{chunk-KGHSKDC7.js → chunk-RVRBTOWX.js} +2 -2
- package/dist/cli/chunks/{chunk-2YDZXFO2.js → chunk-SHCTEXNH.js} +2 -2
- package/dist/cli/chunks/chunk-SNTUKW4Q.js +2 -0
- package/dist/cli/chunks/{chunk-MOXKKY5Q.js → chunk-SRQ3CPJE.js} +4 -4
- package/dist/cli/chunks/{chunk-GS6G7AVS.js → chunk-THBTN7XB.js} +2 -2
- package/dist/cli/chunks/{chunk-LHAUFY4Y.js → chunk-TNRIGQ6U.js} +2 -2
- package/dist/cli/chunks/{chunk-UAPUA6OY.js → chunk-TVMFH5N2.js} +2 -2
- package/dist/cli/chunks/{chunk-HGJQSTQD.js → chunk-TZ73SXQ5.js} +1 -1
- package/dist/cli/chunks/{chunk-CHFTHSMM.js → chunk-TZPKTRJB.js} +2 -2
- package/dist/cli/chunks/{chunk-GV2BS5NC.js → chunk-U2SW6KK5.js} +2 -2
- package/dist/cli/chunks/{chunk-BDGKB2PT.js → chunk-UIPPJKON.js} +2 -2
- package/dist/cli/chunks/{chunk-FXOOOJQD.js → chunk-UMG5URNV.js} +1 -1
- package/dist/cli/chunks/{chunk-7Q74K3HZ.js → chunk-UNIBND6A.js} +1 -1
- package/dist/cli/chunks/{chunk-LGYEOYQJ.js → chunk-USMDIIHY.js} +2 -2
- package/dist/cli/chunks/{chunk-2HCMRGMO.js → chunk-VC6EXDGY.js} +2 -2
- package/dist/cli/chunks/{chunk-5FAWIIWF.js → chunk-VHYMSZNF.js} +2 -2
- package/dist/cli/chunks/{chunk-ZTKCGEB6.js → chunk-VLBV2VL3.js} +1 -1
- package/dist/cli/chunks/{chunk-6E47R27C.js → chunk-VLNPJAVH.js} +1 -1
- package/dist/cli/chunks/{chunk-EH7TSJPS.js → chunk-VSNRPMAZ.js} +2 -2
- package/dist/cli/chunks/{chunk-FJACKKRL.js → chunk-W5YEIHIO.js} +2 -2
- package/dist/cli/chunks/{chunk-4HP7N6SP.js → chunk-WRYT4HTZ.js} +2 -2
- package/dist/cli/chunks/{chunk-ZFLE4D4X.js → chunk-XFCWYQHW.js} +2 -2
- package/dist/cli/chunks/{chunk-72QQDR3Y.js → chunk-XKFE3FLI.js} +2 -2
- package/dist/cli/chunks/{chunk-KXKACV3E.js → chunk-YFGAHNCG.js} +2 -2
- package/dist/cli/chunks/{chunk-S47YGWXK.js → chunk-YPTGE5NJ.js} +2 -2
- package/dist/cli/chunks/{chunk-PEHEANAM.js → chunk-YRQLVGCI.js} +2 -2
- package/dist/cli/chunks/{chunk-L6GZGEFQ.js → chunk-Z6QCOZ2H.js} +2 -2
- package/dist/cli/chunks/{chunk-GGTCD4MA.js → chunk-ZCFZ4USU.js} +1 -1
- package/dist/cli/chunks/{chunk-MZ7SIO6R.js → chunk-ZEIG5IQ4.js} +2 -2
- package/dist/cli/chunks/{chunk-XBOCRCC6.js → chunk-ZJG6N2OK.js} +1 -1
- package/dist/cli/chunks/{chunk-M32DTUZM.js → chunk-ZJIX5FGQ.js} +3 -3
- package/dist/cli/chunks/{chunk-ADQFQBFJ.js → chunk-ZLXBNNNT.js} +2 -2
- package/dist/cli/chunks/{chunk-BEPP57C2.js → chunk-ZOXWASCC.js} +2 -2
- package/dist/cli/chunks/{ci-MMLUV6L6.js → ci-74ZUCO5V.js} +2 -2
- package/dist/cli/chunks/{ci-output-25GS6RXR.js → ci-output-HD6IZNJA.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-4OWAN6R6.js → circuit-breaker-USZVMA42.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-LR3SRBX6.js → claude-flow-setup-S4XKNCD5.js} +2 -2
- package/dist/cli/chunks/client-33PGO5FA.js +2 -0
- package/dist/cli/chunks/{cline-installer-YSZWRZUI.js → cline-installer-6EW4CHAR.js} +2 -2
- package/dist/cli/chunks/{code-UUWUIXI7.js → code-TOLWD2XL.js} +2 -2
- package/dist/cli/chunks/{code-index-extractor-2LSPQORU.js → code-index-extractor-UA4QQ7B3.js} +2 -2
- package/dist/cli/chunks/{codex-installer-E5BVXZVA.js → codex-installer-C2CUP4FW.js} +2 -2
- package/dist/cli/chunks/{completions-YKXBKZSO.js → completions-KVUMQQ4K.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-HNT2QRWB.js → complexity-analyzer-DFH6LMK2.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-AW5VCB66.js → continuedev-installer-LYDQSAU7.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-B6SVZXQT.js → copilot-installer-7USXLZHZ.js} +2 -2
- package/dist/cli/chunks/core-handlers-CSNZIM3A.js +2 -0
- package/dist/cli/chunks/{cost-tracker-POZMBN2V.js → cost-tracker-JBDIUMKZ.js} +2 -2
- package/dist/cli/chunks/{coverage-V5BGPN5Q.js → coverage-RGO3K357.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-DRIBR5L3.js +2 -0
- package/dist/cli/chunks/{cursor-installer-EYBI4QVK.js → cursor-installer-YEZGD37F.js} +2 -2
- package/dist/cli/chunks/{daemon-CF6ENQB2.js → daemon-FVETQ3LL.js} +3 -3
- package/dist/cli/chunks/{daemon-HKARXY2W.js → daemon-LPEXHNYG.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-XIL5IAP7.js → dag-attention-scheduler-UKYE2FII.js} +2 -2
- package/dist/cli/chunks/{detect-RRX2U2KK.js → detect-WBG5P7ER.js} +2 -2
- package/dist/cli/chunks/{dist-node-DOANNRCS.js → dist-node-YW6YRBCU.js} +2 -2
- package/dist/cli/chunks/{domain-handler-QMTJV5OR.js → domain-handler-HH7J4A32.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-FSNH75XW.js → domain-transfer-V34GXD5I.js} +2 -2
- package/dist/cli/chunks/dream-WUNO723O.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-NI7PGONV.js → embed-and-insert-pattern-WYLRS3CL.js} +2 -2
- package/dist/cli/chunks/{eval-6ZAF2RY3.js → eval-EIMVXY5J.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-JMXR7N5G.js → experience-capture-middleware-QMZHRUKM.js} +3 -3
- package/dist/cli/chunks/{fast-paths-YB7XZZ76.js → fast-paths-NHLW6XS6.js} +2 -2
- package/dist/cli/chunks/{feature-flags-KJSP7KR6.js → feature-flags-N3UHMSZ3.js} +2 -2
- package/dist/cli/chunks/{feature-flags-2RC4GFC4.js → feature-flags-NE3MBL3P.js} +2 -2
- package/dist/cli/chunks/{file-discovery-SUPBXFYI.js → file-discovery-SI44X4YS.js} +2 -2
- package/dist/cli/chunks/{fleet-KSXFOLFW.js → fleet-MMYUXRRM.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-DFZ5KPPK.js → gnn-wrapper-RLYXYU2Q.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-G3EADK2H.js → heartbeat-handler-6EDRUYLV.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-VAFQDJLL.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-TIRPA7XE.js +2 -0
- package/dist/cli/chunks/hnsw-index-SSQBRQCQ.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-MA676GER.js → hnsw-legacy-bridge-RVM7EAIH.js} +2 -2
- package/dist/cli/chunks/{better-sqlite3-FE55OGYB.js → hnswlib-node-RJPBJU2Q.js} +2 -2
- package/dist/cli/chunks/{hooks-HTCPMZNZ.js → hooks-ZF4VKHEO.js} +10 -10
- package/dist/cli/chunks/hybrid-router-AKBWZOQ3.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-QPB3IH4A.js → hypergraph-engine-YWS66PGO.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-GBFSVD7N.js → hypergraph-handler-OQHVRPWB.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-46FQIZ6Y.js +2 -0
- package/dist/cli/chunks/{init-handler-XYBTBCPD.js → init-handler-YW74YF2V.js} +6 -6
- package/dist/cli/chunks/init-wizard-U3NHGYSS.js +2 -0
- package/dist/cli/chunks/kernel-ZDXHT6QF.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-LY6JOBFY.js → kilocode-installer-APWB2GMA.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-JF6NXTJL.js → kiro-installer-DICKFVNC.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-6XTW6WO6.js +2 -0
- package/dist/cli/chunks/{learning-BIISN67N.js → learning-MXHNYW5D.js} +3 -3
- package/dist/cli/chunks/{llm-router-YZUNVZQE.js → llm-router-LTFIX7NY.js} +5 -5
- package/dist/cli/chunks/llm-router-service-3F4E64SY.js +2 -0
- package/dist/cli/chunks/{load-MTWNBNLL.js → load-JUMIQ4LZ.js} +2 -2
- package/dist/cli/chunks/load-test-SWZNGEIY.js +2 -0
- package/dist/cli/chunks/{mcp-37PYMNHQ.js → mcp-WHIARJGO.js} +2 -2
- package/dist/cli/chunks/{memory-IXUUDCI3.js → memory-KAHS6Z5A.js} +5 -5
- package/dist/cli/chunks/memory-backend-PR74ZPBA.js +2 -0
- package/dist/cli/chunks/{memory-handlers-RM2VOFJX.js → memory-handlers-DG3RRXB6.js} +2 -2
- package/dist/cli/chunks/{multi-model-executor-RKKS5XYG.js → multi-model-executor-E3Y2RHMX.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-3VXI5MTR.js → opencode-installer-3RKGNGGE.js} +2 -2
- package/dist/cli/chunks/{orchestrator-UO3ZOGFZ.js → orchestrator-TXITUKWD.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-EPE36BVT.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-YJKRL2GI.js → pattern-usage-recorder-EE2BUFZT.js} +2 -2
- package/dist/cli/chunks/{pipeline-GJQJKXWX.js → pipeline-AXTT6KZB.js} +2 -2
- package/dist/cli/chunks/{platform-RHVCZK6C.js → platform-TICPVKE2.js} +2 -2
- package/dist/cli/chunks/{plugin-ZKAIW7O6.js → plugin-VQKNV3EM.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-4X3DSKQV.js → prime-radiant-advanced-wasm-6GY5YY7D.js} +2 -2
- package/dist/cli/chunks/protocol-executor-IELENNST.js +2 -0
- package/dist/cli/chunks/{protocol-handler-KKYQZMB2.js → protocol-handler-YFWDR7UZ.js} +2 -2
- package/dist/cli/chunks/{prove-OD6RPKWX.js → prove-FUMRCXAA.js} +2 -2
- package/dist/cli/chunks/provider-manager-3R3KOBHG.js +2 -0
- package/dist/cli/chunks/qe-reasoning-bank-S2R2PCBS.js +2 -0
- package/dist/cli/chunks/{quality-ZRWBXCKO.js → quality-2APISBW5.js} +2 -2
- package/dist/cli/chunks/{quality-gate-Y6BWQV7J.js → quality-gate-MCC3E5TM.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-2E23NEV4.js +2 -0
- package/dist/cli/chunks/{real-embeddings-YYEUO4P2.js → real-embeddings-CC5TNOTI.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-JBCPS3FK.js → roocode-installer-YAHTEVPI.js} +2 -2
- package/dist/cli/chunks/router-3FVLWO6S.js +2 -0
- package/dist/cli/chunks/routing-feedback-ZQLRNNR7.js +2 -0
- package/dist/cli/chunks/{routing-handler-KTPJOSBJ.js → routing-handler-6NQBW4TQ.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-SCZZVRE7.js → ruvector-commands-ZHXLHUPG.js} +2 -2
- package/dist/cli/chunks/{rvf-dual-writer-IP7GELQJ.js → rvf-dual-writer-5KF2DGCW.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-adapter-WLFTDARU.js → rvf-migration-adapter-BBU57BGF.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-coordinator-MGFDQ5WD.js → rvf-migration-coordinator-VN4VRZA4.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-YFGLQNEB.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-OTOAGT5W.js → rvf-store-integrity-XCY2XQZA.js} +2 -2
- package/dist/cli/chunks/safe-db-4SBLBTW7.js +2 -0
- package/dist/cli/chunks/schedule-5Y3BGVAA.js +2 -0
- package/dist/cli/chunks/scheduler-DOID3QF3.js +2 -0
- package/dist/cli/chunks/{security-B2CLZKRB.js → security-PYP4H3KN.js} +3 -3
- package/dist/cli/chunks/{shared-rvf-adapter-2PMFAQMN.js → shared-rvf-adapter-3CJHRNX6.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-B6P732AV.js → shared-rvf-dual-writer-MKSLKWDI.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-M4JEQO57.js +2 -0
- package/dist/cli/chunks/{status-handler-M6SN2W2D.js → status-handler-VYIZ3VJF.js} +2 -2
- package/dist/cli/chunks/{structural-health-YCCTGI3K.js → structural-health-MVV4OWXP.js} +2 -2
- package/dist/cli/chunks/{sync-KSRF77ID.js → sync-G47OYIQ3.js} +2 -2
- package/dist/cli/chunks/sync-VNX6L3TI.js +2 -0
- package/dist/cli/chunks/{task-handler-MIKRB2SL.js → task-handler-GOWF2GEH.js} +2 -2
- package/dist/cli/chunks/{task-handlers-YXKRUBQ4.js → task-handlers-J2WC6J37.js} +3 -3
- package/dist/cli/chunks/{test-MLOLQCB7.js → test-DMCJ3BXS.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-3KXESUZS.js → test-scheduling-TRFHHKFM.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-6V2PMDBJ.js → token-bootstrap-KEQ7AHFF.js} +2 -2
- package/dist/cli/chunks/{token-usage-DP6THJ3I.js → token-usage-B54FOFOF.js} +2 -2
- package/dist/cli/chunks/transformers-IACZG7IV.js +2 -0
- package/dist/cli/chunks/{tree-sitter-wasm-parser-COK2XERS.js → tree-sitter-wasm-parser-N7H4X37E.js} +2 -2
- package/dist/cli/chunks/{types-PYHUCVOZ.js → types-B3SHT4OD.js} +2 -2
- package/dist/cli/chunks/unified-memory-WNYWTGVX.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-YPAV7U4E.js +2 -0
- package/dist/cli/chunks/unified-persistence-TJ252S7L.js +2 -0
- package/dist/cli/chunks/{upgrade-ONP2HNGL.js → upgrade-A2PQ5EWK.js} +2 -2
- package/dist/cli/chunks/{validate-NWSICDAY.js → validate-UXV7UQUT.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-KXS5P3U7.js → validate-swarm-MMBU4FPP.js} +2 -2
- package/dist/cli/chunks/{vibium-TZSGZRCQ.js → vibium-R4GUVADA.js} +2 -2
- package/dist/cli/chunks/visual-security-VKYXEGJB.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-V2FADNRA.js → web-tree-sitter-MP6E6CJB.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-GQM7KWDC.js → windsurf-installer-Z6BWMUUO.js} +2 -2
- package/dist/cli/chunks/{witness-chain-GTITDIA2.js → witness-chain-EFLTABBA.js} +2 -2
- package/dist/cli/chunks/witness-chain-WVXRXKQP.js +2 -0
- package/dist/cli/chunks/{witness-key-manager-AHRM2M52.js → witness-key-manager-PN36TV43.js} +2 -2
- package/dist/cli/chunks/{workflow-XCGHEL3I.js → workflow-A2AX3RJU.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-GOWSPR3G.js +2 -0
- package/dist/cli/chunks/{wrappers-VGO2GO4J.js → wrappers-NA6FHA63.js} +2 -2
- package/dist/cli/commands/llm-router.js +1 -0
- 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/mcp/bundle.js +397 -386
- 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/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/config-store.js +5 -0
- package/dist/shared/llm/router/hybrid-router.js +2 -2
- 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 +7 -3
- 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-6SQ72FG7.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-ULQCEM7K.js +0 -2
- package/dist/cli/chunks/client-WI7RRUZO.js +0 -2
- 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
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 — Codex CLI (subscription) Provider (ADR-123 / ADR-124 M3.5)
|
|
3
|
+
*
|
|
4
|
+
* Runs QE analysis on the user's ChatGPT subscription by shelling out to the
|
|
5
|
+
* Codex CLI (`codex exec`) instead of calling the OpenAI API with a paid key.
|
|
6
|
+
* The CLI authenticates with the user's existing ChatGPT login (~/.codex/auth.json)
|
|
7
|
+
* and draws from the subscription allowance, so the worst case is "hit the plan
|
|
8
|
+
* limit and pause" rather than a per-token bill. Mirrors the claude-code provider.
|
|
9
|
+
*
|
|
10
|
+
* WHY: gives AQE a cross-vendor (GPT-family) engine — used as a provider fallback
|
|
11
|
+
* and, crucially, as an independent prosecutor/juror in qe-court (ADR-124), where
|
|
12
|
+
* a non-Claude, non-Cognitum brain is the strongest form of writer≠juror.
|
|
13
|
+
*
|
|
14
|
+
* LOAD-BEARING: the child process env has OPENAI_API_KEY / CODEX_API_KEY stripped.
|
|
15
|
+
* If present, the CLI could revert to API-key billing and this provider would be
|
|
16
|
+
* a lie. `parity` test coverage asserts the strip.
|
|
17
|
+
*/
|
|
18
|
+
import { spawn } from 'node:child_process';
|
|
19
|
+
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
20
|
+
import { tmpdir } from 'node:os';
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { createLLMError, } from '../interfaces';
|
|
23
|
+
import { TokenMetricsCollector } from '../../../learning/token-tracker.js';
|
|
24
|
+
/** Env vars whose presence could flip the CLI from subscription to API billing. */
|
|
25
|
+
export const API_BILLING_ENV_VARS = ['OPENAI_API_KEY', 'CODEX_API_KEY'];
|
|
26
|
+
/** Sentinel meaning "let Codex use its own configured default model". */
|
|
27
|
+
export const CODEX_DEFAULT_MODEL = 'default';
|
|
28
|
+
export const DEFAULT_CODEX_CONFIG = {
|
|
29
|
+
model: CODEX_DEFAULT_MODEL,
|
|
30
|
+
maxTokens: 4096,
|
|
31
|
+
temperature: 0.7,
|
|
32
|
+
timeoutMs: 180000,
|
|
33
|
+
maxRetries: 1,
|
|
34
|
+
binaryPath: 'codex',
|
|
35
|
+
maxConcurrency: 2,
|
|
36
|
+
};
|
|
37
|
+
export class CodexProvider {
|
|
38
|
+
type = 'codex';
|
|
39
|
+
name = 'Codex CLI (subscription)';
|
|
40
|
+
billingMode = 'subscription';
|
|
41
|
+
config;
|
|
42
|
+
requestId = 0;
|
|
43
|
+
availabilityCache;
|
|
44
|
+
active = 0;
|
|
45
|
+
queue = [];
|
|
46
|
+
constructor(config = {}) {
|
|
47
|
+
this.config = { ...DEFAULT_CODEX_CONFIG, ...config };
|
|
48
|
+
const envConc = Number.parseInt(process.env.AQE_CODEX_CONCURRENCY ?? '', 10);
|
|
49
|
+
if (Number.isFinite(envConc) && envConc > 0) {
|
|
50
|
+
this.config.maxConcurrency = envConc;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async isAvailable() {
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
if (this.availabilityCache && now - this.availabilityCache.at < 60_000) {
|
|
56
|
+
return this.availabilityCache.available;
|
|
57
|
+
}
|
|
58
|
+
let available = false;
|
|
59
|
+
try {
|
|
60
|
+
const { code } = await this.runProcess(['--version'], undefined, undefined, 5000);
|
|
61
|
+
available = code === 0;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
available = false;
|
|
65
|
+
}
|
|
66
|
+
this.availabilityCache = { at: now, available };
|
|
67
|
+
return available;
|
|
68
|
+
}
|
|
69
|
+
async healthCheck() {
|
|
70
|
+
const start = Date.now();
|
|
71
|
+
const available = await this.isAvailable();
|
|
72
|
+
const latencyMs = Date.now() - start;
|
|
73
|
+
if (!available) {
|
|
74
|
+
return {
|
|
75
|
+
healthy: false,
|
|
76
|
+
latencyMs,
|
|
77
|
+
error: `Codex CLI ("${this.config.binaryPath}") not found or not runnable. ` +
|
|
78
|
+
`Install Codex and log in with your ChatGPT account (\`codex login\`).`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
healthy: true,
|
|
83
|
+
latencyMs,
|
|
84
|
+
models: this.getSupportedModels(),
|
|
85
|
+
details: { binaryPath: this.config.binaryPath, billing: 'subscription' },
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async generate(input, options) {
|
|
89
|
+
const model = options?.model ?? this.config.model ?? CODEX_DEFAULT_MODEL;
|
|
90
|
+
const requestId = `codex-${++this.requestId}-${Date.now()}`;
|
|
91
|
+
const { prompt } = this.flatten(input, options?.systemPrompt);
|
|
92
|
+
// `codex exec` is agentic; keep it read-only and non-interactive. We capture
|
|
93
|
+
// just the final assistant message via -o <file> to avoid parsing the noisy
|
|
94
|
+
// JSONL event stream.
|
|
95
|
+
const tmp = mkdtempSync(join(tmpdir(), 'aqe-codex-'));
|
|
96
|
+
const outFile = join(tmp, 'last-message.txt');
|
|
97
|
+
const args = [
|
|
98
|
+
'exec',
|
|
99
|
+
'--skip-git-repo-check',
|
|
100
|
+
'--sandbox', 'read-only',
|
|
101
|
+
'-o', outFile,
|
|
102
|
+
];
|
|
103
|
+
if (model && model !== CODEX_DEFAULT_MODEL) {
|
|
104
|
+
args.push('-m', model);
|
|
105
|
+
}
|
|
106
|
+
const start = Date.now();
|
|
107
|
+
const timeoutMs = options?.timeoutMs ?? this.config.timeoutMs ?? 180000;
|
|
108
|
+
try {
|
|
109
|
+
const { code, stderr } = await this.withConcurrency(() => this.runProcess(args, prompt, undefined, timeoutMs));
|
|
110
|
+
const latencyMs = Date.now() - start;
|
|
111
|
+
let content = '';
|
|
112
|
+
try {
|
|
113
|
+
content = readFileSync(outFile, 'utf8').trim();
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
content = '';
|
|
117
|
+
}
|
|
118
|
+
if (code !== 0 && !content) {
|
|
119
|
+
throw this.classifyError(stderr || `codex exited with code ${code}`, model);
|
|
120
|
+
}
|
|
121
|
+
// Subscription: no per-token receipt. Estimate usage from text length for
|
|
122
|
+
// visibility only (≈4 chars/token); marginal monetary cost is $0.
|
|
123
|
+
const promptTokens = Math.ceil(prompt.length / 4);
|
|
124
|
+
const completionTokens = Math.ceil(content.length / 4);
|
|
125
|
+
const usage = {
|
|
126
|
+
promptTokens,
|
|
127
|
+
completionTokens,
|
|
128
|
+
totalTokens: promptTokens + completionTokens,
|
|
129
|
+
cacheCreationTokens: 0,
|
|
130
|
+
cacheReadTokens: 0,
|
|
131
|
+
};
|
|
132
|
+
TokenMetricsCollector.recordTokenUsage(requestId, 'codex-provider', 'llm', 'generate', {
|
|
133
|
+
inputTokens: usage.promptTokens,
|
|
134
|
+
outputTokens: usage.completionTokens,
|
|
135
|
+
totalTokens: usage.totalTokens,
|
|
136
|
+
estimatedCostUsd: 0,
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
content,
|
|
140
|
+
model: model === CODEX_DEFAULT_MODEL ? 'codex-default' : model,
|
|
141
|
+
provider: 'codex',
|
|
142
|
+
usage,
|
|
143
|
+
// Subscription billing: marginal cost is $0 and we know it authoritatively.
|
|
144
|
+
cost: { inputCost: 0, outputCost: 0, totalCost: 0, currency: 'USD', source: 'provider-receipt' },
|
|
145
|
+
latencyMs,
|
|
146
|
+
finishReason: 'stop',
|
|
147
|
+
cached: false,
|
|
148
|
+
requestId,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async embed(_text, _options) {
|
|
156
|
+
throw createLLMError('Codex provider does not support embeddings. Use openai, ollama, or cognitum.', 'MODEL_NOT_FOUND', { provider: 'codex', retryable: false });
|
|
157
|
+
}
|
|
158
|
+
async complete(prompt, options) {
|
|
159
|
+
const response = await this.generate(prompt, {
|
|
160
|
+
model: options?.model,
|
|
161
|
+
temperature: options?.temperature ?? 0.2,
|
|
162
|
+
maxTokens: options?.maxTokens ?? 256,
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
completion: response.content,
|
|
166
|
+
model: response.model,
|
|
167
|
+
provider: 'codex',
|
|
168
|
+
usage: response.usage,
|
|
169
|
+
latencyMs: response.latencyMs,
|
|
170
|
+
cached: response.cached,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
getConfig() {
|
|
174
|
+
return { ...this.config };
|
|
175
|
+
}
|
|
176
|
+
getSupportedModels() {
|
|
177
|
+
// Codex resolves the concrete model from its profile/login; these are the
|
|
178
|
+
// common ids accepted via -m. `default` = whatever the CLI is configured to.
|
|
179
|
+
return [CODEX_DEFAULT_MODEL, 'gpt-5-codex', 'o3', 'o4-mini'];
|
|
180
|
+
}
|
|
181
|
+
getCostPerToken() {
|
|
182
|
+
return { input: 0, output: 0 };
|
|
183
|
+
}
|
|
184
|
+
async dispose() {
|
|
185
|
+
// No persistent resources.
|
|
186
|
+
}
|
|
187
|
+
// -- internals -------------------------------------------------------------
|
|
188
|
+
flatten(input, systemPromptOpt) {
|
|
189
|
+
if (typeof input === 'string') {
|
|
190
|
+
return { prompt: systemPromptOpt ? `${systemPromptOpt}\n\n${input}` : input };
|
|
191
|
+
}
|
|
192
|
+
const systemParts = input.filter((m) => m.role === 'system').map((m) => m.content);
|
|
193
|
+
if (systemPromptOpt)
|
|
194
|
+
systemParts.unshift(systemPromptOpt);
|
|
195
|
+
const convo = input
|
|
196
|
+
.filter((m) => m.role !== 'system')
|
|
197
|
+
.map((m) => `${m.role === 'assistant' ? 'Assistant' : 'User'}: ${m.content}`)
|
|
198
|
+
.join('\n\n');
|
|
199
|
+
const preamble = systemParts.length > 0 ? `${systemParts.join('\n\n')}\n\n` : '';
|
|
200
|
+
return { prompt: `${preamble}${convo}` };
|
|
201
|
+
}
|
|
202
|
+
classifyError(message, model) {
|
|
203
|
+
const lower = message.toLowerCase();
|
|
204
|
+
if (lower.includes('rate limit') ||
|
|
205
|
+
lower.includes('usage limit') ||
|
|
206
|
+
lower.includes('429') ||
|
|
207
|
+
lower.includes('quota')) {
|
|
208
|
+
return createLLMError(message, 'RATE_LIMITED', {
|
|
209
|
+
provider: 'codex',
|
|
210
|
+
model,
|
|
211
|
+
retryable: true,
|
|
212
|
+
retryAfterMs: 60_000,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
return createLLMError(message, 'PROVIDER_UNAVAILABLE', {
|
|
216
|
+
provider: 'codex',
|
|
217
|
+
model,
|
|
218
|
+
retryable: true,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Build the child env with API-billing keys stripped (LOAD-BEARING).
|
|
223
|
+
* Exported logic tested by parity/env-strip tests.
|
|
224
|
+
*/
|
|
225
|
+
static childEnv(base = process.env) {
|
|
226
|
+
const env = { ...base };
|
|
227
|
+
for (const key of API_BILLING_ENV_VARS) {
|
|
228
|
+
delete env[key];
|
|
229
|
+
}
|
|
230
|
+
return env;
|
|
231
|
+
}
|
|
232
|
+
runProcess(args, stdin, _unused, timeoutMs) {
|
|
233
|
+
return new Promise((resolve, reject) => {
|
|
234
|
+
const child = spawn(this.config.binaryPath ?? 'codex', args, {
|
|
235
|
+
env: CodexProvider.childEnv(),
|
|
236
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
237
|
+
});
|
|
238
|
+
let stdout = '';
|
|
239
|
+
let stderr = '';
|
|
240
|
+
let settled = false;
|
|
241
|
+
const timer = setTimeout(() => {
|
|
242
|
+
if (settled)
|
|
243
|
+
return;
|
|
244
|
+
settled = true;
|
|
245
|
+
child.kill('SIGKILL');
|
|
246
|
+
reject(createLLMError('codex exec timed out', 'TIMEOUT', {
|
|
247
|
+
provider: 'codex',
|
|
248
|
+
retryable: true,
|
|
249
|
+
}));
|
|
250
|
+
}, timeoutMs);
|
|
251
|
+
child.stdout.on('data', (d) => (stdout += d.toString()));
|
|
252
|
+
child.stderr.on('data', (d) => (stderr += d.toString()));
|
|
253
|
+
child.on('error', (err) => {
|
|
254
|
+
if (settled)
|
|
255
|
+
return;
|
|
256
|
+
settled = true;
|
|
257
|
+
clearTimeout(timer);
|
|
258
|
+
reject(createLLMError(`Failed to spawn codex: ${err.message}`, 'PROVIDER_UNAVAILABLE', {
|
|
259
|
+
provider: 'codex',
|
|
260
|
+
retryable: false,
|
|
261
|
+
cause: err,
|
|
262
|
+
}));
|
|
263
|
+
});
|
|
264
|
+
child.on('close', (code) => {
|
|
265
|
+
if (settled)
|
|
266
|
+
return;
|
|
267
|
+
settled = true;
|
|
268
|
+
clearTimeout(timer);
|
|
269
|
+
resolve({ code: code ?? 0, stdout, stderr });
|
|
270
|
+
});
|
|
271
|
+
// EPIPE guard: if codex exits before reading stdin (e.g. not logged in),
|
|
272
|
+
// the write/end can emit 'error' on the stdin stream. Without a listener
|
|
273
|
+
// Node throws an uncaught exception that crashes the calling process. The
|
|
274
|
+
// 'close'/'error' handlers above already capture the real outcome.
|
|
275
|
+
child.stdin.on('error', () => { });
|
|
276
|
+
try {
|
|
277
|
+
if (stdin !== undefined) {
|
|
278
|
+
child.stdin.write(stdin);
|
|
279
|
+
}
|
|
280
|
+
child.stdin.end();
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
/* stream already torn down — the process handlers report the failure */
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/** Simple semaphore so we don't spawn unbounded `codex` subprocesses. */
|
|
288
|
+
async withConcurrency(fn) {
|
|
289
|
+
const limit = this.config.maxConcurrency ?? 2;
|
|
290
|
+
if (this.active >= limit) {
|
|
291
|
+
await new Promise((resolve) => this.queue.push(resolve));
|
|
292
|
+
}
|
|
293
|
+
this.active++;
|
|
294
|
+
try {
|
|
295
|
+
return await fn();
|
|
296
|
+
}
|
|
297
|
+
finally {
|
|
298
|
+
this.active--;
|
|
299
|
+
const next = this.queue.shift();
|
|
300
|
+
if (next)
|
|
301
|
+
next();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { ClaudeProvider, DEFAULT_CLAUDE_CONFIG } from './claude';
|
|
6
6
|
export { ClaudeCodeProvider, DEFAULT_CLAUDE_CODE_CONFIG, API_BILLING_ENV_VARS, type ClaudeCodeConfig, } from './claude-code';
|
|
7
|
+
export { CodexProvider, DEFAULT_CODEX_CONFIG, CODEX_DEFAULT_MODEL, type CodexConfig, } from './codex';
|
|
7
8
|
export { CognitumProvider, DEFAULT_COGNITUM_CONFIG, type CognitumConfig, type CognitumBudget, } from './cognitum';
|
|
8
9
|
export { OpenAIProvider, DEFAULT_OPENAI_CONFIG } from './openai';
|
|
9
10
|
export { OllamaProvider, DEFAULT_OLLAMA_CONFIG } from './ollama';
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { ClaudeProvider, DEFAULT_CLAUDE_CONFIG } from './claude';
|
|
6
6
|
export { ClaudeCodeProvider, DEFAULT_CLAUDE_CODE_CONFIG, API_BILLING_ENV_VARS, } from './claude-code';
|
|
7
|
+
export { CodexProvider, DEFAULT_CODEX_CONFIG, CODEX_DEFAULT_MODEL, } from './codex';
|
|
7
8
|
export { CognitumProvider, DEFAULT_COGNITUM_CONFIG, } from './cognitum';
|
|
8
9
|
export { OpenAIProvider, DEFAULT_OPENAI_CONFIG } from './openai';
|
|
9
10
|
export { OllamaProvider, DEFAULT_OLLAMA_CONFIG } from './ollama';
|
|
@@ -39,6 +39,10 @@ const PROVIDER_ENV_KEYS = {
|
|
|
39
39
|
// availability is gated on the `claude` binary being on PATH (see the
|
|
40
40
|
// provider's isAvailable()).
|
|
41
41
|
'claude-code': [],
|
|
42
|
+
// ADR-124 M3.5: codex authenticates via the user's ChatGPT login
|
|
43
|
+
// (subscription), NOT an env key. Availability is gated on the `codex`
|
|
44
|
+
// binary being on PATH (see the provider's isAvailable()).
|
|
45
|
+
codex: [],
|
|
42
46
|
openai: ['OPENAI_API_KEY'],
|
|
43
47
|
ollama: [], // ollama is local; no key required
|
|
44
48
|
openrouter: ['OPENROUTER_API_KEY'],
|
|
@@ -59,6 +63,7 @@ const PROVIDER_ENV_KEYS = {
|
|
|
59
63
|
const RUNTIME_CONSTRUCTIBLE_PROVIDERS = new Set([
|
|
60
64
|
'claude',
|
|
61
65
|
'claude-code',
|
|
66
|
+
'codex',
|
|
62
67
|
'openai',
|
|
63
68
|
'ollama',
|
|
64
69
|
'openrouter',
|
|
@@ -518,8 +518,8 @@ export class HybridRouter {
|
|
|
518
518
|
metadata: params.metadata,
|
|
519
519
|
});
|
|
520
520
|
// ADR-123: persist the charge to the cross-process ledger so budgets
|
|
521
|
-
// hold across a fleet of processes.
|
|
522
|
-
this.providerManager.recordResponseSpend(response);
|
|
521
|
+
// hold across a fleet of processes. ADR-124 M2.3: attribute to the agent.
|
|
522
|
+
this.providerManager.recordResponseSpend(response, params.agentType);
|
|
523
523
|
const callLatency = Date.now() - callStartTime;
|
|
524
524
|
// Record success in legacy tracker
|
|
525
525
|
this.metrics.recordSuccess(providerType);
|
|
@@ -28,6 +28,12 @@ export interface SpendEntry {
|
|
|
28
28
|
promptTokens: number;
|
|
29
29
|
completionTokens: number;
|
|
30
30
|
requestId: string;
|
|
31
|
+
/**
|
|
32
|
+
* ADR-124 M2.3: the QE agent type/name this charge is attributed to (e.g.
|
|
33
|
+
* 'qe-security-scanner'). Optional — null when the call site has no agent
|
|
34
|
+
* context. Enables per-agent cost attribution across the fleet.
|
|
35
|
+
*/
|
|
36
|
+
agent?: string;
|
|
31
37
|
}
|
|
32
38
|
/** Cross-process spend ledger. */
|
|
33
39
|
export interface SpendLedger {
|
|
@@ -35,16 +41,33 @@ export interface SpendLedger {
|
|
|
35
41
|
record(entry: SpendEntry): void;
|
|
36
42
|
/** Total USD charged within the last `windowMs` (rolling window ending now). */
|
|
37
43
|
spentSince(windowMs: number, nowMs?: number): number;
|
|
44
|
+
/**
|
|
45
|
+
* ADR-124 M2.3: USD charged within the last `windowMs`, broken down by agent
|
|
46
|
+
* type. Charges with no agent are grouped under '(unattributed)'.
|
|
47
|
+
*/
|
|
48
|
+
spentByAgentSince(windowMs: number, nowMs?: number): Record<string, number>;
|
|
38
49
|
}
|
|
50
|
+
/** Bucket used for charges recorded without an agent context. */
|
|
51
|
+
export declare const UNATTRIBUTED_AGENT = "(unattributed)";
|
|
39
52
|
/**
|
|
40
53
|
* SQLite-backed ledger. Cross-process because every process opens its own
|
|
41
54
|
* connection to the same WAL-mode `memory.db`.
|
|
42
55
|
*/
|
|
43
56
|
export declare class SqliteSpendLedger implements SpendLedger {
|
|
44
57
|
private readonly db;
|
|
58
|
+
/**
|
|
59
|
+
* Whether the `agent_type` column exists. If the additive migration couldn't
|
|
60
|
+
* run (e.g. transient lock), this stays false and record() INSERTs WITHOUT the
|
|
61
|
+
* column — so spend is still recorded and the ADR-123 budget cap still holds.
|
|
62
|
+
* A qe-court review (ADR-124) caught the original bug: a swallowed migration
|
|
63
|
+
* made every INSERT reference a missing column, throw, get caught, and silently
|
|
64
|
+
* drop ALL spend — bypassing the budget cap (the #557 class).
|
|
65
|
+
*/
|
|
66
|
+
private hasAgentColumn;
|
|
45
67
|
constructor(db: DatabaseType);
|
|
46
68
|
record(entry: SpendEntry): void;
|
|
47
69
|
spentSince(windowMs: number, nowMs?: number): number;
|
|
70
|
+
spentByAgentSince(windowMs: number, nowMs?: number): Record<string, number>;
|
|
48
71
|
}
|
|
49
72
|
/**
|
|
50
73
|
* In-process fallback ledger. Used when no unified DB is available. Enforces
|
|
@@ -54,6 +77,7 @@ export declare class InMemorySpendLedger implements SpendLedger {
|
|
|
54
77
|
private readonly entries;
|
|
55
78
|
record(entry: SpendEntry): void;
|
|
56
79
|
spentSince(windowMs: number, nowMs?: number): number;
|
|
80
|
+
spentByAgentSince(windowMs: number, nowMs?: number): Record<string, number>;
|
|
57
81
|
}
|
|
58
82
|
/**
|
|
59
83
|
* Build the default ledger. Prefers the unified `memory.db` (cross-process);
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
* connections (one per process) to a WAL-mode DB is exactly the supported
|
|
18
18
|
* cross-process pattern.
|
|
19
19
|
*/
|
|
20
|
+
/** Bucket used for charges recorded without an agent context. */
|
|
21
|
+
export const UNATTRIBUTED_AGENT = '(unattributed)';
|
|
20
22
|
const CREATE_TABLE_SQL = `
|
|
21
23
|
CREATE TABLE IF NOT EXISTS llm_spend (
|
|
22
24
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -37,27 +39,72 @@ CREATE INDEX IF NOT EXISTS idx_llm_spend_ts ON llm_spend(ts);
|
|
|
37
39
|
*/
|
|
38
40
|
export class SqliteSpendLedger {
|
|
39
41
|
db;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the `agent_type` column exists. If the additive migration couldn't
|
|
44
|
+
* run (e.g. transient lock), this stays false and record() INSERTs WITHOUT the
|
|
45
|
+
* column — so spend is still recorded and the ADR-123 budget cap still holds.
|
|
46
|
+
* A qe-court review (ADR-124) caught the original bug: a swallowed migration
|
|
47
|
+
* made every INSERT reference a missing column, throw, get caught, and silently
|
|
48
|
+
* drop ALL spend — bypassing the budget cap (the #557 class).
|
|
49
|
+
*/
|
|
50
|
+
hasAgentColumn = false;
|
|
40
51
|
constructor(db) {
|
|
41
52
|
this.db = db;
|
|
42
53
|
// Additive schema only — CREATE TABLE/INDEX IF NOT EXISTS never drops data.
|
|
43
54
|
this.db.exec(CREATE_TABLE_SQL);
|
|
55
|
+
// ADR-124 M2.3: additive `agent_type` column for per-agent attribution.
|
|
56
|
+
// ALTER TABLE ADD COLUMN is non-destructive (existing rows get NULL); guarded
|
|
57
|
+
// so re-opening an already-migrated DB is a no-op. Never drops or rewrites.
|
|
58
|
+
try {
|
|
59
|
+
const cols = this.db.prepare(`PRAGMA table_info(llm_spend)`).all();
|
|
60
|
+
if (!cols.some((c) => c.name === 'agent_type')) {
|
|
61
|
+
this.db.exec(`ALTER TABLE llm_spend ADD COLUMN agent_type TEXT`);
|
|
62
|
+
}
|
|
63
|
+
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_llm_spend_agent ON llm_spend(agent_type)`);
|
|
64
|
+
this.hasAgentColumn = true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Attribution is best-effort; never block ledger use on the migration.
|
|
68
|
+
// hasAgentColumn stays false → record() degrades to un-attributed INSERTs.
|
|
69
|
+
}
|
|
44
70
|
}
|
|
45
71
|
record(entry) {
|
|
46
72
|
try {
|
|
47
|
-
this.
|
|
48
|
-
.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
73
|
+
if (this.hasAgentColumn) {
|
|
74
|
+
this.db
|
|
75
|
+
.prepare(`INSERT INTO llm_spend
|
|
76
|
+
(ts, provider, model, cost_usd, cost_source, prompt_tokens, completion_tokens, request_id, agent_type)
|
|
77
|
+
VALUES (@ts, @provider, @model, @cost_usd, @cost_source, @prompt_tokens, @completion_tokens, @request_id, @agent_type)`)
|
|
78
|
+
.run({
|
|
79
|
+
ts: Date.now(),
|
|
80
|
+
provider: entry.provider,
|
|
81
|
+
model: entry.model,
|
|
82
|
+
cost_usd: entry.costUsd,
|
|
83
|
+
cost_source: entry.costSource,
|
|
84
|
+
prompt_tokens: entry.promptTokens,
|
|
85
|
+
completion_tokens: entry.completionTokens,
|
|
86
|
+
request_id: entry.requestId,
|
|
87
|
+
agent_type: entry.agent ?? null,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Column absent (migration couldn't run) — still record spend so the
|
|
92
|
+
// budget cap holds; just without per-agent attribution.
|
|
93
|
+
this.db
|
|
94
|
+
.prepare(`INSERT INTO llm_spend
|
|
95
|
+
(ts, provider, model, cost_usd, cost_source, prompt_tokens, completion_tokens, request_id)
|
|
96
|
+
VALUES (@ts, @provider, @model, @cost_usd, @cost_source, @prompt_tokens, @completion_tokens, @request_id)`)
|
|
97
|
+
.run({
|
|
98
|
+
ts: Date.now(),
|
|
99
|
+
provider: entry.provider,
|
|
100
|
+
model: entry.model,
|
|
101
|
+
cost_usd: entry.costUsd,
|
|
102
|
+
cost_source: entry.costSource,
|
|
103
|
+
prompt_tokens: entry.promptTokens,
|
|
104
|
+
completion_tokens: entry.completionTokens,
|
|
105
|
+
request_id: entry.requestId,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
61
108
|
}
|
|
62
109
|
catch {
|
|
63
110
|
// A ledger write must never break a generation call.
|
|
@@ -74,6 +121,21 @@ export class SqliteSpendLedger {
|
|
|
74
121
|
return 0;
|
|
75
122
|
}
|
|
76
123
|
}
|
|
124
|
+
spentByAgentSince(windowMs, nowMs = Date.now()) {
|
|
125
|
+
try {
|
|
126
|
+
const rows = this.db
|
|
127
|
+
.prepare(`SELECT COALESCE(agent_type, ?) AS agent, COALESCE(SUM(cost_usd), 0) AS total
|
|
128
|
+
FROM llm_spend WHERE ts >= ? GROUP BY COALESCE(agent_type, ?)`)
|
|
129
|
+
.all(UNATTRIBUTED_AGENT, nowMs - windowMs, UNATTRIBUTED_AGENT);
|
|
130
|
+
const out = {};
|
|
131
|
+
for (const r of rows)
|
|
132
|
+
out[r.agent] = r.total;
|
|
133
|
+
return out;
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return {};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
77
139
|
}
|
|
78
140
|
/**
|
|
79
141
|
* In-process fallback ledger. Used when no unified DB is available. Enforces
|
|
@@ -82,7 +144,7 @@ export class SqliteSpendLedger {
|
|
|
82
144
|
export class InMemorySpendLedger {
|
|
83
145
|
entries = [];
|
|
84
146
|
record(entry) {
|
|
85
|
-
this.entries.push({ ts: Date.now(), costUsd: entry.costUsd });
|
|
147
|
+
this.entries.push({ ts: Date.now(), costUsd: entry.costUsd, agent: entry.agent ?? UNATTRIBUTED_AGENT });
|
|
86
148
|
}
|
|
87
149
|
spentSince(windowMs, nowMs = Date.now()) {
|
|
88
150
|
const cutoff = nowMs - windowMs;
|
|
@@ -93,6 +155,15 @@ export class InMemorySpendLedger {
|
|
|
93
155
|
}
|
|
94
156
|
return total;
|
|
95
157
|
}
|
|
158
|
+
spentByAgentSince(windowMs, nowMs = Date.now()) {
|
|
159
|
+
const cutoff = nowMs - windowMs;
|
|
160
|
+
const out = {};
|
|
161
|
+
for (const e of this.entries) {
|
|
162
|
+
if (e.ts >= cutoff)
|
|
163
|
+
out[e.agent] = (out[e.agent] ?? 0) + e.costUsd;
|
|
164
|
+
}
|
|
165
|
+
return out;
|
|
166
|
+
}
|
|
96
167
|
}
|
|
97
168
|
/**
|
|
98
169
|
* Build the default ledger. Prefers the unified `memory.db` (cross-process);
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
const SYSTEM_PROMPT_STRATEGIES = {
|
|
17
17
|
claude: 'native', // Anthropic supports separate system param
|
|
18
18
|
'claude-code': 'native', // ADR-123: passed via --append-system-prompt
|
|
19
|
+
codex: 'native', // ADR-124 M3.5: provider flattens system into the prompt
|
|
19
20
|
openai: 'native', // OpenAI supports system role messages
|
|
20
21
|
ollama: 'native', // Ollama supports system role
|
|
21
22
|
openrouter: 'native', // OpenRouter passes through to underlying provider
|
package/dist/shared/safe-db.d.ts
CHANGED
|
@@ -18,6 +18,16 @@ export interface SafeDbOptions {
|
|
|
18
18
|
busyTimeout?: number;
|
|
19
19
|
/** Enable WAL mode (default: true for writable, false for readonly) */
|
|
20
20
|
walMode?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* M3.2: on a malformed/corrupt existing DB, auto-restore the newest verified
|
|
23
|
+
* backup (from `.agentic-qe/backups/verified/`) and park the corrupt original,
|
|
24
|
+
* instead of opening a broken DB. Default false; enable for the unified
|
|
25
|
+
* `memory.db` open. Non-destructive: the corrupt file is renamed, never deleted,
|
|
26
|
+
* and nothing happens if no verified backup exists. Ignored for readonly opens.
|
|
27
|
+
*/
|
|
28
|
+
autoRestore?: boolean;
|
|
29
|
+
/** Override the verified-backup directory used by autoRestore. */
|
|
30
|
+
backupDir?: string;
|
|
21
31
|
}
|
|
22
32
|
/**
|
|
23
33
|
* Open a SQLite database with safe defaults that prevent corruption.
|
package/dist/shared/safe-db.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* WAL or busy_timeout. When multiple hook processes ran concurrently, the DB corrupted.
|
|
10
10
|
*/
|
|
11
11
|
import Database from 'better-sqlite3';
|
|
12
|
+
import { attemptAutoRestore } from './db-recovery.js';
|
|
12
13
|
/**
|
|
13
14
|
* Open a SQLite database with safe defaults that prevent corruption.
|
|
14
15
|
*
|
|
@@ -23,6 +24,22 @@ export function openDatabase(dbPath, opts) {
|
|
|
23
24
|
const fileMustExist = opts?.fileMustExist ?? false;
|
|
24
25
|
const busyTimeout = opts?.busyTimeout ?? 5000;
|
|
25
26
|
const walMode = opts?.walMode ?? !readonly;
|
|
27
|
+
// M3.2: recover a malformed DB from a verified backup BEFORE opening it, so a
|
|
28
|
+
// corrupt memory.db self-heals instead of surfacing errors on first query.
|
|
29
|
+
// Non-destructive + no-op unless enabled and actually needed.
|
|
30
|
+
if (opts?.autoRestore && !readonly) {
|
|
31
|
+
const result = attemptAutoRestore(dbPath, { backupDir: opts.backupDir });
|
|
32
|
+
if (result.restored) {
|
|
33
|
+
console.warn(`[safe-db] memory DB at ${dbPath} was malformed; auto-restored from ` +
|
|
34
|
+
`${result.backupUsed}. Corrupt original parked at ${result.parkedTo}.`);
|
|
35
|
+
}
|
|
36
|
+
else if (result.reason === 'no-verified-backup') {
|
|
37
|
+
// Reached only when the DB is malformed (attemptAutoRestore short-circuits
|
|
38
|
+
// 'healthy' first) — corrupt AND no backup to restore from.
|
|
39
|
+
console.error(`[safe-db] memory DB at ${dbPath} appears malformed and NO verified backup ` +
|
|
40
|
+
`was found to restore from. Leaving it in place for manual inspection.`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
26
43
|
// Environment override for filesystems where WAL is UNSAFE. WAL prevents
|
|
27
44
|
// concurrent-writer corruption on a normal filesystem, but on a macOS
|
|
28
45
|
// Docker/virtiofs bind mount the `-shm` mmap coherence across the
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QE-Court referee (ADR-124) — the falsifiable core of the adversarial court,
|
|
3
|
+
* as pure, deterministic functions so the court's invariants are ENFORCED in
|
|
4
|
+
* code (and unit-testable as oracles), not merely described in the skill doc.
|
|
5
|
+
*
|
|
6
|
+
* These back the qe-court acceptance eval (`.claude/skills/qe-court/evals`):
|
|
7
|
+
* - verdict resolution + the overturn mechanic (SHIP must survive escalation)
|
|
8
|
+
* - panel validation (writer≠juror, vendor diversity)
|
|
9
|
+
* - DoE-gated scoring (no un-validated numeric score)
|
|
10
|
+
*
|
|
11
|
+
* No I/O, no LLM calls — the orchestration (spawning prosecutors, calling the
|
|
12
|
+
* two-gate judge) lives in the skill; the RULES live here.
|
|
13
|
+
*/
|
|
14
|
+
export type Verdict = 'SHIP' | 'REMAND' | 'BLOCK';
|
|
15
|
+
/** Coarse model vendor — diversity is measured across vendors, not tiers. */
|
|
16
|
+
export type Vendor = 'claude' | 'cognitum' | 'gpt' | 'openrouter' | 'local' | 'unknown';
|
|
17
|
+
/** A charge filed by a prosecutor (or surfaced by a deeper reviewer). */
|
|
18
|
+
export interface Charge {
|
|
19
|
+
id: string;
|
|
20
|
+
/** A fatal charge blocks the ship; a non-fatal charge remands it. */
|
|
21
|
+
fatal: boolean;
|
|
22
|
+
/** Did the charge reproduce (oracle-grade) rather than stay a claim? */
|
|
23
|
+
reproduced: boolean;
|
|
24
|
+
/** Overturn depth at which it was surfaced (0 = base panel, ≥1 = deeper rounds). */
|
|
25
|
+
depthFound: number;
|
|
26
|
+
}
|
|
27
|
+
export interface PanelSeat {
|
|
28
|
+
role: string;
|
|
29
|
+
provider: string;
|
|
30
|
+
}
|
|
31
|
+
/** Map a provider id to its coarse vendor. */
|
|
32
|
+
export declare function vendorOf(providerId: string): Vendor;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the verdict from the surviving charges, applying the overturn window.
|
|
35
|
+
*
|
|
36
|
+
* THE OVERTURN MECHANIC: only charges surfaced at depth ≤ `overturnDepth` count.
|
|
37
|
+
* With `overturnDepth = 0` the deeper-review rounds are disabled, so a mutant a
|
|
38
|
+
* shallow pass missed (surfaced at depth ≥ 1) does NOT count and the verdict
|
|
39
|
+
* stays SHIP — which is exactly the false-SHIP the court exists to catch. With
|
|
40
|
+
* `overturnDepth ≥ 1` that same charge counts and flips the verdict. This
|
|
41
|
+
* asymmetry is the whole point: a SHIP must SURVIVE escalation.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveVerdict(charges: Charge[], overturnDepth: number): Verdict;
|
|
44
|
+
export interface PanelPolicy {
|
|
45
|
+
/** Minimum number of DISTINCT vendors on the panel (default 2). */
|
|
46
|
+
minVendors?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Validate a seated panel against the court's anti-collusion invariants.
|
|
50
|
+
* Returns a list of violation codes (empty == valid).
|
|
51
|
+
* - 'writerIsNeverJuror' : the jury shares a vendor with the writer/defense.
|
|
52
|
+
* - 'vendor-diversity' : fewer than `minVendors` distinct vendors seated.
|
|
53
|
+
*/
|
|
54
|
+
export declare function validatePanel(panel: PanelSeat[], policy?: PanelPolicy): string[];
|
|
55
|
+
/**
|
|
56
|
+
* DoE-gated scoring: emit a numeric score ONLY when the operator asked for one
|
|
57
|
+
* AND the scoring rubric passed the ADR-122 ANOVA screen (it actually
|
|
58
|
+
* discriminates). Otherwise the court reports the verdict class + charges, never
|
|
59
|
+
* a noise "91/100".
|
|
60
|
+
*/
|
|
61
|
+
export declare function shouldEmitScore(rubricDoePassed: boolean, emitScore: boolean): boolean;
|
|
62
|
+
//# sourceMappingURL=referee.d.ts.map
|