{"_id":"@abiezon/qagent","_rev":"18-39e62a3cf8af193213820554e2789f71","name":"@abiezon/qagent","dist-tags":{"latest":"0.12.1"},"versions":{"0.1.1":{"name":"@abiezon/qagent","version":"0.1.1","_id":"@abiezon/qagent@0.1.1","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"428c88f658065bfc0400fb6ab1b940faa1d20498","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.1.1.tgz","fileCount":15,"integrity":"sha512-GudUVv4tZ0vdaXJNgRk+IwA54n8ZIxyDcdC4M1dCe5273gcFC5sOcRDiQUmfPJ+pc8QUfWhuutHsp8VrBOMxDA==","signatures":[{"sig":"MEUCIFQDSdDFqH9sNZB54WaFwvQztgjLmYYOvaTTcciSme5wAiEAxRulKZMyPhFAFf5Liy9jARE3erzAnmeri7vxfovREjo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98513},"type":"module","engines":{"node":">=18"},"gitHead":"d0bf3eef04128811b3b81cfb39090cbb6bb6f469","scripts":{"render":"node scripts/render.mjs","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Hub agêntico de QA — independente de ferramenta de spec","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.1.1_1785421834582_0.6106054279794766","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@abiezon/qagent","version":"0.1.2","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.1.2","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"8a5673e51d7833169244f55090e15f97b1c09354","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.1.2.tgz","fileCount":16,"integrity":"sha512-I+ZZNiVVnkQR6glawEufl8w0yOPCdAGdW4eL7c7MBAI+s9CPRJTlU0ewE6IGg2UIuHXMG+xtpBnDtF1gACKKVQ==","signatures":[{"sig":"MEUCIQC2fecQ+GuZZblEp0sxphsfYxPwGyhdA2+iX0m9AlGrwgIgBEzCYFSJiYklFVis1t9fkqtl/+ucS0YtWnIW/B5Jjfc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98555},"type":"module","engines":{"node":">=18"},"gitHead":"21aef6fcc759fc1740ef066b04b1f36a42608eb6","scripts":{"render":"node scripts/render.mjs","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.1.2_1785423399461_0.9898145382943908","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@abiezon/qagent","version":"0.2.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.2.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"1cbf7ea76d811b991022756525fceccd173eb5c8","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.2.0.tgz","fileCount":16,"integrity":"sha512-ic1IUaAQsFg/gDDZYZzyj0KBQvdis/aggfFGA3oMZPdghAEylZWt09ZM/TgiCkbHQa/8rz09CzLMybW8mOGVPA==","signatures":[{"sig":"MEUCIQCi/RgNS+gy7S0lKhRiZOCjO/t2x7ZgcI6w+VmudHVrGQIgEU4AQitay9bcpkSqgcwT/yI0YsY34m6zbjMUtFkQOHM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":105503},"type":"module","engines":{"node":">=18"},"gitHead":"7b34844359219aca2bd3279d415b8bbe73e7ae1b","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.2.0_1785428934841_0.6051236536310314","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@abiezon/qagent","version":"0.3.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.3.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"f27f9db4af2fb590a3dcd68ab74411c8a0d2f46a","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.3.0.tgz","fileCount":16,"integrity":"sha512-TCmI0GT1xecoCpV+iVS+JqsDdpsYiC0JXFD6hLOiD6j9Ih/nwkFhzvfozmcFx5M8wvHqglyLHj7+k4TOQJaHqg==","signatures":[{"sig":"MEQCIBy1hbPDEzZoafgDY3AjHVNsjdjJ4yL4N/cYQ5ArM2R3AiB9oSZaT+8ep7XiAQlTft0+mV5ecc2jMc2znIQXncx0/Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":107659},"type":"module","engines":{"node":">=18"},"gitHead":"1180f2c491dee00d7aa44445b22d060e4c8a391f","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.3.0_1785437734028_0.7956448278728319","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@abiezon/qagent","version":"0.4.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.4.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"3c62bf4bf2298db12c6d92441c9f386e6cb5bc7a","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.4.0.tgz","fileCount":33,"integrity":"sha512-/+Fn5W8Fny40Ya1UK//dhENNDTKMXGLJwdpFMliKQunIFIsXj2DUbcKvAWj66TDwb1szeAkzA0JiqzcJDQQtOg==","signatures":[{"sig":"MEUCIQD4ZyqqkzqTasO60MSgeWFHeaogMCSDzWutaQqwMHbpAQIgV/EeAGKEeBr2aXepbSdkj+uC37CwJzyPjgwHMe8xkR4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":125247},"type":"module","engines":{"node":">=18"},"gitHead":"cf39b201b4abf70699cec7e581097d09b7e51f92","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.4.0_1785439803334_0.4557918643103829","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@abiezon/qagent","version":"0.5.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.5.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"66e4b8112984a6e965f505261dd5749f26b6eede","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.5.0.tgz","fileCount":40,"integrity":"sha512-79rVxtPhG2bIIxEhzkamBfg6n+U28ByabQC5W4NGgj8vEjANS0OiNyOJ0LPIRST55oaMkdcjSCghzVXO9K5ogw==","signatures":[{"sig":"MEUCIBRleS0Xrxrg82GsmaB9qgsorfFsbyrvM5Lhe049Mx1iAiEA+ZXM1R5gUNk1eIN3x6sgritsfVp8LHwPQXuoXwfXuzo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":218514},"type":"module","engines":{"node":">=18"},"gitHead":"b077872a5127427a4eee50fc82fe0865ea8d4092","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.5.0_1785501404763_0.587568136944318","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@abiezon/qagent","version":"0.6.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.6.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"39e3a2fd105df4d85eb85d05d53b83984f9159be","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.6.0.tgz","fileCount":40,"integrity":"sha512-1zZMcJxXFJUN0l11bmfKBE5jRI4zczzPP9ggd2RZsxhaQAKIif3G1yflT6iZsQE36he0wZd2TLa8nk4sMUesLA==","signatures":[{"sig":"MEUCIQDyRVZwdxCaVZiMKXT1xWIMRQcQX0d9dnuO+JEX20WgsAIgZ4dajR/aBTppGRa8a+logyEuQLPPZ/C58t0tYxpIACc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":237827},"type":"module","engines":{"node":">=18"},"gitHead":"68b775388d3f2462f4487bcefb0d33eb4b8588d9","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.6.0_1785514061814_0.5658421233922515","host":"s3://npm-registry-packages-npm-production"}},"0.6.1":{"name":"@abiezon/qagent","version":"0.6.1","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.6.1","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"662f1e2d3c6ea19ce25a878e340ec6e37f0ab68e","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.6.1.tgz","fileCount":40,"integrity":"sha512-95N+mUeLLsemElNJWVATHTNf1HixGvQwG0FkPrp8pTu6rnWc9aAIcUgiux2yepkrGIAx4v5oTeymPoqtndmHHQ==","signatures":[{"sig":"MEYCIQCBX5wA8jkgaVW/G5YNj6s3ej7Dt29D5psvdrJNMLGySgIhAJEG6xjXpZKtOKc4UAxoGZb3MaSEtttWn8NCoXb//H6a","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":241256},"type":"module","engines":{"node":">=18"},"gitHead":"53416845cdb6bc6e355fa24678794b6980b35f9f","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.6.1_1785515053576_0.2781662848290476","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@abiezon/qagent","version":"0.7.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.7.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"e6a506d8bce5c4f88f90faea2f4e6309b032b1cc","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.7.0.tgz","fileCount":40,"integrity":"sha512-ojVPZv6O+D+2UJnIr+1ZawN0/obLztbcaQ718zszIKZviq2EoZHdFJfMZjZcdy6HuppIovV19TfLe9z+p6MaRg==","signatures":[{"sig":"MEQCIAzky+BwXcJE3FhaiCod2wdvC2xcCr3bnVkgEqbBVqeiAiApfn1tpDXVTf42Qb0lQbcg0GLMcSunDHZPKPNleScuRQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":263381},"type":"module","engines":{"node":">=18"},"gitHead":"a5f2ab553e6a1e5a04b401fb992e1f35ce254888","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.7.0_1785522185759_0.6891444207267947","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"@abiezon/qagent","version":"0.8.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.8.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"84a30f5eb59591aa6bf0446c66c205efd0b41d8d","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.8.0.tgz","fileCount":40,"integrity":"sha512-0/Owgs7voJ5tGQwaVhUS3KQK6U9Sk8NH8Vx/Pi0KPScFmuSjFHdNBIXDRo9eF8zAoXCbpqb7jPwdHWBXQBVnAA==","signatures":[{"sig":"MEUCIQDhJh+ApTIdZC05kiWLZ51Cbkxi70qXjh5jdxd+uzZPZgIgIFn9muuCaYUHZ1z5e92fOh2IWRvPoT3g9tTD4V0MExY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":266196},"type":"module","engines":{"node":">=18"},"gitHead":"e05d17a53a97f0785b146d12c8d4bfae8591968e","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.8.0_1785526811602_0.6370199515032471","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"@abiezon/qagent","version":"0.9.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.9.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"6cbe451fa74e1158df7608afaf5dcee41823d162","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.9.0.tgz","fileCount":40,"integrity":"sha512-aPGqndlDYVZOyI9RZiOt2Ed0bX/omCbwd+iJbiXgNslVrL2oiHMYL3eZWEsuupp/sLQpXip/dNUX6BTRxCMfvw==","signatures":[{"sig":"MEQCIGUDjCyc05N3Wo9sW89iVwb8We8ZIz3/evrfJxHnN2y6AiBZizk08hZ7vnzvs0YqADHjsoHPBwZZQgT3X0QBMlRxyA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":271174},"type":"module","engines":{"node":">=18"},"gitHead":"bb6828ccf69d02af8ae12492bedca26eae8deacf","scripts":{"render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.9.0_1785527259197_0.6635138741637208","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"@abiezon/qagent","version":"0.10.0","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.10.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"1d4bac861d18e0146b9c7a9ff38cda730b152476","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.10.0.tgz","fileCount":57,"integrity":"sha512-RmGs4CAk9TWcgjgyopGEGGoVH210/v/5QqB9MVo3Jny+Allt+HMqf4zicTnIe6316fQw0iXBgATiBpRJXjatLQ==","signatures":[{"sig":"MEQCIFTeS7IFXE5IMoRPH+rH81CEJPqlO9EIzaSRoSFN0CHFAiAsd9tWHta8kE18S1BOpXV5a1lA73/RWlwyayi5X0znWQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":458514},"type":"module","engines":{"node":">=18"},"gitHead":"a623a12ec34ef6fb3f0e8791331029613a8d5f54","scripts":{"test":"node --test test/","render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.10.0_1785857597850_0.47490205085988246","host":"s3://npm-registry-packages-npm-production"}},"0.10.1":{"name":"@abiezon/qagent","version":"0.10.1","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.10.1","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"6f7ba327048383795f0f65ebcc7a7bb9a8e30537","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.10.1.tgz","fileCount":63,"integrity":"sha512-W2BgiDLOW4bVxyzlV/WwVpvKMaXBLvXqZrGpXFeDNAv9JCDWTidA5p0ovNXJQtnYY8a8w2eNndBQpZp3thV/Vg==","signatures":[{"sig":"MEUCIF2VHYVB4ueEbAR0iVVm6fSqIBM7k7OjY0B0A22SjHANAiEAruGHlqhsrnZv6fR8rl2U8B2DbCeh/aIbZSd88RxKWuw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":467871},"type":"module","engines":{"node":">=18"},"gitHead":"4ceac6ee27ccacfbf2382651919b8d697a184cad","scripts":{"test":"node --test test/","render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.10.1_1785858729199_0.9385342462197757","host":"s3://npm-registry-packages-npm-production"}},"0.10.2":{"name":"@abiezon/qagent","version":"0.10.2","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.10.2","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"40bfb0a059dec6e2a49a9e0bd7ccb3118281e397","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.10.2.tgz","fileCount":63,"integrity":"sha512-fyAcWZ1siwMhAWT/noINRISjTykqOFwp393m7slZ048MEOZdqZejMzD+y9EpvF9SPMyPBCl83VZ1t7bffEEteg==","signatures":[{"sig":"MEQCIANaiSooBmsFz2PbUPtg/QL7+pevaRkri9mL1Ruu8HhCAiAg0RvrtZQ+57djEDLih/BODwt7LXBIMBKgfrmOiHSMsg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":467865},"type":"module","engines":{"node":">=18"},"gitHead":"c03b843178f091acb2e687e3dc6bfdc7892c2a54","scripts":{"test":"node --test","render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.10.2_1785870394280_0.6765278867814222","host":"s3://npm-registry-packages-npm-production"}},"0.10.3":{"name":"@abiezon/qagent","version":"0.10.3","keywords":["qa","testing","test-plan","coverage","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.10.3","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"a9f5d4f51b909cabc70dbf3c0a83c8c64a7434d0","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.10.3.tgz","fileCount":69,"integrity":"sha512-qHiKSmz3/idwkcCD3WsIseO2FHsgifTDKTKXyUcTTt8aEIqXw8VO4KXxL1QCOVtsetYe9DsUZ0nVrcRtcph70A==","signatures":[{"sig":"MEQCIHidcsrmYU0upDGWnbNaHwDD9y5b7W+vucP/Z+aaFYO7AiBltv/61BDAInaLzuq9m9e8PNNHlZMTJAF2G44NxSYyOQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":477567},"type":"module","engines":{"node":">=18"},"gitHead":"db8d61a675fc4054a0c1c6dbb5d6d6810f188921","scripts":{"test":"node --test","render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.10.3_1785933971370_0.5234754629468199","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"name":"@abiezon/qagent","version":"0.11.0","keywords":["qa","testing","test-plan","coverage","antigravity","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.11.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"721b0f94c44cf752c219a8ae54f3b71b908e2116","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.11.0.tgz","fileCount":79,"integrity":"sha512-8BSycvqPhfVi+c4hZ/6hagZ33YaSBw/kC42HlBTFkC4LYfpthYa1VvuQumaO3zREXQ8E2DKTB1EsaGuhrQFzjg==","signatures":[{"sig":"MEUCIEUoXV+C63pJc6vmdlIR7sS/tP/b3sc7aYUjvcjRrmQmAiEA0BqxE/iPIsJVk/XIA8VKVw8kMZNWHk6uNZupJy9Xnbs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":498392},"type":"module","engines":{"node":">=18"},"gitHead":"e974150a2424f46d45c57759087eb1ceb98398a2","scripts":{"test":"node --test","render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.1","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.11.0_1785943839879_0.6721188651433445","host":"s3://npm-registry-packages-npm-production"}},"0.12.0":{"name":"@abiezon/qagent","version":"0.12.0","keywords":["qa","testing","test-plan","coverage","antigravity","agentic","ai-agents","spec-driven-development"],"license":"MIT","_id":"@abiezon/qagent@0.12.0","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"homepage":"https://github.com/abiezon/qagent#readme","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"bin":{"qagent":"bin/qagent.mjs"},"dist":{"shasum":"355733d0585869de21bbd3a189bc79bc2957c3d7","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.12.0.tgz","fileCount":79,"integrity":"sha512-YZYwcvJAFMDwqaSdtRdWg2cdhRdHjmOx2CkA4PvfI5G5SH9Dkm0XjTBF6bfXpJjAkWeNToYSzHqOzBQbDYCorw==","signatures":[{"sig":"MEQCIBCF2ZxINa/tn4Z8dbeWW/f3IGqrxWJE8jUzCARYZIe6AiBOF+OUAY3uavtVwZ2Z3I9N/dpjje0NfzFbZg+1gU6CUA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":510093},"type":"module","engines":{"node":">=18"},"gitHead":"3d2b95c9f8ba58cc7c209a6a56789c9235f04488","scripts":{"test":"node --test","render":"node scripts/render.mjs","version":"npm run render && git add -A","render:check":"node scripts/render.mjs --check"},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"repository":{"url":"git+https://github.com/abiezon/qagent.git","type":"git"},"_npmVersion":"10.9.8","description":"Agentic QA hub — spec-tool agnostic","directories":{},"_nodeVersion":"22.23.2","dependencies":{"js-yaml":"^4.1.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/qagent_0.12.0_1786459484395_0.9151532594398573","host":"s3://npm-registry-packages-npm-production"}},"0.12.1":{"name":"@abiezon/qagent","version":"0.12.1","type":"module","description":"Agentic QA hub — spec-tool agnostic","keywords":["qa","testing","test-plan","coverage","antigravity","agentic","ai-agents","spec-driven-development"],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/abiezon/qagent.git"},"bin":{"qagent":"bin/qagent.mjs"},"engines":{"node":">=18"},"scripts":{"test":"node --test","render":"node scripts/render.mjs","render:check":"node scripts/render.mjs --check","version":"npm run render && git add -A"},"dependencies":{"js-yaml":"^4.1.0"},"_id":"@abiezon/qagent@0.12.1","gitHead":"3577692622a192cf29b3ceab5fc419c4a860f21a","bugs":{"url":"https://github.com/abiezon/qagent/issues"},"homepage":"https://github.com/abiezon/qagent#readme","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-Yi0TpHWRmgkKRCdhdVhwCOI2zQEMT8o4HSNGh7nSYJB2mK9Ukt5xVeeEgaP9nmLDt2zNJYq9BOm+TNB8CqkB+Q==","shasum":"28a7fd1fe974fadbcc62c53193a741da24a32ca0","tarball":"https://registry.npmjs.org/@abiezon/qagent/-/qagent-0.12.1.tgz","fileCount":79,"unpackedSize":513978,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDHJoWGWP/y6rLmTSr14MW7llx8tZv6TPmaco1pQo646AIhAKzcMFrytPkNr+Z68pgC6eNEJDoffOZFjwHn+BzJWjli"}]},"_npmUser":{"name":"abiezon","email":"abiezon@gmail.com"},"directories":{},"maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/qagent_0.12.1_1786488759027_0.9149345150935411"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-30T14:30:34.350Z","modified":"2026-08-11T22:52:39.438Z","0.1.1":"2026-07-30T14:30:34.742Z","0.1.2":"2026-07-30T14:56:39.625Z","0.2.0":"2026-07-30T16:28:55.009Z","0.3.0":"2026-07-30T18:55:34.170Z","0.4.0":"2026-07-30T19:30:03.475Z","0.5.0":"2026-07-31T12:36:44.914Z","0.6.0":"2026-07-31T16:07:41.961Z","0.6.1":"2026-07-31T16:24:13.747Z","0.7.0":"2026-07-31T18:23:05.917Z","0.8.0":"2026-07-31T19:40:11.747Z","0.9.0":"2026-07-31T19:47:39.368Z","0.10.0":"2026-08-04T15:33:18.030Z","0.10.1":"2026-08-04T15:52:09.366Z","0.10.2":"2026-08-04T19:06:34.482Z","0.10.3":"2026-08-05T12:46:11.532Z","0.11.0":"2026-08-05T15:30:40.097Z","0.12.0":"2026-08-11T14:44:44.535Z","0.12.1":"2026-08-11T22:52:39.267Z"},"bugs":{"url":"https://github.com/abiezon/qagent/issues"},"license":"MIT","homepage":"https://github.com/abiezon/qagent#readme","keywords":["qa","testing","test-plan","coverage","antigravity","agentic","ai-agents","spec-driven-development"],"repository":{"type":"git","url":"git+https://github.com/abiezon/qagent.git"},"description":"Agentic QA hub — spec-tool agnostic","maintainers":[{"name":"abiezon","email":"abiezon@gmail.com"}],"readme":"# qagent\n\nAgentic QA hub — agnostic to the spec tool. Personal project, not tied to any\nteam.\n\nIt runs with [`spechelix`](playbooks/source-resolution.md) or the `ia-cgr` that\npreceded it, with [OpenSpec](playbooks/source-resolution.md), with a convention\nof the target repo's own, or on its own — with none of the above. The hub never\nassumes specs exist, nor that they follow a single format: every playbook\nstarts by resolving **where the acceptance criterion is** before doing any QA\nwork.\n\n> Instructions in this hub are written in English so the guidance stays\n> consistent across models and tools. **You can talk to the agent in any\n> language** — it replies in the one you use. See the language rule in\n> [`guardrails/qa-quality.md`](guardrails/qa-quality.md).\n\n## Source modes\n\n<!-- qagent:gen sources-table -->\n| Mode | How it is detected | What it reads | Default `QA_DIR` |\n|---|---|---|---|\n| `spechelix` | Target repo has `.ai/features/` (declared) | `HU-XXX`/`FEAT-XXX`/`FIX-XXX`/`QA-HU-XXX`, via `INDEX.md` | `.ai/qa` |\n| `ia-cgr` | Target repo has `.ai/features/` (declared) | `FEAT-XXX.md`/`FIX-XXX.md` | `.ai/qa` |\n| `OpenSpec` | Target repo has `openspec/` | `proposal.md`, `specs/`, `tasks.md` | `.qa` |\n| `custom` | Target repo declares its own convention (in `AGENTS.md`/README) | Whatever the convention points to | `.qa` |\n| `standalone` | None of the above | Description + acceptance criterion straight from the chat | `.qa` |\n<!-- /qagent:gen -->\n\nFull detail in\n[`playbooks/source-resolution.md`](playbooks/source-resolution.md). The table\nabove, the aliases the CLI accepts, and the interactive menu all come from\n[`sources.yaml`](sources.yaml) — see [Generation](#generation).\n\n## Quick start\n\nRequires **Node.js ≥ 18**. Without installing anything:\n\n```bash\nnpx @abiezon/qagent install --mode spechelix\n```\n\nOr installed, for recurring use:\n\n```bash\nnpm i -D @abiezon/qagent\n```\n\n`qagent install` is the recommended entry point: it inspects the topology\nbefore writing anything, because the two common arrangements need different\ntreatment.\n\n**Standalone repository** — the path is itself a git repo. It instruments that:\n\n```\n$ npx qagent install --mode spechelix\n🧭 qagent — standalone repository: /path/my-app\n   declaring SOURCE_MODE=spechelix\n   📋 .qagent/config.yaml: SOURCE_MODE=spechelix\n   📁 .qagent/config.yaml: QA_DIR=.ai/qa (default for spechelix)\n   📂 .ai/qa/ created — test plans, coverage reports and run reports land here\n   ✅ AGENTS.md: pointer block updated (mode: spechelix)\n```\n\n**Workspace** — an aggregating root that *contains* repos without being one.\nThe root is **not** a target: writing config there would create a `.qagent/`\nno playbook reads, since they all resolve the source from the target repo.\n`install` lists what it found, then asks which repo to instrument — or all of\nthem — and walks through [the menu](#the-menu) for the answer:\n\n```\n$ npx qagent install my-workspace\n🧭 qagent — workspace: /path/my-workspace\n   the root is not a target; 2 product repo(s) detected inside it:\n     · my-app\n     · my-api\n   (skipped as tooling, not targets: spechelix —\n    point at the path explicitly if you want to instrument one of them anyway)\n\n  > Which repo should be instrumented?\n      1) my-app\n      2) my-api\n      a) all 2 of them\n    > a\n```\n\nWith a single repo inside, there is nothing to choose and it goes straight to\nthe questions. In a pipe or a CI job nothing is asked: pass `--mode` (with\n`--all`, or the path of one repo) and the listing tells you the exact command.\n\nRepos that are **tooling, not targets** drop out of the listing by two\ncomplementary checks: the directory name (`qagent`, `spechelix`, `ia-cgr`,\n`openspec` — the `tool_repos` list in [`sources.yaml`](sources.yaml), compared\ncase-insensitively) and the agentic-hub shape (`playbooks/` + `guardrails/` at\nthe root), which catches a hub cloned under a different name. Neither is a\nguarantee, which is why they only filter the listing: pointing at the path\nexplicitly still instruments, for whoever wants QA on the hub's own code.\n\n`qagent init` still exists for explicit per-repo use, and refuses a workspace\nroot, pointing at `install`.\n\n### The menu\n\n`qagent init` with no `--mode`, and `qagent install` with none — on a standalone\nrepo **or on a workspace** — walk through the whole setup instead of asking one\nquestion and leaving the rest to flags nobody finds in `--help`. On a workspace\nit first asks which repo to instrument, or all of them, which is what `--all`\nand naming a path would otherwise require rerunning the command to say:\n\n```\n$ npx qagent init\n  > Which acceptance-criterion source does this repo use?\n      1) OpenSpec   — openspec/ exists, or will exist\n      2) spechelix  — Spechelix SDD hub, .ai/features/ exists or will exist\n      3) ia-cgr     — SDD hub that preceded Spechelix, same .ai/features/ layout\n      4) manual/AI  — no spec tool; qagent alone\n    > 2\n\n  > Where should QA artifacts be written (test plans, reports)?\n      enter to accept, or a path relative to the repo root\n    [.ai/qa] >\n\n  > Learning loop: each run reads what earlier ones recorded about\n    this project, and writes back what it learned.\n    enable it? [y/N] y\n\n  > Test credentials directory: a git-ignored place for the logins a\n    QA run needs. Test/dev environments only — never production.\n    create it? [y/N] y\n```\n\nEvery question offers what the repo already has, or the default — including the\n**mode**, so a repo instrumented by an earlier version keeps it by pressing\nenter. That makes the menu the natural way to adopt what a new release added:\nrun it, hold enter, and the repo gains the directories the version created\nwithout changing a single answer it already had. Re-running never resets\nanything, and when several repos are instrumented at once, an accepted default\nleaves each one's own `QA_DIR` alone instead of forcing one path onto all. In a pipe or a CI job\nthere is nothing to ask, so the menu never opens: pass `--mode` (and the flags\nbelow), or `status` reports and exits.\n\nDeclaring the mode explicitly avoids a new repo (one that will gain\n`.ai/features/` or `openspec/` later) being treated as `standalone` just\nbecause those folders do not exist yet.\n\n```\n$ npx qagent init --mode spechelix\n🧭 qagent — declaring SOURCE_MODE=spechelix\n   📋 .qagent/config.yaml: SOURCE_MODE=spechelix\n   📁 .qagent/config.yaml: QA_DIR=.ai/qa (default for spechelix)\n   📂 .ai/qa/ created — test plans, coverage reports and run reports land here\n   ✅ AGENTS.md: pointer block updated (mode: spechelix)\n   ℹ️  .ai/features/ does not exist yet — normal if you are setting spechelix up later\n```\n\nThat writes in the target repo (here, `my-app/`):\n\n**`.qagent/config.yaml`**\n```yaml\nSOURCE_MODE: spechelix\nQA_DIR: .ai/qa\n```\n\n**`<QA_DIR>/README.md`** — a seed explaining what lands in the directory, so\nwhoever finds it in a diff months from now knows what it is. Written only if\nabsent; your edits are never overwritten. It also makes the directory\ncommittable, since git tracks files and not folders.\n\n**`AGENTS.md`** — a managed block, inserted right after the title; if the file\nalready has human content, the rest is preserved:\n```markdown\n# my-app\n\n<!-- qagent:pointer -->\n> QA hub: [qagent](../qagent) · source mode: `spechelix` — see `../qagent/playbooks/source-resolution.md`\n<!-- /qagent:pointer -->\n```\n\n`status` confirms without redoing the work, and reports which hub version is\nanswering:\n\n```\n$ npx qagent status\n🧭 @abiezon/qagent 0.7.0 (package)\n📦 my-app: SOURCE_MODE=spechelix\n   📁 QA_DIR=.ai/qa\n   🧠 KNOWLEDGE=true (.ai/qa/knowledge/, 4 file(s))\n   🔐 CREDENTIALS=true (.qagent/credentials/)\n   🎯 dimensions always in scope: Functional, Regression, Security\n      evidence found: Compatibility (package.json#browserslist), API (openapi.yaml)\n      no marker in this repo: Performance\n   ℹ️  .ai/features/ does not exist yet — normal if you are setting spechelix up later\n```\n\n`qagent version` (also `--version`, `-v`) reports the hub on its own — useful\nwhen a workspace and a clone disagree about which one is answering:\n\n```\n$ npx qagent version\n@abiezon/qagent 0.7.0\n   installed package: /path/node_modules/@abiezon/qagent\n   node: v20.20.2\n   modes: openspec, spechelix, ia-cgr, manual, custom\n```\n\nIt distinguishes `installed package` from `clone` because the two fail\ndifferently: a clone can be behind `main`, and a package cannot regenerate\nartifacts.\n\nOther modes: `--mode openspec`, `--mode ia-cgr` (the SDD hub that preceded\nSpechelix, same `.ai/features/` layout), `--mode manual` (no spec tool), or run\n`init` with no `--mode` for the interactive menu. Full detail in\n`qagent --help`.\n\n### Where the artifacts land\n\n`QA_DIR` is not something to remember to pass. Instrumenting a repo declares it\nand creates the directory, because a test plan the team cannot open and a run\nreport that lives in somebody's chat scrollback are artifacts that may as well\nnot have been produced.\n\nThe default comes from the mode — see the [table above](#source-modes):\n`.ai/qa` for `spechelix`/`ia-cgr`, whose repos already keep this kind of file\nunder `.ai/`, and `.qa` for the rest. `openspec/` deliberately does not get\none: that directory belongs to OpenSpec's change flow, and qagent stays out of\ndirectories another tool manages.\n\n```\n$ npx qagent init --mode manual\n🧭 qagent — declaring SOURCE_MODE=standalone\n   📋 .qagent/config.yaml: SOURCE_MODE=standalone\n   📁 .qagent/config.yaml: QA_DIR=.qa (default for standalone)\n   📂 .qa/ created — test plans, coverage reports and run reports land here\n```\n\n```yaml\nSOURCE_MODE: standalone\nQA_DIR: .qa\n```\n\nTwo flags adjust it, and neither is needed for the normal case:\n\n- `--qa-dir <path>` — a different directory. A reinstall never relocates an\n  existing one: what the repo already declared wins over the default.\n- `--no-qa-dir` — opt out entirely. Nothing is written to the repo and every\n  artifact comes back in the chat, as it did before this was the default. It\n  cannot be combined with `--knowledge`, which needs somewhere to live.\n\nBoth — and `--knowledge` and `--credentials` — **require `--mode`**. Without it\nthe command opens [the menu](#the-menu), which asks for each of those settings,\nso a flag passed alongside would be answered over. It is refused rather than\nignored: a setting you believe landed and did not is worse than an error.\n\nWhat lands there:\n\n<!-- qagent:gen artifacts-table -->\n| Artifact | What it holds | On a rerun |\n|---|---|---|\n| `<QA_DIR>/test-plan-<slug>.md` | Test cases per acceptance criterion, across the seven test dimensions. | Asks first — reused and extended by a later run, never regenerated over |\n| `<QA_DIR>/coverage-audit-<slug>.md` | What the automated suite does and does not cover, per criterion. | Overwritten — it describes the suite at a moment, and the previous moment is not an artifact |\n| `<QA_DIR>/qa-run-<slug>.md` | The consolidated report of a full QA run, ending in a verdict. | Overwritten — it is a snapshot of one cycle, and the history lives in the knowledge ledgers |\n<!-- /qagent:gen -->\n\n`bug-triage` and `e2e-execute` write none of them — the first produces a work\nitem, which belongs to the spec tool's format; the second produces an execution\nresult, not a design artifact.\n\n### The readable copy, and not drowning in artifacts\n\nThree artifacts per run, flat in one directory, forever. A year in, nobody can\ntell a finished item from a live one — and nobody outside the team was ever\ngoing to read a Markdown file in a diff viewer anyway. Two commands, both\nworking **only inside `QA_DIR`**:\n\n```bash\nnpx qagent report --item HU-002     # -> <QA_DIR>/reports/HU-002.html\nnpx qagent archive --item HU-002    # -> <QA_DIR>/_archive/<year>/HU-002/\n```\n\n`report` assembles that item's test plan, coverage audit and run report into one\nself-contained page — no stylesheet, font or script from anywhere, because it\nlands in your repo and may be opened from a `file://` URL or committed. It\nrenders what the artifacts say and **adds no verdict of its own**; the Markdown\nstays the source of truth. With no `--item`, it renders every item.\n\n**The page speaks your language.** It is the one artifact whose wording qagent\nemits rather than the model, so it follows the conversation — and if you ask for\na specific language, that wins over everything:\n\n```bash\nnpx qagent report --item HU-002 --lang pt\n```\n\n`pt-BR` resolves to `pt`; `en`, `pt` and `es` ship with label sets. Pin it per\nrepo with `REPORT_LANG: pt` in `.qagent/config.yaml` (a re-run of `init` keeps\nit) and `--lang` still overrides. A language with no label set falls back to\nEnglish **and says so** — the artifacts it renders are untouched either way,\nsince the run wrote those in the right language to begin with.\n\nAdding a language is a [`labels.yaml`](labels.yaml) edit, not a code change, and\nthe build refuses a half-done one: a missing key, a dropped `{when}`, or markup\nin a label that gets escaped all fail `npm run render:check` rather than\nrendering `undefined` in somebody's report.\n\n`archive` files a **concluded** item's artifacts away and refreshes the index.\nThe HTML report deliberately stays in `reports/` — a link somebody was handed\nmust not break the day the item is archived. It refuses to overwrite an existing\narchived artifact rather than silently replacing the record.\n\nBoth rewrite `<QA_DIR>/INDEX.md`, one row per item: state, artifacts, report\nlink, last update — in the same language as the report beside it. It does\n**not** carry each run's verdict: that lives in the report, written in whatever\nlanguage the operator uses, and an index that pattern-matched it would be right\nin English and confidently wrong in Portuguese.\n\n[`post-verdict`](playbooks/post-verdict.md) runs both for you, on different\nconditions:\n\n- **The report, on every verdict** — approved, reproved, blocked, or a mode with\n  no closing flow. Making it conditional on a closure would deliver the readable\n  version exactly where it is least needed: an approved run is the one nobody\n  has to read carefully, and **a reproved one is the one somebody sits down\n  with** — which case failed, on what evidence, which `FIX` it became.\n- **The archive, only on the closed track.** A reproved or held item stays\n  active; it is the working record of something still open. In\n  `custom`/`standalone` the archive is never automatic — nothing tells qagent the\n  item concluded there — so the run names the command instead.\n\nThe boundary is worth stating twice: this index and this archive are qagent's\nown, inside `QA_DIR`. Archiving **specs** — `.ai/features/`, its `INDEX.md`,\nthe `_archive/<year>/` next to it — remains the spec tool's, untouched.\n\nThe table, the `writes` line of every command surface, and the README seeded\ninto the QA directory all come from the `artifacts:` registry in\n[`commands.yaml`](commands.yaml) — see [Generation](#generation).\n\nThe path is relative to the target repo root and validated: absolute, or\nescaping the repo with `../`, is refused — for the per-mode defaults too, which\nare checked when [`sources.yaml`](sources.yaml) is rendered rather than at\ninstall time. `QA_DIR` never changes where the acceptance criterion is *read*:\na `spechelix` repo still reads `.ai/features/` and now writes its QA artifacts\nnext door, in `.ai/qa/`.\n\n[`scripts/setup.sh`](scripts/setup.sh) still works as a shim —\n`bash ../qagent/scripts/setup.sh --mode spechelix` translates to `init --mode\nspechelix` and delegates. It exists so target repos and CI that already called\nthat path do not break; for new usage, prefer the CLI directly.\n\n## Checking the run against its own bar\n\n`qa-run` ends with a checklist — all seven dimensions present, a verdict at the\nend, the HTML rendered, the evidence where the closing flow looks. Until\nrecently exactly one of those was verified by anything other than the agent\nremembering, which is the failure this hub is built to catch in *other people's*\nwork.\n\n```bash\nnpx qagent check --item HU-002\n```\n\n```\n❌ HU-002 — 3 failed, 0 not verifiable\n   ✅ report: the run report exists.\n   ✅ dimensions: all seven dimensions appear in the report.\n   ✅ verdict: the report ends with a verdict (approved).\n   ❌ report-html: no HTML report — run 'qagent report --item <id> --lang <language>'.\n   ❌ indexed: the item is missing from INDEX.md — 'qagent report' rewrites it.\n   ❌ evidence: .ai/features/QA-HU-002-*.md is not on disk — the closing flow would run against nothing.\n```\n\nIt exits non-zero on a failure, so nothing downstream treats an incomplete cycle\nas finished. Two things it deliberately does **not** do:\n\n- **It never guesses.** The report is prose in the operator's language, so the\n  dimensions are matched against the names declared per language — and a report\n  in a language with no table comes back **not verifiable here**, not \"Security\n  is missing\". Same for files changed outside `QA_DIR`: qagent cannot tell a\n  change this run made from work already in progress, so it surfaces them and\n  calls them nothing.\n- **It checks presence, never judgment.** Whether a dimension was verified\n  honestly is not readable off a document, and the checklist items that say\n  \"did not observe\" stay the agent's to answer.\n\n## The machine interface\n\nqagent's primary consumer is an agent following a playbook, not a person reading\na terminal — so the commands an agent runs during a QA cycle answer `--json`:\n`status`, `handoff`, `report`, `archive`, `version`.\n\n```bash\nnpx qagent status . --json\nnpx qagent handoff --verdict passed --item HU-002 --json\n```\n\nOne JSON object on stdout and nothing else — human lines are suppressed rather\nthan interleaved, because a payload with prose above it is not parseable.\n**Failures are JSON too**, with a stable `error.code` (`no-qa-dir`,\n`no-artifacts`, `archive-clash`, …): getting structure on success and prose on\nfailure means parsing prose exactly when things went wrong.\n\n`schema` is versioned and the field names are a contract. A playbook that\nbranches on `plan.track` breaks *silently* if a field is renamed — the run keeps\nexiting 0 and simply stops closing items — so a rename bumps `schema` rather\nthan landing as a refactor.\n\nFlags accept both `--flag value` and `--flag=value`. `--json` on a command that\ndoes not speak it is an error, never a silent fallback to prose.\n\n## Running a playbook\n\nThe CLI only instruments the repo. **QA itself is run by an AI agent** reading\nthe playbooks — there is no `qagent test` that runs tests by itself.\n\n### By command, in the tool you already use\n\nWith the hub installed as a plugin (or cloned into the workspace), each\nplaybook is exposed as a named command, so you do not have to describe the task\nin prose every time:\n\n| Command | Tool surface |\n|---|---|\n| `qagent-run` | Claude Code skill, Codex skill, Antigravity skill, Copilot prompt, Cursor command |\n| `qagent-test-plan` | idem |\n| `qagent-coverage-audit` | idem |\n| `qagent-bug-triage` | idem |\n| `qagent-e2e-execute` | idem |\n| `qagent-post-verdict` | idem |\n\n```\n/qagent-coverage-audit\n```\n\n`qagent-run` is the one that chains the others — see\n[The full flow in one command](#the-full-flow-in-one-command).\n\nThe `qagent-` prefix is deliberate: it keeps these from colliding with the\nskills of another hub installed in the same workspace.\n\nEach command is a **thin pointer** at its playbook — it states what the\nplaybook does, when to use it, and what it outputs, then hands over. It never\nrestates the procedure, which is what would let six copies drift from the\nplaybook the first time it changes. All forty-two files are generated from\n[`commands.yaml`](commands.yaml).\n\nInstalling the npm package is enough for the **plugin-based** tools: the\ntarball carries `.claude-plugin/`, `.codex-plugin/` and `.antigravity-plugin/`\nwith the trees they name, so Claude Code, Codex and Antigravity can be pointed\nat `node_modules/@abiezon/qagent` and load the commands from there. Codex's\nmanifest points at a root `skills/` rather than at `.agents/skills/` — a\nplugin's skills live at `skills/`, and a manifest naming any other path is\nrejected at install time. `.agents/skills/` stays where it was, for Codex\nreading this as a repository.\n\nAntigravity's plugin is the whole `.antigravity-plugin/` directory — manifest,\nits own `skills/`, and the three read-only agents in its own `agents/` — and it\ninstalls into the operator's home rather than being pointed at:\n\n```bash\nqagent install --antigravity-plugin\n```\n\nThat copies the directory to `~/.gemini/config/plugins/qagent` and rewrites\nevery pointer to this hub's absolute path, since nothing under `~/.gemini` is\nrelative to a `playbooks/` any more. It is global: no `--mode`, no repo\ninstrumented. Rerun it after moving the hub; files you edited yourself are left\nalone.\n\nCopilot and Cursor discover their files by scanning the *project root*, and\nnothing scans inside `node_modules` — for those, the commands only apply in a\nclone of the hub, or copied into the project. The same is true of Antigravity's\ntwo repository surfaces (`.agents/skills/`, `.agent/skills/`), which is what\nthe plugin above exists to sidestep.\n\n### By prose, from anywhere\n\nNaming the playbook always works, whatever the surface:\n\n> Read `node_modules/@abiezon/qagent/AGENTS.md` and run the `coverage-audit`\n> playbook for HU-002.\n\nIn an already-instrumented repo, the `AGENTS.md` pointer block leads the agent\nto the hub, so naming the playbook is usually enough.\n\nWhat happens next, in order: `source-resolution` reads `.qagent/config.yaml` →\nresolves the mode → reads the acceptance criterion from where that mode says →\nruns the requested playbook → writes to `QA_DIR` if one is set, or returns in\nthe chat.\n\n| Ask for | Playbook | Output |\n|---|---|---|\n| The whole QA cycle, in one go | `qa-run` | Plan + coverage + execution + items, one report |\n| Test cases before implementing | `test-plan` | Cases per criterion |\n| Whether the suite covers a feature | `coverage-audit` | Gap report |\n| Structure a raw bug report | `bug-triage` | Work item in the repo's format |\n| Validate by running the app | `e2e-execute` | Verdict per case + evidence |\n\n### The full flow in one command\n\nAsking for one phase at a time is fine when you want exactly that phase. When\nwhat you want is *QA*, ask for the run:\n\n```\n/qagent-run HU-003\n```\n\n[`qa-run`](playbooks/qa-run.md) goes from the request to the verdict without\nhanding control back between phases:\n\n0. **Dimension scoping** — the seven dimensions\n   ([`test-dimensions.md`](guardrails/test-dimensions.md)) are scoped in or\n   ruled out from evidence, once, for the whole run.\n1. **Test plan** — reuses `<QA_DIR>/test-plan-<slug>.md` if it is already\n   there (a hand-revised plan is never regenerated over, only extended with\n   cases the criterion gained). Otherwise generates it from the source the\n   installed mode declares — `spechelix`, `ia-cgr`, `OpenSpec`, `custom` — and\n   saves it to `QA_DIR`. With neither plan nor readable criterion, it stops and\n   says exactly that: write the plan, save it in `QA_DIR`, run again.\n2. **Coverage audit** — plus the repo's own suite actually run (inside Docker\n   if the repo has one), because a case covered by a currently red test is not\n   covered.\n3. **E2E execution** — against the running application, skipping only what a\n   green automated test already covers, and saying which. It **diagnoses before\n   it blocks**: a preflight checks credential, login, target and data, and where\n   the plan named a record this environment does not have, the run finds one\n   that exists and says it substituted. Blocking is the last rung of a ladder\n   (a session the operator opened → Playwright MCP → Playwright CLI →\n   authenticated HTTP probe), never the first answer. It starts by asking whether a session already\n   exists, so an operator with an authenticated tab is never asked to log in\n   again, and it recognizes an identity provider (Keycloak and friends) from the\n   redirect — where two sessions expire independently and a token that dies\n   mid-run must not be reported as a product failure. When the run cannot log in\n   at all — the agent's policy forbids handling passwords, or there is a second\n   factor no software passes — that is a **handoff**, not a block: everything\n   not needing the session is verified first, and the operator spends one login\n   instead of an investigation.\n4. **Work items** — every `Failed` caused by real incorrect behavior, in the\n   format the repo's spec tool reads, deduplicated against what is already\n   open.\n5. **One consolidated report**, written to `<QA_DIR>/qa-run-<slug>.md`, with\n   the seven-row dimension matrix and ending in a verdict. A setup block, a real\n   failure and a case unblocked since the last round stay distinguishable at a\n   glance — the last one carries its earlier evidence marked `superseded`,\n   rather than quietly replacing it.\n6. **The handoff back to the spec tool** — the verdict leaves QA_DIR and reaches\n   whatever actually closes the item, plus the\n   [HTML report](#the-readable-copy-and-not-drowning-in-artifacts) for whoever\n   asked. See [after the verdict](#after-the-verdict) below.\n\nRemoving the stops between phases does not remove the judgment calls. The run\nstill asks — once, batched — when the source is ambiguous, when `QA_DIR` holds\nseveral candidate plans, when more than one compose file could be the test\nenvironment, and before bringing the application up or acting on an\nenvironment that is not disposable. A conflict between a test and the criterion\nnever stops the run and never opens an item on its own: it lands in the\nreport's *awaiting your decision* section with both pieces of evidence.\n\nA phase that fails does not abort the run — no suite, no reachable instance, a\ncase that cannot be executed: each degrades into a reported finding and the\nnext phase still runs. The only early exit is having no acceptance criterion at\nall.\n\nTwo things worth knowing before you ask:\n\n- **The audit playbooks are read-only.** They report gaps and write no tests,\n  even when the fix looks obvious. Writing the tests is implementation work.\n- **Only one kind of finding becomes a work item.** A coverage gap is a risk,\n  not a defect, and never opens a `FIX`. The exception is a test asserting the\n  *opposite* of the criterion — and even then the agent reports both pieces of\n  evidence and asks which side is authoritative.\n\n## After the verdict\n\nA verdict is not a closure. The run writes `qa-run-HU-002.md` into `QA_DIR`,\nconcludes the HU passed, and stops — while the spec tool is looking for *its\nown* evidence file, under its own name, in its own directory. So the QA report\nsits there, perfectly finished, next to an `HU-002` that is still\n`em-andamento`, and nobody notices because nothing failed.\n\n[`post-verdict.md`](playbooks/post-verdict.md) is the step that closes that\ngap. It runs after the report, per mode:\n\n<!-- qagent:gen closure-table -->\n| Mode | QA evidence it leaves | Approved verdict dispatches | Failed verdict dispatches |\n|---|---|---|---|\n| `spechelix` | `.ai/features/QA-<id>-<slug>.md` | `sdd-execute <id>` | `sdd-execute <fix>` |\n| `ia-cgr` | `.ai/features/QA-<id>-<slug>.md` | `sdd-execute <id>` | `sdd-execute <fix>` |\n| `OpenSpec` | — | `openspec archive <change>` | `openspec validate <change>` |\n| `custom` | — | not automatic — the repo's convention is its own, and qagent does not know which command closes an item here | — |\n| `standalone` | — | not automatic — there is no spec tool in this repo to close anything, so the verdict itself is the deliverable | — |\n<!-- /qagent:gen -->\n\nFive rules hold across every row:\n\n- **A dispatch is invoked, not printed.** In the three modes that have a flow —\n  `spechelix`, `ia-cgr`, `OpenSpec` — the agent running the cycle makes the\n  call itself, and that includes the reproved verdict: the `FIX` (or the change)\n  goes straight to `sdd-execute` / the repo's own OpenSpec flow, without coming\n  back to ask. A run that ends with a defect recorded and its fix flow never\n  invoked stopped one step short of its purpose. qagent itself spawns nothing —\n  it computes the filled command; the agent runs it. It falls back to handing\n  the command over only when the tool is not reachable, and asks only for a name\n  it must not invent.\n- **A declared mode is not proof the tool is installed.** `sdd-execute` ships\n  with spechelix/ia-cgr, not with the target repo — a repo carrying\n  `.ai/features/`, opened by someone who never installed the hub, has the source\n  and not the command. So the handoff looks for it (in the repo, and beside it\n  in a workspace) before claiming a dispatch. Not finding it means\n  **reports only**: the evidence and the `FIX` are still written, because those\n  are *files*; the dispatch is not, because it is a *command*. The reports go to\n  whoever develops the repo. It is never reported as \"this cannot be closed\" —\n  the check is local, so if you do have `sdd-execute`, the plan prints the\n  command filled in and ready. `OpenSpec` gets no such check: `openspec/` is the\n  mode's marker *and* the change flow's directory, so having it is the\n  configuration already saying this is the tool.\n\n- **qagent generates the evidence and dispatches the flow — it does not close\n  the item.** Setting an `HU` to `concluído`, updating `INDEX.md`, moving a spec\n  into `_archive/`: all of that belongs to `sdd-execute`/`spec-index`, and a QA\n  hub reaching into it is a QA hub that corrupts spec state on its first edge\n  case. The [full report](#where-the-artifacts-land) stays in `QA_DIR`; only the\n  evidence the closing flow detects is written where the spec tool reads.\n- **An unresolved name is asked, never invented.** Which HU a `FEAT-002` belongs\n  to is read from its `hu:` front-matter, not assumed from the matching number;\n  an OpenSpec change is named by the operator when more than one is active. The\n  command gets printed instead of dispatched.\n- **A mode with no closing flow says so, and the reports are the deliverable.**\n  Running manually, `custom` and `standalone` report the verdict, the artifact,\n  why nothing is automatic, and what to take to the developer — the one thing\n  that never happens is silence.\n\nA blocked verdict, a conflict between the suite and the criterion, or a repo\nwhose declared mode does not match what is on disk all stop at the same place:\nnothing is dispatched, and the operator gets the reason plus the next command.\n\nThen the step renders the operator's copy and, on the closed track, archives the\nrun's artifacts — see [the readable\ncopy](#the-readable-copy-and-not-drowning-in-artifacts).\n\nThe plan is deterministic, and you can ask for it without running QA at all —\nuseful for exactly the case above, a run that already passed and never closed\nanything:\n\n```bash\nnpx qagent handoff --verdict passed --item HU-002 --slug login\n```\n\nIt prints the plan and dispatches nothing: running `sdd-execute` is the agent's\nor the operator's, which is the same boundary that keeps qagent out of the spec\ntool's state. `qagent status` shows the same per-mode summary before any run\nproduces a verdict.\n\n## Updating the hub\n\nRun it where the `package.json` declaring qagent lives — the workspace root,\nnot inside each target repo (those only carry the config, not the dependency):\n\n```bash\nnpm update @abiezon/qagent\n```\n\nThe installed version stays recorded in the consumer's `package.json` and\nlocked by `package-lock.json`, which makes the environment reproducible. To go\nback, `npm i @abiezon/qagent@0.6.1`.\n\nIn a workspace with several target repos, installing at the root (`npm i -D\n@abiezon/qagent`) makes `npx qagent` available to all of them from a single\ndeclared version.\n\n### `npm update` stops working at a minor bump\n\nWhile the hub is on `0.x`, npm's `^` **pins the second number**: `^0.6.0`\nallows `>=0.6.0 <0.7.0`. That is deliberate — before `1.0.0`, npm treats\n`minor` as potentially breaking.\n\nIn practice: `npm update` brings `0.6.1`, `0.6.9`… and **stops silently** when\n`0.7.0` ships. No error, no warning — just a version that never arrives. To\ncross over, you have to be explicit:\n\n```bash\nnpm i -D @abiezon/qagent@latest\n```\n\nThat rewrites the declared range and `npm update` works within it again. To\nfind out whether you are in this situation:\n\n```bash\nnpm outdated @abiezon/qagent\n```\n\n`Wanted` is the most your range allows; `Latest` is what exists. When the two\ndiffer, `npm update` will not resolve it.\n\nUsing `npx` without installing, none of this applies — but use\n`npx @abiezon/qagent@latest`: without `@latest`, npx may serve a local cache\ninstead of resolving the newest version.\n\n## Configuration\n\nAll qagent configuration lives in **one file per target repo**,\n`<repo>/.qagent/config.yaml`. There is no global or per-user configuration —\nwhat applies to a repo is declared inside it.\n\n```yaml\nSOURCE_MODE: spechelix   # required — where the acceptance criterion lives\nQA_DIR: .ai/qa           # where QA artifacts are persisted — set for you, per mode\nKNOWLEDGE: true          # optional — learn about the project across runs\n```\n\n| Key | Values | Effect |\n|---|---|---|\n| `SOURCE_MODE` | `spechelix`, `ia-cgr`, `OpenSpec`, `custom`, `standalone` | Decides what step 0 reads. Without it, [`source-resolution`](playbooks/source-resolution.md) runs automatic detection |\n| `QA_DIR` | path relative to the repo root | `test-plan`, `coverage-audit` and `qa-run` write there. Declared and created at install time from the mode's default; `--qa-dir` overrides it, `--no-qa-dir` opts out |\n| `KNOWLEDGE` | `true` (or absent) | Turns on the [learning loop](#knowledge-the-run-that-learns) in `<QA_DIR>/knowledge/`. Needs `QA_DIR`. Off by default |\n| `CREDENTIALS` | `true` (or absent) | Creates [`.qagent/credentials/`](#test-credentials), git-ignored, for the test logins a run needs. Off by default |\n\nAll three are written by the CLI, not by hand — the first two on any install:\n\n```bash\nnpx qagent install --mode spechelix --knowledge\n```\n\nAnd checked with `npx qagent status`, which also flags inconsistencies — a\ndeclared mode whose marker does not exist, or another mode's marker present in\nthe repo.\n\nEditing the YAML by hand works (it is read at runtime), but the CLI validates\nwhat it writes: it refuses an unknown mode, and refuses a `QA_DIR` that is\nabsolute or escapes the repo with `../`.\n\n### What is **not** configurable\n\nBy decision, not by limitation:\n\n- **Where playbooks look for the test suite** — `coverage-audit` discovers it\n  by convention and asks when ambiguous. An override would become\n  configuration that goes stale without anyone noticing.\n- **Severity, minimum coverage, what counts as testable** — they live in\n  [`guardrails/qa-quality.md`](guardrails/qa-quality.md) and apply equally to\n  every repo. They are a yardstick, not a preference.\n- **Running through Docker** — if the repo has a container, that is where it\n  runs. The run checks for it before its first command (`qagent status` prints\n  the `🐳` line) and installs nothing on the host to get around it. See the\n  guardrail.\n- **The language of the instructions** — they are English on purpose. What is\n  adjustable is the conversation, and that follows the operator without any\n  configuration.\n\n### Migrating from the old format\n\nA repo configured by an older version has `.qagent/config` in `KEY=VALUE`\nformat. It is still read normally — `status` warns about the pending\nmigration and the next `init` converts it to `.qagent/config.yaml`, carrying\nover any other key it held, and removes the old file. Comments from the old\nformat do not survive: YAML carries values only.\n\n## Playbooks\n\n| Playbook | What it does |\n|---|---|\n| [`source-resolution.md`](playbooks/source-resolution.md) | Common step 0 — resolves the acceptance-criterion source |\n| [`qa-run.md`](playbooks/qa-run.md) | The full flow end to end — orchestrates the five below and delivers one report with a verdict |\n| [`bug-triage.md`](playbooks/bug-triage.md) | Turns a raw bug report into a work item |\n| [`test-plan.md`](playbooks/test-plan.md) | Generates test cases (positive/negative/edge case) from the acceptance criterion |\n| [`coverage-audit.md`](playbooks/coverage-audit.md) | Audits whether the automated suite covers the acceptance criterion |\n| [`e2e-execute.md`](playbooks/e2e-execute.md) | Validates the acceptance criterion by running the real application |\n| [`post-verdict.md`](playbooks/post-verdict.md) | Hands the verdict back to the spec tool — QA evidence where its closing flow looks, and the dispatch that closes the item |\n\nQuality guardrails (severity, what counts as \"testable\", minimum coverage,\n**running through Docker whenever the target repo has it**, and the language\nrule) in [`guardrails/qa-quality.md`](guardrails/qa-quality.md).\n\n## Knowledge: the run that learns\n\nOff by default. Turned on per repo, and it lives in the `QA_DIR` the install\nalready created:\n\n```bash\nnpx qagent init --mode spechelix --knowledge\n```\n\nWithout it, run twenty costs what run one cost: rediscovering which compose\nservice holds the app, which user can log in, where the listing endpoint is,\nand which three tests were already red before anybody touched anything. With\nit, each pass through the QA cycle is one turn of a loop —\n[`playbooks/knowledge.md`](playbooks/knowledge.md):\n\n1. **Read** `<QA_DIR>/knowledge/` before scoping anything.\n2. **Use** it — skip the rediscovery, compare against recorded baselines,\n   weight the dimension scoping by recorded risk.\n3. **Verify** — an entry that held is confirmed by that use; one that failed is\n   corrected or deleted **in the same run**.\n4. **Write back** what a future run would otherwise pay to learn again.\n\nA fixed set of files, so no run invents its own taxonomy — and **two shapes**,\nbecause knowledge has two and one storage does not fit both:\n\n<!-- qagent:gen knowledge-shapes -->\n| Shape | Files | Rule |\n|---|---|---|\n| Prose, read whole | `environment.md` (how the app comes up, the suite command that worked, the suite's standing state), `access.md` (fixture users — where credentials come from, never their values), `surface.md` (routes, selectors, which endpoints are AJAX), `risk.md` (fragile modules), `fixtures.md` (records this environment has — **and the ones known to be empty**), `decisions.md` (what the operator already settled) | Current state — rewritten in place |\n| Ledger, one line per observation | `measurements.ndjson` (the series a later run compares its numbers against), `suite-state.ndjson` (tests red independently of any change), `findings.ndjson` (findings per module and dimension) | Append-only — a wrong line is superseded, never edited |\n<!-- /qagent:gen -->\n\nThe split exists because *\"rewrite in place\"* is right for prose and wrong for\nmeasurements: overwriting 1.8s with 4.2s destroys the very evidence that makes\nit a finding. The ledgers are [NDJSON](https://ndjson.org/) — git diffs and\nmerges them line by line, reading one costs no dependency, and a new field never\ninvalidates an old line. If a history ever outgrows plain reading, an `index.db`\nbuilt *from* the ledgers is derived and gitignored; the ledgers stay the truth.\n\nWhat it changes, concretely: performance stops being a lonely number — a\nbaseline of 1.8s makes 4.2s next month a finding even where no SLA exists;\nscoping gains evidence, so a module with two past authorization findings pulls\nsecurity into scope on record; and the run spends its one interruption on\nsomething new instead of re-asking which compose file is the test one.\n\nThree constraints keep it from becoming a liability:\n\n- **It is a cache, never an authority.** Knowledge says how to test this repo,\n  not how the repo should behave. Disagreement with the acceptance criterion is\n  resolved for the source, every time, and the stale entry is fixed on the spot.\n- **No secrets, ever** — no token, password or personal datum, not even as\n  evidence. Where a credential comes from, never what it is.\n- **No standing authorizations.** \"Yes, run the security pass against staging\"\n  authorized *that* run. The gates are asked again on the next one.\n\nEvery entry carries `observed` (date + run), `evidence`, and `invalidated-by` —\nwhat would make it false — so the next run can re-check cheaply instead of\ntrusting blindly. `npx qagent status` shows whether the loop is on and how many\nfiles it has.\n\n## Test credentials\n\nOff by default. Answered in the menu, or `--credentials`:\n\n```bash\nnpx qagent install --mode spechelix --credentials\n```\n\nIt creates `.qagent/credentials/` with a README, an example file, and a\n`.gitignore` that ignores **everything else in the directory**. Copy\n`credentials.example.yaml` to `credentials.yaml`, fill it in, and the values are\ninvisible to git — a run reads them from there instead of asking you for a\npassword in the chat every time.\n\nIt sits under `.qagent/` and not under `QA_DIR` deliberately: `QA_DIR` holds\nteam documents meant to be committed, and mixing \"commit this\" with \"never\ncommit this\" in one tree is how a secret reaches the history. `--no-credentials`\nonly drops the declaration — nothing in the directory is ever deleted by a flag.\n\n`credentials.example.yaml` is **the schema the playbooks read**, not a loose\nsuggestion: a run looks up `users.<name>.role` to pick the login a case needs\nand `api.base_url` to build a request. Keep the key names; extra keys of your\nown are ignored, renamed ones are simply not found and the run falls back to\nasking you in the chat.\n\nThat example is generated from [`credentials.yaml`](credentials.yaml), the same\ndeclaration the CLI parses — the two drifting used to fail *silently*, with the\nrun reporting \"no credential\" and blocking every authenticated case. Each field\nthere also declares whether it may ever be said out loud, and the sanitized view\nbelow is **built from that flag**: a field nobody marked reportable cannot reach\n`status`, a report or a work item, and the generator refuses to mark a password,\ntoken, secret or `base_url` as reportable at all.\n\n`qagent status` reports what is there **without reading a secret out loud** —\nthe declared environment, which users exist and their roles, whether an API is\nconfigured — and shouts if the environment looks like production:\n\n```\n   🔐 CREDENTIALS=true (.qagent/credentials/)\n      environment: local · users: admin (admin), vendedor (seller) · api configured\n```\n\nThat sanitized shape is also what a QA run may put in a report: credential\nfound, role, environment, login ok or rejected. Never a value.\n\n**The file on disk is what a run keys off, not the flag.** `CREDENTIALS: true`\nis your declaration; a repo can perfectly well have\n`.qagent/credentials/credentials.yaml` without it — created by hand, or written\nby an older version of the CLI. So the playbooks check for the file, and\n`status` says so when the two disagree:\n\n```\n   🔐 .qagent/credentials/credentials.yaml exists but CREDENTIALS is not declared\n      runs read the file anyway — 'qagent init --mode spechelix --credentials' declares it\n```\n\nThis matters because of one specific failure: a run reaches a redirect to the\nlogin page, concludes \"authentication required\", and blocks every authenticated\ncase **without ever opening the credentials file** — with a valid fixture user\nsitting in it. So a redirect to login is now an explicit ordered step in\n[`e2e-execute`](playbooks/e2e-execute.md): open the file, pick the entry by\nrole, attempt the login, *then* classify. A run may not report *no credential*,\n*credential rejected*, or a handoff for a login it never tried — the one\nexception being an agent whose own policy forbids handling passwords, which is\nknowable before any attempt and is a handoff from the start. The preflight line\nnames the key it used (`users.admin`), never the value, which is what makes a\nskipped credential visible in the report instead of invisible.\n\nThe seeded README carries the rules, and they are the point of the feature:\n\n- **Test and development environments only.** Never production credentials, not\n  even temporarily. A run that would need production does not get production.\n- **Least privilege** — the smallest role that exercises the flow, not your own\n  account and not an admin token because it was faster.\n- **Never share the file** — not by chat, email, ticket or screenshot. A\n  teammate seeds their own, or it goes through a password manager. What travels\n  through a chat lives in somebody's backup forever.\n- **Rotate what leaks.** Deleting a committed file does not undo it; the only\n  fix that works is invalidating the credential.\n- **Nothing from here reaches a report.** Playbooks use these values and never\n  transcribe them — evidence gets truncated or described.\n\n### LGPD\n\nFilling a test environment with a copy of production data is processing of\npersonal data under Lei 13.709/2018, needing a legal basis and a purpose —\n\"testing\" is neither by itself. The practical guidance the seeded README spells\nout: prefer synthetic data (anonymized data leaves the law's scope, art. 12,\nand synthetic data was never personal); pseudonymizing is not anonymizing, since\nthe remaining attributes usually still re-identify; minimize (art. 6º, III) —\na test needs the records the case exercises, not a dump; a test environment is\ntypically the weakest one, and art. 46 does not lower its bar for that; and a\nleak of real personal data is an incident (art. 48) whether or not it happened\nin production. Operational guidance for QA, not legal advice.\n\n## Test dimensions\n\nThe acceptance criterion says what must work; it rarely says in how many ways\nit can fail. [`guardrails/test-dimensions.md`](guardrails/test-dimensions.md)\ndefines the seven ways — its registry generated from\n[`dimensions.yaml`](dimensions.yaml), its method hand-written — and every\nplaybook applies them — the plan designs\ncases per dimension, the audit classifies coverage per dimension, the execution\nverifies them against the running app.\n\n<!-- qagent:gen dimensions-table -->\n| Dimension | Applies when | Scoped by |\n|---|---|---|\n| **Functional** | Always — it is the floor | Always |\n| **Regression** | Always, on a product already in use | Always |\n| **Performance** | The criterion states a number, or the change touches something whose cost grows with data | Marker: `lighthouserc.json`, `lighthouserc.js`, `.lighthouserc.yml`, `performance-budget.json` |\n| **Security** | Baseline always; deeper on auth, permissions, personal data, upload, external input | Always |\n| **Usability** | The change has a user interface | The run decides from the change |\n| **Compatibility** | The repo declares a support matrix, or a consumer contract changed | Marker: `package.json#browserslist`, `package.json#engines`, `.browserslistrc`, `.nvmrc` |\n| **API** | The product exposes an API the criterion touches | Marker: `openapi.yaml`, `openapi.json`, `swagger.json`, `api/openapi.yaml`, `docs/openapi.yaml` |\n<!-- /qagent:gen -->\n\nThe `Scoped by` column is what `qagent status` can answer for you: where a\ndimension has a marker, the CLI looks for it and reports what the repo actually\ncarries, instead of leaving the run to re-derive it every time. A marker is a\nfloor, not a ceiling — performance is in scope for a change touching a query in\na loop whether or not a budget file exists.\n\nThree rules keep this from becoming theater:\n\n- **Nothing is silently absent.** A dimension is in scope with a verdict, or\n  out of scope with a one-line reason. A missing row and a passing row must\n  never look the same.\n- **Claim only what you observed.** No load tool, browser farm or scanner gets\n  installed in your repo, so some checks end as *not verifiable here*, naming\n  what they would take. That is a real result — \"no performance issues found\"\n  after measuring nothing is not.\n- **Security stays inside the fence.** Only the target application, only in an\n  environment you authorized, no exploit development, no destructive payloads,\n  and evidence redacted before it reaches a tracker.\n\nScoping is decided from evidence and declared in the report, not asked as a\nquestionnaire at the start of the run — and you can override it in the request\n(`/qagent-run HU-003 — só segurança e API`).\n\n## Read-only agents\n\nThree agents run the playbooks above independently, always read-only:\n[`coverage-auditor`](playbooks/agents/coverage-auditor.md),\n[`test-plan-reviewer`](playbooks/agents/test-plan-reviewer.md),\n[`bug-reproducibility-checker`](playbooks/agents/bug-reproducibility-checker.md).\n\nEach has a single source of truth in [`agents/*.yaml`](agents/) —\n`description`, `tools`, what to read, and the read-only constraint. The four\nnative adapters (Claude, `.agents Protocol`, Antigravity as a repository, and\nAntigravity as a plugin) are generated from there — see\n[Generation](#generation).\n\nOnly the two an explicit plugin path reaches ship in the package —\n`.claude/agents/` and `.antigravity-plugin/agents/`. The root-scanned ones stay\nin a clone of the repository: nothing looks inside `node_modules` for them.\n\n## Supported tools\n\nA thin adapter in each native format — none duplicates content, all point back\nat the playbooks: Claude Code (`.claude/`), Gemini CLI (`GEMINI.md`), GitHub\nCopilot (`.github/`), Cursor (`.cursor/commands/`), and the\n[`.agents Protocol`](https://dotagentsprotocol.com/) (`.agents/`), which is\nwhere Codex CLI, Google Antigravity and Cursor all read from. Codex also reads\n`AGENTS.md` at the root natively, and — installed as a plugin rather than opened\nas a repository — the canonical `skills/` tree its manifest requires. `.agent/`\n(singular) is kept for older Antigravity, which has since moved its default to\n`.agents/skills/`.\n\nAntigravity is also a **first-class plugin**:\n[`.antigravity-plugin/`](.antigravity-plugin/) carries a `plugin.json`\ngenerated from `package.json` (so version, description, license and keywords\ncannot drift from what is published) beside the two trees it declares — its own\n`skills/` and its own `agents/`. `qagent install --antigravity-plugin` puts it\nat `~/.gemini/config/plugins/qagent`.\n\nThese are read from the repo root or from a user-global directory — no tool\ndocuments scanning `node_modules`, so installing the npm package gives you the\nCLI and the playbooks, not the invocable commands.\n\n```bash\nnpx qagent install --mode <mode> --commands\n```\n\nThat copies them in, at `.agents/skills/`, `.claude/skills/`, `.claude/agents/`\nand `.github/prompts/`, rewriting each pointer so it resolves from where the copy\nlands — a verbatim copy would have every command point at a `playbooks/`\ndirectory your repo does not have. Rerun to refresh; files you wrote yourself are\nleft alone. The full table is in [`AGENTS.md`](AGENTS.md#per-tool-adapters).\n\n## Generation\n\nAnything that would otherwise be written out in more than one place is declared\nonce in YAML and generated. The rule for what belongs there: **the closed list\ngoes, the judgment stays.** A set of modes, artifacts, dimensions or severity\nlevels is data; when to apply one is prose, and turning that into config is how\na guardrail starts reading like a setting somebody may switch off.\n\nThe urgent case is a copy living in **code** — a template string in the CLI is\nthe one `npm run render:check` can never keep honest, and it is where the QA\ndirectory's README, the knowledge file list and the credentials example each\ndrifted before being moved here.\n\n| Source | Generates |\n|---|---|\n| [`agents/*.yaml`](agents/) | The read-only agent adapters: `.claude/agents/`, `.agents/agents/`, `.agent/skills/`, `.antigravity-plugin/agents/` |\n| [`sources.yaml`](sources.yaml) | `scripts/sources.generated.mjs` (imported by the CLI), the modes table and the post-verdict table in this README |\n| [`dimensions.yaml`](dimensions.yaml) | `scripts/dimensions.generated.mjs` (marker detection in `qagent status`), the dimensions table in this README and in the guardrail |\n| [`commands.yaml`](commands.yaml) | The invocation surfaces in seven formats, the `.claude-plugin/`/`.codex-plugin/`/`.antigravity-plugin/` manifests, and — from its `artifacts:` registry — `scripts/artifacts.generated.mjs` (imported by the CLI to seed the QA directory) and the artifacts table in this README |\n| [`knowledge.yaml`](knowledge.yaml) | `scripts/knowledge.generated.mjs` (the CLI seeds `<QA_DIR>/knowledge/` and counts its entries from it), the file and ledger-field tables in [`knowledge.md`](playbooks/knowledge.md), and the shapes table in this README |\n| [`credentials.yaml`](credentials.yaml) | `scripts/credentials.generated.mjs` — the seeded `credentials.example.yaml`, the schema table in [`e2e-execute.md`](playbooks/e2e-execute.md), and the `reportable` gate that decides what `qagent status` may print |\n| [`labels.yaml`](labels.yaml) | `scripts/labels.generated.mjs` — the HTML report's wording per language, and the order its sections appear in |\n| [`severity.yaml`](severity.yaml) | The taxonomy table in [`qa-quality.md`](guardrails/qa-quality.md) and the severity hint in [`bug-report-TEMPLATE.md`](templates/bug-report-TEMPLATE.md). No `.mjs`: nothing in the CLI classifies a finding |\n\n```bash\nnpm install && npm run render\n```\n\n`npm run render:check` (or `qagent render --check`) writes nothing and exits\nwith status 1 if any generated file diverges from the YAML. It is what runs in\n[`.github/workflows/render-check.yml`](.github/workflows/render-check.yml) on\nevery push to `main` and every PR, catching all three cases: YAML edited\nwithout running `render`, a generated file edited by hand, and a generated file\nnobody committed.\n\nThe same workflow runs `npm test` — Node's own test runner, no dependency, over\nthe CLI's decision logic. Most of this hub is prose a model follows and cannot\nbe unit-tested; what *can* be is the deterministic part, and today that is the\n[post-verdict handoff](#after-the-verdict), whose failure mode is silence rather\nthan a stack trace.\n\n```bash\nnpm test\n```\n\nEditing an agent or a source mode means editing the YAML, never the generated\nfile. The generated files **are committed** on purpose: the hub has to work for\nsomeone who clones the repo and reads `AGENTS.md`, without running a build.\nGeneration is a build step, never an install step — and it is where schema\nvalidation is concentrated (duplicate alias, gap in `menu.order`), so the CLI\nreceives already-checked data.\n\nNote the split of responsibility: `sources.yaml` is the **hub's** config and\ncan therefore be pre-processed; `.qagent/config.yaml` is the **target repo's**\nconfig, hand-written, and therefore parsed at runtime — which is what makes\n`js-yaml` a real dependency rather than a build one.\n\nWhat stays out by decision: the playbooks, the guardrails and\n`source-resolution.md` remain hand-written markdown. The rule of thumb is that\nYAML serves what a program needs to branch on, and markdown what a model needs\nto read.\n\n## For agents\n\n[`AGENTS.md`](AGENTS.md) is the entry point — read that file first if you are\nthe agent running a task in this hub or from it.\n","readmeFilename":"README.md"}