agentic-qe 3.8.13 → 3.9.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/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +48 -0
- package/dist/adapters/a2ui/integration/agui-sync.js +2 -1
- package/dist/audit/witness-chain.js +15 -3
- package/dist/boot/fast-paths.d.ts +24 -0
- package/dist/boot/fast-paths.js +43 -0
- package/dist/boot/parallel-prefetch.d.ts +26 -0
- package/dist/boot/parallel-prefetch.js +36 -0
- package/dist/cli/bundle.js +12 -9431
- package/dist/cli/chunks/adapter-WBR5NXS3.js +2 -0
- package/dist/cli/chunks/agent-booster-wasm-PQYB7VRU.js +2 -0
- package/dist/cli/chunks/agent-handler-QDAB5NQS.js +33 -0
- package/dist/cli/chunks/aqe-learning-engine-TK4JQCGT.js +2 -0
- package/dist/cli/chunks/audit-S7JUYYVP.js +3 -0
- package/dist/cli/chunks/base-2WXOSMBQ.js +2 -0
- package/dist/cli/chunks/better-sqlite3-7KY2RDXO.js +2 -0
- package/dist/cli/chunks/brain-handler-PPEGDCN4.js +68 -0
- package/dist/cli/chunks/branch-enumerator-XK4V5W7L.js +7 -0
- package/dist/cli/chunks/browser-PALA5PL3.js +4 -0
- package/dist/cli/chunks/browser-workflow-42F7GK5T.js +2 -0
- package/dist/cli/chunks/chunk-24FKIJNC.js +15 -0
- package/dist/cli/chunks/chunk-263XS447.js +2 -0
- package/dist/cli/chunks/chunk-2BZFNEN2.js +4 -0
- package/dist/cli/chunks/chunk-2E5NQNSU.js +180 -0
- package/dist/cli/chunks/chunk-2I7J3O6V.js +2 -0
- package/dist/cli/chunks/chunk-3ADGXLTM.js +14 -0
- package/dist/cli/chunks/chunk-3IHG3WOY.js +12 -0
- package/dist/cli/chunks/chunk-3IUNFTIF.js +2 -0
- package/dist/cli/chunks/chunk-3JPRUND5.js +2 -0
- package/dist/cli/chunks/chunk-3NZLZHJI.js +2 -0
- package/dist/cli/chunks/chunk-3THRQEZ2.js +95 -0
- package/dist/cli/chunks/chunk-3ZOONQG6.js +2 -0
- package/dist/cli/chunks/chunk-4B6NCELM.js +2 -0
- package/dist/cli/chunks/chunk-4I2IOUS4.js +2 -0
- package/dist/cli/chunks/chunk-4VBTXZRM.js +2 -0
- package/dist/cli/chunks/chunk-4VUPRTVX.js +3 -0
- package/dist/cli/chunks/chunk-4YOMLWEK.js +70 -0
- package/dist/cli/chunks/chunk-4YS3IJ45.js +2 -0
- package/dist/cli/chunks/chunk-5SKGFSKD.js +2 -0
- package/dist/cli/chunks/chunk-5T2ZQWKF.js +27 -0
- package/dist/cli/chunks/chunk-62ADTHV7.js +2 -0
- package/dist/cli/chunks/chunk-6EOS7KX2.js +2 -0
- package/dist/cli/chunks/chunk-6SVX4DJC.js +6 -0
- package/dist/cli/chunks/chunk-72WOAVK6.js +2 -0
- package/dist/cli/chunks/chunk-7R6YMLVS.js +3 -0
- package/dist/cli/chunks/chunk-7VDBAVTY.js +2 -0
- package/dist/cli/chunks/chunk-AFLLQ5PP.js +15 -0
- package/dist/cli/chunks/chunk-AKE543X2.js +2 -0
- package/dist/cli/chunks/chunk-B36CDR4U.js +2 -0
- package/dist/cli/chunks/chunk-B6LLWYQ6.js +2 -0
- package/dist/cli/chunks/chunk-BDIEMZ22.js +91 -0
- package/dist/cli/chunks/chunk-BGXNSCXX.js +4 -0
- package/dist/cli/chunks/chunk-BLBRY5UD.js +2 -0
- package/dist/cli/chunks/chunk-BPWXXEH2.js +3029 -0
- package/dist/cli/chunks/chunk-BR26T7ZS.js +180 -0
- package/dist/cli/chunks/chunk-BTREG4IW.js +2 -0
- package/dist/cli/chunks/chunk-BULKFVYX.js +2 -0
- package/dist/cli/chunks/chunk-BXAXGEFC.js +24 -0
- package/dist/cli/chunks/chunk-CL6POIX4.js +2 -0
- package/dist/cli/chunks/chunk-CS2KS7LP.js +2 -0
- package/dist/cli/chunks/chunk-CWFB6BSA.js +316 -0
- package/dist/cli/chunks/chunk-DRT3WKQW.js +2 -0
- package/dist/cli/chunks/chunk-EHDQJQ6Y.js +27 -0
- package/dist/cli/chunks/chunk-ESVQ6MEB.js +2 -0
- package/dist/cli/chunks/chunk-FEKY7T6Q.js +2 -0
- package/dist/cli/chunks/chunk-FGA7VIFR.js +7 -0
- package/dist/cli/chunks/chunk-FIA6X7UL.js +2 -0
- package/dist/cli/chunks/chunk-GAOJV3OX.js +2 -0
- package/dist/cli/chunks/chunk-GKNNSCLC.js +5 -0
- package/dist/cli/chunks/chunk-GPQ57KA4.js +2 -0
- package/dist/cli/chunks/chunk-GRUUQAR6.js +2 -0
- package/dist/cli/chunks/chunk-HRO6OZQD.js +2 -0
- package/dist/cli/chunks/chunk-HY6PMO5W.js +66 -0
- package/dist/cli/chunks/chunk-IAV2JMIX.js +167 -0
- package/dist/cli/chunks/chunk-IFNIIK34.js +21 -0
- package/dist/cli/chunks/chunk-IGJPMN4I.js +3 -0
- package/dist/cli/chunks/chunk-J3KWWR6Z.js +1 -0
- package/dist/cli/chunks/chunk-JBANAPWG.js +2 -0
- package/dist/cli/chunks/chunk-JJO7Y4H3.js +604 -0
- package/dist/cli/chunks/chunk-JRYGQO2W.js +2 -0
- package/dist/cli/chunks/chunk-JXM26HEE.js +2 -0
- package/dist/cli/chunks/chunk-JZSDOIXA.js +2 -0
- package/dist/cli/chunks/chunk-KP5NUODU.js +3 -0
- package/dist/cli/chunks/chunk-LHJQD2VU.js +750 -0
- package/dist/cli/chunks/chunk-LNQIY6BP.js +2 -0
- package/dist/cli/chunks/chunk-MDUHYUHF.js +2 -0
- package/dist/cli/chunks/chunk-MV6CMOJQ.js +65 -0
- package/dist/cli/chunks/chunk-MZOFWJTM.js +2 -0
- package/dist/cli/chunks/chunk-N2NS2PHA.js +45 -0
- package/dist/cli/chunks/chunk-N4TL73TH.js +314 -0
- package/dist/cli/chunks/chunk-N5UXCLFI.js +2 -0
- package/dist/cli/chunks/chunk-NZ2VCPN4.js +2 -0
- package/dist/cli/chunks/chunk-OF4D7MYI.js +2 -0
- package/dist/cli/chunks/chunk-OI5NGQO2.js +2 -0
- package/dist/cli/chunks/chunk-OLHKGP35.js +2 -0
- package/dist/cli/chunks/chunk-QOVHWZEP.js +1 -0
- package/dist/cli/chunks/chunk-RFSN6IDA.js +79 -0
- package/dist/cli/chunks/chunk-RTGGL7D7.js +4 -0
- package/dist/cli/chunks/chunk-RU5WAHB7.js +3 -0
- package/dist/cli/chunks/chunk-SUSEVMZT.js +2 -0
- package/dist/cli/chunks/chunk-TLHP5EII.js +2 -0
- package/dist/cli/chunks/chunk-TWUWL5EJ.js +2 -0
- package/dist/cli/chunks/chunk-U5RN7YQW.js +2 -0
- package/dist/cli/chunks/chunk-UFUVUO3J.js +2 -0
- package/dist/cli/chunks/chunk-UQHYFOBX.js +16 -0
- package/dist/cli/chunks/chunk-VOS4NQSF.js +2 -0
- package/dist/cli/chunks/chunk-VSVXUTJN.js +256 -0
- package/dist/cli/chunks/chunk-WBQSXPBI.js +2 -0
- package/dist/cli/chunks/chunk-WGMPEW2T.js +2 -0
- package/dist/cli/chunks/chunk-WIEC7VKK.js +2 -0
- package/dist/cli/chunks/chunk-WJ3DLOXF.js +14 -0
- package/dist/cli/chunks/chunk-X3KI6JOY.js +9 -0
- package/dist/cli/chunks/chunk-X5IJGWYG.js +2 -0
- package/dist/cli/chunks/chunk-XIBDETCS.js +146 -0
- package/dist/cli/chunks/chunk-XLRQYLWW.js +2 -0
- package/dist/cli/chunks/chunk-XO6PVK2P.js +3 -0
- package/dist/cli/chunks/chunk-XRE2HCWG.js +3 -0
- package/dist/cli/chunks/chunk-XT2V2322.js +2 -0
- package/dist/cli/chunks/chunk-Y7BHKZFJ.js +18 -0
- package/dist/cli/chunks/chunk-YAGODYIG.js +59 -0
- package/dist/cli/chunks/chunk-YANUP2RO.js +2 -0
- package/dist/cli/chunks/chunk-YPFOCNOE.js +30 -0
- package/dist/cli/chunks/chunk-YR6ZZGH7.js +81 -0
- package/dist/cli/chunks/chunk-YVA65UZL.js +2 -0
- package/dist/cli/chunks/chunk-YW2THB5Q.js +2 -0
- package/dist/cli/chunks/chunk-ZAPS3UGQ.js +20 -0
- package/dist/cli/chunks/chunk-ZDATDCYN.js +2 -0
- package/dist/cli/chunks/ci-J374KDLI.js +81 -0
- package/dist/cli/chunks/ci-output-7JN7F6CI.js +2 -0
- package/dist/cli/chunks/claude-flow-setup-245JLJCN.js +2 -0
- package/dist/cli/chunks/client-MCSNSH2C.js +2 -0
- package/dist/cli/chunks/cline-installer-LBA2M5N3.js +4 -0
- package/dist/cli/chunks/code-U4N4WONM.js +38 -0
- package/dist/cli/chunks/code-index-extractor-A57Z6BO4.js +3 -0
- package/dist/cli/chunks/codex-installer-UXMK2N4T.js +8 -0
- package/dist/cli/chunks/completions-W66BSCOE.js +1364 -0
- package/dist/cli/chunks/complexity-analyzer-AB4OZARV.js +2 -0
- package/dist/cli/chunks/continuedev-installer-LRFZ2SJM.js +14 -0
- package/dist/cli/chunks/copilot-installer-CQ3JYBIB.js +3 -0
- package/dist/cli/chunks/cost-tracker-4F723RB6.js +2 -0
- package/dist/cli/chunks/coverage-4PUEQXAY.js +27 -0
- package/dist/cli/chunks/cross-domain-router-OWR5IJ5G.js +2 -0
- package/dist/cli/chunks/cursor-installer-JZEDEDHA.js +3 -0
- package/dist/cli/chunks/daemon-B7TWGHXQ.js +19 -0
- package/dist/cli/chunks/dag-attention-scheduler-JWO6XI6A.js +2 -0
- package/dist/cli/chunks/detect-L6ZZHUSX.js +2 -0
- package/dist/cli/chunks/domain-handler-FT5FLZWL.js +25 -0
- package/dist/cli/chunks/domain-transfer-5Y4FGJAJ.js +2 -0
- package/dist/cli/chunks/dream-4TDBIYED.js +2 -0
- package/dist/cli/chunks/esm-node-2PKHKOTS.js +2 -0
- package/dist/cli/chunks/eval-GHMPFGWV.js +15 -0
- package/dist/cli/chunks/fast-paths-B3R647KN.js +2 -0
- package/dist/cli/chunks/feature-flags-DWS7ARSX.js +2 -0
- package/dist/cli/chunks/feature-flags-IVQ3AL4Q.js +2 -0
- package/dist/cli/chunks/file-discovery-QFPA6GMV.js +2 -0
- package/dist/cli/chunks/fleet-EKOKMOMW.js +43 -0
- package/dist/cli/chunks/gnn-wrapper-OYC55N5E.js +2 -0
- package/dist/cli/chunks/heartbeat-handler-MBBS4IBU.js +48 -0
- package/dist/cli/chunks/heartbeat-scheduler-XDGMOT7X.js +2 -0
- package/dist/cli/chunks/hnsw-index-YO7CT23I.js +2 -0
- package/dist/cli/chunks/hnswlib-node-56YWVXFE.js +2 -0
- package/dist/cli/chunks/hooks-L5VLZGEK.js +101 -0
- package/dist/cli/chunks/hypergraph-engine-A4Y2ZRAG.js +2 -0
- package/dist/cli/chunks/hypergraph-handler-3HDGB5SZ.js +35 -0
- package/dist/cli/chunks/impact-analyzer-UEIGXSZ4.js +2 -0
- package/dist/cli/chunks/init-handler-JDET6WUN.js +68 -0
- package/dist/cli/chunks/init-wizard-JWZUGIPJ.js +2 -0
- package/dist/cli/chunks/kernel-YNDTVKIW.js +2 -0
- package/dist/cli/chunks/kilocode-installer-GZZG5AFW.js +4 -0
- package/dist/cli/chunks/kiro-installer-IWNY5TKH.js +74 -0
- package/dist/cli/chunks/knowledge-graph-NGJKFTSN.js +2 -0
- package/dist/cli/chunks/learning-722ZNSZ6.js +107 -0
- package/dist/cli/chunks/llm-router-DNAV746L.js +30 -0
- package/dist/cli/chunks/load-Y3GCUFM4.js +2 -0
- package/dist/cli/chunks/load-test-GZUBXFF3.js +2 -0
- package/dist/cli/chunks/mcp-LKPIBZ3W.js +2 -0
- package/dist/cli/chunks/memory-L57MLFOP.js +32 -0
- package/dist/cli/chunks/memory-backend-3NQIZUXE.js +2 -0
- package/dist/cli/chunks/memory-handlers-MDZQ7HVW.js +2 -0
- package/dist/cli/chunks/opencode-installer-4HUB36H5.js +3 -0
- package/dist/cli/chunks/orchestrator-QHSBB2UC.js +371 -0
- package/dist/cli/chunks/pipeline-D3QER35Z.js +19 -0
- package/dist/cli/chunks/platform-T4E7Q3RD.js +2 -0
- package/dist/cli/chunks/plugin-JHW2YPRC.js +27 -0
- package/dist/cli/chunks/prime-radiant-advanced-wasm-G7CFNNQV.js +2 -0
- package/dist/cli/chunks/protocol-executor-SPUVRDWT.js +2 -0
- package/dist/cli/chunks/protocol-handler-2BQQ4HDM.js +20 -0
- package/dist/cli/chunks/prove-UQ6JFT73.js +3 -0
- package/dist/cli/chunks/qe-reasoning-bank-3HBK2FVD.js +2 -0
- package/dist/cli/chunks/quality-JRZYMC77.js +7 -0
- package/dist/cli/chunks/queen-coordinator-RW3NKO5A.js +2 -0
- package/dist/cli/chunks/real-embeddings-GK63VF35.js +2 -0
- package/dist/cli/chunks/roocode-installer-F4E2LAYR.js +4 -0
- package/dist/cli/chunks/router-RJGHWDQ3.js +2 -0
- package/dist/cli/chunks/routing-feedback-ZXBXFKX6.js +2 -0
- package/dist/cli/chunks/routing-handler-VNKFUUGB.js +20 -0
- package/dist/cli/chunks/ruvector-commands-2TLNHC3A.js +8 -0
- package/dist/cli/chunks/rvf-dual-writer-MQW2SJLT.js +2 -0
- package/dist/cli/chunks/rvf-native-adapter-LKFKTMUN.js +2 -0
- package/dist/cli/chunks/safe-db-G22E5ROA.js +2 -0
- package/dist/cli/chunks/schedule-Y7VVCPYV.js +2 -0
- package/dist/cli/chunks/scheduler-AUQIFQB7.js +2 -0
- package/dist/cli/chunks/security-EBEG2OPU.js +14 -0
- package/dist/cli/chunks/shared-rvf-dual-writer-BVSCQAFS.js +2 -0
- package/dist/cli/chunks/sqlite-persistence-JAVHUGGL.js +2 -0
- package/dist/cli/chunks/status-handler-VZ32M4G4.js +45 -0
- package/dist/cli/chunks/structural-health-K6LRCKV6.js +2 -0
- package/dist/cli/chunks/sync-MHSHNLIM.js +23 -0
- package/dist/cli/chunks/task-handler-JNOIBZ2G.js +49 -0
- package/dist/cli/chunks/task-handlers-P5DSUKND.js +2 -0
- package/dist/cli/chunks/test-DO22BNIL.js +33 -0
- package/dist/cli/chunks/test-scheduling-VLRQZEFL.js +15 -0
- package/dist/cli/chunks/token-bootstrap-4VJKGVMK.js +2 -0
- package/dist/cli/chunks/token-usage-LG3PXRXH.js +25 -0
- package/dist/cli/chunks/transformers-GY7SIKEU.js +2 -0
- package/dist/cli/chunks/tree-sitter-wasm-parser-FT2KB66N.js +2 -0
- package/dist/cli/chunks/types-QJGNBKP2.js +2 -0
- package/dist/cli/chunks/unified-memory-XYGENQUT.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-MVEGQBF3.js +2 -0
- package/dist/cli/chunks/unified-persistence-PFRCWEUG.js +2 -0
- package/dist/cli/chunks/validate-VQCRSVNQ.js +21 -0
- package/dist/cli/chunks/validate-swarm-A5DHAWTP.js +14 -0
- package/dist/cli/chunks/vibium-RZBSL4EB.js +2 -0
- package/dist/cli/chunks/visual-security-V47BLGJM.js +2 -0
- package/dist/cli/chunks/web-tree-sitter-7C4NXEOF.js +2 -0
- package/dist/cli/chunks/windsurf-installer-ES3KPQG3.js +7 -0
- package/dist/cli/chunks/witness-chain-BR63P4A7.js +2 -0
- package/dist/cli/chunks/workflow-JETHX4ML.js +51 -0
- package/dist/cli/chunks/workflow-orchestrator-7PZMX3JZ.js +2 -0
- package/dist/cli/chunks/wrappers-WP5RH745.js +2 -0
- package/dist/cli/commands/daemon.d.ts +13 -0
- package/dist/cli/commands/daemon.js +224 -0
- package/dist/cli/commands/hooks-handlers/hooks-shared.js +2 -1
- package/dist/cli/commands/plugin.d.ts +12 -0
- package/dist/cli/commands/plugin.js +135 -0
- package/dist/cli/commands/workflow.d.ts +10 -0
- package/dist/cli/commands/workflow.js +587 -0
- package/dist/cli/handlers/brain-handler.js +13 -8
- package/dist/cli/handlers/heartbeat-handler.d.ts +1 -0
- package/dist/cli/handlers/heartbeat-handler.js +20 -10
- package/dist/cli/handlers/hypergraph-handler.js +3 -3
- package/dist/cli/handlers/init-handler.js +10 -9
- package/dist/cli/handlers/interfaces.d.ts +4 -4
- package/dist/cli/index.js +159 -638
- package/dist/cli/lazy-registry.d.ts +27 -0
- package/dist/cli/lazy-registry.js +70 -0
- package/dist/context/compaction/context-budget.d.ts +71 -0
- package/dist/context/compaction/context-budget.js +120 -0
- package/dist/context/compaction/index.d.ts +96 -0
- package/dist/context/compaction/index.js +259 -0
- package/dist/context/compaction/llm-caller-adapter.d.ts +14 -0
- package/dist/context/compaction/llm-caller-adapter.js +47 -0
- package/dist/context/compaction/tier1-microcompact.d.ts +33 -0
- package/dist/context/compaction/tier1-microcompact.js +47 -0
- package/dist/context/compaction/tier2-session-summary.d.ts +72 -0
- package/dist/context/compaction/tier2-session-summary.js +172 -0
- package/dist/context/compaction/tier3-llm-compact.d.ts +65 -0
- package/dist/context/compaction/tier3-llm-compact.js +166 -0
- package/dist/context/compaction/tier4-reactive.d.ts +54 -0
- package/dist/context/compaction/tier4-reactive.js +129 -0
- package/dist/coordination/consensus/providers/claude-provider.d.ts +1 -0
- package/dist/coordination/consensus/providers/claude-provider.js +23 -3
- package/dist/domains/test-generation/generators/base-test-generator.d.ts +1 -1
- package/dist/domains/test-generation/generators/base-test-generator.js +11 -11
- package/dist/domains/test-generation/generators/go-test-generator.js +12 -12
- package/dist/domains/test-generation/generators/junit5-generator.js +9 -9
- package/dist/domains/test-generation/generators/kotlin-junit-generator.js +10 -10
- package/dist/domains/test-generation/generators/pytest-generator.js +8 -8
- package/dist/domains/test-generation/generators/swift-testing-generator.js +8 -8
- package/dist/domains/test-generation/generators/test-value-helpers.d.ts +20 -0
- package/dist/domains/test-generation/generators/test-value-helpers.js +48 -0
- package/dist/domains/test-generation/generators/xunit-generator.js +11 -11
- package/dist/hooks/cross-phase-hooks.d.ts +11 -0
- package/dist/hooks/cross-phase-hooks.js +73 -9
- package/dist/hooks/security/config-snapshot.d.ts +21 -0
- package/dist/hooks/security/config-snapshot.js +33 -0
- package/dist/hooks/security/exit-codes.d.ts +28 -0
- package/dist/hooks/security/exit-codes.js +33 -0
- package/dist/hooks/security/index.d.ts +15 -0
- package/dist/hooks/security/index.js +15 -0
- package/dist/hooks/security/ssrf-guard.d.ts +25 -0
- package/dist/hooks/security/ssrf-guard.js +69 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -2
- package/dist/init/init-wizard-hooks.js +15 -1
- package/dist/init/phases/07-hooks.js +2 -2
- package/dist/init/settings-merge.js +3 -7
- package/dist/kernel/kernel.js +35 -0
- package/dist/kernel/memory-backend.js +3 -1
- package/dist/mcp/bundle.js +416 -362
- package/dist/mcp/entry.js +132 -77
- package/dist/mcp/http-server.js +4 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.js +5 -4
- package/dist/mcp/middleware/batch-executor.d.ts +46 -0
- package/dist/mcp/middleware/batch-executor.js +150 -0
- package/dist/mcp/middleware/microcompact.d.ts +97 -0
- package/dist/mcp/middleware/microcompact.js +179 -0
- package/dist/mcp/middleware/middleware-chain.d.ts +37 -0
- package/dist/mcp/middleware/middleware-chain.js +60 -0
- package/dist/mcp/protocol-server.d.ts +16 -0
- package/dist/mcp/protocol-server.js +140 -36
- package/dist/mcp/services/session-durability-middleware.d.ts +22 -0
- package/dist/mcp/services/session-durability-middleware.js +64 -0
- package/dist/mcp/services/session-resume.d.ts +29 -0
- package/dist/mcp/services/session-resume.js +221 -0
- package/dist/mcp/services/session-store.d.ts +84 -0
- package/dist/mcp/services/session-store.js +163 -0
- package/dist/mcp/tool-registry.d.ts +9 -0
- package/dist/mcp/tool-registry.js +30 -1
- package/dist/mcp/types.d.ts +1 -0
- package/dist/plugins/cache.d.ts +44 -0
- package/dist/plugins/cache.js +149 -0
- package/dist/plugins/index.d.ts +15 -0
- package/dist/plugins/index.js +15 -0
- package/dist/plugins/lifecycle.d.ts +67 -0
- package/dist/plugins/lifecycle.js +175 -0
- package/dist/plugins/manifest.d.ts +45 -0
- package/dist/plugins/manifest.js +173 -0
- package/dist/plugins/resolver.d.ts +37 -0
- package/dist/plugins/resolver.js +80 -0
- package/dist/plugins/security.d.ts +23 -0
- package/dist/plugins/security.js +125 -0
- package/dist/plugins/sources/github.d.ts +17 -0
- package/dist/plugins/sources/github.js +77 -0
- package/dist/plugins/sources/local.d.ts +20 -0
- package/dist/plugins/sources/local.js +32 -0
- package/dist/plugins/sources/npm.d.ts +18 -0
- package/dist/plugins/sources/npm.js +82 -0
- package/dist/shared/llm/retry.d.ts +5 -2
- package/dist/shared/llm/retry.js +7 -3
- package/dist/shared/prompt-cache-latch.d.ts +41 -0
- package/dist/shared/prompt-cache-latch.js +63 -0
- package/dist/shared/retry-engine.d.ts +77 -0
- package/dist/shared/retry-engine.js +194 -0
- package/dist/workers/daemon.d.ts +8 -0
- package/dist/workers/daemon.js +13 -0
- package/dist/workers/quality-daemon/ci-monitor.d.ts +55 -0
- package/dist/workers/quality-daemon/ci-monitor.js +147 -0
- package/dist/workers/quality-daemon/coverage-delta.d.ts +72 -0
- package/dist/workers/quality-daemon/coverage-delta.js +135 -0
- package/dist/workers/quality-daemon/git-watcher.d.ts +51 -0
- package/dist/workers/quality-daemon/git-watcher.js +209 -0
- package/dist/workers/quality-daemon/index.d.ts +119 -0
- package/dist/workers/quality-daemon/index.js +343 -0
- package/dist/workers/quality-daemon/nightly-consolidation.d.ts +74 -0
- package/dist/workers/quality-daemon/nightly-consolidation.js +136 -0
- package/dist/workers/quality-daemon/notification-service.d.ts +67 -0
- package/dist/workers/quality-daemon/notification-service.js +178 -0
- package/dist/workers/quality-daemon/persistent-memory.d.ts +31 -0
- package/dist/workers/quality-daemon/persistent-memory.js +30 -0
- package/dist/workers/quality-daemon/priority-queue.d.ts +97 -0
- package/dist/workers/quality-daemon/priority-queue.js +126 -0
- package/dist/workers/quality-daemon/test-suggester.d.ts +50 -0
- package/dist/workers/quality-daemon/test-suggester.js +121 -0
- package/dist/workers/worker-manager.js +2 -1
- package/package.json +1 -1
- package/dist/mcp/server.d.ts +0 -46
- package/dist/mcp/server.js +0 -802
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Unified Retry Engine
|
|
3
|
+
* IMP-03: Retry Engine with Exponential Backoff
|
|
4
|
+
*
|
|
5
|
+
* Provides a single, well-tested retry loop with exponential backoff,
|
|
6
|
+
* jitter, abort signal support, and retryable-error classification.
|
|
7
|
+
*
|
|
8
|
+
* The circuit breaker (circuit-breaker.ts) is a separate concern that
|
|
9
|
+
* receives success/failure signals from callers — this engine does NOT
|
|
10
|
+
* import or depend on it. Integration is planned for a later phase.
|
|
11
|
+
*/
|
|
12
|
+
export interface RetryOptions {
|
|
13
|
+
/** Maximum number of attempts (including the first). Default: 5 */
|
|
14
|
+
maxAttempts: number;
|
|
15
|
+
/** Base delay in milliseconds before the first retry. Default: 1000 */
|
|
16
|
+
baseDelayMs: number;
|
|
17
|
+
/** Upper cap for the computed delay. Default: 32000 */
|
|
18
|
+
maxDelayMs: number;
|
|
19
|
+
/** Fraction of the exponential value added as random jitter (0–1). Default: 0.25 */
|
|
20
|
+
jitterFraction: number;
|
|
21
|
+
/** Optional predicate to override the built-in retryable-error check. */
|
|
22
|
+
retryableErrors?: (error: unknown) => boolean;
|
|
23
|
+
/** Called before each retry sleep — useful for logging / metrics. */
|
|
24
|
+
onRetry?: (attempt: number, error: unknown, delayMs: number) => void;
|
|
25
|
+
/** If the signal fires, the retry loop is cancelled immediately. */
|
|
26
|
+
abortSignal?: AbortSignal;
|
|
27
|
+
}
|
|
28
|
+
export interface RetryResult<T> {
|
|
29
|
+
/** The successful return value. */
|
|
30
|
+
result: T;
|
|
31
|
+
/** Total number of attempts made (1 = succeeded on first try). */
|
|
32
|
+
attempts: number;
|
|
33
|
+
/** Sum of all actual delays waited (ms). */
|
|
34
|
+
totalDelayMs: number;
|
|
35
|
+
/** Record of each retried error (does NOT include the successful attempt). */
|
|
36
|
+
retriedErrors: Array<{
|
|
37
|
+
attempt: number;
|
|
38
|
+
error: string;
|
|
39
|
+
delayMs: number;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compute the delay for a given attempt using exponential backoff + jitter.
|
|
44
|
+
*
|
|
45
|
+
* Formula: `min(baseMs * 2^attempt, maxMs) + random(0, jitterFraction * exponential)`
|
|
46
|
+
*
|
|
47
|
+
* The jitter component is based on the *capped* exponential value so it
|
|
48
|
+
* stays proportional regardless of the cap.
|
|
49
|
+
*/
|
|
50
|
+
export declare function computeBackoff(attempt: number, baseMs: number, maxMs: number, jitterFraction: number): number;
|
|
51
|
+
/**
|
|
52
|
+
* Determine whether an error is transient and therefore worth retrying.
|
|
53
|
+
*
|
|
54
|
+
* Checks — in order:
|
|
55
|
+
* 1. Error `code` property against known errno strings.
|
|
56
|
+
* 2. `status` / `statusCode` property against HTTP status sets.
|
|
57
|
+
* 3. Error message substrings for common transient phrases.
|
|
58
|
+
*
|
|
59
|
+
* Returns `false` for recognised non-retryable client errors (4xx).
|
|
60
|
+
*/
|
|
61
|
+
export declare function isRetryableError(error: unknown): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Execute `fn` with automatic retries on transient errors.
|
|
64
|
+
*
|
|
65
|
+
* On each failure the engine:
|
|
66
|
+
* 1. Checks whether the error is retryable (via `options.retryableErrors`
|
|
67
|
+
* or the built-in `isRetryableError`).
|
|
68
|
+
* 2. If not retryable, throws immediately.
|
|
69
|
+
* 3. If retryable and attempts remain, computes an exponential-backoff
|
|
70
|
+
* delay with jitter, calls `onRetry`, then sleeps.
|
|
71
|
+
* 4. If all attempts are exhausted, throws the last error.
|
|
72
|
+
*
|
|
73
|
+
* Supports `AbortSignal` — if the signal fires during a delay the
|
|
74
|
+
* promise rejects with an `AbortError`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options?: Partial<RetryOptions>): Promise<RetryResult<T>>;
|
|
77
|
+
//# sourceMappingURL=retry-engine.d.ts.map
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Unified Retry Engine
|
|
3
|
+
* IMP-03: Retry Engine with Exponential Backoff
|
|
4
|
+
*
|
|
5
|
+
* Provides a single, well-tested retry loop with exponential backoff,
|
|
6
|
+
* jitter, abort signal support, and retryable-error classification.
|
|
7
|
+
*
|
|
8
|
+
* The circuit breaker (circuit-breaker.ts) is a separate concern that
|
|
9
|
+
* receives success/failure signals from callers — this engine does NOT
|
|
10
|
+
* import or depend on it. Integration is planned for a later phase.
|
|
11
|
+
*/
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Defaults
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
const DEFAULT_OPTIONS = {
|
|
16
|
+
maxAttempts: 5,
|
|
17
|
+
baseDelayMs: 1000,
|
|
18
|
+
maxDelayMs: 32_000,
|
|
19
|
+
jitterFraction: 0.25,
|
|
20
|
+
};
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Backoff computation
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Compute the delay for a given attempt using exponential backoff + jitter.
|
|
26
|
+
*
|
|
27
|
+
* Formula: `min(baseMs * 2^attempt, maxMs) + random(0, jitterFraction * exponential)`
|
|
28
|
+
*
|
|
29
|
+
* The jitter component is based on the *capped* exponential value so it
|
|
30
|
+
* stays proportional regardless of the cap.
|
|
31
|
+
*/
|
|
32
|
+
export function computeBackoff(attempt, baseMs, maxMs, jitterFraction) {
|
|
33
|
+
const exponential = Math.min(baseMs * Math.pow(2, attempt), maxMs);
|
|
34
|
+
const jitter = Math.random() * jitterFraction * exponential;
|
|
35
|
+
return exponential + jitter;
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Error classification
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
/** Errno codes that indicate a transient network / OS-level problem. */
|
|
41
|
+
const RETRYABLE_CODES = new Set([
|
|
42
|
+
'ECONNRESET',
|
|
43
|
+
'ECONNREFUSED',
|
|
44
|
+
'ETIMEDOUT',
|
|
45
|
+
'EPIPE',
|
|
46
|
+
]);
|
|
47
|
+
/** HTTP status codes that are safe to retry. */
|
|
48
|
+
const RETRYABLE_HTTP_STATUSES = new Set([429, 500, 503, 529]);
|
|
49
|
+
/** HTTP status codes that should NOT be retried (client errors). */
|
|
50
|
+
const NON_RETRYABLE_HTTP_STATUSES = new Set([400, 401, 403, 404, 422]);
|
|
51
|
+
/**
|
|
52
|
+
* Determine whether an error is transient and therefore worth retrying.
|
|
53
|
+
*
|
|
54
|
+
* Checks — in order:
|
|
55
|
+
* 1. Error `code` property against known errno strings.
|
|
56
|
+
* 2. `status` / `statusCode` property against HTTP status sets.
|
|
57
|
+
* 3. Error message substrings for common transient phrases.
|
|
58
|
+
*
|
|
59
|
+
* Returns `false` for recognised non-retryable client errors (4xx).
|
|
60
|
+
*/
|
|
61
|
+
export function isRetryableError(error) {
|
|
62
|
+
if (error == null)
|
|
63
|
+
return false;
|
|
64
|
+
// --- code property (errno) -------------------------------------------
|
|
65
|
+
const code = error.code;
|
|
66
|
+
if (typeof code === 'string' && RETRYABLE_CODES.has(code)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
// --- HTTP status -----------------------------------------------------
|
|
70
|
+
const status = error.status ??
|
|
71
|
+
error.statusCode;
|
|
72
|
+
if (typeof status === 'number') {
|
|
73
|
+
if (NON_RETRYABLE_HTTP_STATUSES.has(status))
|
|
74
|
+
return false;
|
|
75
|
+
if (RETRYABLE_HTTP_STATUSES.has(status))
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
// --- message-based heuristic -----------------------------------------
|
|
79
|
+
const message = error instanceof Error
|
|
80
|
+
? error.message
|
|
81
|
+
: typeof error.message === 'string'
|
|
82
|
+
? error.message
|
|
83
|
+
: '';
|
|
84
|
+
if (message) {
|
|
85
|
+
const lower = message.toLowerCase();
|
|
86
|
+
if (lower.includes('econnreset') ||
|
|
87
|
+
lower.includes('econnrefused') ||
|
|
88
|
+
lower.includes('etimedout') ||
|
|
89
|
+
lower.includes('epipe') ||
|
|
90
|
+
lower.includes('rate limit') ||
|
|
91
|
+
lower.includes('too many requests') ||
|
|
92
|
+
lower.includes('service unavailable') ||
|
|
93
|
+
lower.includes('internal server error')) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Default: treat unknown errors as retryable to avoid silent failures.
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// Delay helper
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
/**
|
|
104
|
+
* Sleep for `ms` milliseconds, but reject immediately if `signal` fires.
|
|
105
|
+
*/
|
|
106
|
+
function delay(ms, signal) {
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
if (signal?.aborted) {
|
|
109
|
+
reject(signal.reason ?? new DOMException('The operation was aborted.', 'AbortError'));
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const timer = setTimeout(() => {
|
|
113
|
+
if (signal) {
|
|
114
|
+
signal.removeEventListener('abort', onAbort);
|
|
115
|
+
}
|
|
116
|
+
resolve();
|
|
117
|
+
}, ms);
|
|
118
|
+
function onAbort() {
|
|
119
|
+
clearTimeout(timer);
|
|
120
|
+
reject(signal.reason ?? new DOMException('The operation was aborted.', 'AbortError'));
|
|
121
|
+
}
|
|
122
|
+
if (signal) {
|
|
123
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// Core retry loop
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
/**
|
|
131
|
+
* Execute `fn` with automatic retries on transient errors.
|
|
132
|
+
*
|
|
133
|
+
* On each failure the engine:
|
|
134
|
+
* 1. Checks whether the error is retryable (via `options.retryableErrors`
|
|
135
|
+
* or the built-in `isRetryableError`).
|
|
136
|
+
* 2. If not retryable, throws immediately.
|
|
137
|
+
* 3. If retryable and attempts remain, computes an exponential-backoff
|
|
138
|
+
* delay with jitter, calls `onRetry`, then sleeps.
|
|
139
|
+
* 4. If all attempts are exhausted, throws the last error.
|
|
140
|
+
*
|
|
141
|
+
* Supports `AbortSignal` — if the signal fires during a delay the
|
|
142
|
+
* promise rejects with an `AbortError`.
|
|
143
|
+
*/
|
|
144
|
+
export async function withRetry(fn, options) {
|
|
145
|
+
// Kill switch: bypass retry entirely when disabled
|
|
146
|
+
if (process.env.AQE_RETRY_DISABLED === 'true') {
|
|
147
|
+
const result = await fn();
|
|
148
|
+
return { result, attempts: 1, totalDelayMs: 0, retriedErrors: [] };
|
|
149
|
+
}
|
|
150
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
151
|
+
const isRetryable = opts.retryableErrors ?? isRetryableError;
|
|
152
|
+
const retriedErrors = [];
|
|
153
|
+
let totalDelayMs = 0;
|
|
154
|
+
let lastError;
|
|
155
|
+
for (let attempt = 0; attempt < opts.maxAttempts; attempt++) {
|
|
156
|
+
// Check abort before each attempt.
|
|
157
|
+
if (opts.abortSignal?.aborted) {
|
|
158
|
+
throw opts.abortSignal.reason ?? new DOMException('The operation was aborted.', 'AbortError');
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const result = await fn();
|
|
162
|
+
return {
|
|
163
|
+
result,
|
|
164
|
+
attempts: attempt + 1,
|
|
165
|
+
totalDelayMs,
|
|
166
|
+
retriedErrors,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
lastError = error;
|
|
171
|
+
// Last attempt — don't bother checking retryability, just throw.
|
|
172
|
+
if (attempt === opts.maxAttempts - 1) {
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
// Non-retryable errors bubble immediately.
|
|
176
|
+
if (!isRetryable(error)) {
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
const backoff = computeBackoff(attempt, opts.baseDelayMs, opts.maxDelayMs, opts.jitterFraction);
|
|
180
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
181
|
+
retriedErrors.push({
|
|
182
|
+
attempt: attempt + 1,
|
|
183
|
+
error: errorMessage,
|
|
184
|
+
delayMs: backoff,
|
|
185
|
+
});
|
|
186
|
+
opts.onRetry?.(attempt + 1, error, backoff);
|
|
187
|
+
totalDelayMs += backoff;
|
|
188
|
+
await delay(backoff, opts.abortSignal);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// All attempts exhausted — throw last error.
|
|
192
|
+
throw lastError;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=retry-engine.js.map
|
package/dist/workers/daemon.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Provides start/stop/restart functionality and health monitoring.
|
|
7
7
|
*/
|
|
8
8
|
import { Daemon as IDaemon, DaemonStatus, WorkerManager } from './interfaces';
|
|
9
|
+
import { QualityDaemon, type QualityDaemonConfig } from './quality-daemon';
|
|
9
10
|
/**
|
|
10
11
|
* Daemon configuration
|
|
11
12
|
*/
|
|
@@ -28,6 +29,7 @@ export declare class QEDaemon implements IDaemon {
|
|
|
28
29
|
private _healthCheckTimer?;
|
|
29
30
|
private workerManager;
|
|
30
31
|
private config;
|
|
32
|
+
private _qualityDaemon?;
|
|
31
33
|
constructor(config?: DaemonConfig);
|
|
32
34
|
get running(): boolean;
|
|
33
35
|
get uptime(): number;
|
|
@@ -51,6 +53,12 @@ export declare class QEDaemon implements IDaemon {
|
|
|
51
53
|
* Get the worker manager for direct access
|
|
52
54
|
*/
|
|
53
55
|
getWorkerManager(): WorkerManager;
|
|
56
|
+
/**
|
|
57
|
+
* Get or create the quality daemon (IMP-10).
|
|
58
|
+
* The quality daemon provides proactive quality monitoring:
|
|
59
|
+
* git watching, coverage delta, CI health, test suggestions, nightly consolidation.
|
|
60
|
+
*/
|
|
61
|
+
getQualityDaemon(config?: QualityDaemonConfig): QualityDaemon;
|
|
54
62
|
/**
|
|
55
63
|
* Run a specific worker immediately
|
|
56
64
|
*/
|
package/dist/workers/daemon.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { WorkerManagerImpl } from './worker-manager';
|
|
9
9
|
// Import all QE workers (ADR-014)
|
|
10
10
|
import { TestHealthWorker, CoverageTrackerWorker, FlakyDetectorWorker, SecurityScanWorker, QualityGateWorker, LearningConsolidationWorker, DefectPredictorWorker, RegressionMonitorWorker, PerformanceBaselineWorker, ComplianceCheckerWorker, HeartbeatSchedulerWorker, } from './workers';
|
|
11
|
+
import { QualityDaemon } from './quality-daemon';
|
|
11
12
|
/**
|
|
12
13
|
* Default daemon configuration
|
|
13
14
|
*/
|
|
@@ -26,6 +27,7 @@ export class QEDaemon {
|
|
|
26
27
|
_healthCheckTimer;
|
|
27
28
|
workerManager;
|
|
28
29
|
config;
|
|
30
|
+
_qualityDaemon;
|
|
29
31
|
constructor(config) {
|
|
30
32
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
31
33
|
this.workerManager = new WorkerManagerImpl();
|
|
@@ -112,6 +114,17 @@ export class QEDaemon {
|
|
|
112
114
|
getWorkerManager() {
|
|
113
115
|
return this.workerManager;
|
|
114
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Get or create the quality daemon (IMP-10).
|
|
119
|
+
* The quality daemon provides proactive quality monitoring:
|
|
120
|
+
* git watching, coverage delta, CI health, test suggestions, nightly consolidation.
|
|
121
|
+
*/
|
|
122
|
+
getQualityDaemon(config) {
|
|
123
|
+
if (!this._qualityDaemon) {
|
|
124
|
+
this._qualityDaemon = new QualityDaemon(config);
|
|
125
|
+
}
|
|
126
|
+
return this._qualityDaemon;
|
|
127
|
+
}
|
|
115
128
|
/**
|
|
116
129
|
* Run a specific worker immediately
|
|
117
130
|
*/
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IMP-10: QE Quality Daemon — CI/CD Health Monitor
|
|
3
|
+
*
|
|
4
|
+
* Polls GitHub Actions workflow status via the `gh` CLI.
|
|
5
|
+
* Detects failure patterns (same test failing N times) and
|
|
6
|
+
* enqueues 'now' priority notifications for quality gate failures.
|
|
7
|
+
*/
|
|
8
|
+
import type { PriorityQueue } from './priority-queue';
|
|
9
|
+
export interface CIMonitorOptions {
|
|
10
|
+
/** How many recent runs to fetch per workflow */
|
|
11
|
+
runsPerWorkflow?: number;
|
|
12
|
+
/** Consecutive failure count to trigger flaky detection */
|
|
13
|
+
flakyThreshold?: number;
|
|
14
|
+
/** Repository in owner/repo format (auto-detected if omitted) */
|
|
15
|
+
repo?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface WorkflowRun {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly status: string;
|
|
20
|
+
readonly conclusion: string;
|
|
21
|
+
readonly headBranch: string;
|
|
22
|
+
readonly runNumber: number;
|
|
23
|
+
readonly databaseId: number;
|
|
24
|
+
readonly createdAt: string;
|
|
25
|
+
}
|
|
26
|
+
export interface CIHealthReport {
|
|
27
|
+
readonly timestamp: number;
|
|
28
|
+
readonly workflows: WorkflowStatus[];
|
|
29
|
+
readonly failingWorkflows: number;
|
|
30
|
+
readonly flakyWorkflows: string[];
|
|
31
|
+
readonly healthScore: number;
|
|
32
|
+
}
|
|
33
|
+
export interface WorkflowStatus {
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly recentRuns: number;
|
|
36
|
+
readonly failedRuns: number;
|
|
37
|
+
readonly successRate: number;
|
|
38
|
+
readonly lastConclusion: string;
|
|
39
|
+
readonly consecutiveFailures: number;
|
|
40
|
+
}
|
|
41
|
+
export declare class CIMonitor {
|
|
42
|
+
private readonly queue;
|
|
43
|
+
private options;
|
|
44
|
+
constructor(queue: PriorityQueue, options?: CIMonitorOptions);
|
|
45
|
+
/**
|
|
46
|
+
* Poll GitHub Actions and produce a health report.
|
|
47
|
+
*/
|
|
48
|
+
check(): Promise<CIHealthReport>;
|
|
49
|
+
private fetchRecentRuns;
|
|
50
|
+
private groupByWorkflow;
|
|
51
|
+
private countConsecutiveFailures;
|
|
52
|
+
private calculateHealthScore;
|
|
53
|
+
private enqueueFailureAlert;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=ci-monitor.d.ts.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IMP-10: QE Quality Daemon — CI/CD Health Monitor
|
|
3
|
+
*
|
|
4
|
+
* Polls GitHub Actions workflow status via the `gh` CLI.
|
|
5
|
+
* Detects failure patterns (same test failing N times) and
|
|
6
|
+
* enqueues 'now' priority notifications for quality gate failures.
|
|
7
|
+
*/
|
|
8
|
+
import { execFile } from 'child_process';
|
|
9
|
+
import { promisify } from 'util';
|
|
10
|
+
const execFileAsync = promisify(execFile);
|
|
11
|
+
const DEFAULTS = {
|
|
12
|
+
runsPerWorkflow: 10,
|
|
13
|
+
flakyThreshold: 3,
|
|
14
|
+
repo: '',
|
|
15
|
+
};
|
|
16
|
+
export class CIMonitor {
|
|
17
|
+
queue;
|
|
18
|
+
options;
|
|
19
|
+
constructor(queue, options) {
|
|
20
|
+
this.queue = queue;
|
|
21
|
+
this.options = { ...DEFAULTS, ...options };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Poll GitHub Actions and produce a health report.
|
|
25
|
+
*/
|
|
26
|
+
async check() {
|
|
27
|
+
const runs = await this.fetchRecentRuns();
|
|
28
|
+
const grouped = this.groupByWorkflow(runs);
|
|
29
|
+
const workflows = [];
|
|
30
|
+
const flakyWorkflows = [];
|
|
31
|
+
let failingCount = 0;
|
|
32
|
+
for (const [name, workflowRuns] of Object.entries(grouped)) {
|
|
33
|
+
const failedRuns = workflowRuns.filter((r) => r.conclusion === 'failure').length;
|
|
34
|
+
const successRate = workflowRuns.length > 0
|
|
35
|
+
? ((workflowRuns.length - failedRuns) / workflowRuns.length) * 100
|
|
36
|
+
: 100;
|
|
37
|
+
const consecutiveFailures = this.countConsecutiveFailures(workflowRuns);
|
|
38
|
+
const lastConclusion = workflowRuns[0]?.conclusion ?? 'unknown';
|
|
39
|
+
if (lastConclusion === 'failure') {
|
|
40
|
+
failingCount++;
|
|
41
|
+
}
|
|
42
|
+
if (consecutiveFailures >= this.options.flakyThreshold) {
|
|
43
|
+
flakyWorkflows.push(name);
|
|
44
|
+
// Enqueue 'now' alert for persistent failures
|
|
45
|
+
this.enqueueFailureAlert(name, workflowRuns[0]);
|
|
46
|
+
}
|
|
47
|
+
workflows.push({
|
|
48
|
+
name,
|
|
49
|
+
recentRuns: workflowRuns.length,
|
|
50
|
+
failedRuns,
|
|
51
|
+
successRate: Math.round(successRate * 10) / 10,
|
|
52
|
+
lastConclusion,
|
|
53
|
+
consecutiveFailures,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const healthScore = this.calculateHealthScore(workflows);
|
|
57
|
+
return {
|
|
58
|
+
timestamp: Date.now(),
|
|
59
|
+
workflows,
|
|
60
|
+
failingWorkflows: failingCount,
|
|
61
|
+
flakyWorkflows,
|
|
62
|
+
healthScore,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// Private
|
|
67
|
+
// ============================================================================
|
|
68
|
+
async fetchRecentRuns() {
|
|
69
|
+
try {
|
|
70
|
+
const args = [
|
|
71
|
+
'run', 'list',
|
|
72
|
+
'--limit', String(this.options.runsPerWorkflow * 5), // fetch extra to cover multiple workflows
|
|
73
|
+
'--json', 'name,status,conclusion,headBranch,number,databaseId,createdAt',
|
|
74
|
+
];
|
|
75
|
+
if (this.options.repo) {
|
|
76
|
+
args.push('--repo', this.options.repo);
|
|
77
|
+
}
|
|
78
|
+
const { stdout } = await execFileAsync('gh', args, {
|
|
79
|
+
timeout: 15000,
|
|
80
|
+
});
|
|
81
|
+
const parsed = JSON.parse(stdout);
|
|
82
|
+
return parsed.map((r) => ({
|
|
83
|
+
name: r.name,
|
|
84
|
+
status: r.status,
|
|
85
|
+
conclusion: r.conclusion ?? 'pending',
|
|
86
|
+
headBranch: r.headBranch,
|
|
87
|
+
runNumber: r.number,
|
|
88
|
+
databaseId: r.databaseId,
|
|
89
|
+
createdAt: r.createdAt,
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// gh CLI not available or not authenticated
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
groupByWorkflow(runs) {
|
|
98
|
+
const grouped = {};
|
|
99
|
+
for (const run of runs) {
|
|
100
|
+
if (!grouped[run.name]) {
|
|
101
|
+
grouped[run.name] = [];
|
|
102
|
+
}
|
|
103
|
+
grouped[run.name].push(run);
|
|
104
|
+
}
|
|
105
|
+
// Limit per workflow
|
|
106
|
+
for (const name of Object.keys(grouped)) {
|
|
107
|
+
grouped[name] = grouped[name].slice(0, this.options.runsPerWorkflow);
|
|
108
|
+
}
|
|
109
|
+
return grouped;
|
|
110
|
+
}
|
|
111
|
+
countConsecutiveFailures(runs) {
|
|
112
|
+
let count = 0;
|
|
113
|
+
for (const run of runs) {
|
|
114
|
+
if (run.conclusion === 'failure') {
|
|
115
|
+
count++;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return count;
|
|
122
|
+
}
|
|
123
|
+
calculateHealthScore(workflows) {
|
|
124
|
+
if (workflows.length === 0)
|
|
125
|
+
return 100;
|
|
126
|
+
const avgSuccess = workflows.reduce((sum, w) => sum + w.successRate, 0) / workflows.length;
|
|
127
|
+
return Math.round(avgSuccess);
|
|
128
|
+
}
|
|
129
|
+
enqueueFailureAlert(name, run) {
|
|
130
|
+
const payload = {
|
|
131
|
+
type: 'ci_failure',
|
|
132
|
+
workflowName: name,
|
|
133
|
+
runId: run.databaseId,
|
|
134
|
+
conclusion: run.conclusion,
|
|
135
|
+
};
|
|
136
|
+
const item = {
|
|
137
|
+
id: `ci-failure-${name}-${Date.now()}`,
|
|
138
|
+
priority: 'now',
|
|
139
|
+
payload,
|
|
140
|
+
createdAt: Date.now(),
|
|
141
|
+
source: 'ci-monitor',
|
|
142
|
+
ttlMs: 30 * 60 * 1000, // 30 min TTL
|
|
143
|
+
};
|
|
144
|
+
this.queue.enqueue(item);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=ci-monitor.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IMP-10: QE Quality Daemon — Coverage Delta Analysis
|
|
3
|
+
*
|
|
4
|
+
* Compares current coverage with previous snapshot to identify:
|
|
5
|
+
* - Newly uncovered lines in changed files
|
|
6
|
+
* - Coverage regressions
|
|
7
|
+
* - Coverage gaps exceeding configurable thresholds
|
|
8
|
+
*
|
|
9
|
+
* Enqueues test suggestion tasks when gaps exceed threshold.
|
|
10
|
+
*/
|
|
11
|
+
import type { WorkerMemory } from '../interfaces';
|
|
12
|
+
import type { PriorityQueue } from './priority-queue';
|
|
13
|
+
export interface CoverageSnapshot {
|
|
14
|
+
readonly timestamp: number;
|
|
15
|
+
readonly overall: CoverageMetrics;
|
|
16
|
+
readonly files: Record<string, FileCoverage>;
|
|
17
|
+
}
|
|
18
|
+
export interface CoverageMetrics {
|
|
19
|
+
readonly line: number;
|
|
20
|
+
readonly branch: number;
|
|
21
|
+
readonly function: number;
|
|
22
|
+
readonly statement: number;
|
|
23
|
+
}
|
|
24
|
+
export interface FileCoverage {
|
|
25
|
+
readonly line: number;
|
|
26
|
+
readonly branch: number;
|
|
27
|
+
readonly uncoveredLines: number[];
|
|
28
|
+
readonly totalLines: number;
|
|
29
|
+
}
|
|
30
|
+
export interface CoverageDeltaResult {
|
|
31
|
+
readonly regressionDetected: boolean;
|
|
32
|
+
readonly overallDelta: CoverageMetrics;
|
|
33
|
+
readonly affectedFiles: FileDelta[];
|
|
34
|
+
readonly newGaps: CoverageGap[];
|
|
35
|
+
}
|
|
36
|
+
export interface FileDelta {
|
|
37
|
+
readonly file: string;
|
|
38
|
+
readonly lineDelta: number;
|
|
39
|
+
readonly branchDelta: number;
|
|
40
|
+
readonly newUncoveredLines: number[];
|
|
41
|
+
}
|
|
42
|
+
export interface CoverageGap {
|
|
43
|
+
readonly file: string;
|
|
44
|
+
readonly uncoveredLines: number[];
|
|
45
|
+
readonly currentCoverage: number;
|
|
46
|
+
readonly riskScore: number;
|
|
47
|
+
}
|
|
48
|
+
export interface CoverageDeltaOptions {
|
|
49
|
+
/** Line coverage drop threshold to flag as regression (percentage points) */
|
|
50
|
+
regressionThreshold?: number;
|
|
51
|
+
/** Minimum file coverage to avoid flagging as a gap */
|
|
52
|
+
gapThreshold?: number;
|
|
53
|
+
/** Key prefix in worker memory for snapshots */
|
|
54
|
+
memoryPrefix?: string;
|
|
55
|
+
}
|
|
56
|
+
export declare class CoverageDeltaAnalyzer {
|
|
57
|
+
private readonly queue;
|
|
58
|
+
private options;
|
|
59
|
+
constructor(queue: PriorityQueue, options?: CoverageDeltaOptions);
|
|
60
|
+
/**
|
|
61
|
+
* Analyze coverage delta between the current and previous snapshot.
|
|
62
|
+
* Stores the current snapshot and enqueues test suggestions if needed.
|
|
63
|
+
*/
|
|
64
|
+
analyze(current: CoverageSnapshot, memory: WorkerMemory, changedFiles?: string[]): Promise<CoverageDeltaResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Build a CoverageSnapshot from raw lcov/istanbul data stored in memory.
|
|
67
|
+
*/
|
|
68
|
+
buildSnapshot(memory: WorkerMemory): Promise<CoverageSnapshot | undefined>;
|
|
69
|
+
private computeRiskScore;
|
|
70
|
+
private enqueueTestSuggestion;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=coverage-delta.d.ts.map
|