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
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Follows the OpenCode/Kiro installer pattern (ADR-025).
|
|
7
7
|
*/
|
|
8
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
8
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync, } from 'fs';
|
|
9
9
|
import { join, dirname } from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
10
11
|
import { toErrorMessage } from '../shared/error-utils.js';
|
|
11
12
|
import { createPlatformConfigGenerator, } from './platform-config-generator.js';
|
|
12
13
|
// ============================================================================
|
|
@@ -28,9 +29,13 @@ export class CodexInstaller {
|
|
|
28
29
|
success: true,
|
|
29
30
|
mcpConfigured: false,
|
|
30
31
|
agentsMdInstalled: false,
|
|
32
|
+
hooksConfigured: false,
|
|
33
|
+
skillsInstalled: 0,
|
|
31
34
|
errors: [],
|
|
32
35
|
configPath: '',
|
|
33
36
|
agentsMdPath: '',
|
|
37
|
+
hooksPath: join(this.projectRoot, '.codex', 'hooks.json'),
|
|
38
|
+
skillsPath: join(this.projectRoot, '.agents', 'skills'),
|
|
34
39
|
};
|
|
35
40
|
try {
|
|
36
41
|
// Generate TOML MCP config
|
|
@@ -65,6 +70,8 @@ export class CodexInstaller {
|
|
|
65
70
|
}
|
|
66
71
|
result.agentsMdInstalled = true;
|
|
67
72
|
}
|
|
73
|
+
this.installCodexHooks(result);
|
|
74
|
+
result.skillsInstalled = this.installCodexSkills();
|
|
68
75
|
}
|
|
69
76
|
catch (error) {
|
|
70
77
|
result.success = false;
|
|
@@ -72,6 +79,120 @@ export class CodexInstaller {
|
|
|
72
79
|
}
|
|
73
80
|
return result;
|
|
74
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Install Codex-native lifecycle adapters and merge AQE/ruflo hook groups
|
|
84
|
+
* without removing user-defined hooks.
|
|
85
|
+
*/
|
|
86
|
+
installCodexHooks(result) {
|
|
87
|
+
const sourceRoot = this.resolvePackageRoot();
|
|
88
|
+
if (!sourceRoot)
|
|
89
|
+
return;
|
|
90
|
+
const sourceConfig = join(sourceRoot, '.codex', 'hooks.json');
|
|
91
|
+
const sourceScripts = join(sourceRoot, '.codex', 'hooks');
|
|
92
|
+
if (!existsSync(sourceConfig) || !existsSync(sourceScripts))
|
|
93
|
+
return;
|
|
94
|
+
const targetCodexDir = join(this.projectRoot, '.codex');
|
|
95
|
+
const targetScripts = join(targetCodexDir, 'hooks');
|
|
96
|
+
mkdirSync(targetScripts, { recursive: true });
|
|
97
|
+
for (const file of readdirSync(sourceScripts)) {
|
|
98
|
+
const source = join(sourceScripts, file);
|
|
99
|
+
if (!statSync(source).isFile())
|
|
100
|
+
continue;
|
|
101
|
+
const target = join(targetScripts, file);
|
|
102
|
+
if (!existsSync(target) || this.overwrite) {
|
|
103
|
+
copyFileSync(source, target);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const runtimes = [
|
|
107
|
+
{
|
|
108
|
+
source: join(sourceRoot, '.claude', 'hooks', 'aqe-hook.cjs'),
|
|
109
|
+
target: join(targetScripts, 'aqe-runtime.cjs'),
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
source: join(sourceRoot, '.claude', 'helpers', 'ruflo-hook.cjs'),
|
|
113
|
+
target: join(targetScripts, 'ruflo-runtime.cjs'),
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
for (const runtime of runtimes) {
|
|
117
|
+
if (existsSync(runtime.source) && (!existsSync(runtime.target) || this.overwrite)) {
|
|
118
|
+
copyFileSync(runtime.source, runtime.target);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const generated = JSON.parse(readFileSync(sourceConfig, 'utf-8'));
|
|
122
|
+
const targetConfig = join(targetCodexDir, 'hooks.json');
|
|
123
|
+
if (!existsSync(targetConfig)) {
|
|
124
|
+
writeFileSync(targetConfig, JSON.stringify(generated, null, 2) + '\n');
|
|
125
|
+
result.hooksConfigured = true;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (!this.overwrite)
|
|
129
|
+
return;
|
|
130
|
+
const existing = JSON.parse(readFileSync(targetConfig, 'utf-8'));
|
|
131
|
+
const owned = (value) => JSON.stringify(value).includes('/.codex/hooks/aqe-codex-hook.cjs')
|
|
132
|
+
|| JSON.stringify(value).includes('/.codex/hooks/ruflo-codex-hook.cjs');
|
|
133
|
+
const mergedHooks = {};
|
|
134
|
+
const events = new Set([
|
|
135
|
+
...Object.keys(existing.hooks || {}),
|
|
136
|
+
...Object.keys(generated.hooks || {}),
|
|
137
|
+
]);
|
|
138
|
+
for (const event of events) {
|
|
139
|
+
const userGroups = (existing.hooks?.[event] || []).filter((group) => !owned(group));
|
|
140
|
+
mergedHooks[event] = [...userGroups, ...(generated.hooks?.[event] || [])];
|
|
141
|
+
}
|
|
142
|
+
writeFileSync(targetConfig, JSON.stringify({ ...existing, description: generated.description, hooks: mergedHooks }, null, 2) + '\n');
|
|
143
|
+
result.hooksConfigured = true;
|
|
144
|
+
}
|
|
145
|
+
/** Install the curated repo-scoped AQE skills Codex discovers automatically. */
|
|
146
|
+
installCodexSkills() {
|
|
147
|
+
const sourceRoot = this.resolvePackageRoot();
|
|
148
|
+
if (!sourceRoot)
|
|
149
|
+
return 0;
|
|
150
|
+
const sourceSkills = join(sourceRoot, '.agents', 'skills');
|
|
151
|
+
if (!existsSync(sourceSkills))
|
|
152
|
+
return 0;
|
|
153
|
+
const targetSkills = join(this.projectRoot, '.agents', 'skills');
|
|
154
|
+
mkdirSync(targetSkills, { recursive: true });
|
|
155
|
+
let installed = 0;
|
|
156
|
+
for (const skill of readdirSync(sourceSkills)) {
|
|
157
|
+
if (!skill.startsWith('aqe-'))
|
|
158
|
+
continue;
|
|
159
|
+
const source = join(sourceSkills, skill);
|
|
160
|
+
if (!statSync(source).isDirectory())
|
|
161
|
+
continue;
|
|
162
|
+
const target = join(targetSkills, skill);
|
|
163
|
+
if (existsSync(target) && !this.overwrite)
|
|
164
|
+
continue;
|
|
165
|
+
this.copyDirectory(source, target);
|
|
166
|
+
installed++;
|
|
167
|
+
}
|
|
168
|
+
return installed;
|
|
169
|
+
}
|
|
170
|
+
copyDirectory(source, target) {
|
|
171
|
+
mkdirSync(target, { recursive: true });
|
|
172
|
+
for (const entry of readdirSync(source)) {
|
|
173
|
+
const from = join(source, entry);
|
|
174
|
+
const to = join(target, entry);
|
|
175
|
+
if (statSync(from).isDirectory()) {
|
|
176
|
+
this.copyDirectory(from, to);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
copyFileSync(from, to);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
resolvePackageRoot() {
|
|
184
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
185
|
+
const candidates = [
|
|
186
|
+
join(moduleDir, '..', '..'),
|
|
187
|
+
// esbuild bundles this module into dist/cli/bundle.js, so import.meta.url
|
|
188
|
+
// no longer identifies src/init/codex-installer.ts. Resolve from the
|
|
189
|
+
// running CLI entrypoint as the authoritative packaged layout.
|
|
190
|
+
join(dirname(process.argv[1] || ''), '..', '..'),
|
|
191
|
+
join(this.projectRoot, 'node_modules', 'agentic-qe'),
|
|
192
|
+
];
|
|
193
|
+
return candidates.find((candidate) => existsSync(join(candidate, '.codex', 'hooks.json'))
|
|
194
|
+
|| existsSync(join(candidate, '.agents', 'skills')));
|
|
195
|
+
}
|
|
75
196
|
/**
|
|
76
197
|
* Merge AQE MCP server config into existing TOML.
|
|
77
198
|
* Simple approach: if [mcp_servers.agentic-qe] already exists, skip.
|
|
@@ -303,6 +303,10 @@ export class AssetsPhase extends BasePhase {
|
|
|
303
303
|
context.services.log(` Codex MCP: ${res.configPath}`);
|
|
304
304
|
if (res.agentsMdInstalled)
|
|
305
305
|
context.services.log(` Codex AGENTS.md: ${res.agentsMdPath}`);
|
|
306
|
+
if (res.hooksConfigured)
|
|
307
|
+
context.services.log(` Codex hooks: ${res.hooksPath}`);
|
|
308
|
+
if (res.skillsInstalled > 0)
|
|
309
|
+
context.services.log(` Codex skills: ${res.skillsInstalled} installed`);
|
|
306
310
|
}
|
|
307
311
|
if (options.withWindsurf || (options.autoMode && existsSync(join(projectRoot, '.windsurf')))) {
|
|
308
312
|
const { createWindsurfInstaller } = await import('../windsurf-installer.js');
|
|
@@ -119,7 +119,7 @@ export interface InitOptions {
|
|
|
119
119
|
withKiloCode?: boolean;
|
|
120
120
|
/** Install Roo Code MCP config and custom mode */
|
|
121
121
|
withRooCode?: boolean;
|
|
122
|
-
/** Install OpenAI Codex CLI MCP
|
|
122
|
+
/** Install OpenAI Codex CLI MCP, AGENTS.md, hooks, and QE skills */
|
|
123
123
|
withCodex?: boolean;
|
|
124
124
|
/** Install Windsurf MCP config and rules */
|
|
125
125
|
withWindsurf?: boolean;
|
|
@@ -30,6 +30,7 @@ const V3_DOMAIN_SKILLS = [
|
|
|
30
30
|
'qe-visual-accessibility', // Visual regression, WCAG
|
|
31
31
|
'qe-chaos-resilience', // Fault injection, resilience
|
|
32
32
|
'qe-learning-optimization', // Transfer learning, self-improvement
|
|
33
|
+
'qe-court', // Adversarial review court — overturn-gated SHIP/REMAND/BLOCK verdict (ADR-124)
|
|
33
34
|
// V3 utilities
|
|
34
35
|
'qe-iterative-loop', // QE iteration patterns
|
|
35
36
|
// New skills (ADR-086 skill design standards)
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
* @module integrations/embeddings/base/EmbeddingGenerator
|
|
12
12
|
*/
|
|
13
13
|
import { EmbeddingCache } from '../cache/EmbeddingCache.js';
|
|
14
|
-
import { pipeline } from '@huggingface/transformers';
|
|
15
14
|
import { cosineSimilarity } from '../../../shared/utils/vector-math.js';
|
|
16
15
|
/**
|
|
17
16
|
* Base embedding generator class
|
|
@@ -61,6 +60,19 @@ export class EmbeddingGenerator {
|
|
|
61
60
|
const loadDtype = this.config.quantization === 'none' ? 'fp32' :
|
|
62
61
|
this.config.quantization === 'fp16' ? 'fp16' :
|
|
63
62
|
this.config.quantization === 'int8' ? 'int8' : 'q8';
|
|
63
|
+
// Lazy-load the optional transformers backend (#565). If it isn't
|
|
64
|
+
// installed, fail with an actionable message pointing at the endpoint path.
|
|
65
|
+
let pipeline;
|
|
66
|
+
try {
|
|
67
|
+
({ pipeline } = await import('@huggingface/transformers'));
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
throw new Error('Local (in-process) embeddings require the optional dependency ' +
|
|
71
|
+
'"@huggingface/transformers", which is not installed. Either run ' +
|
|
72
|
+
'`npm install @huggingface/transformers`, or configure an embedding ' +
|
|
73
|
+
'endpoint (e.g. Cognitum /v1/embeddings) so the local backend is not needed. ' +
|
|
74
|
+
`Underlying import error: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
+
}
|
|
64
76
|
this.model = await pipeline('feature-extraction', this.config.model, {
|
|
65
77
|
dtype: loadDtype,
|
|
66
78
|
// v4 narrowed ProgressInfo to a discriminated union — `progress`
|
|
@@ -255,6 +255,10 @@ export class UnifiedMemoryManager {
|
|
|
255
255
|
this.db = openSafeDatabase(this.config.dbPath, {
|
|
256
256
|
walMode: this.config.walMode,
|
|
257
257
|
busyTimeout: this.config.busyTimeout,
|
|
258
|
+
// M3.2: the missing-file case is handled above; this covers the
|
|
259
|
+
// EXISTS-but-MALFORMED case — auto-restore the newest verified backup and
|
|
260
|
+
// park the corrupt original (non-destructive) instead of opening a broken DB.
|
|
261
|
+
autoRestore: true,
|
|
258
262
|
});
|
|
259
263
|
this.db.pragma(`mmap_size = ${this.config.mmapSize}`);
|
|
260
264
|
this.db.pragma(`cache_size = ${this.config.cacheSize}`);
|
|
@@ -150,11 +150,13 @@ function selectHeldOut(docs, ratio) {
|
|
|
150
150
|
*/
|
|
151
151
|
function scoreHeldOut(docs, policy, ratio) {
|
|
152
152
|
if (docs.length === 0)
|
|
153
|
-
return 0;
|
|
153
|
+
return { mean: 0, samples: [] };
|
|
154
154
|
const queries = selectHeldOut(docs, ratio);
|
|
155
155
|
if (queries.length === 0)
|
|
156
|
-
return 0;
|
|
157
|
-
|
|
156
|
+
return { mean: 0, samples: [] };
|
|
157
|
+
// Per-query reciprocal ranks: the mean is the held-out signal; the vector is
|
|
158
|
+
// the paired sample the accept/v1+sig significance gate needs (ADR-118).
|
|
159
|
+
const samples = [];
|
|
158
160
|
for (const queried of queries) {
|
|
159
161
|
const query = queried.bodyTokens; // subject deliberately withheld
|
|
160
162
|
const rels = docs.map((d) => ({ doc: d, rel: relevance(query, d, queried, policy) }));
|
|
@@ -177,9 +179,10 @@ function scoreHeldOut(docs, policy, ratio) {
|
|
|
177
179
|
}
|
|
178
180
|
const ranked = rankMMR(pool, policy.mmrLambda);
|
|
179
181
|
const rank = ranked.indexOf(queried.id) + 1; // 1-based; 0 -> not found
|
|
180
|
-
|
|
182
|
+
samples.push(rank > 0 ? 1 / rank : 0);
|
|
181
183
|
}
|
|
182
|
-
|
|
184
|
+
const mean = samples.reduce((a, b) => a + b, 0) / samples.length;
|
|
185
|
+
return { mean, samples };
|
|
183
186
|
}
|
|
184
187
|
// ---------------------------------------------------------------------------
|
|
185
188
|
// Anchor flat guard (the no-regression floor)
|
|
@@ -283,11 +286,11 @@ export function createCorpusScorer(opts) {
|
|
|
283
286
|
const corpus = loadCorpus(opts.db);
|
|
284
287
|
let anchorMeanCached = null;
|
|
285
288
|
return (policy) => {
|
|
286
|
-
const
|
|
289
|
+
const held = scoreHeldOut(corpus, policy, ratio);
|
|
287
290
|
if (anchorMeanCached === null) {
|
|
288
291
|
anchorMeanCached = gradeAnchor(anchorPath);
|
|
289
292
|
}
|
|
290
|
-
return { heldOut, anchorMean: anchorMeanCached };
|
|
293
|
+
return { heldOut: held.mean, anchorMean: anchorMeanCached, heldOutSamples: held.samples };
|
|
291
294
|
};
|
|
292
295
|
}
|
|
293
296
|
//# sourceMappingURL=corpus-scorer.js.map
|
|
@@ -22,6 +22,13 @@ export interface PolicyScores {
|
|
|
22
22
|
heldOut: number;
|
|
23
23
|
/** Mean over the ADR-117 frozen anchor items (the no-regression signal). */
|
|
24
24
|
anchorMean: number;
|
|
25
|
+
/**
|
|
26
|
+
* Per-held-out-task scores whose mean is `heldOut`. Optional — when present and
|
|
27
|
+
* paired index-for-index with the baseline's, they enable the accept/v1+sig
|
|
28
|
+
* paired-bootstrap significance gate (ADR-118). Scorers that don't provide them
|
|
29
|
+
* simply can't use accept/v1+sig (it fail-closes).
|
|
30
|
+
*/
|
|
31
|
+
heldOutSamples?: number[];
|
|
25
32
|
}
|
|
26
33
|
/** Injected: evaluate a policy → its held-out + anchor scores. */
|
|
27
34
|
export type PolicyScorer = (policy: RetrievalPolicy) => PolicyScores | Promise<PolicyScores>;
|
|
@@ -54,6 +54,11 @@ export async function runFlywheelGeneration(input) {
|
|
|
54
54
|
anchorTol: input.anchorTol,
|
|
55
55
|
provenanceTier,
|
|
56
56
|
allowJudgeTier: input.allowJudgeTier,
|
|
57
|
+
// ADR-118 accept/v1+sig: seal the paired per-task samples ONLY when the sig
|
|
58
|
+
// rule is in use. Left undefined for accept/v1 (and thus absent from the
|
|
59
|
+
// sealed hash), so accept/v1 receipts remain byte-identical to before.
|
|
60
|
+
candidateHeldOutSamples: ruleVersion === 'accept/v1+sig' ? candidateScores.heldOutSamples : undefined,
|
|
61
|
+
baselineHeldOutSamples: ruleVersion === 'accept/v1+sig' ? baselineScores.heldOutSamples : undefined,
|
|
57
62
|
};
|
|
58
63
|
const ruleResult = reExecuteGate(ruleVersion, sealed);
|
|
59
64
|
const verdict = ruleResult.promote ? 'promote' : 'reject';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-side witness verification (ADR-124 M2.2) — the single verifier that
|
|
3
|
+
* reconciles AQE's flywheel receipts with the Cognitum `qe-harness` witness
|
|
4
|
+
* bundles so QE evidence signed by the shared platform identity
|
|
5
|
+
* (fingerprint `f1ac28607da49ec1`) is verifiable on either side.
|
|
6
|
+
*
|
|
7
|
+
* WHAT WAS ALREADY ALIGNED (the bridge that exists): both sides use Ed25519,
|
|
8
|
+
* the same env secret `QE_WITNESS_SIGNING_KEY` (JSON `{publicKey,privateKey}`
|
|
9
|
+
* PEM), and the SAME key-id/fingerprint scheme `sha256(pem.trim()).slice(0,16)`
|
|
10
|
+
* — so both can sign AS the platform identity. `keyFingerprint()` here is
|
|
11
|
+
* byte-identical to `receipt.ts` `keyIdOf` and to qe-harness `witness.ts`.
|
|
12
|
+
*
|
|
13
|
+
* WHAT THIS RECONCILES: the two SIGNED ARTIFACTS are not natively
|
|
14
|
+
* cross-verifiable — AQE signs a fixed-field-order JSON body as HEX; qe-harness
|
|
15
|
+
* signs a `sha256:`-prefixed digest of a recursively key-sorted `stableStringify`
|
|
16
|
+
* as BASE64, wrapped in a nested `witness{}`. This module verifies BOTH.
|
|
17
|
+
*
|
|
18
|
+
* TWO EXTERNAL DEPENDENCIES (tracked, need the qe-harness owner — see M2.2 notes):
|
|
19
|
+
* 1. The public key for `f1ac28607da49ec1` is committed to NEITHER repo (it
|
|
20
|
+
* lives on meta-llm). Offline verification of platform-signed artifacts
|
|
21
|
+
* needs it provisioned via `QE_WITNESS_PUBLIC_KEYS_JSON`. This verifier is
|
|
22
|
+
* READY the moment that allowlist is populated.
|
|
23
|
+
* 2. The qe-harness bundle format here is implemented to the documented
|
|
24
|
+
* algorithm; byte-parity must be confirmed against a REAL qe-harness sample
|
|
25
|
+
* bundle before it gates anything (see witness-verify.test.ts).
|
|
26
|
+
*
|
|
27
|
+
* No new deps — node:crypto only. Reuses receipt.ts for the AQE path.
|
|
28
|
+
*/
|
|
29
|
+
import { type EvolveReceipt } from './receipt.js';
|
|
30
|
+
/** Public-key allowlist: fingerprint (`sha256(pem)[:16]`) → SPKI PEM. */
|
|
31
|
+
export type PublicKeyAllowlist = Map<string, string>;
|
|
32
|
+
/** Byte-identical to receipt.ts `keyIdOf` and qe-harness `witness.ts` fingerprint. */
|
|
33
|
+
export declare function keyFingerprint(publicKeyPem: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Load the trusted public-key allowlist from `QE_WITNESS_PUBLIC_KEYS_JSON`
|
|
36
|
+
* (`{ "<fingerprint>": "<SPKI PEM>", ... }`). Empty map when unset/unparseable —
|
|
37
|
+
* callers decide whether an empty allowlist means "verify signature only" (AQE
|
|
38
|
+
* receipts carry their own PEM) or "reject" (platform bundles need a trust root).
|
|
39
|
+
*/
|
|
40
|
+
export declare function loadAllowlist(json?: string | undefined): PublicKeyAllowlist;
|
|
41
|
+
/**
|
|
42
|
+
* Deterministic serialization matching qe-harness `stableStringify`: recursive
|
|
43
|
+
* key-sort on objects, array order preserved. This MUST stay byte-identical to
|
|
44
|
+
* the qe-harness implementation or digests will not match.
|
|
45
|
+
*/
|
|
46
|
+
export declare function stableStringify(value: unknown): string;
|
|
47
|
+
/** qe-harness canonical digest: `sha256:` + sha256(stableStringify(bundle − digest − witness)). */
|
|
48
|
+
export declare function canonicalDigest(bundle: Record<string, unknown>): string;
|
|
49
|
+
/** The qe-harness witness envelope (packages/engine/src/types.ts). */
|
|
50
|
+
export interface HarnessWitness {
|
|
51
|
+
alg: 'ed25519';
|
|
52
|
+
digest: string;
|
|
53
|
+
/** base64 Ed25519 signature over `digest`. */
|
|
54
|
+
signature: string;
|
|
55
|
+
publicKeyFingerprint: string;
|
|
56
|
+
signedAt?: string;
|
|
57
|
+
}
|
|
58
|
+
export type WitnessFormat = 'aqe-receipt' | 'harness-witness' | 'unknown';
|
|
59
|
+
export interface VerifyResult {
|
|
60
|
+
valid: boolean;
|
|
61
|
+
format: WitnessFormat;
|
|
62
|
+
fingerprint?: string;
|
|
63
|
+
reason?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Verify an AQE flywheel receipt. When an allowlist is provided and non-empty,
|
|
67
|
+
* the receipt's embedded public key must be present (by fingerprint) AND match;
|
|
68
|
+
* an empty allowlist verifies the signature against the receipt's own PEM only.
|
|
69
|
+
* NOTE: this is signature verification; the full AQE trust model ALSO re-executes
|
|
70
|
+
* the frozen gate (ADR-120) — do that separately for promotion decisions.
|
|
71
|
+
*/
|
|
72
|
+
export declare function verifyAqeReceipt(receipt: EvolveReceipt, allowlist?: PublicKeyAllowlist, opts?: {
|
|
73
|
+
allowSelfSigned?: boolean;
|
|
74
|
+
}): VerifyResult;
|
|
75
|
+
/**
|
|
76
|
+
* Verify a qe-harness witness bundle. Requires the signer's public key in the
|
|
77
|
+
* allowlist (platform bundles do NOT embed their PEM). Recomputes the canonical
|
|
78
|
+
* digest to detect payload tampering, then Ed25519-verifies the base64 signature
|
|
79
|
+
* over the digest string.
|
|
80
|
+
*/
|
|
81
|
+
export declare function verifyHarnessWitness(bundle: Record<string, unknown> & {
|
|
82
|
+
witness: HarnessWitness;
|
|
83
|
+
}, allowlist: PublicKeyAllowlist): VerifyResult;
|
|
84
|
+
/** Detect the artifact format and dispatch to the right verifier. */
|
|
85
|
+
export declare function verifyWitness(artifact: unknown, allowlist?: PublicKeyAllowlist): VerifyResult;
|
|
86
|
+
//# sourceMappingURL=witness-verify.d.ts.map
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-side witness verification (ADR-124 M2.2) — the single verifier that
|
|
3
|
+
* reconciles AQE's flywheel receipts with the Cognitum `qe-harness` witness
|
|
4
|
+
* bundles so QE evidence signed by the shared platform identity
|
|
5
|
+
* (fingerprint `f1ac28607da49ec1`) is verifiable on either side.
|
|
6
|
+
*
|
|
7
|
+
* WHAT WAS ALREADY ALIGNED (the bridge that exists): both sides use Ed25519,
|
|
8
|
+
* the same env secret `QE_WITNESS_SIGNING_KEY` (JSON `{publicKey,privateKey}`
|
|
9
|
+
* PEM), and the SAME key-id/fingerprint scheme `sha256(pem.trim()).slice(0,16)`
|
|
10
|
+
* — so both can sign AS the platform identity. `keyFingerprint()` here is
|
|
11
|
+
* byte-identical to `receipt.ts` `keyIdOf` and to qe-harness `witness.ts`.
|
|
12
|
+
*
|
|
13
|
+
* WHAT THIS RECONCILES: the two SIGNED ARTIFACTS are not natively
|
|
14
|
+
* cross-verifiable — AQE signs a fixed-field-order JSON body as HEX; qe-harness
|
|
15
|
+
* signs a `sha256:`-prefixed digest of a recursively key-sorted `stableStringify`
|
|
16
|
+
* as BASE64, wrapped in a nested `witness{}`. This module verifies BOTH.
|
|
17
|
+
*
|
|
18
|
+
* TWO EXTERNAL DEPENDENCIES (tracked, need the qe-harness owner — see M2.2 notes):
|
|
19
|
+
* 1. The public key for `f1ac28607da49ec1` is committed to NEITHER repo (it
|
|
20
|
+
* lives on meta-llm). Offline verification of platform-signed artifacts
|
|
21
|
+
* needs it provisioned via `QE_WITNESS_PUBLIC_KEYS_JSON`. This verifier is
|
|
22
|
+
* READY the moment that allowlist is populated.
|
|
23
|
+
* 2. The qe-harness bundle format here is implemented to the documented
|
|
24
|
+
* algorithm; byte-parity must be confirmed against a REAL qe-harness sample
|
|
25
|
+
* bundle before it gates anything (see witness-verify.test.ts).
|
|
26
|
+
*
|
|
27
|
+
* No new deps — node:crypto only. Reuses receipt.ts for the AQE path.
|
|
28
|
+
*/
|
|
29
|
+
import { createHash, verify as edVerify, createPublicKey } from 'node:crypto';
|
|
30
|
+
import { verifySignature, receiptBodyString } from './receipt.js';
|
|
31
|
+
/** Byte-identical to receipt.ts `keyIdOf` and qe-harness `witness.ts` fingerprint. */
|
|
32
|
+
export function keyFingerprint(publicKeyPem) {
|
|
33
|
+
return createHash('sha256').update(publicKeyPem.trim()).digest('hex').slice(0, 16);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Load the trusted public-key allowlist from `QE_WITNESS_PUBLIC_KEYS_JSON`
|
|
37
|
+
* (`{ "<fingerprint>": "<SPKI PEM>", ... }`). Empty map when unset/unparseable —
|
|
38
|
+
* callers decide whether an empty allowlist means "verify signature only" (AQE
|
|
39
|
+
* receipts carry their own PEM) or "reject" (platform bundles need a trust root).
|
|
40
|
+
*/
|
|
41
|
+
export function loadAllowlist(json = process.env.QE_WITNESS_PUBLIC_KEYS_JSON) {
|
|
42
|
+
const map = new Map();
|
|
43
|
+
if (!json)
|
|
44
|
+
return map;
|
|
45
|
+
try {
|
|
46
|
+
const obj = JSON.parse(json);
|
|
47
|
+
for (const [fp, pem] of Object.entries(obj)) {
|
|
48
|
+
if (typeof pem === 'string')
|
|
49
|
+
map.set(fp, pem);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// An unparseable allowlist yields an empty (fail-closed) trust root — but log
|
|
54
|
+
// it loudly, or a typo'd env var silently disables verification (qe-court finding).
|
|
55
|
+
console.error('[witness-verify] QE_WITNESS_PUBLIC_KEYS_JSON is set but not valid JSON — ' +
|
|
56
|
+
'treating the trust root as EMPTY (verification will fail closed).');
|
|
57
|
+
}
|
|
58
|
+
return map;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Deterministic serialization matching qe-harness `stableStringify`: recursive
|
|
62
|
+
* key-sort on objects, array order preserved. This MUST stay byte-identical to
|
|
63
|
+
* the qe-harness implementation or digests will not match.
|
|
64
|
+
*/
|
|
65
|
+
export function stableStringify(value) {
|
|
66
|
+
if (value === null || typeof value !== 'object')
|
|
67
|
+
return JSON.stringify(value) ?? 'null';
|
|
68
|
+
if (Array.isArray(value))
|
|
69
|
+
return '[' + value.map(stableStringify).join(',') + ']';
|
|
70
|
+
const obj = value;
|
|
71
|
+
const keys = Object.keys(obj).sort();
|
|
72
|
+
return '{' + keys.map((k) => JSON.stringify(k) + ':' + stableStringify(obj[k])).join(',') + '}';
|
|
73
|
+
}
|
|
74
|
+
/** qe-harness canonical digest: `sha256:` + sha256(stableStringify(bundle − digest − witness)). */
|
|
75
|
+
export function canonicalDigest(bundle) {
|
|
76
|
+
const rest = {};
|
|
77
|
+
for (const [k, v] of Object.entries(bundle)) {
|
|
78
|
+
if (k === 'digest' || k === 'witness')
|
|
79
|
+
continue;
|
|
80
|
+
rest[k] = v;
|
|
81
|
+
}
|
|
82
|
+
return 'sha256:' + createHash('sha256').update(stableStringify(rest)).digest('hex');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Verify an AQE flywheel receipt. When an allowlist is provided and non-empty,
|
|
86
|
+
* the receipt's embedded public key must be present (by fingerprint) AND match;
|
|
87
|
+
* an empty allowlist verifies the signature against the receipt's own PEM only.
|
|
88
|
+
* NOTE: this is signature verification; the full AQE trust model ALSO re-executes
|
|
89
|
+
* the frozen gate (ADR-120) — do that separately for promotion decisions.
|
|
90
|
+
*/
|
|
91
|
+
export function verifyAqeReceipt(receipt, allowlist, opts) {
|
|
92
|
+
const fingerprint = keyFingerprint(receipt.publicKeyPem);
|
|
93
|
+
if (allowlist && allowlist.size > 0) {
|
|
94
|
+
const allowed = allowlist.get(fingerprint);
|
|
95
|
+
if (!allowed)
|
|
96
|
+
return { valid: false, format: 'aqe-receipt', fingerprint, reason: 'fingerprint-not-in-allowlist' };
|
|
97
|
+
if (allowed.trim() !== receipt.publicKeyPem.trim()) {
|
|
98
|
+
return { valid: false, format: 'aqe-receipt', fingerprint, reason: 'allowlist-pem-mismatch' };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (!opts?.allowSelfSigned) {
|
|
102
|
+
// FAIL-CLOSED (qe-court finding): with no trust root, verifying against the
|
|
103
|
+
// receipt's OWN embedded key just proves internal consistency — anyone can
|
|
104
|
+
// self-sign a forged receipt. A caller must either provide an allowlist or
|
|
105
|
+
// explicitly opt into self-signed verification (e.g. a consistency check that
|
|
106
|
+
// is NOT used as authorization).
|
|
107
|
+
return { valid: false, format: 'aqe-receipt', fingerprint, reason: 'no-trust-root' };
|
|
108
|
+
}
|
|
109
|
+
const ok = verifySignature(receipt.publicKeyPem, receiptBodyString(receipt), receipt.signature);
|
|
110
|
+
return { valid: ok, format: 'aqe-receipt', fingerprint, reason: ok ? undefined : 'bad-signature' };
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Verify a qe-harness witness bundle. Requires the signer's public key in the
|
|
114
|
+
* allowlist (platform bundles do NOT embed their PEM). Recomputes the canonical
|
|
115
|
+
* digest to detect payload tampering, then Ed25519-verifies the base64 signature
|
|
116
|
+
* over the digest string.
|
|
117
|
+
*/
|
|
118
|
+
export function verifyHarnessWitness(bundle, allowlist) {
|
|
119
|
+
const w = bundle.witness;
|
|
120
|
+
const fingerprint = w?.publicKeyFingerprint;
|
|
121
|
+
// Fail closed on an unexpected algorithm — never verify a non-Ed25519-declared
|
|
122
|
+
// witness as Ed25519 (qe-court finding: ambiguous alg across implementations).
|
|
123
|
+
if (w?.alg !== 'ed25519') {
|
|
124
|
+
return { valid: false, format: 'harness-witness', fingerprint, reason: 'unsupported-alg' };
|
|
125
|
+
}
|
|
126
|
+
const pem = fingerprint ? allowlist.get(fingerprint) : undefined;
|
|
127
|
+
if (!pem)
|
|
128
|
+
return { valid: false, format: 'harness-witness', fingerprint, reason: 'fingerprint-not-in-allowlist' };
|
|
129
|
+
const recomputed = canonicalDigest(bundle);
|
|
130
|
+
if (recomputed !== w.digest) {
|
|
131
|
+
return { valid: false, format: 'harness-witness', fingerprint, reason: 'digest-mismatch' };
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const key = createPublicKey(pem);
|
|
135
|
+
const ok = edVerify(null, Buffer.from(w.digest, 'utf8'), key, Buffer.from(w.signature, 'base64'));
|
|
136
|
+
return { valid: ok, format: 'harness-witness', fingerprint, reason: ok ? undefined : 'bad-signature' };
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return { valid: false, format: 'harness-witness', fingerprint, reason: 'verify-error' };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Detect the artifact format and dispatch to the right verifier. */
|
|
143
|
+
export function verifyWitness(artifact, allowlist = loadAllowlist()) {
|
|
144
|
+
if (artifact && typeof artifact === 'object') {
|
|
145
|
+
const o = artifact;
|
|
146
|
+
const w = o.witness;
|
|
147
|
+
if (w && typeof w === 'object' && typeof w.signature === 'string' && typeof w.publicKeyFingerprint === 'string') {
|
|
148
|
+
return verifyHarnessWitness(o, allowlist);
|
|
149
|
+
}
|
|
150
|
+
if (typeof o.signature === 'string' && typeof o.publicKeyPem === 'string' && typeof o.sealedHash === 'string') {
|
|
151
|
+
return verifyAqeReceipt(o, allowlist);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return { valid: false, format: 'unknown', reason: 'unrecognized-artifact' };
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=witness-verify.js.map
|
|
@@ -125,7 +125,21 @@ async function initializeModel(config = {}) {
|
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
// In-process branch — only here do we import the transformers package.
|
|
128
|
-
|
|
128
|
+
// #565: `@huggingface/transformers` is NOT installed automatically (it
|
|
129
|
+
// transitively pulls onnxruntime-node -> adm-zip <0.6.0, GHSA-xcpc-8h2w-3j85,
|
|
130
|
+
// which upstream has not fixed). Users who want in-process embeddings opt in
|
|
131
|
+
// explicitly; everyone else uses an embedding endpoint. Translate the raw
|
|
132
|
+
// module-resolution failure into actionable guidance.
|
|
133
|
+
let transformers;
|
|
134
|
+
try {
|
|
135
|
+
transformers = await import('@huggingface/transformers');
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
throw new Error('In-process embeddings require the optional package "@huggingface/transformers", ' +
|
|
139
|
+
'which is not installed. Either run `npm install @huggingface/transformers`, or ' +
|
|
140
|
+
'configure an embedding endpoint (EmbeddingConfig.endpoint / AQE_EMBEDDING_ENDPOINT) ' +
|
|
141
|
+
'so no local model is loaded.');
|
|
142
|
+
}
|
|
129
143
|
pipeline = transformers.pipeline;
|
|
130
144
|
console.log(`[RealEmbeddings] Loading model: ${fullConfig.modelName}`);
|
|
131
145
|
const startTime = performance.now();
|