agentic-qe 3.9.7 → 3.9.9
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/README.md +4 -3
- package/.claude/skills/a11y-ally/SKILL.md +40 -18
- package/.claude/skills/accessibility-testing/SKILL.md +4 -0
- package/.claude/skills/compatibility-testing/SKILL.md +23 -0
- package/.claude/skills/e2e-flow-verifier/SKILL.md +87 -52
- package/.claude/skills/enterprise-integration-testing/SKILL.md +4 -0
- package/.claude/skills/localization-testing/SKILL.md +14 -0
- package/.claude/skills/observability-testing-patterns/SKILL.md +16 -0
- package/.claude/skills/qe-browser/SKILL.md +409 -0
- package/.claude/skills/qe-browser/evals/qe-browser.yaml +291 -0
- package/.claude/skills/qe-browser/fixtures/package.json +7 -0
- package/.claude/skills/qe-browser/fixtures/serve-skills.js +130 -0
- package/.claude/skills/qe-browser/references/assertion-kinds.md +132 -0
- package/.claude/skills/qe-browser/references/migration-from-playwright.md +195 -0
- package/.claude/skills/qe-browser/schemas/output.json +188 -0
- package/.claude/skills/qe-browser/scripts/assert.js +378 -0
- package/.claude/skills/qe-browser/scripts/batch.js +292 -0
- package/.claude/skills/qe-browser/scripts/check-injection.js +267 -0
- package/.claude/skills/qe-browser/scripts/intent-score.js +325 -0
- package/.claude/skills/qe-browser/scripts/lib/vibium.js +330 -0
- package/.claude/skills/qe-browser/scripts/package.json +7 -0
- package/.claude/skills/qe-browser/scripts/smoke-test.sh +212 -0
- package/.claude/skills/qe-browser/scripts/validate-config.json +46 -0
- package/.claude/skills/qe-browser/scripts/visual-diff.js +276 -0
- package/.claude/skills/qe-visual-accessibility/SKILL.md +31 -1
- package/.claude/skills/security-visual-testing/SKILL.md +18 -0
- package/.claude/skills/skills-manifest.json +20 -13
- package/.claude/skills/testability-scoring/SKILL.md +23 -0
- package/.claude/skills/trust-tier-manifest.json +14 -3
- package/.claude/skills/visual-testing-advanced/SKILL.md +41 -1
- package/CHANGELOG.md +79 -0
- package/README.md +5 -3
- package/assets/skills/README.md +4 -3
- package/assets/skills/a11y-ally/SKILL.md +40 -18
- package/assets/skills/accessibility-testing/SKILL.md +4 -0
- package/assets/skills/compatibility-testing/SKILL.md +23 -0
- package/assets/skills/e2e-flow-verifier/SKILL.md +87 -52
- package/assets/skills/enterprise-integration-testing/SKILL.md +4 -0
- package/assets/skills/localization-testing/SKILL.md +14 -0
- package/assets/skills/observability-testing-patterns/SKILL.md +16 -0
- package/assets/skills/qe-browser/SKILL.md +409 -0
- package/assets/skills/qe-browser/evals/qe-browser.yaml +291 -0
- package/assets/skills/qe-browser/fixtures/package.json +7 -0
- package/assets/skills/qe-browser/fixtures/serve-skills.js +130 -0
- package/assets/skills/qe-browser/references/assertion-kinds.md +132 -0
- package/assets/skills/qe-browser/references/migration-from-playwright.md +195 -0
- package/assets/skills/qe-browser/schemas/output.json +188 -0
- package/assets/skills/qe-browser/scripts/assert.js +378 -0
- package/assets/skills/qe-browser/scripts/batch.js +292 -0
- package/assets/skills/qe-browser/scripts/check-injection.js +267 -0
- package/assets/skills/qe-browser/scripts/intent-score.js +325 -0
- package/assets/skills/qe-browser/scripts/lib/vibium.js +330 -0
- package/assets/skills/qe-browser/scripts/package.json +7 -0
- package/assets/skills/qe-browser/scripts/smoke-test.sh +212 -0
- package/assets/skills/qe-browser/scripts/validate-config.json +46 -0
- package/assets/skills/qe-browser/scripts/visual-diff.js +276 -0
- package/assets/skills/qe-visual-accessibility/SKILL.md +31 -1
- package/assets/skills/security-visual-testing/SKILL.md +18 -0
- package/assets/skills/skills-manifest.json +211 -15
- package/assets/skills/testability-scoring/SKILL.md +23 -0
- package/assets/skills/trust-tier-manifest.json +14 -3
- package/assets/skills/visual-testing-advanced/SKILL.md +41 -1
- package/dist/cli/bundle.js +5 -5
- package/dist/cli/chunks/adapter-XKXEZEMM.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-MXTWTD4D.js → agent-booster-wasm-QEN7W6VC.js} +2 -2
- package/dist/cli/chunks/{agent-handler-6NEP2BOA.js → agent-handler-F3RLG42J.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-SAPEIGE2.js → agent-memory-branch-U3PZ3CPL.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-K7XGBDMZ.js +2 -0
- package/dist/cli/chunks/{audit-53LCI6R3.js → audit-FF6SP7Q2.js} +2 -2
- package/dist/cli/chunks/base-NUF35LIJ.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-UZSKFGCK.js → better-sqlite3-CVXRDGQX.js} +2 -2
- package/dist/cli/chunks/{brain-handler-67NDDXVO.js → brain-handler-AMTRZ35W.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-IUIGYEK5.js → branch-enumerator-Y4A34YFT.js} +2 -2
- package/dist/cli/chunks/{browser-UFUF65LQ.js → browser-ETSF5GZR.js} +2 -2
- package/dist/cli/chunks/browser-workflow-MWPELXFA.js +2 -0
- package/dist/cli/chunks/{chunk-XD4UFF2Y.js → chunk-22HQFULR.js} +1 -1
- package/dist/cli/chunks/{chunk-W4Y4GFRB.js → chunk-2BSVGL35.js} +1 -1
- package/dist/cli/chunks/{chunk-KHH5UJXY.js → chunk-2HFPJPQW.js} +2 -2
- package/dist/cli/chunks/{chunk-LPLCT2HH.js → chunk-2JAYDTSE.js} +2 -2
- package/dist/cli/chunks/{chunk-RGJ4RMUR.js → chunk-2KY5B4ON.js} +8 -8
- package/dist/cli/chunks/{chunk-XB2GVTY6.js → chunk-2O3WZ6E3.js} +1 -1
- package/dist/cli/chunks/{chunk-5EOM3W6Q.js → chunk-2UP3DYNH.js} +2 -2
- package/dist/cli/chunks/{chunk-DS3XAGGL.js → chunk-2X7LDTVD.js} +2 -2
- package/dist/cli/chunks/{chunk-NJ5IC6ZR.js → chunk-2ZHA6ORO.js} +1 -1
- package/dist/cli/chunks/{chunk-FKJ4XZ6E.js → chunk-3F666FYP.js} +2 -2
- package/dist/cli/chunks/{chunk-7TKZ6LK6.js → chunk-3FAEM5M7.js} +1 -1
- package/dist/cli/chunks/{chunk-TLTRL32T.js → chunk-3JCZTTFY.js} +1 -1
- package/dist/cli/chunks/{chunk-BPYWDM2Y.js → chunk-3NU4C62D.js} +3 -3
- package/dist/cli/chunks/{chunk-ZETZATNY.js → chunk-3XR7ARS6.js} +2 -2
- package/dist/cli/chunks/{chunk-FHBIJBZ3.js → chunk-4CDSEZD6.js} +2 -2
- package/dist/cli/chunks/{chunk-OURDPRGM.js → chunk-4CSINHCB.js} +1 -1
- package/dist/cli/chunks/{chunk-YTF5G3RQ.js → chunk-4HDG7OS4.js} +2 -2
- package/dist/cli/chunks/{chunk-PMZJ54WX.js → chunk-52RZZV4M.js} +3 -3
- package/dist/cli/chunks/{chunk-GOG6L2F7.js → chunk-5DU4YW2S.js} +2 -2
- package/dist/cli/chunks/{chunk-6MMRZYYS.js → chunk-5HM66R4W.js} +3 -3
- package/dist/cli/chunks/{chunk-BTZEKSWH.js → chunk-5L3EUZJA.js} +2 -2
- package/dist/cli/chunks/{chunk-TD2WOW75.js → chunk-5SWY75MJ.js} +2 -2
- package/dist/cli/chunks/{chunk-3DXO5CWI.js → chunk-65XCVUP7.js} +1 -1
- package/dist/cli/chunks/{chunk-VMWLVRJO.js → chunk-6KQLF3ZO.js} +2 -2
- package/dist/cli/chunks/{chunk-HVJXXGB4.js → chunk-6LTJP3DO.js} +4 -4
- package/dist/cli/chunks/{chunk-FJEIX3IS.js → chunk-6PJUDLCT.js} +2 -2
- package/dist/cli/chunks/{chunk-2TRWUJWG.js → chunk-74FBSJVC.js} +2 -2
- package/dist/cli/chunks/{chunk-D3KORDD5.js → chunk-A6GYFTIA.js} +1 -1
- package/dist/cli/chunks/{chunk-3KX7CQEM.js → chunk-ADJGMTIW.js} +1 -1
- package/dist/cli/chunks/{chunk-TT2YXNHH.js → chunk-AHOP227C.js} +4 -4
- package/dist/cli/chunks/{chunk-UXCEJ3AV.js → chunk-ANLFEGDG.js} +2 -2
- package/dist/cli/chunks/{chunk-SQQ57TSJ.js → chunk-AT2VD2ZP.js} +2 -2
- package/dist/cli/chunks/{chunk-KLLHSXIC.js → chunk-AYMIF4W5.js} +2 -2
- package/dist/cli/chunks/{chunk-JJSJSQNJ.js → chunk-B3DA4SCL.js} +1 -1
- package/dist/cli/chunks/{chunk-FBVEHGNE.js → chunk-BSES27JE.js} +3 -3
- package/dist/cli/chunks/{chunk-MUEFXLGX.js → chunk-BVKS3X2I.js} +1 -1
- package/dist/cli/chunks/{chunk-MR7V7QVL.js → chunk-BVOGMK6N.js} +2 -2
- package/dist/cli/chunks/{chunk-PHBE2VBN.js → chunk-BYJEK6LX.js} +2 -2
- package/dist/cli/chunks/{chunk-YV2PVXJE.js → chunk-BYPBKVTC.js} +1 -1
- package/dist/cli/chunks/{chunk-IQLFWO5U.js → chunk-C7YD7O74.js} +2 -2
- package/dist/cli/chunks/{chunk-ZEFDSMF4.js → chunk-CCCBGKVY.js} +2 -2
- package/dist/cli/chunks/{chunk-SIIYQLKH.js → chunk-CJQLJEO4.js} +2 -2
- package/dist/cli/chunks/{chunk-AT6LBLUV.js → chunk-CXWA34RL.js} +2 -2
- package/dist/cli/chunks/{chunk-HFPT7QXQ.js → chunk-CZYTPNUI.js} +2 -2
- package/dist/cli/chunks/{chunk-YIVZ5Z4V.js → chunk-DI6R2AVP.js} +1 -1
- package/dist/cli/chunks/{chunk-JNEG6DKU.js → chunk-DNS7DP2O.js} +1 -1
- package/dist/cli/chunks/{chunk-DKBXIBRS.js → chunk-ECNPBD4Y.js} +2 -2
- package/dist/cli/chunks/{chunk-7OPVTN5W.js → chunk-ENG5UF7M.js} +2 -2
- package/dist/cli/chunks/{chunk-EIGXGMOR.js → chunk-EV2NMWJV.js} +1 -1
- package/dist/cli/chunks/{chunk-426OO3RH.js → chunk-FGW5W3YK.js} +2 -2
- package/dist/cli/chunks/{chunk-SMKRBNO7.js → chunk-FTF34UME.js} +1 -1
- package/dist/cli/chunks/{chunk-VAKJOTGU.js → chunk-GYNGJHYF.js} +2 -2
- package/dist/cli/chunks/{chunk-AHB2F42G.js → chunk-HDM43P7H.js} +1 -1
- package/dist/cli/chunks/{chunk-ZWAJV4SN.js → chunk-HOWZFW7G.js} +2 -2
- package/dist/cli/chunks/{chunk-INJPS7RF.js → chunk-IZC5NPHD.js} +1 -1
- package/dist/cli/chunks/{chunk-HEENVPYF.js → chunk-J2DNMVB5.js} +3 -3
- package/dist/cli/chunks/{chunk-SP3X35XC.js → chunk-J62N66ZH.js} +1 -1
- package/dist/cli/chunks/{chunk-QKJ4LUAM.js → chunk-JIPU4YQK.js} +2 -2
- package/dist/cli/chunks/{chunk-4B5IYFKE.js → chunk-JK4K4EH3.js} +2 -2
- package/dist/cli/chunks/{chunk-LP6EQI2P.js → chunk-JQJHRQRX.js} +2 -2
- package/dist/cli/chunks/{chunk-FOCGOVIM.js → chunk-KSJCMXAJ.js} +2 -2
- package/dist/cli/chunks/{chunk-EFHR7LML.js → chunk-MDTF7LE6.js} +2 -2
- package/dist/cli/chunks/{chunk-PFTR6XAO.js → chunk-MUCFC3YG.js} +2 -2
- package/dist/cli/chunks/{chunk-JRHKFRUB.js → chunk-MUIJVPGB.js} +2 -2
- package/dist/cli/chunks/{chunk-WLYSZV5U.js → chunk-MWZN4PYF.js} +2 -2
- package/dist/cli/chunks/{chunk-JZYCZMHN.js → chunk-MXMKHI2I.js} +2 -2
- package/dist/cli/chunks/{chunk-XOHRM3M7.js → chunk-MZOYBHJ3.js} +3 -3
- package/dist/cli/chunks/{chunk-WV3R5JFE.js → chunk-NLKJI73E.js} +2 -2
- package/dist/cli/chunks/{chunk-D2C4XNF5.js → chunk-NQ3WHTLT.js} +4 -4
- package/dist/cli/chunks/{chunk-BJKRAFS2.js → chunk-NVVF5ROM.js} +2 -2
- package/dist/cli/chunks/{chunk-STASZVMY.js → chunk-OEZA7Q2Z.js} +2 -2
- package/dist/cli/chunks/{chunk-LHGZRKPO.js → chunk-OFOFXJ3M.js} +2 -2
- package/dist/cli/chunks/{chunk-2SJQ3CYN.js → chunk-OMRZUYXN.js} +9 -9
- package/dist/cli/chunks/{chunk-KHEAWN23.js → chunk-P6YMECV2.js} +2 -2
- package/dist/cli/chunks/{chunk-ZSXSUUBS.js → chunk-PEEN4AAK.js} +1 -1
- package/dist/cli/chunks/{chunk-6ULPQTIE.js → chunk-PRJUO2OQ.js} +2 -2
- package/dist/cli/chunks/{chunk-ECRYU5XG.js → chunk-PYTXZMXR.js} +2 -2
- package/dist/cli/chunks/{chunk-4NHE7AJE.js → chunk-Q2ZBPOUX.js} +1 -1
- package/dist/cli/chunks/{chunk-XY5FMZRA.js → chunk-QHATTMJC.js} +2 -2
- package/dist/cli/chunks/{chunk-HE5VY2BI.js → chunk-QMNAELZG.js} +2 -2
- package/dist/cli/chunks/{chunk-KZSZHP32.js → chunk-QQLQEQJM.js} +2 -2
- package/dist/cli/chunks/{chunk-7GPYOMVY.js → chunk-QSA23PJ6.js} +1 -1
- package/dist/cli/chunks/{chunk-GGPGY5QT.js → chunk-QTYTM7C7.js} +2 -2
- package/dist/cli/chunks/{chunk-YR5ZNQT2.js → chunk-QZMBJ67L.js} +2 -2
- package/dist/cli/chunks/{chunk-URBXUDY3.js → chunk-R23PJGH7.js} +2 -2
- package/dist/cli/chunks/{chunk-NKX2Z546.js → chunk-R5ZKFJ3H.js} +1 -1
- package/dist/cli/chunks/{chunk-KO5HO6MY.js → chunk-RLLDZNLF.js} +2 -2
- package/dist/cli/chunks/{chunk-ZLQYGO6N.js → chunk-RZYTJSQT.js} +1 -1
- package/dist/cli/chunks/{chunk-ZV7FGZNJ.js → chunk-S6VT7VAO.js} +2 -2
- package/dist/cli/chunks/{chunk-QI5VGEKC.js → chunk-SVLO2DVL.js} +2 -2
- package/dist/cli/chunks/{chunk-SURZYSSL.js → chunk-TTENF6AH.js} +1 -1
- package/dist/cli/chunks/{chunk-6OKXGDT3.js → chunk-UEKDDUGV.js} +2 -2
- package/dist/cli/chunks/{chunk-UEFAPTBV.js → chunk-UYKIPSRX.js} +1 -1
- package/dist/cli/chunks/{chunk-WS4OVAWU.js → chunk-VIIUJRKA.js} +2 -2
- package/dist/cli/chunks/chunk-VRH3YLO2.js +2 -0
- package/dist/cli/chunks/{chunk-YHZWNT45.js → chunk-VTX4NAWB.js} +2 -2
- package/dist/cli/chunks/{chunk-APPVAGD5.js → chunk-VWHALAEO.js} +1 -1
- package/dist/cli/chunks/{chunk-BWNH22V2.js → chunk-W4VDPHWC.js} +1 -1
- package/dist/cli/chunks/{chunk-CDFYF33M.js → chunk-W57I57M4.js} +2 -2
- package/dist/cli/chunks/{chunk-LZ34CKYE.js → chunk-WDWIJDQR.js} +2 -2
- package/dist/cli/chunks/{chunk-W4HUWBPK.js → chunk-WEJJWJ5M.js} +2 -2
- package/dist/cli/chunks/{chunk-A5VULTCD.js → chunk-WZR4CKR4.js} +1 -1
- package/dist/cli/chunks/{chunk-DL46KSFX.js → chunk-XZ2JYMFT.js} +2 -2
- package/dist/cli/chunks/{chunk-WAP7ROO5.js → chunk-YISXT54V.js} +2 -2
- package/dist/cli/chunks/{chunk-HWDE4RB3.js → chunk-YRORPSPA.js} +2 -2
- package/dist/cli/chunks/{chunk-T7R5NXJW.js → chunk-YXE67VME.js} +6 -6
- package/dist/cli/chunks/{chunk-UDBSEFUT.js → chunk-Z7AFNZMI.js} +2 -2
- package/dist/cli/chunks/{chunk-52MUZGZF.js → chunk-ZEUORIH2.js} +2 -2
- package/dist/cli/chunks/{chunk-SQZ3H6WR.js → chunk-ZKXA4VBK.js} +3 -3
- package/dist/cli/chunks/{chunk-EL2WLSUI.js → chunk-ZTI3BATG.js} +2 -2
- package/dist/cli/chunks/{ci-F4F3SDHP.js → ci-4QYE6JBM.js} +2 -2
- package/dist/cli/chunks/{ci-output-4SUMOQGO.js → ci-output-MV75HUK7.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-NKXPDFMJ.js → claude-flow-setup-CZITY7SG.js} +2 -2
- package/dist/cli/chunks/client-VXVVUQDV.js +2 -0
- package/dist/cli/chunks/{cline-installer-3FMNXEKM.js → cline-installer-ZLQKCPFF.js} +2 -2
- package/dist/cli/chunks/{code-5QEDZNKI.js → code-NYEXOJVP.js} +2 -2
- package/dist/cli/chunks/{code-index-extractor-RD5EAOLE.js → code-index-extractor-TITXUC44.js} +2 -2
- package/dist/cli/chunks/{codex-installer-UU4O2FIE.js → codex-installer-TWT4LIL2.js} +2 -2
- package/dist/cli/chunks/{completions-CS6RJLYZ.js → completions-2KNV2MZG.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-U4DE2QTP.js → complexity-analyzer-2U3OVRDX.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-E55EG2TB.js → continuedev-installer-BWQBRVTC.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-TVJUX3AZ.js → copilot-installer-CYN33NMG.js} +2 -2
- package/dist/cli/chunks/{cost-tracker-IAKDLDJH.js → cost-tracker-2GUCBYLK.js} +2 -2
- package/dist/cli/chunks/{coverage-LX7UIEKV.js → coverage-BAVD66VL.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-HUJG6CFC.js +2 -0
- package/dist/cli/chunks/{cursor-installer-2NJ7MK23.js → cursor-installer-ZQAUD47B.js} +2 -2
- package/dist/cli/chunks/{daemon-T4CPOFHM.js → daemon-VY2LZPIM.js} +3 -3
- package/dist/cli/chunks/{dag-attention-scheduler-GAPYYUHZ.js → dag-attention-scheduler-JNQWWXSW.js} +2 -2
- package/dist/cli/chunks/{detect-RU5LBCCI.js → detect-Y7BBW4LI.js} +2 -2
- package/dist/cli/chunks/{domain-handler-LKPDVPF6.js → domain-handler-473WNSR2.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-Q76ITWBK.js → domain-transfer-R4VK7CRR.js} +2 -2
- package/dist/cli/chunks/dream-QQDRI2EQ.js +2 -0
- package/dist/cli/chunks/esm-node-Y3HIFLTX.js +2 -0
- package/dist/cli/chunks/{eval-TFFIZGTW.js → eval-TJAZGRCM.js} +2 -2
- package/dist/cli/chunks/{fast-paths-V6KA3VWH.js → fast-paths-LMN542IB.js} +2 -2
- package/dist/cli/chunks/{feature-flags-MYSY53UU.js → feature-flags-IMFZ7KED.js} +2 -2
- package/dist/cli/chunks/{feature-flags-DWS4XL2P.js → feature-flags-WMXIDTXL.js} +2 -2
- package/dist/cli/chunks/{file-discovery-AMKZRFLT.js → file-discovery-GXXWQJV3.js} +2 -2
- package/dist/cli/chunks/{fleet-B2BJFKEV.js → fleet-WIC7RHJV.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-SOJHQ7VC.js → gnn-wrapper-PVKCXV25.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-O7FF6NRE.js → heartbeat-handler-BJ6ZZP7Q.js} +4 -4
- package/dist/cli/chunks/{heartbeat-scheduler-WOGW5R7J.js → heartbeat-scheduler-3SQXTFYU.js} +2 -2
- package/dist/cli/chunks/hnsw-adapter-VKS7ORL2.js +2 -0
- package/dist/cli/chunks/hnsw-index-GPUBY6EQ.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-CC5YS47X.js → hnsw-legacy-bridge-23HFWIPK.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-FTWYRETS.js → hnswlib-node-4GRFMUPD.js} +2 -2
- package/dist/cli/chunks/{hooks-ETOFFBMV.js → hooks-IXH5454I.js} +6 -6
- package/dist/cli/chunks/{hypergraph-engine-FGAHFWFO.js → hypergraph-engine-TEQMJFJJ.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-GNWJD7E3.js → hypergraph-handler-3ECUWIG3.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-D6MBGRKX.js +2 -0
- package/dist/cli/chunks/{init-handler-BEYOLKQO.js → init-handler-TZRKW3NZ.js} +6 -6
- package/dist/cli/chunks/init-wizard-S6P2MFJF.js +2 -0
- package/dist/cli/chunks/kernel-EFDDMNXJ.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-ED6LYSEM.js → kilocode-installer-IPH3O3ZS.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-NG77T5YR.js → kiro-installer-VROMOOQO.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-4PM4DFH3.js +2 -0
- package/dist/cli/chunks/{learning-P3WY3LTI.js → learning-JYQLD66S.js} +3 -3
- package/dist/cli/chunks/{llm-router-ETSFMOWS.js → llm-router-CIICNICY.js} +2 -2
- package/dist/cli/chunks/{load-PP3GVQT7.js → load-DMAQB4NC.js} +2 -2
- package/dist/cli/chunks/load-test-PPSWF3TO.js +2 -0
- package/dist/cli/chunks/{mcp-B2VX7EKL.js → mcp-K6CSUBMU.js} +2 -2
- package/dist/cli/chunks/{memory-SBZQ6MZ4.js → memory-5BSXKHSK.js} +5 -5
- package/dist/cli/chunks/memory-backend-3E6BA2JU.js +2 -0
- package/dist/cli/chunks/{memory-handlers-5RMGG2CR.js → memory-handlers-APOLXPNH.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-PIDIFO2L.js → opencode-installer-IUWO2QV6.js} +2 -2
- package/dist/cli/chunks/{orchestrator-FSGUODZI.js → orchestrator-Z2EM76CR.js} +22 -19
- package/dist/cli/chunks/{pipeline-BQ5MWZPT.js → pipeline-OL5SI2RI.js} +2 -2
- package/dist/cli/chunks/{platform-6EJK4QMD.js → platform-VNJIKIHZ.js} +2 -2
- package/dist/cli/chunks/{plugin-EDGOMUJY.js → plugin-SJJUE47D.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-4S6FYKPP.js → prime-radiant-advanced-wasm-ZLVTCNSH.js} +2 -2
- package/dist/cli/chunks/protocol-executor-2RD52J5J.js +2 -0
- package/dist/cli/chunks/{protocol-handler-ETM7PMQU.js → protocol-handler-HTX44YTW.js} +2 -2
- package/dist/cli/chunks/{prove-YUBORZAP.js → prove-MGFLVZNS.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-OGKT52EN.js +2 -0
- package/dist/cli/chunks/{quality-XPZDC5FJ.js → quality-FMFKPICZ.js} +2 -2
- package/dist/cli/chunks/queen-coordinator-B63YXNI6.js +2 -0
- package/dist/cli/chunks/{real-embeddings-KTDUTUJL.js → real-embeddings-2BMEEOA2.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-WADVKI3P.js → roocode-installer-2PA3B5JI.js} +2 -2
- package/dist/cli/chunks/router-NDQCJQC6.js +2 -0
- package/dist/cli/chunks/routing-feedback-PSN2RLDO.js +2 -0
- package/dist/cli/chunks/{routing-handler-OOPOYHEV.js → routing-handler-SNGSQ757.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-UPEZL4OK.js → ruvector-commands-54MYLF63.js} +2 -2
- package/dist/cli/chunks/{rvf-dual-writer-TOBBCJ7K.js → rvf-dual-writer-6Q44XJOJ.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-adapter-U7UM2U36.js → rvf-migration-adapter-JECN625C.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-coordinator-CUX3EU2X.js → rvf-migration-coordinator-MEAVIHQY.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-F56HQKLS.js +2 -0
- package/dist/cli/chunks/safe-db-LMRMNROL.js +2 -0
- package/dist/cli/chunks/schedule-OZSUYPPC.js +2 -0
- package/dist/cli/chunks/scheduler-GFXCQ6ZA.js +2 -0
- package/dist/cli/chunks/{security-AQ4N5YKV.js → security-CXLXTNIV.js} +3 -3
- package/dist/cli/chunks/shared-rvf-adapter-RZPF4WWK.js +2 -0
- package/dist/cli/chunks/{shared-rvf-dual-writer-OKRIHVSY.js → shared-rvf-dual-writer-SOQDKE6S.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-VP67CJPK.js +2 -0
- package/dist/cli/chunks/{status-handler-HSJLJPNG.js → status-handler-NNEF4SQV.js} +2 -2
- package/dist/cli/chunks/{structural-health-KWZAS7ON.js → structural-health-FY6QIA55.js} +2 -2
- package/dist/cli/chunks/{sync-6L5Z4IWH.js → sync-2QMSZ67Q.js} +2 -2
- package/dist/cli/chunks/{task-handler-KEAIPB6G.js → task-handler-GZJPE2QW.js} +2 -2
- package/dist/cli/chunks/{task-handlers-BPDN6OSM.js → task-handlers-AHM37D4I.js} +2 -2
- package/dist/cli/chunks/{test-PICO6RLU.js → test-JVA2S2R2.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-BI3R3DX5.js → test-scheduling-PRMP4H6X.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-KMQC6ALU.js → token-bootstrap-YJEHCBV2.js} +2 -2
- package/dist/cli/chunks/{token-usage-QGDX7MLB.js → token-usage-G73L32OF.js} +2 -2
- package/dist/cli/chunks/{transformers-UNRYJSIU.js → transformers-U3TSLEGO.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-U22JYPOG.js → tree-sitter-wasm-parser-QXP2MNSX.js} +2 -2
- package/dist/cli/chunks/{types-CYXAGOY5.js → types-BIQ7O5VR.js} +2 -2
- package/dist/cli/chunks/unified-memory-JB4KPMPI.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-RPSZZIWP.js +2 -0
- package/dist/cli/chunks/unified-persistence-L23T4C5C.js +2 -0
- package/dist/cli/chunks/{validate-IUY5BWAV.js → validate-CTBEA4BZ.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-FXFKSEOI.js → validate-swarm-PHT6XW3A.js} +2 -2
- package/dist/cli/chunks/{vibium-DKZ64NR3.js → vibium-CRCYAH3V.js} +2 -2
- package/dist/cli/chunks/visual-security-F2I524IQ.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-WQDTN5CV.js → web-tree-sitter-2MH3G7K7.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-O5WOBFOQ.js → windsurf-installer-LBRNYFSI.js} +2 -2
- package/dist/cli/chunks/witness-chain-CN6FCWRY.js +2 -0
- package/dist/cli/chunks/{witness-chain-F7WXEVJA.js → witness-chain-HNFQLO7Q.js} +2 -2
- package/dist/cli/chunks/{workflow-47524I5G.js → workflow-DNAF6BQ2.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-JJBCCNYI.js +2 -0
- package/dist/cli/chunks/{wrappers-MP2HWQD7.js → wrappers-U7AO6ZZN.js} +2 -2
- package/dist/init/browser-engine-installer.d.ts +60 -0
- package/dist/init/browser-engine-installer.js +92 -0
- package/dist/init/phases/09-assets.d.ts +2 -0
- package/dist/init/phases/09-assets.js +65 -0
- package/dist/init/skills-installer.js +1 -0
- package/dist/mcp/bundle.js +1 -1
- package/package.json +1 -1
- package/dist/cli/chunks/adapter-GE3RSG32.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-IYL6TK6E.js +0 -2
- package/dist/cli/chunks/base-L3G3GEZY.js +0 -2
- package/dist/cli/chunks/browser-workflow-7KTCY5FI.js +0 -2
- package/dist/cli/chunks/chunk-N5SLJOBK.js +0 -2
- package/dist/cli/chunks/client-3DPPDO2H.js +0 -2
- package/dist/cli/chunks/cross-domain-router-JOYTUBFT.js +0 -2
- package/dist/cli/chunks/dream-IF2HCRW4.js +0 -2
- package/dist/cli/chunks/esm-node-LNRP5BNU.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-UPX4AXOQ.js +0 -2
- package/dist/cli/chunks/hnsw-index-CSI2EXXR.js +0 -2
- package/dist/cli/chunks/impact-analyzer-2YVBHMES.js +0 -2
- package/dist/cli/chunks/init-wizard-V6GZQMMR.js +0 -2
- package/dist/cli/chunks/kernel-EHJ4SP2Y.js +0 -2
- package/dist/cli/chunks/knowledge-graph-ZYXBWGKL.js +0 -2
- package/dist/cli/chunks/load-test-VDZEYGKV.js +0 -2
- package/dist/cli/chunks/memory-backend-IB3BU4VM.js +0 -2
- package/dist/cli/chunks/protocol-executor-H2ZG7JBJ.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-ZCSHSKZU.js +0 -2
- package/dist/cli/chunks/queen-coordinator-NEC373VS.js +0 -2
- package/dist/cli/chunks/router-3PP5XRTD.js +0 -2
- package/dist/cli/chunks/routing-feedback-JNUFV2X3.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-PTOZXG4W.js +0 -2
- package/dist/cli/chunks/safe-db-CGYNYUES.js +0 -2
- package/dist/cli/chunks/schedule-NRN4WOHX.js +0 -2
- package/dist/cli/chunks/scheduler-DRAQGYLL.js +0 -2
- package/dist/cli/chunks/shared-rvf-adapter-6UVVDOHK.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-3WG7PBPL.js +0 -2
- package/dist/cli/chunks/unified-memory-EXRANFUS.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-GB752D44.js +0 -2
- package/dist/cli/chunks/unified-persistence-V2B3YWFD.js +0 -2
- package/dist/cli/chunks/visual-security-YMPI7X7V.js +0 -2
- package/dist/cli/chunks/witness-chain-7LIPUVMI.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-QPIAR4LI.js +0 -2
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
// Shared helpers for qe-browser scripts.
|
|
2
|
+
// Shells out to the `vibium` CLI and parses its --json output.
|
|
3
|
+
//
|
|
4
|
+
// Why shell-out instead of the vibium npm client:
|
|
5
|
+
// - Keeps this wrapper language-agnostic and truly thin
|
|
6
|
+
// - Matches how other AQE skills (a11y-ally, testability-scoring) invoke external tools
|
|
7
|
+
// - Lets us upgrade Vibium independently without touching our code
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { spawnSync } = require('node:child_process');
|
|
12
|
+
|
|
13
|
+
const SKILL_NAME = 'qe-browser';
|
|
14
|
+
const SKILL_VERSION = '1.0.0';
|
|
15
|
+
const TRUST_TIER = 3;
|
|
16
|
+
|
|
17
|
+
// F1 (Phase 6): typed error so downstream skills can distinguish
|
|
18
|
+
// "vibium isn't installed" from "vibium ran but the test failed".
|
|
19
|
+
// The Fallback Policy in SKILL.md says scripts must surface this as a
|
|
20
|
+
// status: "skipped" envelope with reason: "browser-engine-unavailable"
|
|
21
|
+
// — see unavailableEnvelope() / runOrSkip() below.
|
|
22
|
+
class VibiumUnavailableError extends Error {
|
|
23
|
+
constructor(message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'VibiumUnavailableError';
|
|
26
|
+
// Stable contract field that downstream code can `instanceof`-check OR
|
|
27
|
+
// duck-type via this property when crossing module boundaries (e.g.
|
|
28
|
+
// when the helper is loaded from a different node_modules tree).
|
|
29
|
+
this.code = 'BROWSER_ENGINE_UNAVAILABLE';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Inject `--headless` into every vibium call by default. The qe-browser
|
|
34
|
+
// helper scripts are designed for QE / CI use cases where there's no
|
|
35
|
+
// display server, and Vibium defaults to "visible by default" which fails
|
|
36
|
+
// in headless containers with "Missing X server or $DISPLAY". Users who
|
|
37
|
+
// want a visible browser for interactive debugging should call vibium
|
|
38
|
+
// directly, not through these helpers.
|
|
39
|
+
//
|
|
40
|
+
// Opt out by setting QE_BROWSER_HEADED=1 in the environment.
|
|
41
|
+
function injectHeadless(args) {
|
|
42
|
+
if (process.env.QE_BROWSER_HEADED === '1') return args;
|
|
43
|
+
if (args.includes('--headless') || args.includes('--headed')) return args;
|
|
44
|
+
return ['--headless', ...args];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function vibium(args, { input, timeoutMs = 30000 } = {}) {
|
|
48
|
+
const finalArgs = injectHeadless(args);
|
|
49
|
+
const result = spawnSync('vibium', finalArgs, {
|
|
50
|
+
encoding: 'utf8',
|
|
51
|
+
input,
|
|
52
|
+
timeout: timeoutMs,
|
|
53
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// F1: throw a TYPED error so the per-script main() can catch instanceof
|
|
57
|
+
// VibiumUnavailableError and emit the documented "skipped" envelope
|
|
58
|
+
// instead of a generic "failed" with the reason buried in `actual`.
|
|
59
|
+
if (result.error && result.error.code === 'ENOENT') {
|
|
60
|
+
throw new VibiumUnavailableError(
|
|
61
|
+
'vibium binary not found on PATH. Install via `npm install -g vibium` or run `aqe init`.'
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
status: result.status,
|
|
67
|
+
stdout: (result.stdout || '').toString(),
|
|
68
|
+
stderr: (result.stderr || '').toString(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function vibiumJson(args, opts) {
|
|
73
|
+
const withJson = args.includes('--json') ? args : [...args, '--json'];
|
|
74
|
+
const res = vibium(withJson, opts);
|
|
75
|
+
if (res.status !== 0) {
|
|
76
|
+
const err = new Error(
|
|
77
|
+
`vibium ${args[0] || ''} exited ${res.status}: ${res.stderr.trim() || res.stdout.trim()}`
|
|
78
|
+
);
|
|
79
|
+
err.stdout = res.stdout;
|
|
80
|
+
err.stderr = res.stderr;
|
|
81
|
+
err.exitCode = res.status;
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
const trimmed = res.stdout.trim();
|
|
85
|
+
if (!trimmed) return null;
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(trimmed);
|
|
88
|
+
} catch (_err) {
|
|
89
|
+
// Some vibium commands emit non-JSON even with --json on error paths;
|
|
90
|
+
// return raw text so callers can decide what to do.
|
|
91
|
+
return { __raw: trimmed };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Vibium's `eval` (with or without --stdin) returns the LAST EXPRESSION's
|
|
96
|
+
// value, NOT console.log output. With --json the response shape is:
|
|
97
|
+
// { ok: true, result: "<stringified value>" }
|
|
98
|
+
// where `result` is a STRING if the expression returned a string, or a
|
|
99
|
+
// Go-side serialization if it returned a non-string object. So our scripts
|
|
100
|
+
// MUST wrap their return value in JSON.stringify(...) and we parse the
|
|
101
|
+
// `result` field as JSON ourselves to get a real JS object back.
|
|
102
|
+
//
|
|
103
|
+
// Verified on Vibium v26.3.18 (2026-04-09).
|
|
104
|
+
function unwrapEvalResult(payload) {
|
|
105
|
+
if (payload === null || payload === undefined) return null;
|
|
106
|
+
// payload from vibiumJson is already a parsed object: { ok, result } or { __raw }
|
|
107
|
+
if (payload && typeof payload === 'object' && 'ok' in payload && 'result' in payload) {
|
|
108
|
+
if (payload.ok !== true) {
|
|
109
|
+
throw new Error(`vibium eval failed: ${JSON.stringify(payload)}`);
|
|
110
|
+
}
|
|
111
|
+
const result = payload.result;
|
|
112
|
+
if (typeof result === 'string') {
|
|
113
|
+
// The script wrapped its return value in JSON.stringify so parse it.
|
|
114
|
+
try {
|
|
115
|
+
return JSON.parse(result);
|
|
116
|
+
} catch (_e) {
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
return payload;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function vibiumEval(expression) {
|
|
126
|
+
const raw = vibiumJson(['eval', '--json', expression]);
|
|
127
|
+
return unwrapEvalResult(raw);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function vibiumEvalStdin(script) {
|
|
131
|
+
const raw = vibiumJson(['eval', '--stdin', '--json'], { input: script });
|
|
132
|
+
return unwrapEvalResult(raw);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function envelope({
|
|
136
|
+
operation,
|
|
137
|
+
summary,
|
|
138
|
+
status = 'success',
|
|
139
|
+
details = {},
|
|
140
|
+
metadata = {},
|
|
141
|
+
vibiumUnavailable = false,
|
|
142
|
+
reason = undefined,
|
|
143
|
+
}) {
|
|
144
|
+
const env = {
|
|
145
|
+
skillName: SKILL_NAME,
|
|
146
|
+
version: SKILL_VERSION,
|
|
147
|
+
timestamp: new Date().toISOString(),
|
|
148
|
+
status,
|
|
149
|
+
trustTier: TRUST_TIER,
|
|
150
|
+
output: {
|
|
151
|
+
operation,
|
|
152
|
+
summary,
|
|
153
|
+
...details,
|
|
154
|
+
},
|
|
155
|
+
metadata,
|
|
156
|
+
};
|
|
157
|
+
// Top-level flag so downstream skills can branch on the contract without
|
|
158
|
+
// walking output.* sub-fields. Only set when true to keep the happy-path
|
|
159
|
+
// envelope shape unchanged for the 99% case.
|
|
160
|
+
if (vibiumUnavailable) env.vibiumUnavailable = true;
|
|
161
|
+
if (reason !== undefined) env.output.reason = reason;
|
|
162
|
+
return env;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// F1: produce the documented "skipped" envelope when vibium is missing.
|
|
166
|
+
// Contract per SKILL.md Fallback Policy:
|
|
167
|
+
// status: "skipped"
|
|
168
|
+
// output.reason: "browser-engine-unavailable"
|
|
169
|
+
// vibiumUnavailable: true (top-level)
|
|
170
|
+
// output.summary: actionable install guidance
|
|
171
|
+
function unavailableEnvelope(operation, message) {
|
|
172
|
+
return envelope({
|
|
173
|
+
operation,
|
|
174
|
+
summary: message,
|
|
175
|
+
status: 'skipped',
|
|
176
|
+
vibiumUnavailable: true,
|
|
177
|
+
reason: 'browser-engine-unavailable',
|
|
178
|
+
details: {
|
|
179
|
+
error: message,
|
|
180
|
+
remediation: [
|
|
181
|
+
'Install vibium globally: `npm install -g vibium`',
|
|
182
|
+
'Or re-run `aqe init` to install via the AQE bootstrap',
|
|
183
|
+
'Set QE_BROWSER_HEADED=1 only for interactive debugging (not the cause here)',
|
|
184
|
+
],
|
|
185
|
+
},
|
|
186
|
+
metadata: { executionTimeMs: 0 },
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Predicate so per-script catch blocks can decide whether to swallow an
|
|
191
|
+
// error (regular failure) or re-throw it so the outer runOrSkip can emit
|
|
192
|
+
// the skipped envelope. Cross-module-safe via the duck-typed `code` field.
|
|
193
|
+
function isVibiumUnavailable(err) {
|
|
194
|
+
return Boolean(
|
|
195
|
+
err &&
|
|
196
|
+
(err instanceof VibiumUnavailableError ||
|
|
197
|
+
err.code === 'BROWSER_ENGINE_UNAVAILABLE' ||
|
|
198
|
+
// The error string from vibium() also matches as a final fallback
|
|
199
|
+
// in case both the prototype and the code field were lost while
|
|
200
|
+
// crossing some serialization boundary.
|
|
201
|
+
(typeof err.message === 'string' &&
|
|
202
|
+
err.message.includes('vibium binary not found on PATH')))
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// rethrowIfUnavailable: helper to use INSIDE per-script catch blocks so
|
|
207
|
+
// that the documented missing-vibium contract bubbles past lower-level
|
|
208
|
+
// "convert exception to failed envelope" handlers and reaches runOrSkip.
|
|
209
|
+
//
|
|
210
|
+
// Usage:
|
|
211
|
+
// try { ... vibium calls ... }
|
|
212
|
+
// catch (err) {
|
|
213
|
+
// rethrowIfUnavailable(err);
|
|
214
|
+
// return fail('myop', err.message);
|
|
215
|
+
// }
|
|
216
|
+
function rethrowIfUnavailable(err) {
|
|
217
|
+
if (isVibiumUnavailable(err)) {
|
|
218
|
+
if (err instanceof VibiumUnavailableError) throw err;
|
|
219
|
+
// Promote a duck-typed error to a real VibiumUnavailableError so
|
|
220
|
+
// downstream code only has to handle one type.
|
|
221
|
+
throw new VibiumUnavailableError(err.message || 'browser engine unavailable');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// runOrSkip wraps a per-script main() so that any VibiumUnavailableError
|
|
226
|
+
// thrown anywhere inside the operation is converted to the documented
|
|
227
|
+
// skipped envelope. Each helper script's main() is `() => fn()` returning
|
|
228
|
+
// the exit code from emit(). On unavailable, we emit() the skipped envelope
|
|
229
|
+
// and return its exit code (2).
|
|
230
|
+
function runOrSkip(operation, fn) {
|
|
231
|
+
try {
|
|
232
|
+
return fn();
|
|
233
|
+
} catch (err) {
|
|
234
|
+
if (isVibiumUnavailable(err)) {
|
|
235
|
+
return emit(unavailableEnvelope(operation, err.message));
|
|
236
|
+
}
|
|
237
|
+
throw err;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// parseArgs supports both `--key value` and `--key=value` forms.
|
|
242
|
+
//
|
|
243
|
+
// M5 (devil's-advocate finding): the previous implementation only handled
|
|
244
|
+
// the space-separated form. A user typing `--threshold=0.5` got
|
|
245
|
+
// `args['threshold=0.5'] = true` and a separate `args.threshold` was never
|
|
246
|
+
// set, so the value silently defaulted. The equals form is the dominant
|
|
247
|
+
// idiom in npm/node CLIs (`node --inspect=9229`), so we accept both. When
|
|
248
|
+
// the next token is itself a flag (`--include-hidden --json`) we treat the
|
|
249
|
+
// current flag as boolean — the same behavior as before.
|
|
250
|
+
function parseArgs(argv) {
|
|
251
|
+
const args = {};
|
|
252
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
253
|
+
const token = argv[i];
|
|
254
|
+
if (!token.startsWith('--')) continue;
|
|
255
|
+
const stripped = token.slice(2);
|
|
256
|
+
// --key=value form: split on first '=' only so values containing '='
|
|
257
|
+
// (URLs, regex with capture group names, base64) survive intact.
|
|
258
|
+
const eqIdx = stripped.indexOf('=');
|
|
259
|
+
if (eqIdx !== -1) {
|
|
260
|
+
const key = stripped.slice(0, eqIdx);
|
|
261
|
+
const value = stripped.slice(eqIdx + 1);
|
|
262
|
+
args[key] = value;
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
const key = stripped;
|
|
266
|
+
const next = argv[i + 1];
|
|
267
|
+
if (next === undefined || next.startsWith('--')) {
|
|
268
|
+
args[key] = true;
|
|
269
|
+
} else {
|
|
270
|
+
args[key] = next;
|
|
271
|
+
i += 1;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return args;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function readInlineOrFile(value) {
|
|
278
|
+
if (typeof value !== 'string') return value;
|
|
279
|
+
if (value.startsWith('@')) {
|
|
280
|
+
const fs = require('node:fs');
|
|
281
|
+
return fs.readFileSync(value.slice(1), 'utf8');
|
|
282
|
+
}
|
|
283
|
+
return value;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Exit code contract (F1):
|
|
287
|
+
// 0 — success: every assertion passed / operation completed cleanly
|
|
288
|
+
// 1 — failed: genuine assertion failure or operation error
|
|
289
|
+
// 2 — skipped: vibium unavailable; environment problem, not a test result
|
|
290
|
+
//
|
|
291
|
+
// CI tooling can use this to distinguish "test legitimately failed" from
|
|
292
|
+
// "we couldn't run the test because the browser engine isn't installed."
|
|
293
|
+
function emit(env) {
|
|
294
|
+
process.stdout.write(`${JSON.stringify(env, null, 2)}\n`);
|
|
295
|
+
if (env.status === 'success') return 0;
|
|
296
|
+
if (env.status === 'skipped') return 2;
|
|
297
|
+
return 1;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function fail(operation, message, metadata = {}) {
|
|
301
|
+
return emit(
|
|
302
|
+
envelope({
|
|
303
|
+
operation,
|
|
304
|
+
summary: message,
|
|
305
|
+
status: 'failed',
|
|
306
|
+
details: { error: message },
|
|
307
|
+
metadata,
|
|
308
|
+
})
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
module.exports = {
|
|
313
|
+
SKILL_NAME,
|
|
314
|
+
SKILL_VERSION,
|
|
315
|
+
TRUST_TIER,
|
|
316
|
+
VibiumUnavailableError,
|
|
317
|
+
isVibiumUnavailable,
|
|
318
|
+
rethrowIfUnavailable,
|
|
319
|
+
vibium,
|
|
320
|
+
vibiumJson,
|
|
321
|
+
vibiumEval,
|
|
322
|
+
vibiumEvalStdin,
|
|
323
|
+
envelope,
|
|
324
|
+
unavailableEnvelope,
|
|
325
|
+
runOrSkip,
|
|
326
|
+
parseArgs,
|
|
327
|
+
readInlineOrFile,
|
|
328
|
+
emit,
|
|
329
|
+
fail,
|
|
330
|
+
};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# qe-browser smoke test
|
|
3
|
+
#
|
|
4
|
+
# Runs each helper script against pinned public fixtures (httpbin.org) and
|
|
5
|
+
# verifies the output structure. This is the script that gates PR-reopen
|
|
6
|
+
# per ADR-091 Phase 3 — it MUST be run on a machine with vibium installed
|
|
7
|
+
# before the qe-browser PR is considered safe to reopen.
|
|
8
|
+
#
|
|
9
|
+
# Exit codes:
|
|
10
|
+
# 0 — all smoke tests passed
|
|
11
|
+
# 1 — at least one smoke test failed
|
|
12
|
+
# 2 — vibium binary not on PATH (precondition unmet)
|
|
13
|
+
#
|
|
14
|
+
# Per feedback_no_unverified_failure_modes.md, this is the script we
|
|
15
|
+
# actually run, not just write. Per feedback_synthetic_fixtures_dont_count,
|
|
16
|
+
# all fixtures are pinned public endpoints (httpbin.org) — no synthetic
|
|
17
|
+
# stubs, no inline HTML.
|
|
18
|
+
|
|
19
|
+
set -uo pipefail
|
|
20
|
+
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
|
+
SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
23
|
+
WORK_DIR="$(mktemp -d)"
|
|
24
|
+
trap 'rm -rf "$WORK_DIR"' EXIT
|
|
25
|
+
|
|
26
|
+
GREEN='\033[0;32m'
|
|
27
|
+
RED='\033[0;31m'
|
|
28
|
+
YELLOW='\033[1;33m'
|
|
29
|
+
NC='\033[0m'
|
|
30
|
+
|
|
31
|
+
PASS=0
|
|
32
|
+
FAIL=0
|
|
33
|
+
SKIPPED=0
|
|
34
|
+
|
|
35
|
+
ok() { echo -e "${GREEN}PASS${NC} $1"; PASS=$((PASS + 1)); }
|
|
36
|
+
bad() { echo -e "${RED}FAIL${NC} $1${2:+: $2}"; FAIL=$((FAIL + 1)); }
|
|
37
|
+
skip() { echo -e "${YELLOW}SKIP${NC} $1${2:+: $2}"; SKIPPED=$((SKIPPED + 1)); }
|
|
38
|
+
|
|
39
|
+
# ---------------------------------------------------------------------------
|
|
40
|
+
# Precondition: vibium on PATH
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
if ! command -v vibium >/dev/null 2>&1; then
|
|
43
|
+
echo -e "${RED}vibium binary not found on PATH${NC}"
|
|
44
|
+
echo "Install via: npm install -g vibium"
|
|
45
|
+
exit 2
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
VIBIUM_VERSION=$(vibium --version 2>&1 | head -1)
|
|
49
|
+
echo "Smoke testing against $VIBIUM_VERSION"
|
|
50
|
+
echo "Skill dir: $SKILL_DIR"
|
|
51
|
+
echo "Work dir: $WORK_DIR"
|
|
52
|
+
echo ""
|
|
53
|
+
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
# tc001 — assert.js url_contains against pinned httpbin form
|
|
56
|
+
# ---------------------------------------------------------------------------
|
|
57
|
+
vibium --headless go https://httpbin.org/forms/post >/dev/null 2>&1 || true
|
|
58
|
+
RESULT=$(node "$SKILL_DIR/scripts/assert.js" --checks \
|
|
59
|
+
'[{"kind": "url_contains", "text": "httpbin.org/forms"}]' 2>&1)
|
|
60
|
+
EXIT=$?
|
|
61
|
+
if [ "$EXIT" = "0" ] && echo "$RESULT" | grep -q '"status": "success"'; then
|
|
62
|
+
ok "tc001 url_contains on httpbin form"
|
|
63
|
+
else
|
|
64
|
+
bad "tc001 url_contains on httpbin form" "exit=$EXIT, result=$RESULT"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# tc002 — assert.js selector_visible against pinned httpbin /html
|
|
69
|
+
# ---------------------------------------------------------------------------
|
|
70
|
+
vibium --headless go https://httpbin.org/html >/dev/null 2>&1 || true
|
|
71
|
+
RESULT=$(node "$SKILL_DIR/scripts/assert.js" --checks \
|
|
72
|
+
'[{"kind": "selector_visible", "selector": "h1"}]' 2>&1)
|
|
73
|
+
EXIT=$?
|
|
74
|
+
if [ "$EXIT" = "0" ] && echo "$RESULT" | grep -q '"passed": true'; then
|
|
75
|
+
ok "tc002 selector_visible h1 on httpbin /html"
|
|
76
|
+
else
|
|
77
|
+
bad "tc002 selector_visible h1 on httpbin /html" "exit=$EXIT"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# ---------------------------------------------------------------------------
|
|
81
|
+
# tc003 — assert.js failing assertion exits non-zero
|
|
82
|
+
# ---------------------------------------------------------------------------
|
|
83
|
+
RESULT=$(node "$SKILL_DIR/scripts/assert.js" --checks \
|
|
84
|
+
'[{"kind": "url_contains", "text": "this-does-not-exist"}]' 2>&1)
|
|
85
|
+
EXIT=$?
|
|
86
|
+
if [ "$EXIT" = "1" ] && echo "$RESULT" | grep -q '"status": "failed"'; then
|
|
87
|
+
ok "tc003 failing assertion exits 1"
|
|
88
|
+
else
|
|
89
|
+
bad "tc003 failing assertion exits 1" "exit=$EXIT (expected 1)"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# ---------------------------------------------------------------------------
|
|
93
|
+
# tc004 — batch.js navigate + wait + assert in one call
|
|
94
|
+
# ---------------------------------------------------------------------------
|
|
95
|
+
RESULT=$(node "$SKILL_DIR/scripts/batch.js" --steps \
|
|
96
|
+
'[{"action":"go","url":"https://httpbin.org/html"},{"action":"wait_load"},{"action":"assert","checks":[{"kind":"url_contains","text":"/html"}]}]' \
|
|
97
|
+
--summary-only 2>&1)
|
|
98
|
+
EXIT=$?
|
|
99
|
+
if [ "$EXIT" = "0" ] && echo "$RESULT" | grep -q '"passedSteps": 3'; then
|
|
100
|
+
ok "tc004 batch 3-step happy path"
|
|
101
|
+
else
|
|
102
|
+
bad "tc004 batch 3-step happy path" "exit=$EXIT"
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
# ---------------------------------------------------------------------------
|
|
106
|
+
# tc005 — batch.js stops on failure
|
|
107
|
+
# ---------------------------------------------------------------------------
|
|
108
|
+
RESULT=$(node "$SKILL_DIR/scripts/batch.js" --steps \
|
|
109
|
+
'[{"action":"go","url":"https://httpbin.org/html"},{"action":"click","selector":"#does-not-exist-selector"},{"action":"go","url":"https://httpbin.org/forms/post"}]' 2>&1)
|
|
110
|
+
EXIT=$?
|
|
111
|
+
if [ "$EXIT" = "1" ] && echo "$RESULT" | grep -q '"failedStep"'; then
|
|
112
|
+
ok "tc005 batch stops on first failure"
|
|
113
|
+
else
|
|
114
|
+
bad "tc005 batch stops on first failure" "exit=$EXIT"
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
# ---------------------------------------------------------------------------
|
|
118
|
+
# tc006 — visual-diff.js creates baseline on first run
|
|
119
|
+
#
|
|
120
|
+
# Set explicit viewport BEFORE screenshot so the two visual-diff runs have
|
|
121
|
+
# the same dimensions. Without this the chromium headless window picks
|
|
122
|
+
# whatever size it likes per run, and httpbin.org/html renders at different
|
|
123
|
+
# sizes between runs (768×654 vs 765×672 observed), making pixel-diff
|
|
124
|
+
# spuriously fail. This is documented in references/assertion-kinds.md.
|
|
125
|
+
# ---------------------------------------------------------------------------
|
|
126
|
+
rm -rf "$PWD/.aqe/visual-baselines/smoke_test_baseline"*
|
|
127
|
+
vibium --headless viewport 1280 720 >/dev/null 2>&1 || true
|
|
128
|
+
vibium --headless go https://httpbin.org/html >/dev/null 2>&1 || true
|
|
129
|
+
RESULT=$(node "$SKILL_DIR/scripts/visual-diff.js" --name smoke_test_baseline 2>&1)
|
|
130
|
+
EXIT=$?
|
|
131
|
+
if [ "$EXIT" = "0" ] && echo "$RESULT" | grep -q '"baseline_created"'; then
|
|
132
|
+
ok "tc006 visual-diff baseline created"
|
|
133
|
+
else
|
|
134
|
+
bad "tc006 visual-diff baseline created" "exit=$EXIT"
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# ---------------------------------------------------------------------------
|
|
138
|
+
# tc007 — visual-diff.js matches second identical run
|
|
139
|
+
#
|
|
140
|
+
# Force the same viewport before re-shooting so dimensions match the baseline.
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
vibium --headless viewport 1280 720 >/dev/null 2>&1 || true
|
|
143
|
+
RESULT=$(node "$SKILL_DIR/scripts/visual-diff.js" --name smoke_test_baseline 2>&1)
|
|
144
|
+
EXIT=$?
|
|
145
|
+
if [ "$EXIT" = "0" ] && echo "$RESULT" | grep -qE '"(match|baseline_created)"'; then
|
|
146
|
+
ok "tc007 visual-diff second run matches"
|
|
147
|
+
else
|
|
148
|
+
bad "tc007 visual-diff second run matches" "exit=$EXIT"
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# ---------------------------------------------------------------------------
|
|
152
|
+
# tc008 — check-injection.js clean page
|
|
153
|
+
# ---------------------------------------------------------------------------
|
|
154
|
+
vibium --headless go https://httpbin.org/html >/dev/null 2>&1 || true
|
|
155
|
+
RESULT=$(node "$SKILL_DIR/scripts/check-injection.js" --include-hidden 2>&1)
|
|
156
|
+
EXIT=$?
|
|
157
|
+
if [ "$EXIT" = "0" ] && echo "$RESULT" | grep -q '"severity": "none"'; then
|
|
158
|
+
ok "tc008 check-injection clean page"
|
|
159
|
+
else
|
|
160
|
+
bad "tc008 check-injection clean page" "exit=$EXIT"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
# ---------------------------------------------------------------------------
|
|
164
|
+
# tc010 — intent-score.js submit_form on pinned httpbin form
|
|
165
|
+
# ---------------------------------------------------------------------------
|
|
166
|
+
vibium --headless go https://httpbin.org/forms/post >/dev/null 2>&1 || true
|
|
167
|
+
RESULT=$(node "$SKILL_DIR/scripts/intent-score.js" --intent submit_form 2>&1)
|
|
168
|
+
EXIT=$?
|
|
169
|
+
if [ "$EXIT" = "0" ] && echo "$RESULT" | grep -q '"intent": "submit_form"'; then
|
|
170
|
+
ok "tc010 intent-score submit_form on httpbin form"
|
|
171
|
+
else
|
|
172
|
+
bad "tc010 intent-score submit_form on httpbin form" "exit=$EXIT"
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# ---------------------------------------------------------------------------
|
|
176
|
+
# tc011 — F1 contract: vibium-missing → skipped envelope + exit code 2
|
|
177
|
+
# ---------------------------------------------------------------------------
|
|
178
|
+
# Build a fake bin dir that contains node (so the helper can run) but NOT
|
|
179
|
+
# vibium. The helper must:
|
|
180
|
+
# 1. Throw VibiumUnavailableError from lib/vibium.js
|
|
181
|
+
# 2. Have it caught by runOrSkip wrapping main()
|
|
182
|
+
# 3. Emit a status: "skipped" envelope with vibiumUnavailable: true
|
|
183
|
+
# 4. Exit with code 2 (not 1)
|
|
184
|
+
FAKE_BIN="$WORK_DIR/fake-bin"
|
|
185
|
+
mkdir -p "$FAKE_BIN"
|
|
186
|
+
ln -sf "$(command -v node)" "$FAKE_BIN/node"
|
|
187
|
+
RESULT=$(env -i PATH="$FAKE_BIN" HOME="$HOME" TERM=dumb \
|
|
188
|
+
node "$SKILL_DIR/scripts/assert.js" --checks '[{"kind":"url_contains","text":"foo"}]' 2>&1)
|
|
189
|
+
EXIT=$?
|
|
190
|
+
if [ "$EXIT" = "2" ] \
|
|
191
|
+
&& echo "$RESULT" | grep -q '"status": "skipped"' \
|
|
192
|
+
&& echo "$RESULT" | grep -q '"vibiumUnavailable": true' \
|
|
193
|
+
&& echo "$RESULT" | grep -q '"reason": "browser-engine-unavailable"'; then
|
|
194
|
+
ok "tc011 F1 missing-vibium emits skipped envelope + exit 2"
|
|
195
|
+
else
|
|
196
|
+
bad "tc011 F1 missing-vibium emits skipped envelope + exit 2" "exit=$EXIT"
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
# ---------------------------------------------------------------------------
|
|
200
|
+
# Summary
|
|
201
|
+
# ---------------------------------------------------------------------------
|
|
202
|
+
echo ""
|
|
203
|
+
echo "─────────────────────────────────"
|
|
204
|
+
echo "PASS: $PASS"
|
|
205
|
+
echo "FAIL: $FAIL"
|
|
206
|
+
echo "SKIPPED: $SKIPPED"
|
|
207
|
+
echo "─────────────────────────────────"
|
|
208
|
+
|
|
209
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
210
|
+
exit 1
|
|
211
|
+
fi
|
|
212
|
+
exit 0
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skillName": "qe-browser",
|
|
3
|
+
"skillVersion": "1.0.0",
|
|
4
|
+
"requiredTools": [
|
|
5
|
+
"node",
|
|
6
|
+
"jq"
|
|
7
|
+
],
|
|
8
|
+
"optionalTools": [
|
|
9
|
+
"vibium",
|
|
10
|
+
"pixelmatch",
|
|
11
|
+
"pngjs"
|
|
12
|
+
],
|
|
13
|
+
"schemaPath": "schemas/output.json",
|
|
14
|
+
"requiredFields": [
|
|
15
|
+
"skillName",
|
|
16
|
+
"version",
|
|
17
|
+
"timestamp",
|
|
18
|
+
"status",
|
|
19
|
+
"trustTier",
|
|
20
|
+
"output"
|
|
21
|
+
],
|
|
22
|
+
"requiredNonEmptyFields": [
|
|
23
|
+
".output.operation",
|
|
24
|
+
".output.summary"
|
|
25
|
+
],
|
|
26
|
+
"mustContainTerms": [],
|
|
27
|
+
"mustNotContainTerms": [],
|
|
28
|
+
"enumValidations": {
|
|
29
|
+
".status": [
|
|
30
|
+
"success",
|
|
31
|
+
"partial",
|
|
32
|
+
"failed",
|
|
33
|
+
"skipped"
|
|
34
|
+
],
|
|
35
|
+
".trustTier": [3],
|
|
36
|
+
".output.operation": [
|
|
37
|
+
"assert",
|
|
38
|
+
"batch",
|
|
39
|
+
"visual-diff",
|
|
40
|
+
"check-injection",
|
|
41
|
+
"intent-score",
|
|
42
|
+
"navigate",
|
|
43
|
+
"capture"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|