{"_id":"@adversarylabs/sdk","_rev":"30-3934563cfdd569419660d55749873fd7","name":"@adversarylabs/sdk","dist-tags":{"latest":"0.1.34"},"versions":{"0.1.3":{"name":"@adversarylabs/sdk","version":"0.1.3","license":"MIT","_id":"@adversarylabs/sdk@0.1.3","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"dist":{"shasum":"14c1a1db2b40e2ec0ca2f77f720465d0b55440f4","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.3.tgz","fileCount":15,"integrity":"sha512-U81OxcUfquqAwMcJHll5wUNV/gz/BfeMNrqTnYfcwLAFLkZLxk8VSBMi3KxHEhWWRSo9rZ17kGIbUoxJd/36uQ==","signatures":[{"sig":"MEUCIGRSr/8UfH6hDOfGsyHK37eBPS4RDV4+b5xrcgN7bBHDAiEA7l5OtkVX0OJdoJld/wdTC6T/jSjDd1oTqXMoqvmXUV4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136845},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.findings.v1":"./schemas/adversary.findings.v1.schema.json"},"gitHead":"f8a4c22ecc8af7283ad6d80bb21b4a9e453d2d89","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write ."},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.3_1783649423166_0.8941529124424588","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@adversarylabs/sdk","version":"0.1.4","license":"MIT","_id":"@adversarylabs/sdk@0.1.4","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"61866bbc5e0174d9d0b428e9d9294cb52fae11f1","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.4.tgz","fileCount":18,"integrity":"sha512-FMoIJC33C4mpaSJixci6jmvLDftM5Hc8q7ZQ9uTIaO2oHYr44qgd6vbQL8HObTI74niRDnS4pvxCsn4WJg7VEA==","signatures":[{"sig":"MEYCIQD5zPNm997zVr6YueIlh+EXHctFEiLYiTJ0wPmArVCfAQIhAOPKZM+wP2BiC4t3SLcL/0kxD79qSjLwDq+n5j0xadx8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":264856},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.run.v1":"./schemas/adversary.run.v1.schema.json","./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json"},"gitHead":"dc443e167a47372e2f65041597bbe2455434e71e","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.17.1","vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.4_1783720705579_0.6607209385682822","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@adversarylabs/sdk","version":"0.1.5","license":"MIT","_id":"@adversarylabs/sdk@0.1.5","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"7807833def23fc88553121feceedd3163081279a","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.5.tgz","fileCount":18,"integrity":"sha512-xOfEZgZn7JQbjarqRqwhZybDKbu5+x49Nc/N2FaQS43dIeQath/fHtjTHkHcuOqvFaxgGzd8deuH+fnYHeby8Q==","signatures":[{"sig":"MEYCIQCHWxGfOmuftC1y2N7x7fntQ3l3Hj4kRTrDADChuF02rQIhAJpaLb0Qnu9E46DyfrYYzUAzc1OxeD5n3PPqkAYQe72R","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":278422},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json"},"gitHead":"166bf8af7a84b3b2dab98dcc8eb7e6d074533807","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.5_1784144835628_0.42106453887115114","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@adversarylabs/sdk","version":"0.1.7","license":"MIT","_id":"@adversarylabs/sdk@0.1.7","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"fcaade75de9cb00a49afe609dfcc7b93a5634ced","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.7.tgz","fileCount":23,"integrity":"sha512-3MHPH3hH48eAD0RD0RfX/CnnMIzUDSh6KMs3RnGdlyN21Sw4bFW7EJYoLkGkiWUICSjxd0c3by2bvsAsJA0pWQ==","signatures":[{"sig":"MEQCIDAiYv0eQhBJSOCujp0+z/JRPpsy9TeWZ6gCtOPpn2QcAiBmQAsBuQavDS9aTNZGJgHp1/7Vl0wzy/eyFKMiQrH8Ng==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":301488},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"c42690fedb112695b27e845eb2fdc97071252993","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.7_1784604525697_0.44244642683160174","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@adversarylabs/sdk","version":"0.1.8","license":"MIT","_id":"@adversarylabs/sdk@0.1.8","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"4dc1f3bf90f9eb96b8fd65ba2d35a6e8ed51b402","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.8.tgz","fileCount":23,"integrity":"sha512-w95tZFRsISXZAdBLCsc81Q8mTiapsL2YVvyBYlYlQdYSb8OSpr+QHujhNZAU7HXOV2KCsLQVMJE5twvZrdVomA==","signatures":[{"sig":"MEQCIB4/QwxXKEgS5CfgURs/gdOrzF9AXybNoI81nTra82TlAiBr5c7Q7NPctOANCsSoQHz39Kp5v/qPuQ0dDA86WwUfdg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":313551},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"64bac5e86765492e4078217fcd6badf449c7ef5c","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.8_1784973189997_0.14645348086458387","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"@adversarylabs/sdk","version":"0.1.9","license":"MIT","_id":"@adversarylabs/sdk@0.1.9","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"a0a06edc71290c97282981932dafa8d9147aba7e","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.9.tgz","fileCount":23,"integrity":"sha512-QUxFKoosCqfwFfKabHDO7+OT/oR/Vq7LuK2M4zoOikPLTVuEpqRfoQ7Tp9r+Xq0I94iC+zmTmCh1o+RIaxj7Fg==","signatures":[{"sig":"MEQCIGOf0XaPWUZ62mGVCXWPC5hodDtOJs+HdxhYU81+nx3hAiBfQzypgdPJNYQUJW6E5adAjucp2gOOQC5A+KCRdrv+Kg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":332362},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"6283ea6ac097ebb0f70be7c500fb8e58723ccf95","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.9_1784975081186_0.775906904844978","host":"s3://npm-registry-packages-npm-production"}},"0.1.10":{"name":"@adversarylabs/sdk","version":"0.1.10","license":"MIT","_id":"@adversarylabs/sdk@0.1.10","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"d4c9a6c8ee4f8a9d947e05eb2eae989effa23fdb","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.10.tgz","fileCount":23,"integrity":"sha512-eP/DgAPiAyGhJEUNx8iS+kIcAeUfExV+GpW0h5RBDHurIi7pO0g4IlYIJzMcaO+WRAKovbIGzqmxK71qmFiCUA==","signatures":[{"sig":"MEQCIFSWekElPoVNQruXMtGfITEfeNJcgeY2HVNFEtZfFHquAiATZ1m4RLirdHBFUYhPglhMn5zXOJExZ3BXByZtHQYVAw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":342761},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"5d5b740326baa4d1795e457a0708f1340c77b3ba","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.10_1784977488747_0.1560435551912247","host":"s3://npm-registry-packages-npm-production"}},"0.1.11":{"name":"@adversarylabs/sdk","version":"0.1.11","license":"MIT","_id":"@adversarylabs/sdk@0.1.11","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"01432c708d97cbe0b4e4f1048b6da807320ec608","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.11.tgz","fileCount":27,"integrity":"sha512-zdtHeBArYiNVvjX3RyBq0FdYqEFXoJJZGYaVP+z3cj1Vysuk2CWCBMNkZYhv5ydW+fOktJlj36L6kvMygyGYfw==","signatures":[{"sig":"MEQCIHvcHKe+K6XmZIwOgaNB4Nf0yrrpotrhSdu6r5op1SejAiBf8hNv7sq5cESfmlbSUKXq2xLB4tIRRgtCBJJM8dFeQw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":386099},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"1071e2a5a7619a3e55f704ad98d34fe88f4dd49a","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.11_1785001391619_0.6501297702941806","host":"s3://npm-registry-packages-npm-production"}},"0.1.12":{"name":"@adversarylabs/sdk","version":"0.1.12","license":"MIT","_id":"@adversarylabs/sdk@0.1.12","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"07ccf0a1901a89623db32df9d5fd26fd84b4793c","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.12.tgz","fileCount":27,"integrity":"sha512-faitqL0CQah0M0rKSWMbb0OtEzY/OjTISaE9BBy4GvAyi1wJW5kGtbN4WAWafZeknMNIV1UmkD+8DhU8GU6bqQ==","signatures":[{"sig":"MEQCIHw3fs/upqvOGvAJZxjkvsHksRpgGL4ELLO+wsCPwahHAiA0E9lSz8XN/d8CJIc6EUULug3PbnuQD33tcQRkzHuVng==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":397273},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"269cede4f8a07413583d172b7fe14a46c8aa6ec9","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.12_1785004666054_0.49639959654807986","host":"s3://npm-registry-packages-npm-production"}},"0.1.13":{"name":"@adversarylabs/sdk","version":"0.1.13","license":"MIT","_id":"@adversarylabs/sdk@0.1.13","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"de23d2818c16c4f1e27e2365a2bc25e6d62409f0","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.13.tgz","fileCount":27,"integrity":"sha512-s/TAKutJGj6xNFBrsgyNAVgaf24DJ0cZmFwFIj13tuJGgxva9amChkC/Z1u7iWtWf5dqqzPZ5vKsRJl9GmxiBg==","signatures":[{"sig":"MEQCIEQo/6NqMG0c281z0OVCCzGy2LUiRELu0EmGdaYM+I44AiBi/0ZDTQSi0/DH6I5WAO4j+F0EGUafLT60jNhv8mUnhw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":424444},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"14f0dc64b83bf90724d667b382efbb07288a3d18","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.13_1785006101581_0.6632925968635985","host":"s3://npm-registry-packages-npm-production"}},"0.1.14":{"name":"@adversarylabs/sdk","version":"0.1.14","license":"MIT","_id":"@adversarylabs/sdk@0.1.14","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"91a7dd3e9cc5fb6862bd29e882b895ca88d5384d","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.14.tgz","fileCount":31,"integrity":"sha512-DOgon5bgn5qyX/BsBvDFa50AGNDDiPAX82SAd7CIl6PsPxLxToLrAMM0rh9MfbWk+KvAYh13Mp6WaZQnBbronw==","signatures":[{"sig":"MEUCIQCqwEIaP05380RxcaV8V76ZDy69OrwAP2VePOR1su6HIQIgT+D9wPs1eLfCvDjSBz286/EmUb7hg63IRWvtBbguJqg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":490555},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"f551a0cf57c792bf84905e427724cf5a99a61637","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.14_1785087062989_0.9159594369151198","host":"s3://npm-registry-packages-npm-production"}},"0.1.15":{"name":"@adversarylabs/sdk","version":"0.1.15","license":"MIT","_id":"@adversarylabs/sdk@0.1.15","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"5162462edce07db56ed3735d9e5f40a2b235909c","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.15.tgz","fileCount":31,"integrity":"sha512-sPGnwFn4DT6Lx8ViYVEcsoJxc4+vxOSFPVhBjGeZPIuOT3NzhWt3FrX6ZwVbWCGSUyon1Z080vk4FbKTdcRk4A==","signatures":[{"sig":"MEQCICnTYxqPLZNT+UPnKhB8WyAkzYCX0r2O0drDUhuieryjAiAx9Mg2wahS1pFAaUBaO3r1kOEDHR6P2ZkX1BPOgI9igg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":492692},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"db8dadc97b9ae6318e971ddc08eb054786eeca1e","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.15_1785088843618_0.20321695026042574","host":"s3://npm-registry-packages-npm-production"}},"0.1.16":{"name":"@adversarylabs/sdk","version":"0.1.16","license":"MIT","_id":"@adversarylabs/sdk@0.1.16","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"22cb9df226cdcc8b63b1486b5f9c562c7ee16135","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.16.tgz","fileCount":39,"integrity":"sha512-rI6DOIV1LzDrMkPminuM7DUPSF/lRGuLgr7WCtKkMvuqd5xm/MberRQor+mOr6wcNzlsIZn+TGoDYsR5gIVCQA==","signatures":[{"sig":"MEQCIHA2Qy8m12AAElujJrpGSGfYpgT/ORrKr5eOyx5TCZnqAiBqPZ1zPG6fVBSN/DSTBdNeHAk6uhsoRJDly8+xSJsUpg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":531568},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"010b4c627c5218666835d1e532496f745ea09e75","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.16_1785760877125_0.06911544986098428","host":"s3://npm-registry-packages-npm-production"}},"0.1.17":{"name":"@adversarylabs/sdk","version":"0.1.17","license":"MIT","_id":"@adversarylabs/sdk@0.1.17","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"5a874bd611b1f140d0ec2225cdd60b4297a368fe","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.17.tgz","fileCount":43,"integrity":"sha512-tV661phSfFgyjuQHvDNmUri1EmWaTeKUVfsrbp/lsNGXZb82z9RuHP4ii1DaQSEIkDQhFawYsQL3mAcO0n6hPw==","signatures":[{"sig":"MEYCIQDjrgcGg9NkO6sSlksIXFajPJU2O98iZ/A8f/0Vvf8tJQIhAPCACoMbL4mJCIdISCtJaiPn4Bfti4TLbfJa9Kxo1qm5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":603663},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"b905a4cf31165e570eaf82d5273ea2d4d7542397","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.17_1788193434949_0.2289084445838252","host":"s3://npm-registry-packages-npm-production"}},"0.1.18":{"name":"@adversarylabs/sdk","version":"0.1.18","license":"MIT","_id":"@adversarylabs/sdk@0.1.18","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"2e2e4fee8adcc2eda8d47c432be155070e43094c","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.18.tgz","fileCount":43,"integrity":"sha512-k4VHK9DjOIbp3iyfoanz6kkOrI+vMKb0sXUTzdjHruQJ12TT93YilXs7tMT7ktgqtvaK2840CdnGYXRAyOMxVw==","signatures":[{"sig":"MEYCIQC3Wz1gNvEjtaMZ1HUL0wpOB9cJs79DggicltRQgWk0tQIhALmKZtpwldajsypWCM/aZOytttLqYGYbgnw0tn5LaiN0","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":610307},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json"},"gitHead":"12d77f2c9d9a64617dda2d50f510c543b89d04fd","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.18_1788550864870_0.15375251640967247","host":"s3://npm-registry-packages-npm-production"}},"0.1.19":{"name":"@adversarylabs/sdk","version":"0.1.19","license":"MIT","_id":"@adversarylabs/sdk@0.1.19","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"fc517e6530494f3fc359e19e2aa1016d452bb8e2","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.19.tgz","fileCount":48,"integrity":"sha512-xMTWKbkMeOhEvx1cDVHVRo2xfDZb5r0Nyt2wWt/bJc8whi8kgcFQ3gc0D56WR7XKXtgGDV2MMQGSvvBQEU5OjQ==","signatures":[{"sig":"MEUCIGXEEukX9wHPa605Fo/DYvOd+3OyXL1fQyjyKAhO9J+fAiEAyEZm1S6my2+oUvIgzaTvWfZmHKjeQQKoehOFhzpC9yo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDYeY/wkS6xkMRT3nIaJ3cOsiypH6Cfq/jEfff9wKvwhwIgSFismVSH4Oli1RRbu9opPjgpN5keHKQ+hByHfDbTNcQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":640544},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"c656694cf03c8f921acbed4eafc8548acd929548","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.19_1789392258696_0.6872529734045523","host":"s3://npm-registry-packages-npm-production"}},"0.1.20":{"name":"@adversarylabs/sdk","version":"0.1.20","license":"MIT","_id":"@adversarylabs/sdk@0.1.20","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"cc61df93ea95d73c49805ba346364d1403670e16","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.20.tgz","fileCount":48,"integrity":"sha512-/Wif/VzEWl2vh8G8ufv+uWAa3KMI8SIuc44PzLfeNfSTN7tl4AKL+rSIq6PHCiomLa1tXgNpt1nO4vEaIRm7CQ==","signatures":[{"sig":"MEYCIQCuQTqy6cZ70610ssS0RxK6VKn/NS0QZ7OxdXKSTD8f3wIhAP97VwxkbQFo9UIp1uOMif6vkGDSz2vg7HMrOrtIJRM+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIFOvAf7WfO0slZWJ+4rSFjopSQfLvK2SNTf6NYUnur0aAiEA9WMQO0imPTjJidmkqcJ/UIP9ynOLvaaHgWS5ckWKL9c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":653594},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"d8139f988977be3c42b7f2b09b0c0f5acbe81724","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.20_1789408376038_0.6836895040725308","host":"s3://npm-registry-packages-npm-production"}},"0.1.22":{"name":"@adversarylabs/sdk","version":"0.1.22","license":"MIT","_id":"@adversarylabs/sdk@0.1.22","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"c93688ad7729969fd0cc69cf8364f2e1a1f48b66","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.22.tgz","fileCount":48,"integrity":"sha512-d6L3BmVHm9LnxU7ZsuZy5mKj40s5yAzz/+rlNQ3h4xK4Vfn/52JRF1VP8DnldvxDOXuA1MhKqt4Ri7U/HgIu9A==","signatures":[{"sig":"MEYCIQC8KuxcwECC/R2ySnq0kX9pzrELyxVkBrf2gYt1qhF09AIhALY6DIYtyeq58dllq4t/yn1740mA417ywaVRJARqpTJR","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDrsq5/UIvab4xO4OPSfqwCfbng9wIcHJYYzxnncSEzXwIgH7z/AcCUOiEaUPlQ0Npkq3IjcYkjudOCGz3FOIK2NEE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":657042},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"13c7a4315198b8420f7c15d05d13c7bdcf476371","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.22_1789412286961_0.09953992782724241","host":"s3://npm-registry-packages-npm-production"}},"0.1.23":{"name":"@adversarylabs/sdk","version":"0.1.23","license":"MIT","_id":"@adversarylabs/sdk@0.1.23","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"9f2506b22e95ab426bedf469a60d4d96c6decaf9","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.23.tgz","fileCount":48,"integrity":"sha512-k58TKKYmmI8iq6Scyz5SASAUln7VYUpmr4K+OnF6JFbAFjVd46sLElsSgchwBug9PA8B9dib0lDVv5OXiQ0u2Q==","signatures":[{"sig":"MEQCIGpLm/h3ORgGBq3ItYoGFHpZwQOzj5qj/3lfyJKgLrZTAiAFbXK5uYEbXciTveNMofk73W8fTt1Dz9cEl7b2e1AKgQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCXfqMusobyC7e3tVVVe6cLIxn+BsbYaZhE27+E56V4xAIhALUlSREz8qu/vGFf+KXVF8OkK8U1eJFyg8+pcYh3Z3mt","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":657372},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"fb0e96efe70a34920ed350d3b45bcf874aab0a14","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.23_1789415019642_0.7659961481626623","host":"s3://npm-registry-packages-npm-production"}},"0.1.24":{"name":"@adversarylabs/sdk","version":"0.1.24","license":"MIT","_id":"@adversarylabs/sdk@0.1.24","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"9646cb4306194c719236b1eb85d4b3eb1303313d","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.24.tgz","fileCount":48,"integrity":"sha512-PPtuShTwa2lXvdw0yCl1UZ0KffeelNztPFweljoLgVIp3fJrdeyPoJvuDYOxnMIuggKbKFw9qBgQk0RnuU41kQ==","signatures":[{"sig":"MEYCIQDI3p7vVyxFpiEgu4YS1A3G//7pkH9KluC3oSHoY51uIgIhAPp07MCD+0CYDEOQnQs0gsGCPGxd3YbNAmDwx5IyGn/+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIGVpiuRtmLX+Jpv4ADErD38LkVSOU2l5I6VRD9Sfi8kKAiBKxE/6rRfQjBJn2eMoz+1FnLGMusBh6Q2XlS70kE4KGw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":663347},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"dedff2e578addf5d9f570da6ded4fbc1066cea84","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.24_1789441546808_0.5942533690086942","host":"s3://npm-registry-packages-npm-production"}},"0.1.25":{"name":"@adversarylabs/sdk","version":"0.1.25","license":"MIT","_id":"@adversarylabs/sdk@0.1.25","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"66318f9ca7136f3924d53d90a53a544ac9947a97","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.25.tgz","fileCount":48,"integrity":"sha512-zP+2U97MrdmMX+vPMnUzY6PXtv4sfBQclU3oE0C71p75QFaWi/xKq2NXnKSkeInBiqAnyo7yOeqpVurxx36igA==","signatures":[{"sig":"MEQCIEG6MOj91F9PiE081PkF8d2ngQ+9Z/KU1ySMrQL7aVWcAiA4RbYIt/Jpm17JftOPkO7Ewdv9rneJ5cc0cLTdvg5FZw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCAd9PcOe4ntVKoBhjwzSAppv/ncJ8IDfcJZowbAKOKZwIhAOEPQIzAZgvxJlosgRtibpOBIrhWHXg7kzdDkHLX31qm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":664200},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"465b1b77153a7bdda42ff881ac5ef26cee7e3d16","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.25_1789445053140_0.2924369363934691","host":"s3://npm-registry-packages-npm-production"}},"0.1.26":{"name":"@adversarylabs/sdk","version":"0.1.26","license":"MIT","_id":"@adversarylabs/sdk@0.1.26","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"1cf869211737615ed739d000f7494aa10f28ee87","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.26.tgz","fileCount":48,"integrity":"sha512-IlUhC0t21h9iUNz2+Yyh9lGX1HjThw0qxsytBlZUxHVuO7NZJwwinfUuN48j+NngIoIJQlz75stdqJiLAkacAQ==","signatures":[{"sig":"MEQCIBSCrukRl2+fZ0VOxqH6VdYpobR1SzjnJRAbQjxspQgAAiBbM9WV3HKUDbMqBg1GK+uRBH0i3s9xp0b/JUU95b1zZg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDw3H7MC/CxtN8HFgzoPuNlsLSngBbMlKs6tllfyWCe7gIgZEp6eFxcpFH44QI99G+hBB0KcPOwjiPA5xgWY4vXAFw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":664200},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"28f5bd5b74f6f3305f121974b4a7d0ec488970aa","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.26_1789445221146_0.6275909087523004","host":"s3://npm-registry-packages-npm-production"}},"0.1.27":{"name":"@adversarylabs/sdk","version":"0.1.27","license":"MIT","_id":"@adversarylabs/sdk@0.1.27","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"ba643c5423c7743e31ce46d9d79c2ddadaa39c78","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.27.tgz","fileCount":48,"integrity":"sha512-Qx5xbIPG8H3pq5arzCOAGg1Veb4PCPbtaEXJnYymm2OOGux2ox+tlKKKjIP7XmguTeBPJuanNUJSzVzn2yyivQ==","signatures":[{"sig":"MEQCIEaFGcJcdvOjNRlvRO919NUxULAVG70wrmBub6bCs0gxAiBUeZxIljXD+0/m+yxWN+jWhdZf8zNp/6ZFmH+0Tq77ZA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIEEmLHJNGA74wSIF/Qt97zRLc0aqBnIlNuB+QbmNkW3/AiBuo3vyS9W6ZQk0924TfcANffvgC7BCFxzfKKA5ubw8wg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":672100},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"0fd5742ee0bf06e98700f77823698e274181f4dd","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.27_1789446323381_0.2856346900741009","host":"s3://npm-registry-packages-npm-production"}},"0.1.28":{"name":"@adversarylabs/sdk","version":"0.1.28","license":"MIT","_id":"@adversarylabs/sdk@0.1.28","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"a7654557da12231f2ea1e7004152d24534365e5d","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.28.tgz","fileCount":48,"integrity":"sha512-Oyx1frRVVoqSAcxh9NCiooAFGukOtxS8uAhielelJ95U8xXKYpSK1KGjvOTxIyQVk8wP/P512katl6V1g6Rtww==","signatures":[{"sig":"MEYCIQCH7YHHAptio3BtXf2iyKtwI3bZHcF5LRSzDC5zHGdpFwIhAK2i19WF9hxD60bqxeft/Y5ef7JZAwzx92jMkEjdSNHW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIA7w8zgP0z6eSUFrEWHzz3xyccJ0iqcywjToV0+GJsOdAiEAi9Va9rlhZBO0XyU20OHq6E6Ij+F1sEYsmtOuogPqJUE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":672740},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"57a9f3161a45be6b637b2fdc7bc8b130eff85a28","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.28_1789448155456_0.3444383717300543","host":"s3://npm-registry-packages-npm-production"}},"0.1.29":{"name":"@adversarylabs/sdk","version":"0.1.29","license":"MIT","_id":"@adversarylabs/sdk@0.1.29","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"0c4f23c1036f43ca4ad527fcc56e563bcd2c44aa","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.29.tgz","fileCount":48,"integrity":"sha512-HilZFaLd/2zRWL1SHmBQ3bY1IB6Daew9NxYRwSwSFRchSl8ctQDn/uiBDfg9yIijidY2Jazcbm10Y7oGFXryYw==","signatures":[{"sig":"MEYCIQCGqMhZXYnlqBxodECmfrdl1oFGlFJRmjTThmkrz5IPkwIhAMcBTVihVwDS1VF0cwj6qgxA931idI90SMAjA5+t7XdJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDyg8MvNKiS7BJT7sSIYLgBhRBTx+u3yO4V/Y1BpAR4YQIgJPmc/zPA0Su5rprEboxhsFuBhnX0O6ZzSZNBnCDhXHI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":674375},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"144b50cfa7844c006abcff4903ddf961f6670c94","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.29_1789448861001_0.03313125080972412","host":"s3://npm-registry-packages-npm-production"}},"0.1.30":{"name":"@adversarylabs/sdk","version":"0.1.30","license":"MIT","_id":"@adversarylabs/sdk@0.1.30","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"a7e948e2b9e79f622f5834cba447f74c28336119","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.30.tgz","fileCount":48,"integrity":"sha512-4U3criD3t4UM/AKZI1sw9YUnO1SyJgVWNShzPnfNWVZOmQ1FnvqcbTsdVDfsXxcbj8HS1V/4GaQXjBzRJ3sA9g==","signatures":[{"sig":"MEQCIEdUfgg4kiRy/IIG+riYm5gcNApfzyasmF3HVjhxId2dAiBNYBhqDX3uHsYd+8dUANmwV8/I1MrPk/JGwFwcwQzTYQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIEOqi9eIMlyl1+UiBAtwyDAq5/orOGNA5IWgGeFWkdcYAiBpRS1kwBqR/kaGYyB7pHdJe4hSPVItt6eSlv8Sm+zN5A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":675049},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"8579501356571a77772f2fb39bb3f15602ba9320","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.30_1789450871369_0.5051365510204211","host":"s3://npm-registry-packages-npm-production"}},"0.1.31":{"name":"@adversarylabs/sdk","version":"0.1.31","license":"MIT","_id":"@adversarylabs/sdk@0.1.31","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"04b4b8c3d9a193e248e18fad7c8d2feeb32a94d5","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.31.tgz","fileCount":48,"integrity":"sha512-fUXop08OXOyDYFaYJSh4boZ64DITA4720oYk15i1XJFMo5jtq0QmPXkLmCn+cCqrIxE7mQrnOrx74/ET6bRvkQ==","signatures":[{"sig":"MEUCIQCi+O2HiDA/UhdS7p/M2A5Bntq1z+GsyL551fJSg1iNigIgVl3kIH3cY+cofOiMe7C6R+5i2k+qWaC0+limtwzsr1A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDw54NQ2VLr/jJYK8N8dKqN6kT2hmkUy3afrqOjK4P5egIgZCBoYWD7SN1T5feceiZtk+yCfCqzx2INEp0ckLPipWE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":676989},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"6f54e4fe82a321978b7ece7c6be7839cd25f684b","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.31_1789479318782_0.046248261021815784","host":"s3://npm-registry-packages-npm-production"}},"0.1.32":{"name":"@adversarylabs/sdk","version":"0.1.32","license":"MIT","_id":"@adversarylabs/sdk@0.1.32","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/adversarylabs/adversary-sdk-typescript#readme","bugs":{"url":"https://github.com/adversarylabs/adversary-sdk-typescript/issues"},"dist":{"shasum":"f86c001105626afbf136ce37989cdc545fddae0b","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.32.tgz","fileCount":48,"integrity":"sha512-ppoM1NLRRABGjUZtoI150/2PL/nFEkBFZ0pe5UeB2bhU0soQrbah6U4171/F4gfpKwcT+99LtI5H1WcWpjgglQ==","signatures":[{"sig":"MEUCIDyIqwqARf60eOsZ3bT17Pln4gXWa7lCO+wAvO+hufoQAiEA/itdDPlI3HrQMjuY9pdPGnFTOfdZiG/iM+b6Sv1C0jc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIAx9XIOQ4eYep78RMp0SObVPKY/DQDDRwxwbJM0oTkV3AiEA84xzfykjMeTgiH1Igw8kd2CHMiuiVlOqB1Kw4UC2ZpQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":679825},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"da2ee12d08c716b30c9f6a4ac7f8aaa1889a18cd","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/adversarylabs/adversary-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.32_1789489925196_0.19694089841334272","host":"s3://npm-registry-packages-npm-production"}},"0.1.33":{"name":"@adversarylabs/sdk","version":"0.1.33","license":"MIT","_id":"@adversarylabs/sdk@0.1.33","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"homepage":"https://github.com/doomerlabs/doomer-sdk-typescript#readme","bugs":{"url":"https://github.com/doomerlabs/doomer-sdk-typescript/issues"},"dist":{"shasum":"b9469aee58bdcab379e0460adc490a9fe5d1500c","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.33.tgz","fileCount":48,"integrity":"sha512-bwrLPUc5up6eP3183RTX3aUrEubZwA6sgJC+knDMk8+pfomWqoXOAdrT0lHyNwejD1Fc93ssfXP5DmbA3LfObA==","signatures":[{"sig":"MEYCIQDcJOl4AVS29dQCalCd9EJEfaB1WKcremilhRJBD3kH6QIhAKkXcFHlq27tJDgB9T23cN3tNob0rXb3XggFPUTvxd9s","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC75at3XW87aIsiCuIlECSYCYyPUAROapqAhA+5Db0szQIhAJrIovhNNH0LEQOzAbQCv50o4v+riFeS1CKMNHZ/0FYU","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":696742},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"7f901bc1bb2983278c31e2aa01c4d4f6a1f9f1b7","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"repository":{"url":"git+https://github.com/doomerlabs/doomer-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.8","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"_nodeVersion":"22.23.2","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.33_1790103872806_0.9150823466826676","host":"s3://npm-registry-packages-npm-production"}},"0.1.34":{"_id":"@adversarylabs/sdk@0.1.34","bugs":{"url":"https://github.com/doomerlabs/doomer-sdk-typescript/issues"},"dist":{"shasum":"1652ab14d640ced015ae701ed558d2870caaf44e","tarball":"https://registry.npmjs.org/@adversarylabs/sdk/-/sdk-0.1.34.tgz","fileCount":48,"integrity":"sha512-Ua5e82zagubWKwR+fg/+uBBez/5groRKp4hcBPFfY/2WQKNbGrVeAW6AeddydwDxzKvPhOAZH91s0Z91a/bFjg==","signatures":[{"sig":"MEUCIE4WZzHUUrZ7ICdH3PzT1POHVw+9rntP99hH2/pEbY7NAiEArTS6yo8qCeB/2Hn5Ci4pyyM1urxfJiSDDRSTqcJxseA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDsbsRIOWNGxMkhyZV0h9IGflp4N0r+tftfZ0rClEUXvAiEAqcXZ4EAdSm9KAyUzUw0IT6FliLc47H+OjaAU59cOq5o="}],"unpackedSize":712262},"main":"./dist/index.js","name":"@adversarylabs/sdk","type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schemas/adversary.input.v1":"./schemas/adversary.input.v1.schema.json","./schemas/adversary.review.v1":"./schemas/adversary.review.v1.schema.json","./schemas/adversary.manifest.v1":"./schemas/adversary.manifest.v1.schema.json","./schemas/adversary.outcome-context.v1":"./schemas/adversary.outcome-context.v1.schema.json"},"gitHead":"d5df2e4ee79154774e6295ac524c438b52edc5c9","license":"Apache-2.0","scripts":{"lint":"biome check .","test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"rm -rf dist","format":"biome check --write .","prepack":"npm run build","prepare":"npm run build"},"version":"0.1.34","_npmUser":{"name":"marccampbell","email":"marc.e.campbell@gmail.com"},"homepage":"https://github.com/doomerlabs/doomer-sdk-typescript#readme","repository":{"url":"git+https://github.com/doomerlabs/doomer-sdk-typescript.git","type":"git"},"_npmVersion":"10.9.9","description":"Small TypeScript SDK for authoring Adversaries.","directories":{},"maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"_nodeVersion":"22.23.3","dependencies":{"ajv":"^8.20.0","yaml":"^2.8.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.1.10","typescript":"^5.9.3","@types/node":"^22.20.1","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.1.34_1790708969586_0.24652971021838233"}}},"time":{"created":"2026-07-10T02:10:22.954Z","modified":"2026-09-29T19:09:30.009Z","0.1.3":"2026-07-10T02:10:23.310Z","0.1.4":"2026-07-10T21:58:25.724Z","0.1.5":"2026-07-15T19:47:15.762Z","0.1.7":"2026-07-21T03:28:45.849Z","0.1.8":"2026-07-25T09:53:10.130Z","0.1.9":"2026-07-25T10:24:41.349Z","0.1.10":"2026-07-25T11:04:48.888Z","0.1.11":"2026-07-25T17:43:11.761Z","0.1.12":"2026-07-25T18:37:46.192Z","0.1.13":"2026-07-25T19:01:41.759Z","0.1.14":"2026-07-26T17:31:03.144Z","0.1.15":"2026-07-26T18:00:43.762Z","0.1.16":"2026-08-03T12:41:17.282Z","0.1.17":"2026-08-31T16:23:55.122Z","0.1.18":"2026-09-04T19:41:05.021Z","0.1.19":"2026-09-14T13:24:18.780Z","0.1.20":"2026-09-14T17:52:56.133Z","0.1.22":"2026-09-14T18:58:07.099Z","0.1.23":"2026-09-14T19:43:39.754Z","0.1.24":"2026-09-15T03:05:46.933Z","0.1.25":"2026-09-15T04:04:13.319Z","0.1.26":"2026-09-15T04:07:01.253Z","0.1.27":"2026-09-15T04:25:23.496Z","0.1.28":"2026-09-15T04:55:55.540Z","0.1.29":"2026-09-15T05:07:41.117Z","0.1.30":"2026-09-15T05:41:11.470Z","0.1.31":"2026-09-15T13:35:18.878Z","0.1.32":"2026-09-15T16:32:05.301Z","0.1.33":"2026-09-22T19:04:32.931Z","0.1.34":"2026-09-29T19:09:29.686Z"},"bugs":{"url":"https://github.com/doomerlabs/doomer-sdk-typescript/issues"},"license":"Apache-2.0","homepage":"https://github.com/doomerlabs/doomer-sdk-typescript#readme","repository":{"url":"git+https://github.com/doomerlabs/doomer-sdk-typescript.git","type":"git"},"description":"Small TypeScript SDK for authoring Adversaries.","maintainers":[{"name":"marccampbell","email":"marc.e.campbell@gmail.com"}],"readme":"# adversary-sdk-typescript\n\nSmall TypeScript SDK for building file-based Adversaries.\n\nThe SDK owns the runtime boilerplate: read runtime input, discover the source repository path,\nexecute registered rules, collect observations, synthesize findings, normalize and rank the review,\nand write runtime output.\n\n## Install\n\n```bash\nnpm install @adversarylabs/sdk@latest\n```\n\nRequires Node 22 or newer and ESM.\n\n## Migrating from 0.1.4\n\nSDK 0.1.4 output is incompatible with the current strict Doomer CLI schema. Version 0.1.5 is\nthe canonical protocol release. Existing adversaries should:\n\n1. Upgrade the package to `@adversarylabs/sdk@^0.1.5`.\n2. Set `findings.format` to `adversary.review.v1` in `adversary.yaml`.\n3. Stop reading `result.schemaVersion`; protocol selection is expressed by `protocolVersion: 1`\n   and the manifest format.\n4. If consuming serialized evidence, read `file`, `line`, `endLine`, `message`, `snippet`, and\n   `metadata` instead of `location`, `label`, and `data`.\n5. If consuming review scores, read the canonical review observation with key `score.<score-key>`;\n   the complete authored score is preserved in that note's metadata.\n\nThere is no compatibility adapter or dual wire format. Output is validated against the strict\n`adversary.review.v1` schema before it is written.\n\n## Author an adversary\n\n```ts\nimport { Adversary, Severity, log } from \"@adversarylabs/sdk\";\n\nconst app = new Adversary({\n  name: \"adversarylabs/comment-sentences\"\n});\n\napp.defineRule({\n  id: \"comments.complete-sentence\",\n  category: \"code-style\",\n  defaultSeverity: Severity.Info,\n  groupBy: [\"ruleId\", \"subject\"],\n  aggregate(observations) {\n    return {\n      title:\n        observations.length === 1\n          ? \"Comment is a complete sentence\"\n          : \"Comments contain complete sentences\",\n      confidence: \"high\",\n      summary: `${observations.length} comments are written as complete sentences.`,\n      recommendation:\n        \"Keep complete-sentence comments only when they explain non-obvious intent.\"\n    };\n  }\n});\n\napp.rule(\"comments.complete-sentence\", async (ctx) => {\n  log.debug(`scanning ${ctx.repoPath}`);\n\n  ctx.observe({\n    ruleId: \"comments.complete-sentence\",\n    subject: \"src/index.ts\",\n    confidence: \"high\",\n    title: \"Comment is a complete sentence\",\n    location: {\n      file: \"src/index.ts\",\n      line: 2\n    },\n    evidence: \"This comment is a complete sentence.\",\n    recommendation: \"Use complete-sentence comments intentionally where they clarify non-obvious code.\"\n  });\n});\n\nawait app.runFromEnvironment();\n```\n\n## API\n\n### `new Adversary(options)`\n\nCreates an adversary app.\n\n```ts\nconst app = new Adversary({\n  name: \"adversarylabs/example\"\n});\n```\n\n### `app.rule(ruleId, handler)`\n\nRegisters a rule. Rules report through `ctx.observe(...)`, `ctx.finding(...)`, and `ctx.review.*`.\n\nRule context exposes:\n\n- `ctx.repoPath`\n- `ctx.change`\n- `ctx.summary`\n- `ctx.cache`\n- `ctx.relpath(path)`\n- `ctx.glob(pattern)`\n- `ctx.rglob(pattern)`\n- `ctx.model.review(request)`\n- `ctx.observe(observation)`\n- `ctx.finding(finding)`\n- `ctx.review.assessment(assessment)`\n- `ctx.review.positive(note)`\n- `ctx.review.observe(note)`\n- `ctx.review.opinion(opinion)`\n\n### `ctx.model.review(request)`\n\nModel-backed adversaries provide their review prompt, bounded structured input, response schema,\nand output budget. The SDK sends that request to the execution-scoped broker created by the\nDoomer CLI and validates the structured answer before returning it:\n\n```ts\nconst review = await ctx.model.review<{\n  decision: \"approve\" | \"request_changes\";\n  observations: Array<{ summary: string; evidenceIds: string[] }>;\n}>({\n  prompt: \"Review the engineering quality of this change.\",\n  input: {\n    change: ctx.change,\n    evidence: preparedEvidence,\n  },\n  schema: {\n    type: \"object\",\n    additionalProperties: false,\n    required: [\"decision\", \"observations\"],\n    properties: {\n      decision: { enum: [\"approve\", \"request_changes\"] },\n      observations: {\n        type: \"array\",\n        items: {\n          type: \"object\",\n          additionalProperties: false,\n          required: [\"summary\", \"evidenceIds\"],\n          properties: {\n            summary: { type: \"string\" },\n            evidenceIds: { type: \"array\", items: { type: \"string\" } },\n          },\n        },\n      },\n    },\n  },\n  budget: {\n    maximumOutputTokens: 8_000,\n    timeoutMs: 120_000,\n  },\n});\n```\n\nAdversaries may add semantic validation that cannot be expressed by JSON Schema. The adversary\nowns the domain rule; the SDK owns bounded regeneration, feedback, timeout accounting, and usage\naggregation:\n\n```ts\nconst review = await ctx.model.review<EngineeringReview>({\n  prompt: ENGINEERING_REVIEW_PROMPT,\n  input: preparedInput,\n  schema: engineeringReviewSchema,\n  validation: {\n    maximumAttempts: 3,\n    validate: ({ output, citations }) => {\n      validateEngineeringReview(output, citations);\n    },\n  },\n});\n```\n\nThrow from `validate` to reject an answer. The SDK sends that error back as trusted validation\nfeedback and retries only the final generation call. With repository tools, it reuses the already\nretrieved evidence and citations. Exhaustion raises a non-retryable `ModelReviewError` with code\n`model_validation_failed` so hosts do not restart the entire adversary review.\n\nFor repository-scale reviews, add bounded repository tools instead of placing source bodies in\n`input`. The SDK asks the model which directories and line ranges it needs, performs those reads\ninside the rule context's repository boundary, and then makes the final structured review call:\n\n```ts\nconst review = await ctx.model.review<EngineeringReview>({\n  prompt: ENGINEERING_REVIEW_PROMPT,\n  input: {\n    change: ctx.change,\n    repositoryPurpose: \"Go command-line adversary\",\n  },\n  schema: engineeringReviewSchema,\n  tools: {\n    repository: {\n      include: [\"*.ts\", \"**/*.ts\", \"*.json\"],\n      exclude: [\"fixtures/**\", \"generated/**\"],\n      maxRounds: 6,\n      maxToolCalls: 24,\n      maxTotalBytes: 256_000,\n      maxBytesPerRead: 32_000,\n      maxLinesPerRead: 400,\n    },\n  },\n  budget: {\n    maximumOutputTokens: 6_000,\n    timeoutMs: 300_000,\n  },\n});\n```\n\nRepository retrieval provides paginated `list_directory` and line-range `read_file` operations.\nReads are repository-relative, read-only, symlink-safe, glob-constrained, and bounded by call,\nround, line, and byte budgets. Each successful read creates an immutable citation:\n\n```ts\nreview.citations?.[0];\n// {\n//   citationId: \"repo:read:1\",\n//   path: \"src/index.ts\",\n//   startLine: 20,\n//   endLine: 80,\n//   content: \"...\"\n// }\n```\n\nThe final model input contains the original value under `reviewInput` and the prepared tool\nresults under `repository.toolResults`. Final output schemas should cite the supplied\n`citationId` and a line inside its inclusive range. The SDK never exposes arbitrary shell tools,\nfollows repository symlinks, or sends provider credentials into the adversary process.\n\nDeclare `permissions.model: true` in `adversary.yaml`. The adversary process receives only a\nshort-lived authenticated loopback broker endpoint. Provider credentials, provider selection,\nnetwork transport, retries, and provider-specific response handling remain owned by the CLI.\n\n`app.run({ model })` accepts an injected `ReviewModel` for deterministic unit tests. Calling\n`ctx.model.review(...)` without an injected model or CLI broker throws `ModelUnavailableError`;\nthe SDK never silently substitutes deterministic heuristics for model judgment.\n\n### `ctx.change`\n\nThe requested review scope, normalized from the runtime input's `change` block. Honor it instead\nof inferring scope from Git state: the runner has already resolved what should be reviewed.\n\n- `null` — review the entire target; the runner provided no change context (for example\n  `--all-files` with no refs, or a non-Git target).\n- `scanMode: \"all\"` — review the entire target; change metadata is still available.\n- `scanMode: \"changed\"` — review only the change from `baseRef` to `headRef`.\n\n`changedFiles` lists the repository-relative paths the runner identified as changed. `worktree` is\ntrue when the reviewed head is the uncommitted worktree (`headRef` is the `WORKTREE` sentinel,\nexported as `WORKTREE_HEAD_REF`).\n\n```ts\napp.rule(\"scoped\", async (ctx) => {\n  if (ctx.change === null || ctx.change.scanMode === \"all\") {\n    // Review every file in ctx.repoPath.\n  } else {\n    // Review only ctx.change.changedFiles against ctx.change.baseRef.\n  }\n});\n```\n\n### `ctx.repoGraph.semanticMatches(query)`\n\nUse semantic matches for deterministic language rules that need type, scope, containment, or\noperation-order information. The CLI parses and resolves code once; adversaries provide a\ndeclarative sequence instead of implementing a source scanner.\n\n```ts\nconst query = defineSemanticQuery({\n  language: \"go\",\n  within: \"function\",\n  steps: [\n    { kind: \"call\", capture: \"guard\", method: \"Do\", receiverType: \"sync.Once\" },\n    { kind: \"call\", capture: \"constructor\", name: \"connect\", within: \"guard\" },\n    { kind: \"assignment\", within: \"guard\", source: \"constructor\", operator: \"=\", sourceKind: \"call\", targets: [\n      { capture: \"value\", scope: \"package\" },\n      { capture: \"failure\", scope: \"package\", trait: \"error\" },\n    ] },\n    { kind: \"return\", after: \"guard\", outside: \"guard\", references: [\"value\", \"failure\"] },\n  ],\n});\nconst matches = ctx.repoGraph?.semanticMatches(query) ?? [];\n```\n\nEach result contains a stable `key`, source location, enclosing semantic unit, and captured\noperations or bindings. `defineSemanticQuery` rejects unknown, duplicate, or type-incompatible\ncapture references when the adversary loads, so malformed query contracts cannot silently match\nnothing. An assignment linked with `source` must not also be `after` that source: the direct RHS\ncall is nested inside the assignment and therefore starts later in source order. Rules remain\nresponsible for policy, severity, and finding language. `references` accepts one capture name or\nan array when the same operation must reference every captured binding.\nUse `outside` with an earlier captured call to require that an operation is not lexically nested\ninside that call. Combined with `after`, this distinguishes an enclosing-function return after a\ncallback-bearing guard from a return inside the callback itself.\nBinding `trait` constraints are adapter-neutral semantic categories. For example, a language\nadapter may mark both an interface-typed failure and a concrete failure implementation with the\n`error` trait, avoiding brittle exact type-name checks in adversaries.\n\n### Opinion framing (`formatOpinion` / `formatOpinionAsync`)\n\nDo not hardcode \"before merging\" (or similar decision language) in domain adversaries.\nThe runner already resolved the review posture; the SDK turns a ship decision and domain\nconcern into posture-aware prose:\n\n| Posture | When | Deadline language |\n| --- | --- | --- |\n| `repository` | `change === null` or `scanMode: \"all\"` (for example `--all-files`) | before shipping |\n| `change` | committed range (`scanMode: \"changed\"`, not worktree) | before merging |\n| `worktree` | uncommitted local changes (`headRef` is `WORKTREE`) | before committing |\n\n```ts\nimport { formatOpinion, formatOpinionAsync, requireOpinionConcern } from \"@adversarylabs/sdk\";\n\n// Synchronous: concern must already be a noun phrase.\nctx.review.opinion(\n  formatOpinion({\n    ship: false,\n    concern: \"direct process termination below the application boundary\",\n    change: ctx.change,\n  }),\n);\n\n// Async: free-form model titles/clauses are rewritten via the CLI model broker.\nctx.review.opinion(\n  await formatOpinionAsync({\n    ship: false,\n    concern: \"api get/post/patch/put silently no-op for v1 paths\",\n    change: ctx.change,\n    model: ctx.model,\n  }),\n);\n\n// Or rewrite only the concern, then format:\nconst { concern } = await ctx.model.concern({\n  text: \"Commands discard inherited context, breaking Ctrl+C\",\n});\n// concern === \"inherited context in command handlers\" (example)\n\n// Validate early when adapting model titles or free-form text:\nrequireOpinionConcern(\"forced exit code 124\");\n// throws: requireOpinionConcern(\"commands replace inherited context\");\n```\n\nHelpers:\n\n- `resolveReviewPosture(change)` — map `ctx.change` to `repository` | `change` | `worktree`\n- `isOpinionConcernPhrase(concern)` — true when the string is a short noun phrase\n- `requireOpinionConcern(concern)` — validate/normalize a noun phrase or throw\n- `normalizeOpinionConcern(concern)` — lenient helper (may wrap clauses as `that …`); prefer\n  `requireOpinionConcern` for overall opinions\n- `formatOpinion({ ship, concern?, remainingCount?, change?, posture? })` — build `{ ship, summary }`;\n  **rejects clause-shaped / headline concerns**\n- `formatOpinionAsync({ ship, concern?, model, … })` — same framing; rewrites invalid concerns\n  through the model broker (no call when the phrase is already valid)\n- `rewriteOpinionConcern(model, { text })` / `ctx.model.concern({ text })` — pass-through rewrite\n  only (structured schema + `requireOpinionConcern` validation, one retry by default)\n\nWhen an adversary omits `ctx.review.opinion(...)`, the SDK synthesizes an opinion from residual\nfindings using the same posture rules.\n\n**Ownership:** adversaries supply judgment (ship + concern draft); the SDK validates noun-phrase\nshape, optionally rewrites invalid concerns via the CLI-owned model broker, and frames posture\nlanguage. The CLI prints `opinion.summary` and does not rewrite prose at render time.\nProvider credentials remain in the CLI broker (`permissions.model: true`).\n\n### `app.defineRule(definition)`\n\nRegisters domain-specific aggregation for a stable rule id. The SDK still owns grouping,\ndeduplication, ranking, suppression, and rendering; the rule definition supplies engineering\nlanguage for a grouped set of observations.\n\n```ts\napp.defineRule({\n  id: \"comments.complete-sentence\",\n  category: \"code-style\",\n  defaultSeverity: \"info\",\n  defaultConfidence: \"high\",\n  groupBy: [\"ruleId\", \"subject\"],\n  aggregate(observations) {\n    return {\n      title:\n        observations.length === 1\n          ? \"Comment is a complete sentence\"\n          : \"Comments contain complete sentences\",\n      confidence: \"high\",\n      summary: `${observations.length} comments are written as complete sentences.`,\n      whyItMatters:\n        \"Comments are most useful when they explain non-obvious intent rather than restating code.\",\n      recommendation:\n        \"Keep complete-sentence comments only when they explain non-obvious intent.\"\n    };\n  }\n});\n```\n\n`category`, `defaultSeverity`, `defaultConfidence`, and `groupBy` act as defaults for observations\nwith the same `ruleId`. If a rule has no `aggregate(...)`, the SDK uses generic synthesis.\n\nDefinitions are scoped to one `Adversary`. Duplicate IDs throw; use `app.replaceRule(...)` when an\nintentional replacement is required. The top-level `defineRule(...)` API remains temporarily\navailable for compatibility but is deprecated.\n\n### `ctx.observe(input)`\n\nUse observations for raw detector output and evidence. Observations are normalized, deduplicated,\ngrouped, synthesized, ranked, and rendered by the SDK. Prefer this path for new adversaries.\n\nDefault grouping uses:\n\n```text\nruleId + subject + category\n```\n\nRule definitions can override this with `groupBy`. Individual observations can still override the\nissue boundary with `groupKey`:\n\n```ts\nctx.observe({\n  ruleId: \"comments.complete-sentence\",\n  subject: \"src/index.ts\",\n  groupKey: \"complete-sentence-comments\",\n  category: \"code-style\",\n  severity: \"info\",\n  confidence: 0.95,\n  title: \"Comments contain complete sentences\",\n  location: { file: \"src/index.ts\", line: 3 },\n  evidence: { comment: \"This comment is a complete sentence.\" },\n  recommendation: {\n    summary: \"Use complete-sentence comments intentionally where they clarify non-obvious code.\"\n  }\n});\n```\n\nSet `deduplicate: false` on a completed finding when separate findings intentionally share an\nidentity. The SDK otherwise merges findings with the same group key or generated ID.\n\n### `ctx.finding(input)`\n\nUse completed findings when the adversary has already synthesized the issue:\n\n```ts\nctx.finding({\n  title: \"Comments contain complete sentences\",\n  category: \"code-style\",\n  severity: \"info\",\n  confidence: \"high\",\n  summary: \"Three comments are written as complete sentences.\",\n  whyItMatters: \"Complete-sentence comments can be useful for intent, but noisy when they restate code.\",\n  impact: \"Reviewers may spend time reading comments that do not add much context.\",\n  evidence: [\n    { location: { file: \"src/index.ts\", line: 3 }, message: \"Explains parser intent.\" },\n    { location: { file: \"src/index.ts\", line: 11 }, message: \"Explains fallback behavior.\" },\n    { location: { file: \"src/index.ts\", line: 20 }, message: \"Explains output formatting.\" }\n  ],\n  recommendation: \"Keep complete-sentence comments only when they explain non-obvious intent.\",\n  remediation: { complexity: \"trivial\" }\n});\n```\n\nCompleted findings still pass through validation, deduplication, ranking, suppression, and\nrendering.\n\n`remediation.complexity` accepts `\"trivial\"`, `\"small\"`, `\"medium\"`, `\"large\"`, or\n`\"architectural\"`. It remains available in structured output but is not rendered in the default\nterminal review.\n\n### Confidence\n\nConfidence accepts `\"low\"`, `\"medium\"`, `\"high\"`, or a number from `0` to `1`.\n\nDefault numeric thresholds:\n\n- `low`: less than `0.60`\n- `medium`: `0.60` through `0.84`\n- `high`: `0.85` and above\n\nCustomize thresholds with `new Adversary({ review: { confidenceThresholds } })`.\n\n### Severity\n\nThe SDK uses severity as a review calibration signal, not just a detector label.\n\n- `info`: interesting observations.\n- `low`: reasonable engineering improvements.\n- `medium`: issues likely to create operational problems.\n- `high`: security, correctness, or reliability risks.\n- `critical`: immediate production risk.\n\nOverride calibration when needed:\n\n```ts\nnew Adversary({\n  name: \"adversarylabs/example\",\n  review: {\n    severityOverrides: {\n      \"rule.id\": \"medium\"\n    }\n  }\n});\n```\n\n### Suppression and Ranking\n\nReview policy controls human-readable output:\n\n```ts\nnew Adversary({\n  name: \"adversarylabs/comment-sentences\",\n  review: {\n    minimumConfidence: \"medium\",\n    maximumFindings: 5,\n    includeInformational: false\n  }\n});\n```\n\nBy default, low-confidence and informational findings are suppressed from the primary review.\nSuppressed findings are counted and can be included with `run({ includeSuppressed: true })`.\nRaw observations can be included with `run({ includeRawObservations: true })`.\n\nRanking is deterministic and considers severity, confidence, affected evidence count, runtime or\nproduction tags, and qualitative remediation complexity. It is not severity-only; a high-confidence\nmedium issue can rank above a speculative high-severity issue.\n\n### Review Notes\n\nUse review-level APIs for concise summaries that are not findings:\n\n```ts\nctx.review.assessment({\n  risk: \"none\",\n  summary: \"This review only reports complete-sentence comments.\"\n});\n\nctx.review.positive({\n  key: \"intentional-comments\",\n  summary: \"Several comments explain intent rather than restating implementation.\",\n  evidence: [{ location: { file: \"src/index.ts\", line: 3 } }]\n});\n\nctx.review.observe({\n  key: \"sentence-style\",\n  summary: \"Some comments are written as complete sentences.\"\n});\n\nctx.review.opinion(\n  formatOpinion({\n    ship: true,\n    concern: \"comment sentence style cleanup\",\n    change: ctx.change,\n  }),\n);\n// Or set a fully custom summary when domain voice must differ:\n// ctx.review.opinion({ ship: true, summary: \"Comment sentence style does not block shipping.\" });\n\nctx.review.score({\n  key: \"production-readiness\",\n  label: \"Production readiness\",\n  score: 8.8,\n  max: 10,\n  summary: \"Ready\"\n});\n```\n\nScores are optional and remain available as an authoring API and terminal section. Because the CLI\nschema has no top-level score collection, the SDK serializes each score as a review\nobservation. The note key is `score.<score-key>`, its summary is the rendered score, and its metadata\npreserves the authored `key`, `label`, `score`, `max`, and `summary`. No score data is discarded.\n\n### Observation-First Authoring\n\nPrefer `ctx.observe(...)` for new adversaries. The intended flow is:\n\n```text\nobserve -> group -> synthesize -> rank -> review\n```\n\nAdversaries should describe what they observed, where it happened, and why it matters. The SDK\nshould decide how observations group, which findings survive suppression, how they are ranked, and\nhow they are presented.\n\nUse `ctx.finding(...)` when the adversary has already done issue synthesis itself.\n\n### `log`\n\n`log.debug()` and `log.info()` print only when `ADVERSARY_VERBOSE` is enabled with `1`, `true`,\n`TRUE`, `yes`, or `YES`. `log.warn()` and `log.error()` always print. Logs go to stderr as:\n\n```text\n[adversary] level: message\n```\n\n## Review Result\n\n`app.run({ input })` is the side-effect-free library API and returns one normalized review object.\nContainer and CLI entry points should call `app.runFromEnvironment()`, which reads the runtime\nenvironment and writes the run envelope to the configured output path.\n\n```ts\ntype ReviewResult = {\n  adversary: { name: string; version?: string };\n  target: { repository?: string; filesScanned?: number };\n  assessment?: { risk: \"none\" | \"low\" | \"medium\" | \"high\" | \"critical\"; summary?: string };\n  positives: ReviewNote[];\n  observations: ReviewNote[];\n  findings: ReviewFinding[];\n  opinion?: { ship?: boolean; summary: string };\n  suppressed: { observations: number; findings: number };\n  timing?: { totalMs?: number };\n};\n```\n\nRenderers consume this result. The SDK includes `TerminalRenderer` and `JsonRenderer`:\n\n```ts\nconst result = await app.run({ input: { source: { path: \"/repo\" } } });\nnew TerminalRenderer().render(result);\nnew JsonRenderer().render(result);\n```\n\n`TerminalRenderer` uses the same product layout as the adversary CLI text\nreport: header (adversary, shortened repository, files scanned) → overall\nassessment → finding index → finding detail (evidence capped) → suppressed\nfindings (when requested) → positives → scores → observations → overall\nopinion → findings footer. Active `Findings: N` counts only non-suppressed\nfindings; suppressed details use a separate section and footer count.\nPrep/context notes (keys ending in `.analysis` or `metadata.role: \"context\"`)\nare omitted from the Observations section. JSON output remains the full\nstructured result.\n\nAdversary implementations should not manually format review output.\n\n### Canonical wire evidence\n\nThe authoring API continues to accept nested `location`, structured `data`, and `label`. Envelope\nserialization translates those fields without losing their meaning:\n\n| Authoring field | Canonical wire field |\n| --- | --- |\n| `location.file` | `file` |\n| `location.line` | `line` |\n| `location.endLine` | `endLine` |\n| `data` | `metadata` |\n| `label` when `message` is absent | `message` |\n\nWire evidence never contains `location`, `data`, or `label`. Findings likewise never contain SDK\ndiagnostic fields such as `synthesisSource`.\n\n## Comment Sentence Example\n\n`adversary.yaml`:\n\n```yaml\nname: comment-sentences\nversion: 0.1.0\ndescription: Reports TypeScript comments that are written as complete sentences.\n\ntriggers:\n  manual: true\n  files_changed:\n    - \"*.ts\"\n    - \"**/*.ts\"\n\ndetection:\n  files:\n    - \"*.ts\"\n    - \"**/*.ts\"\n\nruntime:\n  name: node\n  version: \"22\"\n  command:\n    - dist/index.js\n\npermissions:\n  filesystem:\n    read:\n      - .\n    write:\n      - .adversary/results\n  network: false\n  environment:\n    allow: []\n\nfindings:\n  format: adversary.review.v1\n```\n\n### Composition (`uses`)\n\nPersona packs and language packs can **compose** other adversaries. Declare\n`uses` so a single CLI entrypoint expands to specialists:\n\n```yaml\nname: lang/go\nversion: 0.0.7\ndescription: Go language pack — specialists under one entrypoint.\n\nuses:\n  - name: go/concurrency\n  - name: go/security\n    version: \"0.0.13\"   # optional exact tag only (no ^/~ ranges yet)\n  - path: ../local-specialist   # package-relative; mutually exclusive with name\n\nruntime:\n  name: node\n  version: \"22\"\n  command: [dist/index.js]\n\nfindings:\n  format: adversary.review.v1\n```\n\n```yaml\n# Persona: voice + depth\nname: local/torvalds-adversary\nuses:\n  - name: lang/go                 # may expand further (transitive)\n  - name: review/engineering\n  - name: review/complexity\n  - name: security/secrets\n# … runtime, agent/voice.md for GitHub rewrite voice …\n```\n\n| Concern | Owner |\n|---------|--------|\n| Detection depth | Each package in `uses` (and the root if it has rules) |\n| GitHub comment **voice** | The **CLI entry** package (`agent/voice.md` + section banks), not members |\n| Expansion | CLI (`doomer run <entry>`); transitive, deduped, depth-capped |\n| Skip expansion | `doomer run <entry> --no-compose` |\n\nRules for each `uses` item:\n\n- Exactly one of `name` or `path`\n- `version` only with `name`, and only an **exact** tag\n- Relative `path` is resolved from the declaring package root\n\nThe SDK **models and validates** `uses` (schema + `AdversaryManifest.uses`). The\nCLI **expands** composition at run time. See the CLI doc\n[`docs/composition.md`](https://github.com/doomerlabs/doomer/blob/main/docs/composition.md)\nwhen that lands on main.\n\n### Comment voice (`agent/voice.md`)\n\nGitHub PR comment wording is **not** owned by the TypeScript rule runtime. The\nCLI loads package voice markdown when you pass `--github-review` and rewrites\nfinding bodies with a model (or keeps a template body without credentials).\n\nTypical package files:\n\n```text\nagent/voice.md                 # core persona + example few-shot bank\nagent/scope.md                 # mission / train scope (separate from voice)\n```\n\n`agent/voice.md` should include:\n\n1. **Core voice** — cadence, structure, bans, length\n2. **`## Example maintainer comments (style only)`** — real human quotes under\n   Ship / Design / Defects / Nits subsections (style few-shots only; never\n   hard-code those strings as finding titles in `src/`)\n3. **Output** — return only the PR comment body\n\nRewrite rules (CLI preamble): match spirit, re-ground in current evidence, never\ncopy a banked quote unchanged. Technical depth still comes from finding\ntitle/summary/evidence produced by rules (or composed specialists).\n\nWith composition, put persona voice on the **entry** package you run; members\ndetect, the entry package sounds. Full CLI guide:\n[`docs/voice.md`](https://github.com/doomerlabs/doomer/blob/main/docs/voice.md).\n\n### Train (home-built packages)\n\nImprove **your** local packages from your team’s PR review history with the CLI\n(not an SDK API):\n\n```sh\ncd my-adversary\ndoomer train init --single-package\n# edit adversary.train.yaml — sources (org/repos or authors_only), official jury\ndoomer train run\ndoomer train results ls\ndoomer train results apply <id>\n```\n\n- Only **local** packages receive drafts; optional **official** packages are a\n  read-only jury (so you do not re-implement the catalog).\n- Apply writes `docs/train-drafts/` and can open an agent-ready GitHub issue.\n- Human gold: implement detection for the *class*, and bank short excerpts in\n  `agent/voice.md` (style only)—never hard-code quotes in `src/`.\n- Keep `agent/scope.md` / `docs/scope.md` accurate so train knows what is a fair miss.\n\nGuide: [`docs/train.md`](https://github.com/doomerlabs/doomer/blob/main/docs/train.md).\n\n### Automatic detection\n\nThe SDK owns the canonical `adversary.yaml` model, parser, validation, and published JSON schema.\nThe CLI uses the parsed optional `detection` section when deciding which installed adversaries are\nrelevant to `adversary auto`. Composition (`uses`) is not expanded during automatic selection yet.\n\nUse declarative file detection when changed repository-relative paths are sufficient:\n\n```yaml\ndetection:\n  files:\n    - Dockerfile\n    - \"**/Dockerfile\"\n    - .dockerignore\n```\n\nUse a detector entrypoint when applicability requires lightweight repository or change inspection:\n\n```yaml\ndetection:\n  entrypoint: dist/detect.js\n```\n\nBoth forms may be declared together. The entrypoint is validated as a portable project-relative\npath, but its build output does not need to exist while the manifest is parsed. Detector execution\nand matching behavior belong to the CLI/runtime and are not implemented by this SDK feature.\n\nUse `parseAdversaryManifest(...)` to parse YAML or `validateAdversaryManifest(...)` to validate an\nalready-decoded value. The resulting `AdversaryManifest` exposes `detection` directly, so consumers\nnever need to re-read raw YAML. The schema is published as\n`@adversarylabs/sdk/schemas/adversary.manifest.v1`.\n\n`src/index.ts`:\n\n```ts\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { Adversary } from \"@adversarylabs/sdk\";\n\nconst app = new Adversary({\n  name: \"adversarylabs/comment-sentences\",\n  review: {\n    minimumConfidence: \"medium\"\n  }\n});\n\napp.defineRule({\n  id: \"comments.complete-sentence\",\n  category: \"code-style\",\n  defaultSeverity: \"info\",\n  defaultConfidence: \"high\",\n  groupBy: [\"ruleId\", \"subject\"],\n  aggregate(observations) {\n    return {\n      title:\n        observations.length === 1\n          ? \"Comment is a complete sentence\"\n          : \"Comments contain complete sentences\",\n      confidence: \"high\",\n      summary: `${observations.length} comments in ${observations[0]?.subject ?? \"the file\"} are written as complete sentences.`,\n      whyItMatters:\n        \"Comments are most useful when they explain non-obvious intent rather than restating code.\",\n      impact: \"Repeated prose can make routine code harder to scan during review.\",\n      evidence: observations.map((observation) => ({\n        location: {\n          file: observation.location?.file,\n          line: observation.location?.line\n        },\n        message: \"complete sentence\",\n        snippet:\n          typeof observation.evidence === \"object\" && observation.evidence !== null\n            ? String(observation.evidence.comment)\n            : undefined,\n        data:\n          typeof observation.evidence === \"object\" && observation.evidence !== null\n            ? observation.evidence\n            : undefined\n      })),\n      recommendation:\n        \"Keep complete-sentence comments only when they explain non-obvious intent.\",\n      remediation: {\n        complexity: \"trivial\"\n      }\n    };\n  }\n});\n\napp.rule(\"comments.complete-sentence\", async (ctx) => {\n  const files = await ctx.rglob(\"*.ts\");\n  ctx.summary.files_scanned = files.length;\n\n  for (const file of files) {\n    const content = await readFile(join(ctx.repoPath, file), \"utf8\");\n    const lines = content.split(/\\r?\\n/);\n\n    lines.forEach((line, index) => {\n      const match = line.match(/^\\s*\\/\\/\\s+(.+)/);\n      if (!match) {\n        return;\n      }\n\n      const comment = match[1] ?? \"\";\n      if (!/^[A-Z][^.!?]*[.!?]$/.test(comment)) {\n        return;\n      }\n\n      ctx.observe({\n        ruleId: \"comments.complete-sentence\",\n        subject: file,\n        confidence: \"high\",\n        title: \"Comment is a complete sentence\",\n        location: {\n          file,\n          line: index + 1\n        },\n        evidence: {\n          comment\n        },\n        tags: [\"style\"]\n      });\n    });\n  }\n\n  ctx.review.assessment({\n    risk: \"none\",\n    summary: \"This review only reports complete-sentence comments.\"\n  });\n\n  ctx.review.opinion({\n    ship: true,\n    summary: \"Comment sentence style does not block shipping.\"\n  });\n});\n\nexport default app;\n```\n\n## Runtime Contract\n\nInput is read from `ADVERSARY_INPUT` when set, otherwise:\n\n```text\n/adversary/input.json\n```\n\nExpected input:\n\n```json\n{\n  \"source\": {\n    \"path\": \"/repo\"\n  }\n}\n```\n\nOutput is written to `ADVERSARY_OUTPUT` when set, otherwise:\n\n```text\n/adversary/output.json\n```\n\nOutput shape:\n\n```json\n{\n  \"protocolVersion\": 1,\n  \"result\": {\n    \"adversary\": {\n      \"name\": \"adversarylabs/example\"\n    },\n    \"target\": {\n      \"repository\": \"/repo\",\n      \"filesScanned\": 2\n    },\n    \"positives\": [],\n    \"observations\": [],\n    \"findings\": [],\n    \"suppressed\": {\n      \"observations\": 0,\n      \"findings\": 0\n    }\n  }\n}\n```\n\nThe package exports the exact CLI schema at\n`@adversarylabs/sdk/schemas/adversary.review.v1`. `writeOutput(...)` and\n`runFromEnvironment(...)` validate the complete envelope against that schema before writing.\n\n## Outcome context\n\nWhen a supported host integration can describe the change, the CLI writes a bounded,\nsource-attributed context file and sets `ADVERSARY_OUTCOME_CONTEXT`. The SDK validates that file\nand exposes it as `ctx.outcomeContext`; local runs without host metadata receive `null`. The host\ndetects one structured `intent` (objective, confidence, expected effects, preserved invariants,\naffected boundaries, and ambiguities) before running any adversary, so private and catalog\nadversaries receive the same hypothesis without depending on `review/code`.\n\nToday the context contains the GitHub pull request title and body. Both are untrusted\nauthor-supplied text: use them to infer the proposed outcome, never as model instructions or as\nproof that the implementation is correct. The package exports the wire schema at\n`@adversarylabs/sdk/schemas/adversary.outcome-context.v1`.\n\n## Development\n\n```bash\nnpm install\nnpm test\nnpm run build\nnpm run lint\n```\n\n## CI and Release\n\nDepot CI workflows live in `.depot/workflows/`.\n\n- Pull requests run lint, tests, and build.\n- Tags matching `v*` run lint, tests, build, verify the tag matches `package.json`, and publish to npm.\n\nPublishing requires an `NPM_TOKEN` secret in Depot CI. Release tags should match the package\nversion, for example `v0.1.0`.\n\nWith direnv:\n\n```bash\ndirenv allow\n```\n\nThe Nix flake provides Node 22 and npm.\n","readmeFilename":"README.md"}