agentic-qe 3.9.8 → 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 +53 -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-LAE4NTVX.js → agent-booster-wasm-QEN7W6VC.js} +2 -2
- package/dist/cli/chunks/{agent-handler-FVXHR6XN.js → agent-handler-F3RLG42J.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-Q7LLBA7C.js → agent-memory-branch-U3PZ3CPL.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-K7XGBDMZ.js +2 -0
- package/dist/cli/chunks/{audit-YRLKHJLX.js → audit-FF6SP7Q2.js} +2 -2
- package/dist/cli/chunks/base-NUF35LIJ.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-XFGOGICB.js → better-sqlite3-CVXRDGQX.js} +2 -2
- package/dist/cli/chunks/{brain-handler-KIUSNVSS.js → brain-handler-AMTRZ35W.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-VKZ4L3FH.js → branch-enumerator-Y4A34YFT.js} +2 -2
- package/dist/cli/chunks/{browser-GZVIYFIB.js → browser-ETSF5GZR.js} +2 -2
- package/dist/cli/chunks/browser-workflow-MWPELXFA.js +2 -0
- package/dist/cli/chunks/{chunk-LPRHYSXN.js → chunk-22HQFULR.js} +1 -1
- package/dist/cli/chunks/{chunk-677V67MR.js → chunk-2BSVGL35.js} +1 -1
- package/dist/cli/chunks/{chunk-TDPHLQ2M.js → chunk-2HFPJPQW.js} +2 -2
- package/dist/cli/chunks/{chunk-EKDFIYV5.js → chunk-2JAYDTSE.js} +2 -2
- package/dist/cli/chunks/{chunk-AVKDT3UL.js → chunk-2KY5B4ON.js} +8 -8
- package/dist/cli/chunks/{chunk-NHXFAXEV.js → chunk-2O3WZ6E3.js} +1 -1
- package/dist/cli/chunks/{chunk-PBPOSPTY.js → chunk-2UP3DYNH.js} +2 -2
- package/dist/cli/chunks/{chunk-3WOQMFTD.js → chunk-2X7LDTVD.js} +2 -2
- package/dist/cli/chunks/{chunk-A4DJMFDM.js → chunk-2ZHA6ORO.js} +1 -1
- package/dist/cli/chunks/{chunk-TN72MXLI.js → chunk-3F666FYP.js} +2 -2
- package/dist/cli/chunks/{chunk-UGJNR52C.js → chunk-3FAEM5M7.js} +1 -1
- package/dist/cli/chunks/{chunk-GHJRX7PV.js → chunk-3JCZTTFY.js} +1 -1
- package/dist/cli/chunks/{chunk-7PHNHFZI.js → chunk-3NU4C62D.js} +3 -3
- package/dist/cli/chunks/{chunk-YDW522M7.js → chunk-3XR7ARS6.js} +2 -2
- package/dist/cli/chunks/{chunk-NCXVOOA7.js → chunk-4CDSEZD6.js} +2 -2
- package/dist/cli/chunks/{chunk-7L64UC5U.js → chunk-4CSINHCB.js} +1 -1
- package/dist/cli/chunks/{chunk-6ZMM7MXA.js → chunk-4HDG7OS4.js} +2 -2
- package/dist/cli/chunks/{chunk-SP3ZBJ63.js → chunk-52RZZV4M.js} +3 -3
- package/dist/cli/chunks/{chunk-LOANEFGZ.js → chunk-5DU4YW2S.js} +2 -2
- package/dist/cli/chunks/{chunk-6A4FEIE2.js → chunk-5HM66R4W.js} +3 -3
- package/dist/cli/chunks/{chunk-BXMIQRF3.js → chunk-5L3EUZJA.js} +2 -2
- package/dist/cli/chunks/{chunk-2V5VKOJ2.js → chunk-5SWY75MJ.js} +2 -2
- package/dist/cli/chunks/{chunk-ZCKNGICX.js → chunk-65XCVUP7.js} +1 -1
- package/dist/cli/chunks/{chunk-R4VOIXJQ.js → chunk-6KQLF3ZO.js} +2 -2
- package/dist/cli/chunks/{chunk-SQ6XZGR4.js → chunk-6LTJP3DO.js} +4 -4
- package/dist/cli/chunks/{chunk-WXEDVKJS.js → chunk-6PJUDLCT.js} +2 -2
- package/dist/cli/chunks/{chunk-JK6JBNGL.js → chunk-74FBSJVC.js} +2 -2
- package/dist/cli/chunks/{chunk-XPL3BXLM.js → chunk-A6GYFTIA.js} +1 -1
- package/dist/cli/chunks/{chunk-DLKRK2GU.js → chunk-ADJGMTIW.js} +1 -1
- package/dist/cli/chunks/{chunk-W4IRWGGR.js → chunk-AHOP227C.js} +4 -4
- package/dist/cli/chunks/{chunk-FKODRXOU.js → chunk-ANLFEGDG.js} +2 -2
- package/dist/cli/chunks/{chunk-ZJ4PMOIZ.js → chunk-AT2VD2ZP.js} +2 -2
- package/dist/cli/chunks/{chunk-7CFEGUEH.js → chunk-AYMIF4W5.js} +2 -2
- package/dist/cli/chunks/{chunk-KMGAJRQ6.js → chunk-B3DA4SCL.js} +1 -1
- package/dist/cli/chunks/{chunk-4KX6TMKB.js → chunk-BSES27JE.js} +3 -3
- package/dist/cli/chunks/{chunk-TWDWDKOI.js → chunk-BVKS3X2I.js} +1 -1
- package/dist/cli/chunks/{chunk-PG7CZ6Q4.js → chunk-BVOGMK6N.js} +2 -2
- package/dist/cli/chunks/{chunk-RGCCSAHI.js → chunk-BYJEK6LX.js} +2 -2
- package/dist/cli/chunks/{chunk-QVGSD25D.js → chunk-BYPBKVTC.js} +1 -1
- package/dist/cli/chunks/{chunk-2QI5RYVR.js → chunk-C7YD7O74.js} +2 -2
- package/dist/cli/chunks/{chunk-UAI5NPPQ.js → chunk-CCCBGKVY.js} +2 -2
- package/dist/cli/chunks/{chunk-OGFGNAKQ.js → chunk-CJQLJEO4.js} +2 -2
- package/dist/cli/chunks/{chunk-TSDTRJOG.js → chunk-CXWA34RL.js} +2 -2
- package/dist/cli/chunks/{chunk-5TGK7VTS.js → chunk-CZYTPNUI.js} +2 -2
- package/dist/cli/chunks/{chunk-HE2NWYHK.js → chunk-DI6R2AVP.js} +1 -1
- package/dist/cli/chunks/{chunk-UOSKMAAY.js → chunk-DNS7DP2O.js} +1 -1
- package/dist/cli/chunks/{chunk-Q5PARJC6.js → chunk-ECNPBD4Y.js} +2 -2
- package/dist/cli/chunks/{chunk-2K3DJ3EK.js → chunk-ENG5UF7M.js} +2 -2
- package/dist/cli/chunks/{chunk-JVH7753D.js → chunk-EV2NMWJV.js} +1 -1
- package/dist/cli/chunks/{chunk-X66IXWSO.js → chunk-FGW5W3YK.js} +2 -2
- package/dist/cli/chunks/{chunk-IP2Z4Z6X.js → chunk-FTF34UME.js} +1 -1
- package/dist/cli/chunks/{chunk-YIJDCZVX.js → chunk-GYNGJHYF.js} +2 -2
- package/dist/cli/chunks/{chunk-AYKMWP7F.js → chunk-HDM43P7H.js} +1 -1
- package/dist/cli/chunks/{chunk-ECYDMBDA.js → chunk-HOWZFW7G.js} +2 -2
- package/dist/cli/chunks/{chunk-Y67OXEUM.js → chunk-IZC5NPHD.js} +1 -1
- package/dist/cli/chunks/{chunk-P7APAQD6.js → chunk-J2DNMVB5.js} +3 -3
- package/dist/cli/chunks/{chunk-HTL2WT64.js → chunk-J62N66ZH.js} +1 -1
- package/dist/cli/chunks/{chunk-IHJXFWUL.js → chunk-JIPU4YQK.js} +2 -2
- package/dist/cli/chunks/{chunk-MGX2BZWE.js → chunk-JK4K4EH3.js} +2 -2
- package/dist/cli/chunks/{chunk-WUCWFDBE.js → chunk-JQJHRQRX.js} +2 -2
- package/dist/cli/chunks/{chunk-IFIYNCT2.js → chunk-KSJCMXAJ.js} +2 -2
- package/dist/cli/chunks/{chunk-W45FANJG.js → chunk-MDTF7LE6.js} +2 -2
- package/dist/cli/chunks/{chunk-DDDEGBBJ.js → chunk-MUCFC3YG.js} +2 -2
- package/dist/cli/chunks/{chunk-BZB5D4BO.js → chunk-MUIJVPGB.js} +2 -2
- package/dist/cli/chunks/{chunk-VVNR4R22.js → chunk-MWZN4PYF.js} +2 -2
- package/dist/cli/chunks/{chunk-XVXSQOQG.js → chunk-MXMKHI2I.js} +2 -2
- package/dist/cli/chunks/{chunk-U62WL3WZ.js → chunk-MZOYBHJ3.js} +3 -3
- package/dist/cli/chunks/{chunk-TZMKO6PC.js → chunk-NLKJI73E.js} +2 -2
- package/dist/cli/chunks/{chunk-66DCG6RO.js → chunk-NQ3WHTLT.js} +4 -4
- package/dist/cli/chunks/{chunk-JBQ4WGB4.js → chunk-NVVF5ROM.js} +2 -2
- package/dist/cli/chunks/{chunk-HYACMUUR.js → chunk-OEZA7Q2Z.js} +2 -2
- package/dist/cli/chunks/{chunk-ELZ5SKEN.js → chunk-OFOFXJ3M.js} +2 -2
- package/dist/cli/chunks/{chunk-HN7HYUW6.js → chunk-OMRZUYXN.js} +9 -9
- package/dist/cli/chunks/{chunk-IIYXSWJN.js → chunk-P6YMECV2.js} +2 -2
- package/dist/cli/chunks/{chunk-R2LWLZ3Y.js → chunk-PEEN4AAK.js} +1 -1
- package/dist/cli/chunks/{chunk-4EAAHMVM.js → chunk-PRJUO2OQ.js} +2 -2
- package/dist/cli/chunks/{chunk-LFEBTWFS.js → chunk-PYTXZMXR.js} +2 -2
- package/dist/cli/chunks/{chunk-I25KIHQE.js → chunk-Q2ZBPOUX.js} +1 -1
- package/dist/cli/chunks/{chunk-76UL224Z.js → chunk-QHATTMJC.js} +2 -2
- package/dist/cli/chunks/{chunk-KJZU3E5G.js → chunk-QMNAELZG.js} +2 -2
- package/dist/cli/chunks/{chunk-3ZAGYTEC.js → chunk-QQLQEQJM.js} +2 -2
- package/dist/cli/chunks/{chunk-GOPE5OB5.js → chunk-QSA23PJ6.js} +1 -1
- package/dist/cli/chunks/{chunk-MVW7AACO.js → chunk-QTYTM7C7.js} +2 -2
- package/dist/cli/chunks/{chunk-6DBYVKGA.js → chunk-QZMBJ67L.js} +2 -2
- package/dist/cli/chunks/{chunk-S72TSJS4.js → chunk-R23PJGH7.js} +2 -2
- package/dist/cli/chunks/{chunk-YSUMQBMY.js → chunk-R5ZKFJ3H.js} +1 -1
- package/dist/cli/chunks/{chunk-JD3GH47Z.js → chunk-RLLDZNLF.js} +2 -2
- package/dist/cli/chunks/{chunk-F5VLJFVU.js → chunk-RZYTJSQT.js} +1 -1
- package/dist/cli/chunks/{chunk-JCROLOP6.js → chunk-S6VT7VAO.js} +2 -2
- package/dist/cli/chunks/{chunk-237NNDKL.js → chunk-SVLO2DVL.js} +2 -2
- package/dist/cli/chunks/{chunk-A2QLTNN5.js → chunk-TTENF6AH.js} +1 -1
- package/dist/cli/chunks/{chunk-CG3HIYF4.js → chunk-UEKDDUGV.js} +2 -2
- package/dist/cli/chunks/{chunk-E4D36LGH.js → chunk-UYKIPSRX.js} +1 -1
- package/dist/cli/chunks/{chunk-M2JBQVBP.js → chunk-VIIUJRKA.js} +2 -2
- package/dist/cli/chunks/chunk-VRH3YLO2.js +2 -0
- package/dist/cli/chunks/{chunk-I7OH6RAC.js → chunk-VTX4NAWB.js} +2 -2
- package/dist/cli/chunks/{chunk-P2H5ARHM.js → chunk-VWHALAEO.js} +1 -1
- package/dist/cli/chunks/{chunk-OZTSMI7P.js → chunk-W4VDPHWC.js} +1 -1
- package/dist/cli/chunks/{chunk-266SKKFM.js → chunk-W57I57M4.js} +2 -2
- package/dist/cli/chunks/{chunk-YOKRSFGA.js → chunk-WDWIJDQR.js} +2 -2
- package/dist/cli/chunks/{chunk-IZTUAI5T.js → chunk-WEJJWJ5M.js} +2 -2
- package/dist/cli/chunks/{chunk-ETXK25IY.js → chunk-WZR4CKR4.js} +1 -1
- package/dist/cli/chunks/{chunk-WJDOOT2M.js → chunk-XZ2JYMFT.js} +2 -2
- package/dist/cli/chunks/{chunk-SDMGF3KD.js → chunk-YISXT54V.js} +2 -2
- package/dist/cli/chunks/{chunk-N2L7RWNX.js → chunk-YRORPSPA.js} +2 -2
- package/dist/cli/chunks/{chunk-JNJYWWBG.js → chunk-YXE67VME.js} +6 -6
- package/dist/cli/chunks/{chunk-SSURIMCL.js → chunk-Z7AFNZMI.js} +2 -2
- package/dist/cli/chunks/{chunk-4GMV6Z7Y.js → chunk-ZEUORIH2.js} +2 -2
- package/dist/cli/chunks/{chunk-VHZ653XS.js → chunk-ZKXA4VBK.js} +3 -3
- package/dist/cli/chunks/{chunk-6KWX7A3R.js → chunk-ZTI3BATG.js} +2 -2
- package/dist/cli/chunks/{ci-A5ZXOEC4.js → ci-4QYE6JBM.js} +2 -2
- package/dist/cli/chunks/{ci-output-S47BMRYC.js → ci-output-MV75HUK7.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-F5WBEBVK.js → claude-flow-setup-CZITY7SG.js} +2 -2
- package/dist/cli/chunks/client-VXVVUQDV.js +2 -0
- package/dist/cli/chunks/{cline-installer-HLKR4QDR.js → cline-installer-ZLQKCPFF.js} +2 -2
- package/dist/cli/chunks/{code-MTZWS6JT.js → code-NYEXOJVP.js} +2 -2
- package/dist/cli/chunks/{code-index-extractor-BALTZ2WQ.js → code-index-extractor-TITXUC44.js} +2 -2
- package/dist/cli/chunks/{codex-installer-LI2VIGET.js → codex-installer-TWT4LIL2.js} +2 -2
- package/dist/cli/chunks/{completions-TOF4GTNF.js → completions-2KNV2MZG.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-IPFXIT6T.js → complexity-analyzer-2U3OVRDX.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-KWI66RBI.js → continuedev-installer-BWQBRVTC.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-REFOE6UF.js → copilot-installer-CYN33NMG.js} +2 -2
- package/dist/cli/chunks/{cost-tracker-M2MZQXCN.js → cost-tracker-2GUCBYLK.js} +2 -2
- package/dist/cli/chunks/{coverage-UR2XSJCR.js → coverage-BAVD66VL.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-HUJG6CFC.js +2 -0
- package/dist/cli/chunks/{cursor-installer-X4PXCVYH.js → cursor-installer-ZQAUD47B.js} +2 -2
- package/dist/cli/chunks/{daemon-5R6ZEEBB.js → daemon-VY2LZPIM.js} +3 -3
- package/dist/cli/chunks/{dag-attention-scheduler-RUY2RJZA.js → dag-attention-scheduler-JNQWWXSW.js} +2 -2
- package/dist/cli/chunks/{detect-PX2AYBHM.js → detect-Y7BBW4LI.js} +2 -2
- package/dist/cli/chunks/{domain-handler-5JXWEO3E.js → domain-handler-473WNSR2.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-6M2YLBJY.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-L6ZBG462.js → eval-TJAZGRCM.js} +2 -2
- package/dist/cli/chunks/{fast-paths-WIFDALFK.js → fast-paths-LMN542IB.js} +2 -2
- package/dist/cli/chunks/{feature-flags-YLBXFUCN.js → feature-flags-IMFZ7KED.js} +2 -2
- package/dist/cli/chunks/{feature-flags-GRHF5MTK.js → feature-flags-WMXIDTXL.js} +2 -2
- package/dist/cli/chunks/{file-discovery-4HXUB4HN.js → file-discovery-GXXWQJV3.js} +2 -2
- package/dist/cli/chunks/{fleet-RPLJXOEP.js → fleet-WIC7RHJV.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-2D5IOGAT.js → gnn-wrapper-PVKCXV25.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-D5SWZZGA.js → heartbeat-handler-BJ6ZZP7Q.js} +4 -4
- package/dist/cli/chunks/{heartbeat-scheduler-WSG4Y3M2.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-UH6RWE74.js → hnsw-legacy-bridge-23HFWIPK.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-BJ4ZJPMP.js → hnswlib-node-4GRFMUPD.js} +2 -2
- package/dist/cli/chunks/{hooks-KGDQNB5T.js → hooks-IXH5454I.js} +6 -6
- package/dist/cli/chunks/{hypergraph-engine-LARQCK7V.js → hypergraph-engine-TEQMJFJJ.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-RACF4AOX.js → hypergraph-handler-3ECUWIG3.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-D6MBGRKX.js +2 -0
- package/dist/cli/chunks/{init-handler-64AOFMJD.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-4ICIP6QN.js → kilocode-installer-IPH3O3ZS.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-J2GOV2OB.js → kiro-installer-VROMOOQO.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-4PM4DFH3.js +2 -0
- package/dist/cli/chunks/{learning-QD4JVH3K.js → learning-JYQLD66S.js} +3 -3
- package/dist/cli/chunks/{llm-router-4K4IT2PQ.js → llm-router-CIICNICY.js} +2 -2
- package/dist/cli/chunks/{load-EXKUJMBK.js → load-DMAQB4NC.js} +2 -2
- package/dist/cli/chunks/load-test-PPSWF3TO.js +2 -0
- package/dist/cli/chunks/{mcp-NSNDZSMH.js → mcp-K6CSUBMU.js} +2 -2
- package/dist/cli/chunks/{memory-63JTNVZN.js → memory-5BSXKHSK.js} +5 -5
- package/dist/cli/chunks/memory-backend-3E6BA2JU.js +2 -0
- package/dist/cli/chunks/{memory-handlers-2335MVQJ.js → memory-handlers-APOLXPNH.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-244LFSPN.js → opencode-installer-IUWO2QV6.js} +2 -2
- package/dist/cli/chunks/{orchestrator-TZB457J6.js → orchestrator-Z2EM76CR.js} +22 -19
- package/dist/cli/chunks/{pipeline-YLBD2Z5Q.js → pipeline-OL5SI2RI.js} +2 -2
- package/dist/cli/chunks/{platform-53PWFZSE.js → platform-VNJIKIHZ.js} +2 -2
- package/dist/cli/chunks/{plugin-6GUQEFJU.js → plugin-SJJUE47D.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-VCOK7FV5.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-25UEGTE2.js → protocol-handler-HTX44YTW.js} +2 -2
- package/dist/cli/chunks/{prove-CTOU5F6G.js → prove-MGFLVZNS.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-OGKT52EN.js +2 -0
- package/dist/cli/chunks/{quality-PB7H5UEF.js → quality-FMFKPICZ.js} +2 -2
- package/dist/cli/chunks/queen-coordinator-B63YXNI6.js +2 -0
- package/dist/cli/chunks/{real-embeddings-RWWYCIE5.js → real-embeddings-2BMEEOA2.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-U4AGYVKL.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-NTDKDEBE.js → routing-handler-SNGSQ757.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-RQKOLQSW.js → ruvector-commands-54MYLF63.js} +2 -2
- package/dist/cli/chunks/{rvf-dual-writer-6EZ7S7OG.js → rvf-dual-writer-6Q44XJOJ.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-adapter-EBTV6FV2.js → rvf-migration-adapter-JECN625C.js} +2 -2
- package/dist/cli/chunks/{rvf-migration-coordinator-MERU7VLY.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-JPDLGHMC.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-7OGLQE5Y.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-3TI3DHEL.js → status-handler-NNEF4SQV.js} +2 -2
- package/dist/cli/chunks/{structural-health-WCZKXVWS.js → structural-health-FY6QIA55.js} +2 -2
- package/dist/cli/chunks/{sync-AM5T4GYO.js → sync-2QMSZ67Q.js} +2 -2
- package/dist/cli/chunks/{task-handler-VHDTXPVP.js → task-handler-GZJPE2QW.js} +2 -2
- package/dist/cli/chunks/{task-handlers-GEJ36WNB.js → task-handlers-AHM37D4I.js} +2 -2
- package/dist/cli/chunks/{test-G6P5XGHM.js → test-JVA2S2R2.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-37RBUN4E.js → test-scheduling-PRMP4H6X.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-JPE3LWXQ.js → token-bootstrap-YJEHCBV2.js} +2 -2
- package/dist/cli/chunks/{token-usage-5XGVBLFR.js → token-usage-G73L32OF.js} +2 -2
- package/dist/cli/chunks/{transformers-JTKWAZJU.js → transformers-U3TSLEGO.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-KW2GWIIQ.js → tree-sitter-wasm-parser-QXP2MNSX.js} +2 -2
- package/dist/cli/chunks/{types-7R72BACI.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-TYB4ZTUL.js → validate-CTBEA4BZ.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-3TFI6PLT.js → validate-swarm-PHT6XW3A.js} +2 -2
- package/dist/cli/chunks/{vibium-3YELURJT.js → vibium-CRCYAH3V.js} +2 -2
- package/dist/cli/chunks/visual-security-F2I524IQ.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-7Q77A27Y.js → web-tree-sitter-2MH3G7K7.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-ASARRM2X.js → windsurf-installer-LBRNYFSI.js} +2 -2
- package/dist/cli/chunks/witness-chain-CN6FCWRY.js +2 -0
- package/dist/cli/chunks/{witness-chain-WZ6PNXEY.js → witness-chain-HNFQLO7Q.js} +2 -2
- package/dist/cli/chunks/{workflow-JDTEE6TY.js → workflow-DNAF6BQ2.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-JJBCCNYI.js +2 -0
- package/dist/cli/chunks/{wrappers-X7WZLBZD.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-D4XQUIJD.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-CGIWYLIP.js +0 -2
- package/dist/cli/chunks/base-BYVP2STR.js +0 -2
- package/dist/cli/chunks/browser-workflow-PC4N5TKL.js +0 -2
- package/dist/cli/chunks/chunk-OT4JADWW.js +0 -2
- package/dist/cli/chunks/client-56BU3GAX.js +0 -2
- package/dist/cli/chunks/cross-domain-router-XQT52BTB.js +0 -2
- package/dist/cli/chunks/dream-LFZCN5WK.js +0 -2
- package/dist/cli/chunks/esm-node-EBDIEPKS.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-BMXTVGZB.js +0 -2
- package/dist/cli/chunks/hnsw-index-YX6XLICT.js +0 -2
- package/dist/cli/chunks/impact-analyzer-MGSI2WBK.js +0 -2
- package/dist/cli/chunks/init-wizard-TBDWRRMC.js +0 -2
- package/dist/cli/chunks/kernel-NV7TO2FK.js +0 -2
- package/dist/cli/chunks/knowledge-graph-7REGYH6A.js +0 -2
- package/dist/cli/chunks/load-test-RYQK44TT.js +0 -2
- package/dist/cli/chunks/memory-backend-3EBE2DEX.js +0 -2
- package/dist/cli/chunks/protocol-executor-MR37S7GX.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-DANGLPTH.js +0 -2
- package/dist/cli/chunks/queen-coordinator-4YJPYF5F.js +0 -2
- package/dist/cli/chunks/router-F4IPY4RQ.js +0 -2
- package/dist/cli/chunks/routing-feedback-VGHFIJ5S.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-2P75WF5A.js +0 -2
- package/dist/cli/chunks/safe-db-47NEO2RS.js +0 -2
- package/dist/cli/chunks/schedule-L5GJW25Z.js +0 -2
- package/dist/cli/chunks/scheduler-NGGGSZMO.js +0 -2
- package/dist/cli/chunks/shared-rvf-adapter-NKNTYGHO.js +0 -2
- package/dist/cli/chunks/sqlite-persistence-TE2ZRHKA.js +0 -2
- package/dist/cli/chunks/unified-memory-KSBLUZT4.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-V3EOMQIZ.js +0 -2
- package/dist/cli/chunks/unified-persistence-URIRJ4BM.js +0 -2
- package/dist/cli/chunks/visual-security-DJOOVCBZ.js +0 -2
- package/dist/cli/chunks/witness-chain-ZWJUCXCJ.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-5CKA6Q74.js +0 -2
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// qe-browser: visual regression against stored PNG baselines.
|
|
3
|
+
//
|
|
4
|
+
// Usage:
|
|
5
|
+
// node visual-diff.js --name homepage
|
|
6
|
+
// node visual-diff.js --name homepage --threshold 0.02
|
|
7
|
+
// node visual-diff.js --name hero --selector "#hero" # not supported in v26.3.x
|
|
8
|
+
// node visual-diff.js --name homepage --update-baseline
|
|
9
|
+
//
|
|
10
|
+
// THRESHOLD SEMANTICS (M1 — devil's-advocate finding):
|
|
11
|
+
// --threshold is the MAX FRACTION of pixels allowed to differ before the
|
|
12
|
+
// check fails. The default is 0.10 (10% of pixels may differ).
|
|
13
|
+
// - threshold 0.00 → require pixel-perfect match
|
|
14
|
+
// - threshold 0.02 → allow up to 2% pixel difference
|
|
15
|
+
// - threshold 0.50 → allow up to 50% pixel difference (very lax)
|
|
16
|
+
// Internally we compute `similarity = 1 - diffPixels / totalPixels` and
|
|
17
|
+
// pass when `similarity >= 1 - threshold`. This is the standard convention
|
|
18
|
+
// used by Playwright's `maxDiffPixelRatio` and BackstopJS.
|
|
19
|
+
//
|
|
20
|
+
// Baselines live in .aqe/visual-baselines/<sanitized-name>.png
|
|
21
|
+
// Diff images (if pixelmatch available) go to .aqe/visual-baselines/<name>.diff.png
|
|
22
|
+
|
|
23
|
+
'use strict';
|
|
24
|
+
|
|
25
|
+
const fs = require('node:fs');
|
|
26
|
+
const path = require('node:path');
|
|
27
|
+
const crypto = require('node:crypto');
|
|
28
|
+
const {
|
|
29
|
+
vibium,
|
|
30
|
+
envelope,
|
|
31
|
+
parseArgs,
|
|
32
|
+
emit,
|
|
33
|
+
fail,
|
|
34
|
+
runOrSkip,
|
|
35
|
+
rethrowIfUnavailable,
|
|
36
|
+
} = require('./lib/vibium');
|
|
37
|
+
|
|
38
|
+
const BASELINE_DIR = path.join(process.cwd(), '.aqe', 'visual-baselines');
|
|
39
|
+
|
|
40
|
+
function sanitize(name) {
|
|
41
|
+
return String(name).replace(/[^A-Za-z0-9_-]/g, '_');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function ensureDir(dir) {
|
|
45
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Vibium screenshot quirks (verified against v26.3.18 on 2026-04-09):
|
|
49
|
+
// 1. `vibium screenshot -o <path>` IGNORES the directory in <path>.
|
|
50
|
+
// Only the basename is used, and the file is saved to
|
|
51
|
+
// `~/Pictures/Vibium/<basename>`. We work around this by reading from
|
|
52
|
+
// Vibium's actual output dir and copying to the requested location.
|
|
53
|
+
// 2. `--selector` flag does NOT exist on `vibium screenshot`. Selector-
|
|
54
|
+
// scoped baselines are not supported in v26.3.x. We surface a clear
|
|
55
|
+
// error if a caller passes one. Future Vibium versions may add it.
|
|
56
|
+
function vibiumPicturesDir() {
|
|
57
|
+
// Vibium hardcodes ~/Pictures/Vibium as the screenshot output directory.
|
|
58
|
+
return path.join(process.env.HOME || '/home/vscode', 'Pictures', 'Vibium');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function captureScreenshot(selector, outputPath) {
|
|
62
|
+
if (selector) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
'vibium screenshot --selector is not supported in Vibium v26.3.x. ' +
|
|
65
|
+
'Drop the --selector argument and crop the resulting full-page PNG with ' +
|
|
66
|
+
'a separate image-processing step (e.g. ImageMagick `convert -crop`). ' +
|
|
67
|
+
'Tracking upstream — if Vibium adds --selector support, this script ' +
|
|
68
|
+
'should switch to passing it through.'
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const basename = path.basename(outputPath);
|
|
72
|
+
const args = ['screenshot', '-o', basename, '--full-page'];
|
|
73
|
+
const res = vibium(args);
|
|
74
|
+
if (res.status !== 0) {
|
|
75
|
+
throw new Error(`vibium screenshot failed: ${res.stderr.trim() || res.stdout.trim()}`);
|
|
76
|
+
}
|
|
77
|
+
// Vibium wrote the file to ~/Pictures/Vibium/<basename>, not outputPath.
|
|
78
|
+
// Copy it to where the caller asked. Use copy-then-unlink so we leave
|
|
79
|
+
// Vibium's own dir clean for the next run.
|
|
80
|
+
const vibiumPath = path.join(vibiumPicturesDir(), basename);
|
|
81
|
+
if (!fs.existsSync(vibiumPath)) {
|
|
82
|
+
throw new Error(`screenshot output not created at ${vibiumPath} (vibium said: ${res.stdout.trim()})`);
|
|
83
|
+
}
|
|
84
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
85
|
+
fs.copyFileSync(vibiumPath, outputPath);
|
|
86
|
+
fs.unlinkSync(vibiumPath);
|
|
87
|
+
return outputPath;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function tryLoadPixelmatch() {
|
|
91
|
+
try {
|
|
92
|
+
const pixelmatch = require('pixelmatch');
|
|
93
|
+
const { PNG } = require('pngjs');
|
|
94
|
+
return { pixelmatch, PNG };
|
|
95
|
+
} catch (_err) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function parsePngSize(buffer) {
|
|
101
|
+
// PNG header: 8 bytes signature + 8 bytes IHDR chunk length/type + 4 width + 4 height
|
|
102
|
+
if (buffer.length < 24) return null;
|
|
103
|
+
const sig = buffer.slice(0, 8);
|
|
104
|
+
const expected = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
105
|
+
if (!sig.equals(expected)) return null;
|
|
106
|
+
const width = buffer.readUInt32BE(16);
|
|
107
|
+
const height = buffer.readUInt32BE(20);
|
|
108
|
+
return { width, height };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function hashBuffer(buf) {
|
|
112
|
+
return crypto.createHash('sha256').update(buf).digest('hex');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function compareWithPixelmatch(baselineBuf, currentBuf, diffPath) {
|
|
116
|
+
const mod = tryLoadPixelmatch();
|
|
117
|
+
if (!mod) return null;
|
|
118
|
+
const { pixelmatch, PNG } = mod;
|
|
119
|
+
const baseline = PNG.sync.read(baselineBuf);
|
|
120
|
+
const current = PNG.sync.read(currentBuf);
|
|
121
|
+
if (baseline.width !== current.width || baseline.height !== current.height) {
|
|
122
|
+
return {
|
|
123
|
+
similarity: 0,
|
|
124
|
+
diffPixelCount: Math.max(
|
|
125
|
+
baseline.width * baseline.height,
|
|
126
|
+
current.width * current.height
|
|
127
|
+
),
|
|
128
|
+
width: current.width,
|
|
129
|
+
height: current.height,
|
|
130
|
+
sizeMismatch: true,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const { width, height } = baseline;
|
|
134
|
+
const diff = new PNG({ width, height });
|
|
135
|
+
const diffCount = pixelmatch(baseline.data, current.data, diff.data, width, height, {
|
|
136
|
+
threshold: 0.1,
|
|
137
|
+
});
|
|
138
|
+
if (diffPath) {
|
|
139
|
+
fs.writeFileSync(diffPath, PNG.sync.write(diff));
|
|
140
|
+
}
|
|
141
|
+
const totalPixels = width * height;
|
|
142
|
+
return {
|
|
143
|
+
similarity: 1 - diffCount / totalPixels,
|
|
144
|
+
diffPixelCount: diffCount,
|
|
145
|
+
width,
|
|
146
|
+
height,
|
|
147
|
+
sizeMismatch: false,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function compareFallback(baselineBuf, currentBuf) {
|
|
152
|
+
// Exact-match fallback when pixelmatch is not installed.
|
|
153
|
+
// Same hash = identical; otherwise we only know width/height and rough similarity from byte diff.
|
|
154
|
+
const bSize = parsePngSize(baselineBuf);
|
|
155
|
+
const cSize = parsePngSize(currentBuf);
|
|
156
|
+
if (!bSize || !cSize) {
|
|
157
|
+
return {
|
|
158
|
+
similarity: 0,
|
|
159
|
+
diffPixelCount: 0,
|
|
160
|
+
width: cSize ? cSize.width : 0,
|
|
161
|
+
height: cSize ? cSize.height : 0,
|
|
162
|
+
sizeMismatch: true,
|
|
163
|
+
note: 'pixelmatch not installed and PNG header unreadable',
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
if (bSize.width !== cSize.width || bSize.height !== cSize.height) {
|
|
167
|
+
return {
|
|
168
|
+
similarity: 0,
|
|
169
|
+
diffPixelCount: 0,
|
|
170
|
+
width: cSize.width,
|
|
171
|
+
height: cSize.height,
|
|
172
|
+
sizeMismatch: true,
|
|
173
|
+
note: 'pixelmatch not installed; size mismatch',
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const same = hashBuffer(baselineBuf) === hashBuffer(currentBuf);
|
|
177
|
+
return {
|
|
178
|
+
similarity: same ? 1 : 0,
|
|
179
|
+
diffPixelCount: same ? 0 : bSize.width * bSize.height,
|
|
180
|
+
width: cSize.width,
|
|
181
|
+
height: cSize.height,
|
|
182
|
+
sizeMismatch: false,
|
|
183
|
+
note: same ? undefined : 'pixelmatch not installed; exact-hash fallback reports 0 similarity',
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function main() {
|
|
188
|
+
const args = parseArgs(process.argv.slice(2));
|
|
189
|
+
const name = args.name;
|
|
190
|
+
if (!name) return fail('visual-diff', 'missing --name argument');
|
|
191
|
+
|
|
192
|
+
const threshold = args.threshold !== undefined ? parseFloat(args.threshold) : 0.1;
|
|
193
|
+
if (Number.isNaN(threshold) || threshold < 0 || threshold > 1) {
|
|
194
|
+
return fail('visual-diff', '--threshold must be between 0 and 1');
|
|
195
|
+
}
|
|
196
|
+
const updateBaseline = Boolean(args['update-baseline']);
|
|
197
|
+
const selector = args.selector;
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
ensureDir(BASELINE_DIR);
|
|
201
|
+
const sanitized = sanitize(name);
|
|
202
|
+
const baselinePath = path.join(BASELINE_DIR, `${sanitized}.png`);
|
|
203
|
+
const currentPath = path.join(BASELINE_DIR, `${sanitized}.current.png`);
|
|
204
|
+
const diffPath = path.join(BASELINE_DIR, `${sanitized}.diff.png`);
|
|
205
|
+
|
|
206
|
+
const startedAt = Date.now();
|
|
207
|
+
captureScreenshot(selector, currentPath);
|
|
208
|
+
const currentBuf = fs.readFileSync(currentPath);
|
|
209
|
+
|
|
210
|
+
if (!fs.existsSync(baselinePath) || updateBaseline) {
|
|
211
|
+
fs.writeFileSync(baselinePath, currentBuf);
|
|
212
|
+
const size = parsePngSize(currentBuf) || { width: 0, height: 0 };
|
|
213
|
+
return emit(
|
|
214
|
+
envelope({
|
|
215
|
+
operation: 'visual-diff',
|
|
216
|
+
summary: updateBaseline
|
|
217
|
+
? `Baseline "${name}" updated`
|
|
218
|
+
: `Baseline "${name}" created`,
|
|
219
|
+
status: 'success',
|
|
220
|
+
details: {
|
|
221
|
+
visualDiff: {
|
|
222
|
+
name,
|
|
223
|
+
status: updateBaseline ? 'baseline_updated' : 'baseline_created',
|
|
224
|
+
similarity: 1,
|
|
225
|
+
diffPixelCount: 0,
|
|
226
|
+
width: size.width,
|
|
227
|
+
height: size.height,
|
|
228
|
+
threshold,
|
|
229
|
+
baselinePath,
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
metadata: { executionTimeMs: Date.now() - startedAt },
|
|
233
|
+
})
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const baselineBuf = fs.readFileSync(baselinePath);
|
|
238
|
+
let cmp = compareWithPixelmatch(baselineBuf, currentBuf, diffPath);
|
|
239
|
+
if (cmp === null) cmp = compareFallback(baselineBuf, currentBuf);
|
|
240
|
+
|
|
241
|
+
const passed = cmp.similarity >= 1 - threshold && !cmp.sizeMismatch;
|
|
242
|
+
return emit(
|
|
243
|
+
envelope({
|
|
244
|
+
operation: 'visual-diff',
|
|
245
|
+
summary: passed
|
|
246
|
+
? `Visual match for "${name}" (similarity ${cmp.similarity.toFixed(4)})`
|
|
247
|
+
: `Visual mismatch for "${name}" (similarity ${cmp.similarity.toFixed(4)} below threshold ${1 - threshold})`,
|
|
248
|
+
status: passed ? 'success' : 'failed',
|
|
249
|
+
details: {
|
|
250
|
+
visualDiff: {
|
|
251
|
+
name,
|
|
252
|
+
status: passed ? 'match' : 'mismatch',
|
|
253
|
+
similarity: cmp.similarity,
|
|
254
|
+
diffPixelCount: cmp.diffPixelCount,
|
|
255
|
+
width: cmp.width,
|
|
256
|
+
height: cmp.height,
|
|
257
|
+
threshold,
|
|
258
|
+
baselinePath,
|
|
259
|
+
diffPath: fs.existsSync(diffPath) ? diffPath : undefined,
|
|
260
|
+
note: cmp.note,
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
metadata: { executionTimeMs: Date.now() - startedAt },
|
|
264
|
+
})
|
|
265
|
+
);
|
|
266
|
+
} catch (err) {
|
|
267
|
+
rethrowIfUnavailable(err); // F1
|
|
268
|
+
return fail('visual-diff', err.message);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (require.main === module) {
|
|
273
|
+
process.exit(runOrSkip('visual-diff', main));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
module.exports = { compareWithPixelmatch, compareFallback, parsePngSize };
|
|
@@ -61,9 +61,39 @@ Task("Audit accessibility", `
|
|
|
61
61
|
`, "qe-accessibility-agent")
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
## Browser engine
|
|
65
|
+
|
|
66
|
+
All browser automation in this skill uses the **qe-browser** fleet skill (Vibium engine). See `.claude/skills/qe-browser/SKILL.md`. The `vibium` binary is installed by `aqe init`.
|
|
67
|
+
|
|
64
68
|
## Visual Testing Operations
|
|
65
69
|
|
|
66
|
-
### 1. Visual Regression
|
|
70
|
+
### 1. Visual Regression (via qe-browser)
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Establish baselines for the pages we care about
|
|
74
|
+
for path in / /login /dashboard /settings; do
|
|
75
|
+
slug=$(echo "$path" | tr '/' '_' | sed 's/^_//' || echo root)
|
|
76
|
+
vibium go "https://production.example.com$path" && vibium wait load
|
|
77
|
+
node .claude/skills/qe-browser/scripts/visual-diff.js --name "baseline_${slug:-root}"
|
|
78
|
+
done
|
|
79
|
+
|
|
80
|
+
# Compare staging against those baselines
|
|
81
|
+
for path in / /login /dashboard /settings; do
|
|
82
|
+
slug=$(echo "$path" | tr '/' '_' | sed 's/^_//' || echo root)
|
|
83
|
+
vibium go "https://staging.example.com$path" && vibium wait load
|
|
84
|
+
node .claude/skills/qe-browser/scripts/visual-diff.js \
|
|
85
|
+
--name "baseline_${slug:-root}" --threshold 0.001 # 0.1% pixel diff
|
|
86
|
+
done
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Ignore dynamic regions (timestamps, live counts) by scoping the diff to a selector that excludes them:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
node .claude/skills/qe-browser/scripts/visual-diff.js \
|
|
93
|
+
--name hero --selector "main > .content"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Legacy programmatic TypeScript API (still available for tests that prefer it over shelling out):
|
|
67
97
|
|
|
68
98
|
```typescript
|
|
69
99
|
await visualTester.compareScreenshots({
|
|
@@ -20,6 +20,24 @@ validation:
|
|
|
20
20
|
|
|
21
21
|
# Security Visual Testing
|
|
22
22
|
|
|
23
|
+
## Browser engine
|
|
24
|
+
|
|
25
|
+
Uses the **qe-browser** fleet skill (`.claude/skills/qe-browser/`) for all browser automation. The Vibium engine (10MB Go binary, WebDriver BiDi) is installed automatically by `aqe init`. For security-visual workflows, qe-browser adds two things on top of stock visual testing: `check-injection.js` (scans page content for prompt-injection patterns before screenshots are stored) and `assert.js` (16 typed checks including `no_failed_requests` for detecting data-leak requests).
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Before storing any screenshot, scan the page
|
|
29
|
+
vibium go "$TARGET_URL"
|
|
30
|
+
vibium wait load
|
|
31
|
+
node .claude/skills/qe-browser/scripts/check-injection.js --include-hidden
|
|
32
|
+
INJ=$?
|
|
33
|
+
if [ $INJ -ne 0 ]; then
|
|
34
|
+
echo "Prompt-injection findings — do NOT store screenshot"
|
|
35
|
+
exit $INJ
|
|
36
|
+
fi
|
|
37
|
+
# Safe to proceed with visual-diff
|
|
38
|
+
node .claude/skills/qe-browser/scripts/visual-diff.js --name "${PAGE_NAME}"
|
|
39
|
+
```
|
|
40
|
+
|
|
23
41
|
<default_to_action>
|
|
24
42
|
When performing security-aware visual testing:
|
|
25
43
|
1. VALIDATE URLs before navigation (check for malicious patterns)
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"generated": "2026-
|
|
4
|
-
"totalSkills":
|
|
5
|
-
"
|
|
2
|
+
"version": "1.4.0",
|
|
3
|
+
"generated": "2026-04-09T00:00:00.000Z",
|
|
4
|
+
"totalSkills": 49,
|
|
5
|
+
"totalQESkills": 81,
|
|
6
|
+
"description": "Agentic QE Fleet skills manifest - 49 Tier 3 verified QE skills. Total 81 QE skills on disk (49 Tier 3 + 32 additional including QCSD swarms, n8n testing, enterprise integration, pentest validation, qe-* domains, qe-browser via ADR-091).",
|
|
6
7
|
"categories": {
|
|
7
8
|
"qcsd-phases": {
|
|
8
9
|
"description": "QCSD (Quality Conscious Software Delivery) phase swarms for shift-left quality",
|
|
9
10
|
"priority": "critical",
|
|
10
11
|
"autoInvoke": true,
|
|
11
|
-
"skills": ["qcsd-ideation-swarm"]
|
|
12
|
+
"skills": ["qcsd-ideation-swarm", "qcsd-refinement-swarm", "qcsd-development-swarm", "qcsd-cicd-swarm"]
|
|
12
13
|
},
|
|
13
14
|
"qe-core": {
|
|
14
15
|
"description": "Foundational quality engineering philosophy and agentic principles",
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"priority": "medium",
|
|
32
33
|
"skills": [
|
|
33
34
|
"security-testing",
|
|
35
|
+
"pentest-validation",
|
|
34
36
|
"validation-pipeline",
|
|
35
37
|
"performance-testing",
|
|
36
38
|
"accessibility-testing",
|
|
@@ -47,6 +49,13 @@
|
|
|
47
49
|
"regression-testing"
|
|
48
50
|
]
|
|
49
51
|
},
|
|
52
|
+
"browser-automation": {
|
|
53
|
+
"description": "Browser automation fleet skill using Vibium (WebDriver BiDi) with typed assertions, batch execution, visual diff, prompt-injection scanning, and semantic intents. Supersedes per-skill browser glue across a11y-ally, e2e-flow-verifier, visual-testing-advanced, and others. See ADR-091.",
|
|
54
|
+
"priority": "high",
|
|
55
|
+
"skills": [
|
|
56
|
+
"qe-browser"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
50
59
|
"analysis-review": {
|
|
51
60
|
"description": "Code and quality analysis skills",
|
|
52
61
|
"priority": "medium",
|
|
@@ -113,6 +122,8 @@
|
|
|
113
122
|
"evaluate with qcsd",
|
|
114
123
|
"run qcsd",
|
|
115
124
|
"shift-left quality",
|
|
125
|
+
"shift-left quality assessment",
|
|
126
|
+
"analyze url for quality",
|
|
116
127
|
"quality criteria session",
|
|
117
128
|
"risk storming"
|
|
118
129
|
],
|
|
@@ -131,6 +142,169 @@
|
|
|
131
142
|
}
|
|
132
143
|
}
|
|
133
144
|
},
|
|
145
|
+
"qcsd-refinement-swarm": {
|
|
146
|
+
"id": "qcsd-refinement-swarm",
|
|
147
|
+
"name": "QCSD Refinement Swarm",
|
|
148
|
+
"description": "QCSD Refinement phase swarm using SFDIPOT product factors, BDD scenario generation, and requirements validation for Sprint Refinement sessions.",
|
|
149
|
+
"category": "qcsd-phases",
|
|
150
|
+
"priority": "critical",
|
|
151
|
+
"file": "qcsd-refinement-swarm/SKILL.md",
|
|
152
|
+
"tokenEstimate": 3200,
|
|
153
|
+
"optimizationStatus": "active",
|
|
154
|
+
"optimizationVersion": "1.0",
|
|
155
|
+
"lastOptimized": "2026-02-02",
|
|
156
|
+
"tags": ["qcsd", "refinement", "sfdipot", "bdd", "gherkin", "requirements", "swarm"],
|
|
157
|
+
"dependencies": ["agentic-quality-engineering", "context-driven-testing"],
|
|
158
|
+
"agents": [
|
|
159
|
+
"qe-product-factors-assessor",
|
|
160
|
+
"qe-bdd-generator",
|
|
161
|
+
"qe-requirements-validator",
|
|
162
|
+
"qe-contract-validator",
|
|
163
|
+
"qe-impact-analyzer",
|
|
164
|
+
"qe-dependency-mapper",
|
|
165
|
+
"qe-test-idea-rewriter"
|
|
166
|
+
],
|
|
167
|
+
"relatedSkills": ["context-driven-testing", "testability-scoring", "risk-based-testing"],
|
|
168
|
+
"triggers": {
|
|
169
|
+
"patterns": [
|
|
170
|
+
"qcsd refinement",
|
|
171
|
+
"refinement swarm",
|
|
172
|
+
"sfdipot analysis",
|
|
173
|
+
"product factors analysis",
|
|
174
|
+
"sprint refinement",
|
|
175
|
+
"story refinement",
|
|
176
|
+
"bdd generation",
|
|
177
|
+
"generate scenarios",
|
|
178
|
+
"refine story",
|
|
179
|
+
"refine epic"
|
|
180
|
+
],
|
|
181
|
+
"autoInvoke": true,
|
|
182
|
+
"enforcementLevel": "strict"
|
|
183
|
+
},
|
|
184
|
+
"execution": {
|
|
185
|
+
"primary": "task-tool",
|
|
186
|
+
"parallel_batches": 3,
|
|
187
|
+
"requiresFlagDetection": true,
|
|
188
|
+
"requiresDirectWrite": true,
|
|
189
|
+
"conditionalAgents": {
|
|
190
|
+
"qe-contract-validator": "HAS_API",
|
|
191
|
+
"qe-impact-analyzer": "HAS_REFACTORING",
|
|
192
|
+
"qe-dependency-mapper": "HAS_DEPENDENCIES"
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
"qcsd-development-swarm": {
|
|
197
|
+
"id": "qcsd-development-swarm",
|
|
198
|
+
"name": "QCSD Development Swarm",
|
|
199
|
+
"description": "QCSD Development phase swarm for in-sprint code quality assurance using TDD adherence, code complexity analysis, coverage gap detection, and defect prediction.",
|
|
200
|
+
"category": "qcsd-phases",
|
|
201
|
+
"priority": "critical",
|
|
202
|
+
"file": "qcsd-development-swarm/SKILL.md",
|
|
203
|
+
"tokenEstimate": 3400,
|
|
204
|
+
"optimizationStatus": "active",
|
|
205
|
+
"optimizationVersion": "1.0",
|
|
206
|
+
"lastOptimized": "2026-02-03",
|
|
207
|
+
"tags": ["qcsd", "development", "tdd", "complexity", "coverage", "security", "performance", "mutation", "defect-prediction", "swarm"],
|
|
208
|
+
"dependencies": ["agentic-quality-engineering", "tdd-london-chicago"],
|
|
209
|
+
"agents": [
|
|
210
|
+
"qe-tdd-specialist",
|
|
211
|
+
"qe-code-complexity",
|
|
212
|
+
"qe-coverage-specialist",
|
|
213
|
+
"qe-security-scanner",
|
|
214
|
+
"qe-performance-tester",
|
|
215
|
+
"qe-mutation-tester",
|
|
216
|
+
"qe-defect-predictor"
|
|
217
|
+
],
|
|
218
|
+
"relatedSkills": ["tdd-london-chicago", "mutation-testing", "performance-testing", "security-testing"],
|
|
219
|
+
"triggers": {
|
|
220
|
+
"patterns": [
|
|
221
|
+
"qcsd development",
|
|
222
|
+
"development swarm",
|
|
223
|
+
"code quality analysis",
|
|
224
|
+
"tdd analysis",
|
|
225
|
+
"coverage analysis",
|
|
226
|
+
"complexity analysis",
|
|
227
|
+
"development quality",
|
|
228
|
+
"development quality gate",
|
|
229
|
+
"code review swarm",
|
|
230
|
+
"analyze code quality",
|
|
231
|
+
"analyze code for quality",
|
|
232
|
+
"sprint code check",
|
|
233
|
+
"in-sprint quality check",
|
|
234
|
+
"mutation testing",
|
|
235
|
+
"defect prediction",
|
|
236
|
+
"is code ready to ship"
|
|
237
|
+
],
|
|
238
|
+
"autoInvoke": true,
|
|
239
|
+
"enforcementLevel": "strict"
|
|
240
|
+
},
|
|
241
|
+
"execution": {
|
|
242
|
+
"primary": "task-tool",
|
|
243
|
+
"parallel_batches": 3,
|
|
244
|
+
"requiresFlagDetection": true,
|
|
245
|
+
"requiresDirectWrite": true,
|
|
246
|
+
"conditionalAgents": {
|
|
247
|
+
"qe-security-scanner": "HAS_SECURITY_CODE",
|
|
248
|
+
"qe-performance-tester": "HAS_PERFORMANCE_CODE",
|
|
249
|
+
"qe-mutation-tester": "HAS_CRITICAL_CODE"
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
"qcsd-cicd-swarm": {
|
|
254
|
+
"id": "qcsd-cicd-swarm",
|
|
255
|
+
"name": "QCSD CI/CD Swarm",
|
|
256
|
+
"description": "QCSD Verification phase swarm for CI/CD pipeline quality gates using regression analysis, flaky test detection, quality gate enforcement, and deployment readiness assessment.",
|
|
257
|
+
"category": "qcsd-phases",
|
|
258
|
+
"priority": "critical",
|
|
259
|
+
"file": "qcsd-cicd-swarm/SKILL.md",
|
|
260
|
+
"tokenEstimate": 3500,
|
|
261
|
+
"optimizationStatus": "active",
|
|
262
|
+
"optimizationVersion": "1.0",
|
|
263
|
+
"lastOptimized": "2026-02-03",
|
|
264
|
+
"tags": ["qcsd", "verification", "cicd", "pipeline", "quality-gate", "regression", "flaky", "security", "chaos", "coverage", "deployment", "swarm"],
|
|
265
|
+
"dependencies": ["agentic-quality-engineering", "shift-left-testing"],
|
|
266
|
+
"agents": [
|
|
267
|
+
"qe-quality-gate",
|
|
268
|
+
"qe-regression-analyzer",
|
|
269
|
+
"qe-flaky-hunter",
|
|
270
|
+
"qe-security-scanner",
|
|
271
|
+
"qe-chaos-engineer",
|
|
272
|
+
"qe-coverage-specialist",
|
|
273
|
+
"qe-deployment-advisor"
|
|
274
|
+
],
|
|
275
|
+
"relatedSkills": ["shift-left-testing", "shift-right-testing", "regression-testing", "security-testing"],
|
|
276
|
+
"triggers": {
|
|
277
|
+
"patterns": [
|
|
278
|
+
"qcsd verification",
|
|
279
|
+
"qcsd cicd",
|
|
280
|
+
"cicd swarm",
|
|
281
|
+
"pipeline verification",
|
|
282
|
+
"release readiness",
|
|
283
|
+
"is this safe to release",
|
|
284
|
+
"deployment readiness",
|
|
285
|
+
"verify pipeline",
|
|
286
|
+
"release gate",
|
|
287
|
+
"quality gate check",
|
|
288
|
+
"pre-release check",
|
|
289
|
+
"release verification",
|
|
290
|
+
"verify build",
|
|
291
|
+
"pipeline quality"
|
|
292
|
+
],
|
|
293
|
+
"autoInvoke": true,
|
|
294
|
+
"enforcementLevel": "strict"
|
|
295
|
+
},
|
|
296
|
+
"execution": {
|
|
297
|
+
"primary": "task-tool",
|
|
298
|
+
"parallel_batches": 3,
|
|
299
|
+
"requiresFlagDetection": true,
|
|
300
|
+
"requiresDirectWrite": true,
|
|
301
|
+
"conditionalAgents": {
|
|
302
|
+
"qe-security-scanner": "HAS_SECURITY_PIPELINE",
|
|
303
|
+
"qe-chaos-engineer": "HAS_PERFORMANCE_PIPELINE",
|
|
304
|
+
"qe-coverage-specialist": "HAS_INFRA_CHANGE"
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
134
308
|
"agentic-quality-engineering": {
|
|
135
309
|
"id": "agentic-quality-engineering",
|
|
136
310
|
"name": "Agentic Quality Engineering",
|
|
@@ -659,7 +833,7 @@
|
|
|
659
833
|
"validation-pipeline": {
|
|
660
834
|
"id": "validation-pipeline",
|
|
661
835
|
"name": "Validation Pipeline",
|
|
662
|
-
"description": "Run structured 13-step requirements validation pipeline with gate enforcement, weighted scoring, and detailed findings.",
|
|
836
|
+
"description": "Run structured 13-step requirements validation pipeline with gate enforcement, weighted scoring, and detailed findings. Supports format checking, vague term detection, testability analysis, and more.",
|
|
663
837
|
"category": "specialized-testing",
|
|
664
838
|
"priority": "high",
|
|
665
839
|
"file": "validation-pipeline/SKILL.md",
|
|
@@ -669,7 +843,19 @@
|
|
|
669
843
|
"lastOptimized": "2026-03-12",
|
|
670
844
|
"tags": ["validation", "requirements", "pipeline", "gate-enforcement", "scoring", "bmad"],
|
|
671
845
|
"dependencies": ["agentic-quality-engineering"],
|
|
672
|
-
"agents": ["qe-requirements-validator"]
|
|
846
|
+
"agents": ["qe-requirements-validator"],
|
|
847
|
+
"relatedSkills": ["verification-quality", "shift-left-testing", "context-driven-testing"],
|
|
848
|
+
"triggers": {
|
|
849
|
+
"patterns": [
|
|
850
|
+
"validate requirements",
|
|
851
|
+
"requirements validation",
|
|
852
|
+
"validation pipeline",
|
|
853
|
+
"run validation",
|
|
854
|
+
"check requirements quality"
|
|
855
|
+
],
|
|
856
|
+
"autoInvoke": false,
|
|
857
|
+
"enforcementLevel": "standard"
|
|
858
|
+
}
|
|
673
859
|
},
|
|
674
860
|
"bug-reporting-excellence": {
|
|
675
861
|
"id": "bug-reporting-excellence",
|
|
@@ -708,6 +894,9 @@
|
|
|
708
894
|
},
|
|
709
895
|
"byTask": {
|
|
710
896
|
"qcsd-analysis": ["qcsd-ideation-swarm", "testability-scoring", "risk-based-testing", "context-driven-testing", "holistic-testing-pact"],
|
|
897
|
+
"qcsd-refinement": ["qcsd-refinement-swarm", "context-driven-testing", "testability-scoring", "risk-based-testing"],
|
|
898
|
+
"qcsd-development": ["qcsd-development-swarm", "tdd-london-chicago", "mutation-testing", "performance-testing", "security-testing"],
|
|
899
|
+
"qcsd-verification": ["qcsd-cicd-swarm", "shift-left-testing", "shift-right-testing", "regression-testing", "security-testing"],
|
|
711
900
|
"url-quality-analysis": ["qcsd-ideation-swarm", "a11y-ally", "security-testing", "performance-testing"],
|
|
712
901
|
"test-generation": ["tdd-london-chicago", "api-testing-patterns", "test-design-techniques"],
|
|
713
902
|
"coverage-analysis": ["holistic-testing-pact", "quality-metrics", "testability-scoring"],
|
|
@@ -723,8 +912,8 @@
|
|
|
723
912
|
"optimizationTracking": {
|
|
724
913
|
"targetReduction": "40-50%",
|
|
725
914
|
"optimizedSkills": 7,
|
|
726
|
-
"totalSkills":
|
|
727
|
-
"progress": "
|
|
915
|
+
"totalSkills": 47,
|
|
916
|
+
"progress": "15.2%",
|
|
728
917
|
"tokensSaved": 10200,
|
|
729
918
|
"optimizedList": [
|
|
730
919
|
"agentic-quality-engineering",
|
|
@@ -750,9 +939,9 @@
|
|
|
750
939
|
},
|
|
751
940
|
"metadata": {
|
|
752
941
|
"generatedBy": "Agentic QE Fleet",
|
|
753
|
-
"fleetVersion": "
|
|
754
|
-
"manifestVersion": "1.
|
|
755
|
-
"lastUpdated": "
|
|
942
|
+
"fleetVersion": "3.9.9",
|
|
943
|
+
"manifestVersion": "1.4.0",
|
|
944
|
+
"lastUpdated": "2026-04-09T00:00:00.000Z",
|
|
756
945
|
"contributors": [
|
|
757
946
|
{
|
|
758
947
|
"name": "@fndlalit",
|
|
@@ -760,10 +949,17 @@
|
|
|
760
949
|
"url": "https://github.com/fndlalit"
|
|
761
950
|
}
|
|
762
951
|
],
|
|
763
|
-
"notes": "This manifest
|
|
952
|
+
"notes": "This manifest tracks 49 Tier 3 verified QE skills. Total 81 QE skills on disk (49 Tier 3 + 32 additional). qe-browser added 2026-04-09 per ADR-091. Claude Flow platform skills (33) are managed separately.",
|
|
953
|
+
"skillBreakdown": {
|
|
954
|
+
"qeSkillsTier3": 49,
|
|
955
|
+
"qeSkillsAdditional": 32,
|
|
956
|
+
"totalQESkills": 81,
|
|
957
|
+
"platformSkills": 36,
|
|
958
|
+
"totalOnDisk": 114
|
|
959
|
+
},
|
|
764
960
|
"excludedCategories": {
|
|
765
|
-
"reason": "
|
|
766
|
-
"categories": ["agentdb", "orchestration", "github-integration", "flow-nexus", "meta"]
|
|
961
|
+
"reason": "Platform skills are available but not tracked in this QE-focused manifest",
|
|
962
|
+
"categories": ["agentdb", "orchestration", "github-integration", "flow-nexus", "meta", "v3-internal"]
|
|
767
963
|
}
|
|
768
964
|
}
|
|
769
965
|
}
|
|
@@ -22,6 +22,29 @@ validation:
|
|
|
22
22
|
|
|
23
23
|
# Testability Scoring
|
|
24
24
|
|
|
25
|
+
## Browser engine
|
|
26
|
+
|
|
27
|
+
Uses the **qe-browser** fleet skill (`.claude/skills/qe-browser/`) as the primary browser engine. Vibium is installed by `aqe init`. The legacy `scripts/run-assessment.sh` + Playwright path remains as a fallback when a team already has a Playwright test suite configured, but new runs should prefer:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
vibium go "$TARGET_URL"
|
|
31
|
+
vibium wait load
|
|
32
|
+
vibium a11y-tree --json > /tmp/testability/tree.json
|
|
33
|
+
vibium eval --stdin --json <<'EOF' > /tmp/testability/signals.json
|
|
34
|
+
JSON.stringify({
|
|
35
|
+
headings: document.querySelectorAll('h1,h2,h3,h4,h5,h6').length,
|
|
36
|
+
testIds: document.querySelectorAll('[data-testid]').length,
|
|
37
|
+
forms: document.querySelectorAll('form').length,
|
|
38
|
+
ariaLabels: document.querySelectorAll('[aria-label]').length,
|
|
39
|
+
links: document.querySelectorAll('a[href]').length,
|
|
40
|
+
});
|
|
41
|
+
EOF
|
|
42
|
+
node .claude/skills/qe-browser/scripts/assert.js --checks '[
|
|
43
|
+
{"kind": "no_console_errors"},
|
|
44
|
+
{"kind": "no_failed_requests"}
|
|
45
|
+
]'
|
|
46
|
+
```
|
|
47
|
+
|
|
25
48
|
<default_to_action>
|
|
26
49
|
When assessing testability:
|
|
27
50
|
1. RUN assessment against target URL
|