agentic-qe 3.12.2 → 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 +104 -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-3KYNICBC.js → agent-booster-wasm-ACX2DK7Y.js} +2 -2
- package/dist/cli/chunks/{agent-handler-NGPTMI6E.js → agent-handler-B45WP4ZJ.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-GNTQKQMG.js → agent-memory-branch-QQLZDE56.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-OTXT2DLN.js +2 -0
- package/dist/cli/chunks/{arena-HQEP2NWI.js → arena-G3IKZAG5.js} +4 -4
- package/dist/cli/chunks/{arena-PA7VIYD4.js → arena-SDB7723R.js} +2 -2
- package/dist/cli/chunks/{audit-XSDM57GC.js → audit-GY46XUZA.js} +3 -3
- package/dist/cli/chunks/base-O3SPSWBA.js +2 -0
- package/dist/cli/chunks/{hnswlib-node-BCASOCNU.js → better-sqlite3-DUZ6FFAH.js} +2 -2
- package/dist/cli/chunks/brain-handler-347CYMPN.js +89 -0
- package/dist/cli/chunks/{branch-enumerator-ZW7RNMUF.js → branch-enumerator-Z3ULBFSM.js} +2 -2
- package/dist/cli/chunks/{browser-4LU22CPP.js → browser-OYEIHD7F.js} +2 -2
- package/dist/cli/chunks/browser-workflow-MXS3ZKY2.js +2 -0
- package/dist/cli/chunks/{chunk-CKFZOPZN.js → chunk-2DIT5AUU.js} +2 -2
- package/dist/cli/chunks/{chunk-RXH2TC2K.js → chunk-2NRZYQSF.js} +2 -2
- package/dist/cli/chunks/chunk-2VQVEQS4.js +153 -0
- package/dist/cli/chunks/{chunk-KDGLNJPB.js → chunk-32ZGV4Q4.js} +1 -1
- package/dist/cli/chunks/{chunk-327YEKBU.js → chunk-34PEINFS.js} +2 -2
- package/dist/cli/chunks/{chunk-CTFW7CMI.js → chunk-3GSYD5SL.js} +2 -2
- package/dist/cli/chunks/{chunk-YRO7HNS4.js → chunk-3JVUWKCO.js} +2 -2
- package/dist/cli/chunks/{chunk-TERRRQVY.js → chunk-3K4SF57Q.js} +1 -1
- package/dist/cli/chunks/{chunk-6N62KS3C.js → chunk-3NOCK6ED.js} +2 -2
- package/dist/cli/chunks/{chunk-7DV42KFP.js → chunk-3UHEZ5HZ.js} +2 -2
- package/dist/cli/chunks/{chunk-N57BKUVE.js → chunk-4BDLD7V2.js} +1 -1
- package/dist/cli/chunks/{chunk-5SM57X4D.js → chunk-4BESADKE.js} +2 -2
- package/dist/cli/chunks/{chunk-GCQATSMK.js → chunk-54MFKCLT.js} +2 -2
- package/dist/cli/chunks/{chunk-GUGUYFU5.js → chunk-56WZFXTQ.js} +2 -2
- package/dist/cli/chunks/{chunk-OELLHV7S.js → chunk-5EIOQCGN.js} +2 -2
- package/dist/cli/chunks/{chunk-Z63IOTDW.js → chunk-5FLTZ3KT.js} +2 -2
- package/dist/cli/chunks/{chunk-EKTWIEEO.js → chunk-5ICQL42E.js} +2 -2
- package/dist/cli/chunks/{chunk-VQU2JXTK.js → chunk-5KAT6WBQ.js} +2 -2
- package/dist/cli/chunks/{chunk-VHYACXLN.js → chunk-6AOBLBR4.js} +2 -2
- package/dist/cli/chunks/{chunk-Z3FA5KR6.js → chunk-6DTOGSDV.js} +4 -4
- package/dist/cli/chunks/{chunk-SYLTJKN2.js → chunk-6SXKCIN5.js} +2 -2
- package/dist/cli/chunks/{chunk-MF4FULAI.js → chunk-7DMXCCSD.js} +1 -1
- package/dist/cli/chunks/{chunk-BOR5MME3.js → chunk-7UNY32PU.js} +1 -1
- package/dist/cli/chunks/{chunk-T6TQPF5P.js → chunk-7YXT6BXN.js} +3 -3
- package/dist/cli/chunks/{chunk-ADZTWGEB.js → chunk-A4QLGPYO.js} +2 -2
- package/dist/cli/chunks/{chunk-RFQIC6ZF.js → chunk-A7GLWWSE.js} +1 -1
- package/dist/cli/chunks/{chunk-WC5PM33J.js → chunk-ANIDFJCT.js} +3 -3
- package/dist/cli/chunks/{chunk-TFVWUR2U.js → chunk-ANYYTWOQ.js} +2 -2
- package/dist/cli/chunks/{chunk-YZ44FUVJ.js → chunk-AO7AHX6K.js} +2 -2
- package/dist/cli/chunks/{chunk-PHIEJAQK.js → chunk-BCKTBGDM.js} +3 -3
- package/dist/cli/chunks/{chunk-GECWGFRR.js → chunk-BGYLNCL6.js} +2 -2
- package/dist/cli/chunks/{chunk-PXKVW6PT.js → chunk-BOVH6WSM.js} +2 -2
- package/dist/cli/chunks/{chunk-P65S7AZA.js → chunk-BUGWPTMF.js} +2 -2
- package/dist/cli/chunks/{chunk-RXEQB4OT.js → chunk-CFVEDUTW.js} +2 -2
- package/dist/cli/chunks/{chunk-HNU32LN3.js → chunk-CPH5JP4L.js} +1 -1
- package/dist/cli/chunks/{chunk-LIAW5FD7.js → chunk-CQFT7H3F.js} +2 -2
- package/dist/cli/chunks/{chunk-WY5CX3VH.js → chunk-CWUBOLKY.js} +2 -2
- package/dist/cli/chunks/{chunk-X47GHZY3.js → chunk-CYL2FV23.js} +2 -2
- package/dist/cli/chunks/{chunk-W7LBT3BF.js → chunk-D3MPV5G7.js} +2 -2
- package/dist/cli/chunks/{chunk-7KMYBRKJ.js → chunk-DRIJYTSK.js} +2 -2
- package/dist/cli/chunks/{chunk-BDVOXGY5.js → chunk-DYUC7WFA.js} +1 -1
- package/dist/cli/chunks/{chunk-ZBYMF2QJ.js → chunk-E3B5XTXJ.js} +1 -1
- package/dist/cli/chunks/{chunk-TMQ3S7HR.js → chunk-EECM5XKY.js} +1 -1
- package/dist/cli/chunks/{chunk-7OD6HFCP.js → chunk-EFRESRLB.js} +3 -3
- package/dist/cli/chunks/{chunk-HU6ETNA7.js → chunk-ES7WCYOU.js} +1 -1
- package/dist/cli/chunks/chunk-FAQLI3P5.js +2 -0
- package/dist/cli/chunks/{chunk-K43YXI7C.js → chunk-FBBZHATF.js} +2 -2
- package/dist/cli/chunks/{chunk-2R7J4ZGT.js → chunk-FL3BM54K.js} +1 -1
- package/dist/cli/chunks/{chunk-KBXW7S3W.js → chunk-FQLWQWRU.js} +3 -3
- package/dist/cli/chunks/{chunk-LWVUNBZO.js → chunk-FQY3UTGA.js} +2 -2
- package/dist/cli/chunks/{chunk-2L7K2J2T.js → chunk-FUU32QY5.js} +2 -2
- package/dist/cli/chunks/{chunk-3LELACAQ.js → chunk-G4GTE3RJ.js} +2 -2
- package/dist/cli/chunks/{chunk-APVXTHTA.js → chunk-G5DFYX3J.js} +3 -3
- package/dist/cli/chunks/chunk-G7FMYFTN.js +2 -0
- package/dist/cli/chunks/{chunk-CMKCPRWX.js → chunk-GFBLWFRV.js} +1 -1
- package/dist/cli/chunks/{chunk-5YLY2WT2.js → chunk-GJMZR7WU.js} +3 -3
- package/dist/cli/chunks/{chunk-R6LDR3IO.js → chunk-GTUFX7AR.js} +2 -2
- package/dist/cli/chunks/{chunk-5CGTBAVF.js → chunk-GUEZQOHL.js} +1 -1
- package/dist/cli/chunks/{chunk-DGOZ3CGB.js → chunk-HL2QMM4M.js} +2 -2
- package/dist/cli/chunks/{chunk-VOHYQ6MX.js → chunk-HOKON5EL.js} +2 -2
- package/dist/cli/chunks/{chunk-DTXHRALB.js → chunk-HTPM3URI.js} +2 -2
- package/dist/cli/chunks/chunk-HVB2L52I.js +2 -0
- package/dist/cli/chunks/{chunk-GP7IXYOY.js → chunk-IHQTXJAQ.js} +1 -1
- package/dist/cli/chunks/{chunk-LOZAUP6L.js → chunk-IPHLXAMX.js} +2 -2
- package/dist/cli/chunks/{chunk-56MXYSYY.js → chunk-IYDYJ33J.js} +2 -2
- package/dist/cli/chunks/{chunk-QYST2TZW.js → chunk-IZRLIWFN.js} +2 -2
- package/dist/cli/chunks/{chunk-XNNYHQLW.js → chunk-J3L52EA4.js} +5 -5
- package/dist/cli/chunks/{chunk-P2FYRAC5.js → chunk-JGM6XCCP.js} +1 -1
- package/dist/cli/chunks/chunk-JPIBPKBP.js +54 -0
- package/dist/cli/chunks/{chunk-ILNQPPKB.js → chunk-K5N6SLHO.js} +1 -1
- package/dist/cli/chunks/{chunk-UEIIIDBJ.js → chunk-KSYLRM4Q.js} +2 -2
- package/dist/cli/chunks/{chunk-TRHUH24V.js → chunk-KUA4HHU6.js} +2 -2
- package/dist/cli/chunks/{chunk-OEZNUXY7.js → chunk-KVL63BSU.js} +1 -1
- package/dist/cli/chunks/{chunk-WMNGPIP3.js → chunk-KZTBNDNE.js} +1 -1
- package/dist/cli/chunks/{chunk-OSAPKOGN.js → chunk-L2SFGFE6.js} +1 -1
- package/dist/cli/chunks/{chunk-IQ56KMMH.js → chunk-L4LLA5U7.js} +1 -1
- package/dist/cli/chunks/{chunk-KBAXD6PH.js → chunk-L4S722JD.js} +1 -1
- package/dist/cli/chunks/{chunk-C7VNQ4PY.js → chunk-LBE2P6UC.js} +2 -2
- package/dist/cli/chunks/{chunk-KNOO6TFO.js → chunk-LOXVVMS4.js} +3 -3
- package/dist/cli/chunks/{chunk-B7DI76SY.js → chunk-LWYLW7RX.js} +2 -2
- package/dist/cli/chunks/{chunk-6SWR2BN7.js → chunk-LXPB7H2P.js} +1 -1
- package/dist/cli/chunks/{chunk-LGEPR7MH.js → chunk-MBCGI3M2.js} +3 -3
- package/dist/cli/chunks/{chunk-WL5VMIO4.js → chunk-MVI2QMRW.js} +1 -1
- package/dist/cli/chunks/{chunk-OIUIVV2N.js → chunk-N5MMBA35.js} +1 -1
- package/dist/cli/chunks/{chunk-TQNNKW7K.js → chunk-N7VOOI3U.js} +2 -2
- package/dist/cli/chunks/{chunk-BPSEFLJ6.js → chunk-NETN3OUG.js} +1 -1
- package/dist/cli/chunks/chunk-NQNKKVNO.js +29 -0
- package/dist/cli/chunks/{chunk-ACDZ2CRV.js → chunk-NUQBJGGF.js} +2 -2
- package/dist/cli/chunks/chunk-OETDMOOE.js +2 -0
- package/dist/cli/chunks/{chunk-R5HC6JVJ.js → chunk-OXXMVQDF.js} +2 -2
- package/dist/cli/chunks/{chunk-J6EFAKDQ.js → chunk-OZR25R7W.js} +2 -2
- package/dist/cli/chunks/{chunk-ZL7ZOIHO.js → chunk-PERJO2DY.js} +1 -1
- package/dist/cli/chunks/{chunk-WKWIUS5G.js → chunk-PP2RYSHT.js} +3 -3
- package/dist/cli/chunks/{chunk-WE5QHYL7.js → chunk-Q7PBGNUD.js} +1 -1
- package/dist/cli/chunks/{chunk-E5XWCGSX.js → chunk-QCEW4ZDW.js} +2 -2
- package/dist/cli/chunks/{chunk-EGU54SNK.js → chunk-QI4CGJNK.js} +1 -1
- package/dist/cli/chunks/{chunk-MNNNA57O.js → chunk-QQB55ZJJ.js} +2 -2
- package/dist/cli/chunks/{chunk-KV5OZ6T3.js → chunk-QTU3CVOB.js} +2 -2
- package/dist/cli/chunks/{chunk-M4XVEUUM.js → chunk-QWYISZTN.js} +2 -2
- package/dist/cli/chunks/{chunk-OMIGKGJJ.js → chunk-R3GEXYO4.js} +2 -2
- package/dist/cli/chunks/{chunk-4KEOBDEI.js → chunk-RDU4WTV2.js} +2 -2
- package/dist/cli/chunks/{chunk-3AJUJAUJ.js → chunk-RJZRWVL4.js} +1 -1
- package/dist/cli/chunks/{chunk-UFPCNUJA.js → chunk-RLCWR7TS.js} +10 -10
- package/dist/cli/chunks/{chunk-FTG4ZVTX.js → chunk-RSFIOR2I.js} +10 -10
- package/dist/cli/chunks/{chunk-FKUH33L3.js → chunk-RVJPWRV6.js} +2 -2
- package/dist/cli/chunks/{chunk-AMPYON7M.js → chunk-RVRBTOWX.js} +2 -2
- package/dist/cli/chunks/{chunk-AJ6DZXKK.js → chunk-SHCTEXNH.js} +2 -2
- package/dist/cli/chunks/chunk-SNTUKW4Q.js +2 -0
- package/dist/cli/chunks/{chunk-F3CKOVZM.js → chunk-SRQ3CPJE.js} +6 -6
- package/dist/cli/chunks/{chunk-V2QYW5KW.js → chunk-THBTN7XB.js} +2 -2
- package/dist/cli/chunks/{chunk-6FBXYS6X.js → chunk-TNRIGQ6U.js} +2 -2
- package/dist/cli/chunks/{chunk-UF3YOGHV.js → chunk-TVMFH5N2.js} +2 -2
- package/dist/cli/chunks/{chunk-FUBN5GPY.js → chunk-TZ73SXQ5.js} +1 -1
- package/dist/cli/chunks/chunk-TZPKTRJB.js +9 -0
- package/dist/cli/chunks/{chunk-IKIKIHFQ.js → chunk-U2SW6KK5.js} +2 -2
- package/dist/cli/chunks/{chunk-ZHWXI4SK.js → chunk-UIPPJKON.js} +2 -2
- package/dist/cli/chunks/{chunk-MNHGBG4D.js → chunk-UMG5URNV.js} +1 -1
- package/dist/cli/chunks/{chunk-YYV3FYVB.js → chunk-UNIBND6A.js} +1 -1
- package/dist/cli/chunks/{chunk-HH5Y4NCR.js → chunk-USMDIIHY.js} +2 -2
- package/dist/cli/chunks/{chunk-TLYZPOA7.js → chunk-VC6EXDGY.js} +2 -2
- package/dist/cli/chunks/{chunk-BMRR3MBR.js → chunk-VHYMSZNF.js} +2 -2
- package/dist/cli/chunks/{chunk-SVUWAV6Y.js → chunk-VLBV2VL3.js} +1 -1
- package/dist/cli/chunks/{chunk-BDX54WJV.js → chunk-VLNPJAVH.js} +1 -1
- package/dist/cli/chunks/{chunk-R554WVIG.js → chunk-VSNRPMAZ.js} +2 -2
- package/dist/cli/chunks/{chunk-AL5QT6OX.js → chunk-W5YEIHIO.js} +2 -2
- package/dist/cli/chunks/{chunk-NDAJWCXN.js → chunk-WRYT4HTZ.js} +2 -2
- package/dist/cli/chunks/{chunk-PSA2SOON.js → chunk-XFCWYQHW.js} +2 -2
- package/dist/cli/chunks/{chunk-6X65BGGK.js → chunk-XKFE3FLI.js} +2 -2
- package/dist/cli/chunks/{chunk-ZF65VOQH.js → chunk-YFGAHNCG.js} +2 -2
- package/dist/cli/chunks/{chunk-YSCEUK55.js → chunk-YPTGE5NJ.js} +2 -2
- package/dist/cli/chunks/{chunk-YDZIPP3Y.js → chunk-YRQLVGCI.js} +2 -2
- package/dist/cli/chunks/{chunk-ERQL3D2O.js → chunk-Z6QCOZ2H.js} +2 -2
- package/dist/cli/chunks/{chunk-WYFEVPLO.js → chunk-ZCFZ4USU.js} +1 -1
- package/dist/cli/chunks/{chunk-2R7XZ2WP.js → chunk-ZEIG5IQ4.js} +2 -2
- package/dist/cli/chunks/{chunk-KJJP446A.js → chunk-ZJG6N2OK.js} +1 -1
- package/dist/cli/chunks/{chunk-BUKGW63B.js → chunk-ZJIX5FGQ.js} +3 -3
- package/dist/cli/chunks/{chunk-EZ3JVN6S.js → chunk-ZLXBNNNT.js} +2 -2
- package/dist/cli/chunks/{chunk-4FHJYJCH.js → chunk-ZOXWASCC.js} +2 -2
- package/dist/cli/chunks/{ci-NT4DUGQ4.js → ci-74ZUCO5V.js} +2 -2
- package/dist/cli/chunks/{ci-output-PXBD2QPH.js → ci-output-HD6IZNJA.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-ZPCCEEDX.js → circuit-breaker-USZVMA42.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-CZCDFZOE.js → claude-flow-setup-S4XKNCD5.js} +2 -2
- package/dist/cli/chunks/client-33PGO5FA.js +2 -0
- package/dist/cli/chunks/{cline-installer-6J2S7GLM.js → cline-installer-6EW4CHAR.js} +2 -2
- package/dist/cli/chunks/{code-UTERK5AP.js → code-TOLWD2XL.js} +2 -2
- package/dist/cli/chunks/{code-index-extractor-O3MJTOS2.js → code-index-extractor-UA4QQ7B3.js} +2 -2
- package/dist/cli/chunks/{codex-installer-AZJIVXJR.js → codex-installer-C2CUP4FW.js} +2 -2
- package/dist/cli/chunks/{completions-A6ANQSZN.js → completions-KVUMQQ4K.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-MRSN7VUP.js → complexity-analyzer-DFH6LMK2.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-6LMKQRUI.js → continuedev-installer-LYDQSAU7.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-KP3TWUNO.js → copilot-installer-7USXLZHZ.js} +2 -2
- package/dist/cli/chunks/core-handlers-CSNZIM3A.js +2 -0
- package/dist/cli/chunks/{cost-tracker-R3C5IQPZ.js → cost-tracker-JBDIUMKZ.js} +2 -2
- package/dist/cli/chunks/{coverage-MR4QA2NM.js → coverage-RGO3K357.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-DRIBR5L3.js +2 -0
- package/dist/cli/chunks/{cursor-installer-LPZ7NGOS.js → cursor-installer-YEZGD37F.js} +2 -2
- package/dist/cli/chunks/{daemon-X5KXHRY3.js → daemon-FVETQ3LL.js} +3 -3
- package/dist/cli/chunks/{daemon-K3KW2UDV.js → daemon-LPEXHNYG.js} +4 -4
- package/dist/cli/chunks/{dag-attention-scheduler-J4FJSGNN.js → dag-attention-scheduler-UKYE2FII.js} +2 -2
- package/dist/cli/chunks/{detect-22TX2NCA.js → detect-WBG5P7ER.js} +2 -2
- package/dist/cli/chunks/{dist-node-QI4I4QPS.js → dist-node-YW6YRBCU.js} +2 -2
- package/dist/cli/chunks/{domain-handler-ZYZGPNOQ.js → domain-handler-HH7J4A32.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-2EEQTNIU.js → domain-transfer-V34GXD5I.js} +2 -2
- package/dist/cli/chunks/dream-WUNO723O.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-LYCTU5BS.js → embed-and-insert-pattern-WYLRS3CL.js} +2 -2
- package/dist/cli/chunks/{eval-SOA72GUX.js → eval-EIMVXY5J.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-AFFYOMYM.js → experience-capture-middleware-QMZHRUKM.js} +3 -3
- package/dist/cli/chunks/{fast-paths-WNMHOSUH.js → fast-paths-NHLW6XS6.js} +2 -2
- package/dist/cli/chunks/{feature-flags-HAP5IAAY.js → feature-flags-N3UHMSZ3.js} +2 -2
- package/dist/cli/chunks/{feature-flags-FT4YBZH4.js → feature-flags-NE3MBL3P.js} +2 -2
- package/dist/cli/chunks/{file-discovery-B4FFOH3Z.js → file-discovery-SI44X4YS.js} +2 -2
- package/dist/cli/chunks/{fleet-2ICPYV3J.js → fleet-MMYUXRRM.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-XIBJAHMW.js → gnn-wrapper-RLYXYU2Q.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-NSLSKDOI.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-FTV4CCBB.js → hnsw-legacy-bridge-RVM7EAIH.js} +2 -2
- package/dist/cli/chunks/{better-sqlite3-RQCOOAZC.js → hnswlib-node-RJPBJU2Q.js} +2 -2
- package/dist/cli/chunks/{hooks-SM4EU52N.js → hooks-ZF4VKHEO.js} +10 -10
- package/dist/cli/chunks/hybrid-router-AKBWZOQ3.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-RRMX4N3L.js → hypergraph-engine-YWS66PGO.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-MNFGDKAP.js → hypergraph-handler-OQHVRPWB.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-46FQIZ6Y.js +2 -0
- package/dist/cli/chunks/{init-handler-BNHIJ5TX.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-GFKUKPLY.js → kilocode-installer-APWB2GMA.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-YBIYKODN.js → kiro-installer-DICKFVNC.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-6XTW6WO6.js +2 -0
- package/dist/cli/chunks/{learning-QEWUPCK6.js → learning-MXHNYW5D.js} +3 -3
- package/dist/cli/chunks/{llm-router-D5FQIMVQ.js → llm-router-LTFIX7NY.js} +5 -5
- package/dist/cli/chunks/llm-router-service-3F4E64SY.js +2 -0
- package/dist/cli/chunks/{load-CLBUCKZQ.js → load-JUMIQ4LZ.js} +2 -2
- package/dist/cli/chunks/load-test-SWZNGEIY.js +2 -0
- package/dist/cli/chunks/{mcp-VOMG5DPV.js → mcp-WHIARJGO.js} +2 -2
- package/dist/cli/chunks/{memory-WZO63VSC.js → memory-KAHS6Z5A.js} +5 -5
- package/dist/cli/chunks/memory-backend-PR74ZPBA.js +2 -0
- package/dist/cli/chunks/memory-handlers-DG3RRXB6.js +2 -0
- package/dist/cli/chunks/{multi-model-executor-7UKW43VV.js → multi-model-executor-E3Y2RHMX.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-MLFPRRL2.js → opencode-installer-3RKGNGGE.js} +2 -2
- package/dist/cli/chunks/{orchestrator-XNYDBGIN.js → orchestrator-TXITUKWD.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-EPE36BVT.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-ZAP7ASQI.js → pattern-usage-recorder-EE2BUFZT.js} +2 -2
- package/dist/cli/chunks/{pipeline-4EJYOPBC.js → pipeline-AXTT6KZB.js} +2 -2
- package/dist/cli/chunks/{platform-ALPOWCOH.js → platform-TICPVKE2.js} +2 -2
- package/dist/cli/chunks/{plugin-S2RX3KHR.js → plugin-VQKNV3EM.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-P2JB73XX.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-ZBJXSESA.js → protocol-handler-YFWDR7UZ.js} +2 -2
- package/dist/cli/chunks/{prove-MYJ5YV45.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-NIACQC4M.js → quality-2APISBW5.js} +2 -2
- package/dist/cli/chunks/{quality-gate-OAZ23ON5.js → quality-gate-MCC3E5TM.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-2E23NEV4.js +2 -0
- package/dist/cli/chunks/{real-embeddings-6I4LP7PL.js → real-embeddings-CC5TNOTI.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-LRQHP6MK.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-A7BW7MV4.js → routing-handler-6NQBW4TQ.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-ZDRRFSJS.js → ruvector-commands-ZHXLHUPG.js} +2 -2
- package/dist/cli/chunks/{rvf-dual-writer-QWE3Z6BB.js → rvf-dual-writer-5KF2DGCW.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-adapter-6UDAP7QB.js → rvf-migration-adapter-BBU57BGF.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-coordinator-FEW2N4R4.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-XCY2XQZA.js +2 -0
- 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-KFXBV65O.js → security-PYP4H3KN.js} +3 -3
- package/dist/cli/chunks/shared-rvf-adapter-3CJHRNX6.js +2 -0
- package/dist/cli/chunks/{shared-rvf-dual-writer-CXXTB7CU.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-CXSVM236.js → status-handler-VYIZ3VJF.js} +2 -2
- package/dist/cli/chunks/{structural-health-LMHSM7MJ.js → structural-health-MVV4OWXP.js} +2 -2
- package/dist/cli/chunks/{sync-DMOUY2EY.js → sync-G47OYIQ3.js} +2 -2
- package/dist/cli/chunks/sync-VNX6L3TI.js +2 -0
- package/dist/cli/chunks/{task-handler-DMSNFIH3.js → task-handler-GOWF2GEH.js} +2 -2
- package/dist/cli/chunks/{task-handlers-3Z3QV7X7.js → task-handlers-J2WC6J37.js} +3 -3
- package/dist/cli/chunks/{test-U6CGMDLN.js → test-DMCJ3BXS.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-YHYA3BP5.js → test-scheduling-TRFHHKFM.js} +3 -3
- package/dist/cli/chunks/token-bootstrap-KEQ7AHFF.js +2 -0
- package/dist/cli/chunks/{token-usage-EOOTM7Q3.js → token-usage-B54FOFOF.js} +2 -2
- package/dist/cli/chunks/transformers-IACZG7IV.js +2 -0
- package/dist/cli/chunks/{tree-sitter-wasm-parser-HTGAXDQA.js → tree-sitter-wasm-parser-N7H4X37E.js} +2 -2
- package/dist/cli/chunks/{types-GLRXY4RY.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-KU55H77X.js → upgrade-A2PQ5EWK.js} +2 -2
- package/dist/cli/chunks/{validate-26VSBOJN.js → validate-UXV7UQUT.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-OIALRDKF.js → validate-swarm-MMBU4FPP.js} +2 -2
- package/dist/cli/chunks/{vibium-LOTWW25P.js → vibium-R4GUVADA.js} +2 -2
- package/dist/cli/chunks/visual-security-VKYXEGJB.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-6LWPPBYU.js → web-tree-sitter-MP6E6CJB.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-ILOQYENG.js → windsurf-installer-Z6BWMUUO.js} +2 -2
- package/dist/cli/chunks/{witness-chain-YBS6OHS4.js → witness-chain-EFLTABBA.js} +2 -2
- package/dist/cli/chunks/witness-chain-WVXRXKQP.js +2 -0
- package/dist/cli/chunks/{witness-key-manager-SI3WV3ZQ.js → witness-key-manager-PN36TV43.js} +2 -2
- package/dist/cli/chunks/{workflow-GY6SJRQW.js → workflow-A2AX3RJU.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-GOWSPR3G.js +2 -0
- package/dist/cli/chunks/{wrappers-MMO5YKOZ.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/integrations/ruvector/brain-rvf-exporter.js +115 -13
- package/dist/integrations/ruvector/rvf-dual-writer.js +20 -3
- package/dist/integrations/ruvector/rvf-store-integrity.d.ts +49 -0
- package/dist/integrations/ruvector/rvf-store-integrity.js +137 -0
- package/dist/integrations/ruvector/shared-rvf-adapter.js +23 -5
- package/dist/kernel/unified-memory.js +4 -0
- package/dist/learning/pattern-store.js +23 -5
- 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/platform-signer.d.ts +32 -0
- package/dist/learning/qe-flywheel/platform-signer.js +60 -0
- package/dist/learning/qe-flywheel/receipt.js +9 -2
- 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 +398 -387
- 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 +8 -4
- package/dist/cli/chunks/adapter-RL6GNUOS.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-UEEW6AQG.js +0 -2
- package/dist/cli/chunks/base-JQA5YULE.js +0 -2
- package/dist/cli/chunks/brain-handler-T7RDPKNM.js +0 -89
- package/dist/cli/chunks/browser-workflow-XTKUHTIT.js +0 -2
- package/dist/cli/chunks/chunk-ABHKXMOJ.js +0 -2
- package/dist/cli/chunks/chunk-CDMAVNV5.js +0 -2
- package/dist/cli/chunks/chunk-CQKEVUMO.js +0 -153
- package/dist/cli/chunks/chunk-KPV4N4KT.js +0 -9
- package/dist/cli/chunks/chunk-MALFTRCT.js +0 -29
- package/dist/cli/chunks/chunk-T75VH6NT.js +0 -2
- package/dist/cli/chunks/chunk-VM6VBRRU.js +0 -43
- package/dist/cli/chunks/chunk-WRMUQVKY.js +0 -2
- package/dist/cli/chunks/chunk-YY4KXDI6.js +0 -2
- package/dist/cli/chunks/client-S7DIRNFJ.js +0 -2
- package/dist/cli/chunks/core-handlers-NM2KCI6Z.js +0 -2
- package/dist/cli/chunks/cross-domain-router-3TSZMCBM.js +0 -2
- package/dist/cli/chunks/dream-QIIJONYI.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-CDNGLJJO.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-CR7Y4OAM.js +0 -2
- package/dist/cli/chunks/hnsw-index-TEDO4MQC.js +0 -2
- package/dist/cli/chunks/hybrid-router-O24ZDIP5.js +0 -2
- package/dist/cli/chunks/impact-analyzer-PDM4SDB6.js +0 -2
- package/dist/cli/chunks/init-wizard-F4KODPNW.js +0 -2
- package/dist/cli/chunks/kernel-77UM35L6.js +0 -2
- package/dist/cli/chunks/knowledge-graph-R6ZWWV2K.js +0 -2
- package/dist/cli/chunks/llm-router-service-7QYCZ66H.js +0 -2
- package/dist/cli/chunks/load-test-AWVA3CAQ.js +0 -2
- package/dist/cli/chunks/memory-backend-YESSIHFW.js +0 -2
- package/dist/cli/chunks/memory-handlers-EOOWSUHI.js +0 -2
- package/dist/cli/chunks/pattern-null-store-X3UXLJNL.js +0 -2
- package/dist/cli/chunks/protocol-executor-KXDCTMWI.js +0 -2
- package/dist/cli/chunks/provider-manager-XJZVHYI6.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-DPHPNIC6.js +0 -2
- package/dist/cli/chunks/queen-coordinator-EVGWME5C.js +0 -2
- package/dist/cli/chunks/router-R2N7TMAS.js +0 -2
- package/dist/cli/chunks/routing-feedback-G6W3H26L.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-D7R2GWXK.js +0 -2
- package/dist/cli/chunks/safe-db-CQZGF2KA.js +0 -2
- package/dist/cli/chunks/schedule-UP7E3LRC.js +0 -2
- package/dist/cli/chunks/scheduler-ENIZHYSL.js +0 -2
- package/dist/cli/chunks/shared-rvf-adapter-HDDCXCHY.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-CEVJVWS5.js +0 -2
- package/dist/cli/chunks/sync-REEFKICL.js +0 -2
- package/dist/cli/chunks/token-bootstrap-MQCTJURQ.js +0 -2
- package/dist/cli/chunks/transformers-EKDJW2H6.js +0 -2
- package/dist/cli/chunks/unified-memory-PXOQ4N53.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-VEXD6ASE.js +0 -2
- package/dist/cli/chunks/unified-persistence-46G6MZYC.js +0 -2
- package/dist/cli/chunks/visual-security-4X3T3MFL.js +0 -2
- package/dist/cli/chunks/witness-chain-XW4S3LVW.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-IIVV6TCP.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.13.0");process.exit(0)}
|
|
2
|
+
import{a,b,c,d}from"./chunk-54MFKCLT.js";import"./chunk-IYDYJ33J.js";import"./chunk-G5DFYX3J.js";import"./chunk-W5YEIHIO.js";import"./chunk-BUGWPTMF.js";import"./chunk-HVB2L52I.js";import"./chunk-OXXMVQDF.js";import"./chunk-NUQBJGGF.js";import"./chunk-2DIT5AUU.js";import"./chunk-QI4CGJNK.js";import"./chunk-CYL2FV23.js";import"./chunk-E3B5XTXJ.js";import"./chunk-SNTUKW4Q.js";import"./chunk-TVMFH5N2.js";import"./chunk-THBTN7XB.js";import"./chunk-RDU4WTV2.js";import"./chunk-LBE2P6UC.js";import"./chunk-IZRLIWFN.js";import"./chunk-AO7AHX6K.js";import"./chunk-YRQLVGCI.js";import"./chunk-3GSYD5SL.js";import"./chunk-ES7WCYOU.js";export{b as DEFAULT_WORKFLOW_CONFIG,a as WorkflowEvents,c as WorkflowOrchestrator,d as createWorkflowOrchestrator};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.
|
|
2
|
-
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v as L,w as M,x as N}from"./chunk-
|
|
1
|
+
import{createRequire as __cr}from"module";const require=__cr(import.meta.url);if(process.argv.includes('--version')||process.argv.includes('-v')){console.log("3.13.0");process.exit(0)}
|
|
2
|
+
import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v as L,w as M,x as N}from"./chunk-HOKON5EL.js";import{a as v,b as w,c as x,d as y,e as z,f as A,g as B,h as C,i as D,j as E,k as F,l as G,m as H,n as I,o as J,p as K}from"./chunk-HTPM3URI.js";import"./chunk-G5DFYX3J.js";import"./chunk-W5YEIHIO.js";import"./chunk-BUGWPTMF.js";import"./chunk-HVB2L52I.js";import"./chunk-OXXMVQDF.js";import"./chunk-NUQBJGGF.js";import"./chunk-2DIT5AUU.js";import"./chunk-CYL2FV23.js";import"./chunk-SNTUKW4Q.js";import"./chunk-TVMFH5N2.js";import"./chunk-THBTN7XB.js";import"./chunk-RDU4WTV2.js";import"./chunk-LBE2P6UC.js";import"./chunk-IZRLIWFN.js";import"./chunk-AO7AHX6K.js";import"./chunk-YRQLVGCI.js";import"./chunk-3GSYD5SL.js";import"./chunk-ES7WCYOU.js";export{z as GNNLayerFactory,i as QEFlashAttention,x as QEGNNEmbeddingIndex,y as QEGNNIndexFactory,a as QESONA,e as QE_FLASH_ATTENTION_CONFIG,g as QE_PERFORMANCE_TARGETS,f as QE_SONA_CONFIG,A as TensorCompressionFactory,u as batchComputeAttention,K as batchDifferentiableSearch,M as checkRuvectorPackagesAvailable,c as createDomainQESONA,j as createQEFlashAttention,b as createQESONA,D as getDifferentiableSearch,F as getGetCompressionLevel,E as getHierarchicalForward,G as getInit,h as getOptimalBlockConfig,k as getQEFlashAttentionConfig,n as getRuvectorDotProductAttention,m as getRuvectorFlashAttention,p as getRuvectorHyperbolicAttention,B as getRuvectorLayer,q as getRuvectorLinearAttention,r as getRuvectorMoEAttention,o as getRuvectorMultiHeadAttention,L as getRuvectorPackageVersions,C as getTensorCompress,l as getWorkloadTypes,N as initAllRuvectorPackages,w as initGNN,d as isAttentionAvailable,v as isGNNAvailable,s as toFloat32Array,H as toFloat32ArrayGNN,J as toIEmbedding,t as toNumberArrayAttn,I as toNumberArrayGNN};
|
|
@@ -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`
|
|
@@ -3,11 +3,82 @@
|
|
|
3
3
|
* `.rvf` file using the @ruvector/rvf-node native binding via rvf-native-adapter.
|
|
4
4
|
* Falls back to JSONL directory format when the native binding is unavailable.
|
|
5
5
|
*/
|
|
6
|
-
import { existsSync, statSync, unlinkSync, writeFileSync } from 'fs';
|
|
7
|
-
import { resolve } from 'path';
|
|
6
|
+
import { existsSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from 'fs';
|
|
7
|
+
import { basename, dirname, join, resolve } from 'path';
|
|
8
8
|
import { createRvfStore, openRvfStore, openRvfStoreReadonly, isRvfNativeAvailable, } from './rvf-native-adapter.js';
|
|
9
9
|
import { sha256, tableExists, queryAll, domainFilterForColumn, ensureTargetTables, mergeGenericRow, mergeAppendOnlyRow, TABLE_CONFIGS, TABLE_BLOB_COLUMNS, PK_COLUMNS, CONFIDENCE_COLUMNS, TIMESTAMP_COLUMNS, serializeRowBlobs, deserializeRowBlobs, } from './brain-shared.js';
|
|
10
10
|
// --- Export ---
|
|
11
|
+
/**
|
|
12
|
+
* Sidecar suffixes that make up a complete store on disk. `''` is the store
|
|
13
|
+
* itself; the adapter writes `.idmap.json` on close, and we write the manifest.
|
|
14
|
+
*/
|
|
15
|
+
const RVF_STORE_SUFFIXES = ['', '.idmap.json', '.manifest.json'];
|
|
16
|
+
/**
|
|
17
|
+
* Everything an abandoned tmp export can leave behind. `.lock` is cleaned up
|
|
18
|
+
* but deliberately absent from RVF_STORE_SUFFIXES — renaming a lock into the
|
|
19
|
+
* final path is the very corruption this fix exists to prevent.
|
|
20
|
+
*/
|
|
21
|
+
const RVF_CLEANUP_SUFFIXES = [...RVF_STORE_SUFFIXES, '.lock'];
|
|
22
|
+
/** Best-effort removal of a store and its sidecars at `base`. */
|
|
23
|
+
function removeStoreFiles(base) {
|
|
24
|
+
for (const suffix of RVF_CLEANUP_SUFFIXES) {
|
|
25
|
+
try {
|
|
26
|
+
const p = `${base}${suffix}`;
|
|
27
|
+
if (existsSync(p))
|
|
28
|
+
unlinkSync(p);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// best-effort — a leftover tmp is inert, unlike a corrupt final store
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Remove tmp stores orphaned by killed exports (#563). Each interrupted export
|
|
37
|
+
* strands a full-size tmp store, so on a project where the checkpoint hook is
|
|
38
|
+
* killed regularly these would accumulate unbounded.
|
|
39
|
+
*
|
|
40
|
+
* Only tmps whose owning pid is gone are removed: a live pid means a concurrent
|
|
41
|
+
* export is mid-write, and deleting its tmp would corrupt exactly what this
|
|
42
|
+
* change exists to protect.
|
|
43
|
+
*/
|
|
44
|
+
function sweepStaleTmpFiles(outPath) {
|
|
45
|
+
const dir = dirname(outPath);
|
|
46
|
+
const prefix = `${basename(outPath)}.tmp.`;
|
|
47
|
+
let entries;
|
|
48
|
+
try {
|
|
49
|
+
entries = readdirSync(dir);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
if (!entry.startsWith(prefix))
|
|
56
|
+
continue;
|
|
57
|
+
// `<name>.rvf.tmp.<pid>` and its `<...>.tmp.<pid>.idmap.json` siblings.
|
|
58
|
+
const pid = Number.parseInt(entry.slice(prefix.length).split('.')[0], 10);
|
|
59
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
60
|
+
continue;
|
|
61
|
+
if (pid !== process.pid && isPidAlive(pid))
|
|
62
|
+
continue;
|
|
63
|
+
try {
|
|
64
|
+
unlinkSync(join(dir, entry));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// best-effort
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** True when a process with `pid` exists (signal 0 probes without delivering). */
|
|
72
|
+
function isPidAlive(pid) {
|
|
73
|
+
try {
|
|
74
|
+
process.kill(pid, 0);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
// EPERM means it exists but belongs to another user — still alive.
|
|
79
|
+
return err.code === 'EPERM';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
11
82
|
/** Export brain state to a single `.rvf` file with vector embeddings + kernel. */
|
|
12
83
|
export function exportBrainToRvf(db, options, sourceDbLabel = 'memory.db') {
|
|
13
84
|
if (!isRvfNativeAvailable()) {
|
|
@@ -15,14 +86,20 @@ export function exportBrainToRvf(db, options, sourceDbLabel = 'memory.db') {
|
|
|
15
86
|
}
|
|
16
87
|
const outPath = resolve(options.outputPath);
|
|
17
88
|
const dimension = options.dimension ?? 384;
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
89
|
+
// Issue #563: build the store at a private tmp path and rename it over the
|
|
90
|
+
// final path only once it is closed and complete. The previous code deleted
|
|
91
|
+
// the old store and then built the new one in place, so any interruption
|
|
92
|
+
// (hook timeout, session teardown, SIGKILL) left a created-but-incomplete
|
|
93
|
+
// store that could neither be opened (ManifestNotFound) nor created over
|
|
94
|
+
// (FsyncFailed) — permanently disabling the RVF backend. With tmp+rename an
|
|
95
|
+
// interrupted export leaves the *previous* good store untouched and orphans
|
|
96
|
+
// only an inert tmp file, which the next export sweeps.
|
|
97
|
+
const tmpPath = `${outPath}.tmp.${process.pid}`;
|
|
98
|
+
sweepStaleTmpFiles(outPath);
|
|
99
|
+
removeStoreFiles(tmpPath);
|
|
24
100
|
// Create RVF container via adapter (handles idmap automatically)
|
|
25
|
-
const rvf = createRvfStore(
|
|
101
|
+
const rvf = createRvfStore(tmpPath, dimension);
|
|
102
|
+
let closed = false;
|
|
26
103
|
try {
|
|
27
104
|
// --- Export all tables using TABLE_CONFIGS ---
|
|
28
105
|
const allTableData = {};
|
|
@@ -153,12 +230,37 @@ export function exportBrainToRvf(db, options, sourceDbLabel = 'memory.db') {
|
|
|
153
230
|
catch { /* best-effort */ }
|
|
154
231
|
}
|
|
155
232
|
// Persist manifest as sidecar JSON alongside the .rvf file
|
|
156
|
-
|
|
157
|
-
|
|
233
|
+
writeFileSync(`${tmpPath}.manifest.json`, JSON.stringify(manifest, null, 2), 'utf-8');
|
|
234
|
+
// Close before promoting: close() flushes the store and writes the idmap
|
|
235
|
+
// sidecar, so renaming any earlier would publish an incomplete store.
|
|
236
|
+
rvf.close();
|
|
237
|
+
closed = true;
|
|
238
|
+
// Promote tmp → final. The store itself goes last: until it lands, the
|
|
239
|
+
// previous store (if any) is still the one on disk, and a crash mid-promote
|
|
240
|
+
// leaves the old store readable rather than a half-written new one.
|
|
241
|
+
for (const suffix of [...RVF_STORE_SUFFIXES].reverse()) {
|
|
242
|
+
const from = `${tmpPath}${suffix}`;
|
|
243
|
+
const to = `${outPath}${suffix}`;
|
|
244
|
+
if (existsSync(from)) {
|
|
245
|
+
renameSync(from, to);
|
|
246
|
+
}
|
|
247
|
+
else if (existsSync(to)) {
|
|
248
|
+
// No new sidecar produced — drop the stale one so it can't be read
|
|
249
|
+
// against the new store.
|
|
250
|
+
unlinkSync(to);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
158
253
|
return manifest;
|
|
159
254
|
}
|
|
160
|
-
|
|
161
|
-
|
|
255
|
+
catch (err) {
|
|
256
|
+
if (!closed) {
|
|
257
|
+
try {
|
|
258
|
+
rvf.close();
|
|
259
|
+
}
|
|
260
|
+
catch { /* best-effort */ }
|
|
261
|
+
}
|
|
262
|
+
removeStoreFiles(tmpPath);
|
|
263
|
+
throw err;
|
|
162
264
|
}
|
|
163
265
|
}
|
|
164
266
|
/** Legacy field-to-table mapping for older RVF exports. */
|
|
@@ -87,14 +87,31 @@ export class RvfDualWriter {
|
|
|
87
87
|
nativeAdapter = adapter.openRvfStore(this.config.rvfPath);
|
|
88
88
|
}
|
|
89
89
|
catch {
|
|
90
|
-
|
|
90
|
+
try {
|
|
91
|
+
nativeAdapter = adapter.createRvfStore(this.config.rvfPath, this.config.dimensions);
|
|
92
|
+
}
|
|
93
|
+
catch (createErr) {
|
|
94
|
+
// Issue #563: open failed *and* create failed, so the file on disk is
|
|
95
|
+
// provably unusable — the signature of an export killed mid-write
|
|
96
|
+
// (open → ManifestNotFound, create → FsyncFailed because the path
|
|
97
|
+
// exists). Previously this fell to the catch below and disabled RVF
|
|
98
|
+
// silently for the whole run. Quarantine and rebuild instead.
|
|
99
|
+
const { quarantineUnusableStore } = await import('./rvf-store-integrity.js');
|
|
100
|
+
const quarantined = quarantineUnusableStore(this.config.rvfPath, createErr instanceof Error ? createErr.message : String(createErr));
|
|
101
|
+
if (!quarantined)
|
|
102
|
+
throw createErr; // live peer, or nothing to move
|
|
103
|
+
nativeAdapter = adapter.createRvfStore(this.config.rvfPath, this.config.dimensions);
|
|
104
|
+
}
|
|
91
105
|
}
|
|
92
106
|
this.rvfStore = wrapNativeAdapter(nativeAdapter, this.config.dimensions);
|
|
93
107
|
this.rvfAvailable = true;
|
|
94
108
|
}
|
|
95
|
-
catch {
|
|
96
|
-
// Native adapter
|
|
109
|
+
catch (err) {
|
|
110
|
+
// Native adapter unavailable, or recovery itself failed. Degrade to
|
|
111
|
+
// sqlite-only — but say so, instead of vanishing silently (#563).
|
|
97
112
|
this.rvfAvailable = false;
|
|
113
|
+
console.warn(`[RVF] Dual-writer disabled for ${this.config.rvfPath}; falling back to SQLite: ` +
|
|
114
|
+
`${err instanceof Error ? err.message : String(err)}`);
|
|
98
115
|
}
|
|
99
116
|
}
|
|
100
117
|
/**
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RVF store integrity helpers (issue #563).
|
|
3
|
+
*
|
|
4
|
+
* An export that is killed mid-write leaves a store that was created but never
|
|
5
|
+
* completed. Such a file cannot be opened (`RVF error 0x0106: ManifestNotFound`)
|
|
6
|
+
* and cannot be created over either, because the path already exists
|
|
7
|
+
* (`RVF error 0x0303: FsyncFailed`). Both paths fail forever, so the RVF
|
|
8
|
+
* backend stays disabled for the life of the project until someone deletes the
|
|
9
|
+
* file by hand.
|
|
10
|
+
*
|
|
11
|
+
* Recovery has to be evidence-based rather than fingerprint-based. Measured
|
|
12
|
+
* against @ruvector/rvf-node 0.1.8:
|
|
13
|
+
*
|
|
14
|
+
* • A *valid, empty* store is 162 bytes with magic `SFVR` — byte-for-byte
|
|
15
|
+
* the size the issue reports as "truncated: header only". Size and magic
|
|
16
|
+
* therefore cannot distinguish a broken store from a healthy empty one.
|
|
17
|
+
* • `<store>.lock` is a 104-byte record with magic `FLVR` and the owning pid
|
|
18
|
+
* as a little-endian u32 at offset 4. `FLVR` in a lock is the *normal*
|
|
19
|
+
* case — the issue reads it as "RVF store bytes leaked into the lock", but
|
|
20
|
+
* the store magic is `SFVR`; a 104-byte `FLVR` lock is just a live-or-stale
|
|
21
|
+
* lock record.
|
|
22
|
+
*
|
|
23
|
+
* So the only sound trigger is "open failed *and* create failed": at that point
|
|
24
|
+
* the file is provably unusable. The lock's pid is used as a *guard* — if it is
|
|
25
|
+
* held by a live process, the store is presumed healthy and left alone.
|
|
26
|
+
*/
|
|
27
|
+
/** The pid recorded in `<rvfPath>.lock`, or null if there is no readable lock. */
|
|
28
|
+
export declare function readLockOwnerPid(rvfPath: string): number | null;
|
|
29
|
+
/**
|
|
30
|
+
* True when the store's lock is held by a process that is still running.
|
|
31
|
+
*
|
|
32
|
+
* Deliberately conservative: an unreadable or pid-less lock reports false (the
|
|
33
|
+
* caller's open already failed, so there is nothing to protect), while a live
|
|
34
|
+
* pid reports true and blocks recovery. Pid reuse can only produce a false
|
|
35
|
+
* "alive", which fails safe — we leave the store alone.
|
|
36
|
+
*/
|
|
37
|
+
export declare function isLockHeldByLiveProcess(rvfPath: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Move an unusable store and its sidecars aside so the next create succeeds.
|
|
40
|
+
* Returns the quarantine base path, or null if nothing was quarantined.
|
|
41
|
+
*
|
|
42
|
+
* Only call this once open *and* create have both failed — that is the proof
|
|
43
|
+
* the file is unusable. The store is a derived cache, rebuilt from the unified
|
|
44
|
+
* DB, so quarantining is recoverable; we move rather than delete because the
|
|
45
|
+
* bytes may hold writes that never reached SQLite, and they are the only
|
|
46
|
+
* evidence if this recurs.
|
|
47
|
+
*/
|
|
48
|
+
export declare function quarantineUnusableStore(rvfPath: string, reason: string): string | null;
|
|
49
|
+
//# sourceMappingURL=rvf-store-integrity.d.ts.map
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RVF store integrity helpers (issue #563).
|
|
3
|
+
*
|
|
4
|
+
* An export that is killed mid-write leaves a store that was created but never
|
|
5
|
+
* completed. Such a file cannot be opened (`RVF error 0x0106: ManifestNotFound`)
|
|
6
|
+
* and cannot be created over either, because the path already exists
|
|
7
|
+
* (`RVF error 0x0303: FsyncFailed`). Both paths fail forever, so the RVF
|
|
8
|
+
* backend stays disabled for the life of the project until someone deletes the
|
|
9
|
+
* file by hand.
|
|
10
|
+
*
|
|
11
|
+
* Recovery has to be evidence-based rather than fingerprint-based. Measured
|
|
12
|
+
* against @ruvector/rvf-node 0.1.8:
|
|
13
|
+
*
|
|
14
|
+
* • A *valid, empty* store is 162 bytes with magic `SFVR` — byte-for-byte
|
|
15
|
+
* the size the issue reports as "truncated: header only". Size and magic
|
|
16
|
+
* therefore cannot distinguish a broken store from a healthy empty one.
|
|
17
|
+
* • `<store>.lock` is a 104-byte record with magic `FLVR` and the owning pid
|
|
18
|
+
* as a little-endian u32 at offset 4. `FLVR` in a lock is the *normal*
|
|
19
|
+
* case — the issue reads it as "RVF store bytes leaked into the lock", but
|
|
20
|
+
* the store magic is `SFVR`; a 104-byte `FLVR` lock is just a live-or-stale
|
|
21
|
+
* lock record.
|
|
22
|
+
*
|
|
23
|
+
* So the only sound trigger is "open failed *and* create failed": at that point
|
|
24
|
+
* the file is provably unusable. The lock's pid is used as a *guard* — if it is
|
|
25
|
+
* held by a live process, the store is presumed healthy and left alone.
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, openSync, readSync, closeSync, renameSync, unlinkSync } from 'fs';
|
|
28
|
+
/** Magic of a lock record (the store's own magic is `SFVR`). */
|
|
29
|
+
const LOCK_MAGIC = 'FLVR';
|
|
30
|
+
/** Byte offset of the owning pid within a lock record (u32 LE). */
|
|
31
|
+
const LOCK_PID_OFFSET = 4;
|
|
32
|
+
/** Sidecars that belong to a store and must be quarantined alongside it. */
|
|
33
|
+
const STORE_SIDECAR_SUFFIXES = ['', '.idmap.json', '.manifest.json'];
|
|
34
|
+
/** Read the first `n` bytes of a file, or null if unreadable/shorter. */
|
|
35
|
+
function readHead(path, n) {
|
|
36
|
+
let fd;
|
|
37
|
+
try {
|
|
38
|
+
fd = openSync(path, 'r');
|
|
39
|
+
const buf = Buffer.alloc(n);
|
|
40
|
+
if (readSync(fd, buf, 0, n, 0) < n)
|
|
41
|
+
return null;
|
|
42
|
+
return buf;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
if (fd !== undefined) {
|
|
49
|
+
try {
|
|
50
|
+
closeSync(fd);
|
|
51
|
+
}
|
|
52
|
+
catch { /* best-effort */ }
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** True when a process with `pid` exists (signal 0 probes without delivering). */
|
|
57
|
+
function isPidAlive(pid) {
|
|
58
|
+
try {
|
|
59
|
+
process.kill(pid, 0);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
// EPERM means it exists but belongs to another user — still alive.
|
|
64
|
+
return err.code === 'EPERM';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** The pid recorded in `<rvfPath>.lock`, or null if there is no readable lock. */
|
|
68
|
+
export function readLockOwnerPid(rvfPath) {
|
|
69
|
+
const head = readHead(`${rvfPath}.lock`, LOCK_PID_OFFSET + 4);
|
|
70
|
+
if (!head || head.subarray(0, 4).toString('latin1') !== LOCK_MAGIC)
|
|
71
|
+
return null;
|
|
72
|
+
const pid = head.readUInt32LE(LOCK_PID_OFFSET);
|
|
73
|
+
return pid > 0 ? pid : null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* True when the store's lock is held by a process that is still running.
|
|
77
|
+
*
|
|
78
|
+
* Deliberately conservative: an unreadable or pid-less lock reports false (the
|
|
79
|
+
* caller's open already failed, so there is nothing to protect), while a live
|
|
80
|
+
* pid reports true and blocks recovery. Pid reuse can only produce a false
|
|
81
|
+
* "alive", which fails safe — we leave the store alone.
|
|
82
|
+
*/
|
|
83
|
+
export function isLockHeldByLiveProcess(rvfPath) {
|
|
84
|
+
const pid = readLockOwnerPid(rvfPath);
|
|
85
|
+
if (pid === null)
|
|
86
|
+
return false;
|
|
87
|
+
return pid !== process.pid && isPidAlive(pid);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Move an unusable store and its sidecars aside so the next create succeeds.
|
|
91
|
+
* Returns the quarantine base path, or null if nothing was quarantined.
|
|
92
|
+
*
|
|
93
|
+
* Only call this once open *and* create have both failed — that is the proof
|
|
94
|
+
* the file is unusable. The store is a derived cache, rebuilt from the unified
|
|
95
|
+
* DB, so quarantining is recoverable; we move rather than delete because the
|
|
96
|
+
* bytes may hold writes that never reached SQLite, and they are the only
|
|
97
|
+
* evidence if this recurs.
|
|
98
|
+
*/
|
|
99
|
+
export function quarantineUnusableStore(rvfPath, reason) {
|
|
100
|
+
if (!existsSync(rvfPath))
|
|
101
|
+
return null;
|
|
102
|
+
// Never pull a store out from under a live peer.
|
|
103
|
+
if (isLockHeldByLiveProcess(rvfPath)) {
|
|
104
|
+
console.warn(`[RVF] ${rvfPath} is unusable but its lock is held by a live process — ` +
|
|
105
|
+
'leaving it alone and degrading to SQLite for this run.');
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
// Keyed by pid, not a timestamp: a crash-loop quarantining the same file
|
|
109
|
+
// repeatedly overwrites its own copy instead of filling .agentic-qe/ with
|
|
110
|
+
// one corrupt store per startup.
|
|
111
|
+
const quarantineBase = `${rvfPath}.corrupt-${process.pid}`;
|
|
112
|
+
for (const sidecar of STORE_SIDECAR_SUFFIXES) {
|
|
113
|
+
const from = `${rvfPath}${sidecar}`;
|
|
114
|
+
if (!existsSync(from))
|
|
115
|
+
continue;
|
|
116
|
+
try {
|
|
117
|
+
renameSync(from, `${quarantineBase}${sidecar}`);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// A failed quarantine must not throw and take down the caller; the
|
|
121
|
+
// caller's retry will simply fail again and degrade as before.
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// The store is gone, so its lock — stale by definition here — goes with it.
|
|
125
|
+
try {
|
|
126
|
+
if (existsSync(`${rvfPath}.lock`))
|
|
127
|
+
unlinkSync(`${rvfPath}.lock`);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// best-effort
|
|
131
|
+
}
|
|
132
|
+
console.warn(`[RVF] Quarantined unusable store ${rvfPath} → ${quarantineBase} (${reason}). ` +
|
|
133
|
+
'It is a derived cache and will be rebuilt from the unified DB. ' +
|
|
134
|
+
'Please report a recurrence with the quarantined files (issue #563).');
|
|
135
|
+
return quarantineBase;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=rvf-store-integrity.js.map
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
// Issue #516: lightweight, sqlite-free project-root resolver (static import so it
|
|
14
14
|
// resolves under the test runner; avoids pulling unified-memory's sqlite graph).
|
|
15
15
|
import { findProjectRoot } from '../../kernel/project-root.js';
|
|
16
|
+
// Issue #563: static import — this module is fs-only, and a require() here
|
|
17
|
+
// would not resolve under the test runner.
|
|
18
|
+
import { quarantineUnusableStore, isLockHeldByLiveProcess, readLockOwnerPid, } from './rvf-store-integrity.js';
|
|
16
19
|
let sharedAdapter = null;
|
|
17
20
|
let initAttempted = false;
|
|
18
21
|
// ---------------------------------------------------------------------------
|
|
@@ -131,16 +134,23 @@ function openOrCreateRvf(openFn, createFn, rvfPath, dimensions) {
|
|
|
131
134
|
// .lock that subsequent invocations interpret as `LockHeld`. Since AQE
|
|
132
135
|
// CLI is overwhelmingly single-shot serial, the realistic case is "the
|
|
133
136
|
// prior process is dead and the lock is stale". We unlink the .lock and
|
|
134
|
-
// retry open exactly once.
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
//
|
|
137
|
+
// retry open exactly once.
|
|
138
|
+
//
|
|
139
|
+
// Issue #563: the lock record turns out to carry its owner's pid (u32 LE at
|
|
140
|
+
// offset 4, after the `FLVR` magic), so "is it stale?" is now a check rather
|
|
141
|
+
// than an assumption. This previously unlinked the lock unconditionally,
|
|
142
|
+
// which breaks a genuinely-live peer — the one case the old comment admitted
|
|
143
|
+
// it could not distinguish.
|
|
138
144
|
if (!opened && isLockHeld(openErr)) {
|
|
139
145
|
try {
|
|
140
146
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
141
147
|
const fs = require('fs');
|
|
142
148
|
const lockPath = `${rvfPath}.lock`;
|
|
143
|
-
if (fs.existsSync(lockPath)) {
|
|
149
|
+
if (fs.existsSync(lockPath) && isLockHeldByLiveProcess(rvfPath)) {
|
|
150
|
+
console.warn(`[RVF] ${rvfPath} is locked by a live process (pid ${readLockOwnerPid(rvfPath)}) — ` +
|
|
151
|
+
'not breaking the lock; degrading to SQLite for this run.');
|
|
152
|
+
}
|
|
153
|
+
else if (fs.existsSync(lockPath)) {
|
|
144
154
|
fs.unlinkSync(lockPath);
|
|
145
155
|
console.warn(`[RVF] Removed stale lock file at ${lockPath} (prior process exited without closing). ` +
|
|
146
156
|
'Retrying open. If you see this repeatedly under live concurrency, file an issue.');
|
|
@@ -187,6 +197,14 @@ function openOrCreateRvf(openFn, createFn, rvfPath, dimensions) {
|
|
|
187
197
|
return reopened;
|
|
188
198
|
}
|
|
189
199
|
catch {
|
|
200
|
+
// Pass 4 (#563): open failed, create failed, re-open failed. The file is
|
|
201
|
+
// provably unusable — the signature of an export killed mid-write, which
|
|
202
|
+
// used to disable the RVF backend permanently. Quarantine it (unless a
|
|
203
|
+
// live process holds its lock) and rebuild the derived cache.
|
|
204
|
+
const quarantined = quarantineUnusableStore(rvfPath, createErr instanceof Error ? createErr.message : String(createErr));
|
|
205
|
+
if (quarantined) {
|
|
206
|
+
return createFn(rvfPath, dimensions);
|
|
207
|
+
}
|
|
190
208
|
// Fall through with the more informative original error.
|
|
191
209
|
throw createErr instanceof Error ? createErr : new Error(String(createErr));
|
|
192
210
|
}
|
|
@@ -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}`);
|
|
@@ -11,7 +11,13 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
11
11
|
import { findProjectRoot } from '../kernel/project-root.js';
|
|
12
12
|
import { ok, err } from '../shared/types/index.js';
|
|
13
13
|
import { RvfPatternStore } from './rvf-pattern-store.js';
|
|
14
|
-
import { createRvfStore as _createRvfStore, isRvfNativeAvailable } from '../integrations/ruvector/rvf-native-adapter.js';
|
|
14
|
+
import { createRvfStore as _createRvfStore, openRvfStore as _openRvfStore, isRvfNativeAvailable, } from '../integrations/ruvector/rvf-native-adapter.js';
|
|
15
|
+
// Issue #563: static imports — a require() of a source module resolves in the
|
|
16
|
+
// esbuild bundle but throws under the test runner, which silently changed which
|
|
17
|
+
// code path tests exercised. Neither module loads the native binding at import
|
|
18
|
+
// time, so this costs nothing at startup.
|
|
19
|
+
import { quarantineUnusableStore } from '../integrations/ruvector/rvf-store-integrity.js';
|
|
20
|
+
import { getSharedRvfAdapter } from '../integrations/ruvector/shared-rvf-adapter.js';
|
|
15
21
|
import { toErrorMessage, toError } from '../shared/error-utils.js';
|
|
16
22
|
import { calculateQualityScore, shouldPromotePattern, validateQEPattern, mapQEDomainToAQE, PROMOTION_THRESHOLD, } from './qe-patterns.js';
|
|
17
23
|
import { applyFilterSync } from '../integrations/ruvector/filter-adapter.js';
|
|
@@ -1419,7 +1425,9 @@ export function createPatternStore(memory, config) {
|
|
|
1419
1425
|
// deadlock on the native lock.
|
|
1420
1426
|
let useSharedAdapter = false;
|
|
1421
1427
|
try {
|
|
1422
|
-
|
|
1428
|
+
// Statically imported (#563): this require() throws "Cannot find
|
|
1429
|
+
// module" under the test runner, so every test silently took the
|
|
1430
|
+
// fallback ladder below instead of this preferred path.
|
|
1423
1431
|
const shared = getSharedRvfAdapter(rvfDir, mergedConfig.embeddingDimension);
|
|
1424
1432
|
if (shared) {
|
|
1425
1433
|
useSharedAdapter = true;
|
|
@@ -1439,11 +1447,13 @@ export function createPatternStore(memory, config) {
|
|
|
1439
1447
|
// open first, fall back to create, retry open on create-race.
|
|
1440
1448
|
// (Jordi #439 / RUFLO P020.)
|
|
1441
1449
|
const store = new RvfPatternStore((path, dim) => {
|
|
1442
|
-
//
|
|
1443
|
-
|
|
1450
|
+
// Statically imported (#563): a require() here resolves in the
|
|
1451
|
+
// esbuild bundle but throws "Cannot find module" under the test
|
|
1452
|
+
// runner, so this ladder — including its corruption recovery —
|
|
1453
|
+
// was unreachable from any test.
|
|
1444
1454
|
const tryOpen = () => {
|
|
1445
1455
|
try {
|
|
1446
|
-
return
|
|
1456
|
+
return _openRvfStore(path);
|
|
1447
1457
|
}
|
|
1448
1458
|
catch {
|
|
1449
1459
|
return null;
|
|
@@ -1467,6 +1477,14 @@ export function createPatternStore(memory, config) {
|
|
|
1467
1477
|
adapter = tryOpen();
|
|
1468
1478
|
if (adapter && adapter.dimension() === dim)
|
|
1469
1479
|
return adapter;
|
|
1480
|
+
// Issue #563: open failed, create failed, re-open failed — the
|
|
1481
|
+
// store is provably unusable (an export killed mid-write leaves
|
|
1482
|
+
// exactly this). Without recovery, RvfPatternStore.initialize()
|
|
1483
|
+
// logs "vector search is DISABLED" and stays that way for the
|
|
1484
|
+
// life of the process.
|
|
1485
|
+
if (quarantineUnusableStore(path, createErr instanceof Error ? createErr.message : String(createErr))) {
|
|
1486
|
+
return _createRvfStore(path, dim);
|
|
1487
|
+
}
|
|
1470
1488
|
throw createErr;
|
|
1471
1489
|
}
|
|
1472
1490
|
}, { rvfPath, base: mergedConfig });
|
|
@@ -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';
|