{"_id":"@desurfofficial-ship-it/desurf","_rev":"15-681e5702ab341ce102288f37582ca321","name":"@desurfofficial-ship-it/desurf","dist-tags":{"latest":"1.0.1"},"versions":{"0.1.1":{"name":"@desurfofficial-ship-it/desurf","version":"0.1.1","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.1.1","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"96fc33c23b42d6e9392a1977ba3466eb8e646d07","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.1.1.tgz","fileCount":27,"integrity":"sha512-Gs4qbCpHASIjkrdPEPLB3geEVlWVxzw6FRCTS9e5PGBdFOVaH6D02I2TEBM4jxUAQ18+yOa39WKGar0knFTDtw==","signatures":[{"sig":"MEQCIBEHaFa6Bn9d+WCLaJNntu7lp9tMLyaNopgEejDpFTasAiAApbcs/CzP+q1hpoM0shdFq+KbAPXZn6oJVf5TmeRqew==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":48939},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"3a7f3414e7d86198e45df01176203eb13407b80a","scripts":{"test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"desurf","email":"desurf.official@gmail.com"},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.9.0","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.1.1_1787715291233_0.5321517181081641","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@desurfofficial-ship-it/desurf","version":"0.1.2","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.1.2","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"0a70cdde7d80beca64d26495be36fcefb3393ca9","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.1.2.tgz","fileCount":32,"integrity":"sha512-0O2lqstovOEL3y2FiFSqAYuFrMEgZu3e2shC4rTs+YXhxg3y7TUc+uzKTQUWyNM5zGWR6obHdtaSyhl1heEEDA==","signatures":[{"sig":"MEYCIQC61GWm8wY2tD7bo5D5bar5OctFcmuQlPfRduKlarvUkwIhAIuSrsroqh1+R4iGerbS3n8rnZ+LRRseqzSRoV/GW3+z","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":70378},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"66398888e9e96ce2606bd2ca391c0a9a2a9a0ca2","scripts":{"test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"desurf","email":"desurf.official@gmail.com"},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.9.0","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.1.2_1787814698727_0.909851265371699","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@desurfofficial-ship-it/desurf","version":"0.1.3","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.1.3","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"a7d21c53c0e750daa8376a19b96a249fb6a16f69","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.1.3.tgz","fileCount":32,"integrity":"sha512-ymxYfvwiX/mVvrfJPMphzW3AZUpb56FC0DkBp9iupzbRAcxFm80RQGWj8otv/9R1N4SJ6HmQ0dk0UYILy1hiTg==","signatures":[{"sig":"MEUCIQCTAYVJVSGWr+yTiL/xF3oc4mxCQPoXBfRShGDhcFq1fwIgRrP/rosX1N9WT5oLtEo0QaAQzM4zXr0qxMeZI5OwUY8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":70378},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"2e2f3bd630d39fe07fc9152ce39b29fdcaaec1f8","scripts":{"test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"desurf","email":"desurf.official@gmail.com"},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.9.0","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.1.3_1787890788394_0.9911623583211508","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@desurfofficial-ship-it/desurf","version":"0.2.0","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.2.0","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"3543a87b3297555d96a6f4cc025329937865fad2","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.2.0.tgz","fileCount":29,"integrity":"sha512-pi7F5BYprp7xlt0lJPZazx7r8QEDKoCnY03DIy2tv3EdEbCXGcLMs0M65WhvRCYoyl9lurLKRPrNmpxPJhDd2Q==","signatures":[{"sig":"MEYCIQCsQGrbscVAaYdP3DprI3+MRGy7QmvBJVfUP351nTT85gIhAKXZA0bcA32cKwrgGR4GD+HVLL94VwgDxuUAyVZ19yDC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":57542},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"f492fd25dcc70a39278f04eb6c57bde8a73b20c2","scripts":{"test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"desurf","email":"desurf.official@gmail.com"},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.12.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.2.0_1787964877628_0.7654579879409633","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@desurfofficial-ship-it/desurf","version":"0.3.0","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.3.0","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"022cee5130df40de3b47a201266ead181b8bf6a0","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.3.0.tgz","fileCount":31,"integrity":"sha512-MmxFq8SBGl0aqU8mmegcNrKA0X0sRmyp+qs05hx+WO1HZY/hNulPGeW3HCCq3xwdfwwYYDmxk4+YxMvvMDSyHA==","signatures":[{"sig":"MEUCIQCTZjvxS827fMbXnvUtj0VNfWaBMocxf+GH0DiwY7tvcQIgFuABTkWD8aMuG/DqEs0Ed2znB2CRNcCL5Ozc/o/bdb8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@desurfofficial-ship-it%2fdesurf@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":64261},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"1fcc5fe61df6905fbe685ad8e717222fd9a96c64","scripts":{"dev":"tsx server.ts","test":"vitest run","build":"tsc","start":"node server.ts","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a6908317-86cd-4614-8433-3bc866e8300e"}},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.19.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.19.0","dependencies":{"express":"^5.2.1","@types/express":"^5.0.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.3.0_1788055635795_0.34377356808651793","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@desurfofficial-ship-it/desurf","version":"0.4.0","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.4.0","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"1efcd982f43edea4c0ce5056f8a07b33d68c8ac6","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.4.0.tgz","fileCount":33,"integrity":"sha512-AUcnW0b4scQckzEgx3kRaNyaaho7wSzQSw825dr/bf0/8m6qWSvZSE9udzQe+HByb009i9fcfuZ4M2zpgRrjhA==","signatures":[{"sig":"MEYCIQCVtMB2scmI+KUYaBXHzC+0IvevvxliDKE+WXl8TwaiOgIhAK1EcZkQ2nnax0ViKh23MOp+sOVV6YXP7Uk/LIvXNhOj","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@desurfofficial-ship-it%2fdesurf@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":80645},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"00fea21c6e98b21cd9656aa8a1c1ae2396d98478","scripts":{"dev":"tsx server.ts","test":"vitest run","build":"tsc","start":"node server.ts","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a6908317-86cd-4614-8433-3bc866e8300e"}},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.19.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.19.0","dependencies":{"express":"^5.2.1","@types/express":"^5.0.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.4.0_1788078014233_0.17234420949970475","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@desurfofficial-ship-it/desurf","version":"0.4.1","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.4.1","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"88b087371ff4378be40d8bb173a9d744783e149f","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.4.1.tgz","fileCount":45,"integrity":"sha512-DwgvPCJzpIVPnFiR+sW6PwGnnkJOyyu7NMhyyJSQzGRG/JKtZiI0VHidtLaKMTfEwWCMLBTp2JcpesfkEXWRGQ==","signatures":[{"sig":"MEUCIFZYcRRPsJUo0oD5qfJHuuDGscaBYfCDyDu9u2Nkl+xOAiEAkfgJBSCVRBfGa98bf/+4Rlg/4U3AB3vXS1SpMinXemU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@desurfofficial-ship-it%2fdesurf@0.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":162914},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"552d4c187aa42f3a53b1c3060fba8015cef1a76c","scripts":{"dev":"tsx server.ts","lint":"tsc --noEmit","test":"vitest run","build":"tsc","start":"node server.ts","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a6908317-86cd-4614-8433-3bc866e8300e"}},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.19.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.19.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","express":"^5.2.1","typescript":"^5.7.2","@types/node":"^22.10.0","@types/express":"^5.0.6"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.4.1_1788139801189_0.8389790264529804","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@desurfofficial-ship-it/desurf","version":"0.4.2","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.4.2","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"f24629743a86ee69dab806d1eeb494855715f032","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.4.2.tgz","fileCount":49,"integrity":"sha512-nMdxVsgX7GvllkhAYxOgSMlNgKrWBXXy0XdLRkweXNFQAPVkvhBqPoL4qg5FtWyftrmcYs+hG6Ao6F567NJJCg==","signatures":[{"sig":"MEYCIQCnAbYWspwQDynf1TQaGJl+5Iev4YrKOpjvoXByrC0TkgIhAPcL/9tNYV+E/U9dZXAeI76dC9qqYiIkcvo4TpjOdGwk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@desurfofficial-ship-it%2fdesurf@0.4.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":193554},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"838ea2129bdf79774f60cde675c7b27e4ad2bd70","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a6908317-86cd-4614-8433-3bc866e8300e"}},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.19.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.19.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.4.2_1788150836800_0.7037892448986371","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"@desurfofficial-ship-it/desurf","version":"0.4.3","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.4.3","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"2cbd6e987a4769a18452c7e17c58a6bea1a02397","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.4.3.tgz","fileCount":49,"integrity":"sha512-Ig4Om8lSKSU1AOKZKWkX9bkuR9aT0MArFUwwMkfMyeZhEhpVlTzCF9hK+S+Oyy1AcTV6IgA/dBVpz5iZShysiA==","signatures":[{"sig":"MEUCIQDrA+2TvsXbi/Fl2UIyLFE1TphMT5jECWWOsv7MEBlj3gIgSljdcXMsNx0N9YhU9mPGuriVWdg+KfSOOLVbchxY5iY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@desurfofficial-ship-it%2fdesurf@0.4.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":206423},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"f323dd34df134a376039036adfd538f9abd5f078","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a6908317-86cd-4614-8433-3bc866e8300e"}},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.19.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.19.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.4.3_1788166370403_0.9156421834157014","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"@desurfofficial-ship-it/desurf","version":"0.6.0","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.6.0","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"ac8c47676204509e2d13c9ba75694a5fef5ce782","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.6.0.tgz","fileCount":51,"integrity":"sha512-Rgyj1r+2hQHCmP7aA7UfStvOo+sSTuYp72ggMb5xRDEZT9ms3aQipTAjYHyIXPlpFzdG9bR9BY0A1ZUsMdfXVA==","signatures":[{"sig":"MEUCIQCuIh9YEHhgt3Bqkqb+MOjSB+5vTIeivIfqzj/A/32r9AIgVGN0sBkX2eM7CX+mxwIM8TjCqRXY5TBCOjO9hTENt4k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":247330},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"9802d71ac48888906bcebfff44322f32dd58845e","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"desurf","email":"desurf.official@gmail.com"},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.12.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.15.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.6.0_1788252579867_0.3770381731820047","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"@desurfofficial-ship-it/desurf","version":"0.7.0","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.7.0","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"1763b60952f01ff7f3275de014da46c098af5038","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.7.0.tgz","fileCount":51,"integrity":"sha512-jdZNc+aFSZiGedX4Z4MznP+3y+xLHT7mBVZcu+uFflcnFiqdWtplzqWrGeCLkgJjFUn5Gicr8MG9lRjGmiW5Tw==","signatures":[{"sig":"MEQCIGCmZ4yqzDLEZo7WT6uJYJeUN9sHYl9xCeHCi7D+/a/GAiAwuOZcLl1QOIvQvlQ0VPlwpRS9nVaJDbp6EKPv2ZyZnQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":265041},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"1d05517f570035c0a5e6e704cf5f2ad99c375130","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"desurf","email":"desurf.official@gmail.com"},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.12.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.15.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.7.0_1788260239825_0.48235070224943755","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"@desurfofficial-ship-it/desurf","version":"0.8.0","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.8.0","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"6614b25b24a9fa1be224df45bc4c04ca4cfb5451","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.8.0.tgz","fileCount":51,"integrity":"sha512-DC1lZjcUgI3TxXBVAz0rbXhYJXNZ1YwMeX8+1WxySY74/BoexF3wwmKAPxjArfuLMj4Hsz9E5m6LmYdX3DJzHw==","signatures":[{"sig":"MEYCIQC4TmcpinBxYdMSUJh2xhGFMyEweU/BMU0DUdyiuFf9OAIhAKfzqTkS8w6CAgGugakbZWr5ax2K0vJ3bkrOAc3orF3E","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":280561},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"e6a21481cbb274c621419620ad16e66b17d2ca12","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"desurf","email":"desurf.official@gmail.com"},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.12.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.15.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.8.0_1788271769821_0.43686110801828715","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"@desurfofficial-ship-it/desurf","version":"0.9.0","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@0.9.0","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"878769ce0f0c2eff4654914e965a9e6deed34283","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-0.9.0.tgz","fileCount":51,"integrity":"sha512-n/MMfhLWEeC3Rl/QiUVUq+4UL0cK9YGN8fr/Sv7sD/IMa6141m9Zgu8CJa2jo6SxKbDMds+Hs1PJ1Ez4ZMPD5w==","signatures":[{"sig":"MEYCIQDIm7htmS1M2pUT1wz+L7EReetwnG4lGtRKo37wY/vGJwIhAJSzT71aXLWzXz+kNCCh/XuVRDfFKCm36jBsEjqs+2AN","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@desurfofficial-ship-it%2fdesurf@0.9.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":284401},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"3c2a2accec79b7824305d2573ff1a28f014a2d1f","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a6908317-86cd-4614-8433-3bc866e8300e"}},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.19.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.19.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_0.9.0_1788342846127_0.5529761352180813","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@desurfofficial-ship-it/desurf","version":"1.0.0","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","_id":"@desurfofficial-ship-it/desurf@1.0.0","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"bin":{"desurf":"dist/cli.js"},"dist":{"shasum":"576ed07ea4bdd793f5d37de2a5048022e5531db1","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-1.0.0.tgz","fileCount":51,"integrity":"sha512-q8C2n+XPwplYU/pm6AsJAzX+3ItUJ4y3TcuDlGXanh7yUDWa0dGO6uKn74PUKJCNviKL7o9dNwNiROWN+o2BEw==","signatures":[{"sig":"MEQCIBQ5Vyj9hhMyJ5s7PpTPOlRJYHYAW/5dy9JObZhh1i7YAiBiq6DuA+T7UhnqmOgmB+x5F9H7vrjx1dpa7OW+tuROsA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@desurfofficial-ship-it%2fdesurf@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":284401},"main":"./dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"1211a5aec06f5c5dac78cf2196a5c36c50f19e5f","scripts":{"lint":"tsc --noEmit","test":"vitest run","build":"tsc","desurf":"tsx src/cli.ts","test:ci":"node dist/cli.js test --suite fixtures/basic","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:watch":"vitest","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a6908317-86cd-4614-8433-3bc866e8300e"}},"repository":{"url":"git+https://github.com/desurfofficial-ship-it/Desurf.git","type":"git"},"_npmVersion":"11.19.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","directories":{},"_nodeVersion":"24.19.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.19.2","vitest":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.0"},"_npmOperationalInternal":{"tmp":"tmp/desurf_1.0.0_1788352321530_0.7211913918977071","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@desurfofficial-ship-it/desurf","version":"1.0.1","description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","type":"module","main":"./dist/cli.js","bin":{"desurf":"dist/cli.js"},"scripts":{"build":"tsc","prepublishOnly":"npm run build","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","lint":"tsc --noEmit","desurf":"tsx src/cli.ts","test:offline":"tsx src/cli.ts test --suite fixtures/basic --repeat 3","test:ci":"node dist/cli.js test --suite fixtures/basic","pack:check":"npm pack --dry-run"},"engines":{"node":">=18"},"keywords":["llm","prompt","testing","regression","cli","offline","ai"],"author":{"name":"Desurf"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/desurfofficial-ship-it/Desurf.git"},"bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","publishConfig":{"access":"public"},"devDependencies":{"@types/node":"^22.10.0","tsx":"^4.19.2","typescript":"^5.7.2","vitest":"^2.1.8"},"dependencies":{},"gitHead":"fd063d66b4e5195873876d8d6dd909507117547f","types":"./dist/cli.d.ts","_id":"@desurfofficial-ship-it/desurf@1.0.1","_nodeVersion":"24.20.0","_npmVersion":"11.19.1","dist":{"integrity":"sha512-frQ4NBpWldVsbpJ6Am4pm9nC4tt5yzsDPf5KMJj9ApaR994mnpqCrm4ASDKUBdhc0E2ouXl7ab1+wgcuBt+gDQ==","shasum":"a81652c8e0463c06f36741985659dcb32d71b07a","tarball":"https://registry.npmjs.org/@desurfofficial-ship-it/desurf/-/desurf-1.0.1.tgz","fileCount":51,"unpackedSize":285264,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@desurfofficial-ship-it%2fdesurf@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCVPu/KYIaptvE6RkwSP96AVHm1cKJMW3qL+kTp4rZelwIhAPWn/J5mH7vmoeQLZCaEWYpWRqgGh65f2PXBuudZ85wD"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:a6908317-86cd-4614-8433-3bc866e8300e"}},"directories":{},"maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/desurf_1.0.1_1788427410063_0.5741727862750592"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-26T03:34:51.031Z","modified":"2026-09-03T09:23:30.762Z","0.1.1":"2026-08-26T03:34:51.368Z","0.1.2":"2026-08-27T07:11:38.857Z","0.1.3":"2026-08-28T04:19:48.541Z","0.2.0":"2026-08-29T00:54:37.776Z","0.3.0":"2026-08-30T02:07:15.910Z","0.4.0":"2026-08-30T08:20:14.363Z","0.4.1":"2026-08-31T01:30:01.334Z","0.4.2":"2026-08-31T04:33:56.929Z","0.4.3":"2026-08-31T08:52:50.534Z","0.6.0":"2026-09-01T08:49:40.028Z","0.7.0":"2026-09-01T10:57:19.985Z","0.8.0":"2026-09-01T14:09:29.982Z","0.9.0":"2026-09-02T09:54:06.286Z","1.0.0":"2026-09-02T12:32:01.857Z","1.0.1":"2026-09-03T09:23:30.223Z"},"bugs":{"url":"https://github.com/desurfofficial-ship-it/Desurf/issues"},"author":{"name":"Desurf"},"license":"MIT","homepage":"https://github.com/desurfofficial-ship-it/Desurf#readme","keywords":["llm","prompt","testing","regression","cli","offline","ai"],"repository":{"type":"git","url":"git+https://github.com/desurfofficial-ship-it/Desurf.git"},"description":"Offline-first CLI for testing AI prompt behavior and detecting regressions","maintainers":[{"name":"desurf","email":"desurf.official@gmail.com"}],"readme":"# Desurf\n\n**Offline-first CLI for testing AI prompt behavior and detecting regressions.**\n\n![CI](https://github.com/desurfofficial-ship-it/Desurf/actions/workflows/ci.yml/badge.svg)\n\nVersion **1.0.0**\n\nDesurf lets developers define expected AI behavior as testable contracts and detect behavioral regressions when model outputs change.\n\n## Install\n\n```bash\nnpm install -g @desurfofficial-ship-it/desurf\n```\n\nOr without a global install:\n\n```bash\nnpx @desurfofficial-ship-it/desurf --version\n```\n\nThe published package name is **`@desurfofficial-ship-it/desurf`**. The CLI binary is still `desurf`.\n\n## Quickstart\n\n```bash\ndesurf init ./my-suite\ndesurf test --suite ./my-suite\ndesurf --version   # 1.0.0\n```\n\n`desurf init` scaffolds a **sealed** example suite (output + `.desurf` provenance) so the first `desurf test` is fully offline and protected against prompt/input drift.\n\n## Cassette states\n\nEvery test case has an output cassette. That cassette is in one of three states:\n\n| State | What exists on disk | Assertions | Prompt/input drift detection |\n|-------|---------------------|------------|------------------------------|\n| **UNSEALED** | output only (no `.desurf`) | run normally | **not** detected (legacy-compatible) |\n| **SEALED** | output + `.desurf` from `desurf seal` | run normally | detected → **ERROR (exit 2)** |\n| **RECORDED** | output + `.desurf` from `desurf record` | run normally | detected → **WARNING** (soft; run stays green unless assertions fail) |\n\n- **UNSEALED** — useful for quick experiments or v0.2/v0.3 suites that never adopted provenance. Safe to keep; you simply will not catch stale fixtures.\n- **SEALED** — you already have a trusted response file (from a prior model run, a hand-authored golden file, or a teammate). `desurf seal` fingerprints the current input and prompt **locally**. No API key, no network.\n- **RECORDED** — you want a fresh capture from a live provider. `desurf record` writes the output and the provenance metadata together.\n\n`seal` and `record` produce the same `.desurf` shape. The difference is only how the output was obtained.\n\n\n## v0.5.0 — Safe recording workflow\n\n`desurf record` proposes (new/unchanged/drift) without mutating baselines.\nReview with `desurf diff` / `desurf history`, promote with `desurf accept --yes`.\nLegacy: `--fill-gaps` (old plain record), `--force` (overwrite + baseline-backup).\nAdd `.desurf-history/` to `.gitignore` if desired.\n\n## Recommended workflow\n\n**You already have a response file:**\n\n```bash\ndesurf seal --suite ./my-suite\ndesurf test --suite ./my-suite\n```\n\n**You want a live model capture:**\n\n```bash\n# OpenRouter\nexport OPENROUTER_API_KEY=...\ndesurf record --suite ./my-suite --provider openrouter\n\n# OpenAI\nexport OPENAI_API_KEY=...\ndesurf record --suite ./my-suite --provider openai --model gpt-4o-mini\n\n# Anthropic\nexport ANTHROPIC_API_KEY=...\ndesurf record --suite ./my-suite --provider anthropic --model claude-3-5-haiku-20241022\n\n# Google Gemini\nexport GEMINI_API_KEY=...\ndesurf record --suite ./my-suite --provider gemini --model gemini-2.0-flash\n\n# Deterministic offline gate\ndesurf test --suite ./my-suite\n```\n\n**After changing a prompt or input** (sealed/recorded suite):\n\n1. `desurf test` behaves differently depending on the cassette origin:\n   - **Sealed cassette**: fails with **ERROR (exit 2)** — the prompt/input no longer matches the cassette fingerprints, so Desurf refuses to treat the result as a contract verdict.\n   - **Recorded cassette**: reports a **WARNING** and still evaluates the current assertions against the drifted baseline, showing a saved-vs-evaluated diff. The run stays green (exit 0) unless the assertions themselves fail. This keeps the iterate → re-record loop from crying wolf on every intentional prompt edit.\n2. Choose an explicit remediation (Desurf never auto-repairs):\n   - **Keep the existing output** and re-fingerprint current prompt/input (offline, no API key):\n     `desurf seal --suite ./my-suite --force`\n   - **Obtain a new provider output** and provenance:\n     `desurf record --suite ./my-suite --provider <name> --force`\n   - Or restore the previous prompt/input files.\n\n### Why exit 2 vs exit 1?\n\n| Exit | Meaning | Typical cause |\n|------|---------|----------------|\n| **0** | PASS | Contract held |\n| **1** | REGRESSION / FLAKY | Output was evaluated; assertions failed (behavior changed) |\n| **2** | ERROR | Could not trust or evaluate the cassette (stale sealed provenance, missing files, bad config, provider failure) |\n\nStale **sealed** prompt/input is **not** a regression: the saved output no longer corresponds to the files under test, so Desurf refuses to treat the result as a contract verdict. Stale **recorded** prompt/input is a soft **WARNING** (the cassette was live-captured and is expected to be refreshed) — the run stays green unless assertions fail.\n\n## How offline testing works\n\nOffline mode **evaluates saved output cassettes**. It does **not** execute the prompt against a live model.\n\n```\nprompt + input\n      ↓\n[desurf record (live provider)]  OR  [existing response + desurf seal (offline)]\n      ↓\nfingerprinted cassette (.desurf sidecar with SHA-256 hashes)\n      ↓\ndesurf test (offline) ← evaluates behavioral contract deterministically\n```\n\n### Establishing Cassette Provenance\n\n- **`desurf record`**: Obtains a response from a supported live provider (e.g. OpenRouter) and creates the fingerprinted `.desurf` metadata in the same step.\n- **`desurf seal`**: Takes an existing output file on disk and writes `.desurf` from the current input and prompt files. Purely offline (no API keys, no network).\n- **`.desurf` sidecar**: Stores `inputSha256` / `promptSha256` next to each cassette. If those files change without updating the cassette, `desurf test` fails with **ERROR (exit 2)**.\n- **Legacy / unsealed suites**: Missing `.desurf` files remain supported. Assertions still run; stale-fixture protection is simply off until you seal.\n\n`desurf seal` safety rules:\n\n- Requires a non-empty output file per case (missing or empty → error).\n- Does **not** overwrite existing `.desurf` metadata unless `--force` is set.\n- Supports suite directory or direct `suite.json` path, and `--case <id>` to seal one case.\n\n## Commands\n\n- `desurf test --suite <path> [--verbose] [--json] [--repeat N] [--provider offline|openrouter|openai|anthropic|gemini] [--model id]`\n- `desurf init <directory>` — scaffold a runnable structured-output example suite (refuses overwrite)\n- `desurf record --suite <path> --provider <name> [--model id] [--force] [--case id]` — capture live provider outputs\n- `desurf seal --suite <path> [--force] [--case id]` — establish offline provenance from existing output files\n- `desurf inspect --suite <path> [--json] [--case id]` — inspect cassette provenance status (read-only)\n- `desurf watch --suite <path> [--repeat N] [--provider <name>]` — re-run the suite whenever its files change\n\nExit codes: **0** PASS · **1** REGRESSION/FLAKY · **2** ERROR\n\n## Assertions\n\n`required`, `forbidden` (optional `caseSensitive: false`), `regex`, `json_schema`, `max_diff_lines`, `json_path` (minimal: `type`, `required`, `properties.*.const`, `properties.*.enum` against **parsed** JSON).\n\nUnknown assertion fields are rejected (exit 2).\n\n## CI (GitHub Actions)\n\nDesurf is designed for offline CI gating. Exit codes fail the job automatically:\n\n| Exit | Meaning | CI result |\n|------|---------|-----------|\n| 0 | PASS | green |\n| 1 | REGRESSION / FLAKY | red |\n| 2 | ERROR (config, missing files, stale fixture, …) | red |\n\n### Reusable Action (recommended for app repos)\n\n```yaml\n- uses: actions/checkout@v4\n- uses: desurfofficial-ship-it/Desurf@main   # or a full commit SHA; do not invent tags\n  with:\n    suite: ./desurf-suite\n    version: \"1.0.0\"   # npm package pin (never \"latest\")\n```\n\n**Pins are independent:**\n- **Action ref** (`uses: ...@ref`) selects the Action definition (composite steps in this repository). Prefer a full **commit SHA** for production supply-chain pinning. `@main` tracks development and can change at any time. A stable **`v0.4` Action tag** is planned for the v0.4 release and is **not** created until that release is cut—do not invent tags that do not exist yet.\n- **`version`** selects the published **`@desurfofficial-ship-it/desurf`** npm package the Action installs (default `1.0.0`). It does **not** run the Action checkout's source tree.\n\n**Network vs offline:** npm install needs network once. The Desurf **test** gate is offline (no live provider, no `OPENROUTER_API_KEY`, no record).\n\n**Stale cassettes:** sealed prompt/input drift → exit **2**. Recorded prompt/input drift → soft **WARNING** (run stays green unless assertions fail). Refresh offline with `desurf seal --force` (keeps output) or re-capture with `desurf record --force`.\n\n- Propagates exit codes **0 / 1 / 2**.\n- Installs into a temporary directory (does not modify consumer `package.json` / lockfile / `node_modules`).\n- See [`action.yml`](action.yml) and [`examples/github-actions/desurf.yml`](examples/github-actions/desurf.yml).\n\n### This repository (source build)\n\n```bash\nnpm install\nnpm run build\nnode dist/cli.js test --suite fixtures/basic\n```\n\n**Alternative (inline CLI):** copy [`examples/github-actions/desurf.yml`](examples/github-actions/desurf.yml) or run:\n\n```yaml\n- run: npx --yes @desurfofficial-ship-it/desurf test --suite ./desurf-suite\n```\n\nNever set `OPENROUTER_API_KEY` in the merge gate. Live providers are optional and manual only.\n\n## Docs\n\nSee `docs/cli-contract.md`, `docs/test-case-schema.md`, `docs/architecture.md`.\n\n## License\n\nMIT\n\n## Drift-watch (v0.6.0)\n\nScheduled live monitoring that opens GitHub issues on sustained REGRESSION. See [docs/drift-watch.md](docs/drift-watch.md) and `examples/github-actions/desurf-drift-watch.yml`.\n\n\n## Multi-turn conversations (v0.7.0)\n\nTest conversational flows with an ordered list of user turns. The model answers each turn with full prior context; the cassette is a JSON transcript.\n\n```json\n{\n  \"id\": \"support-chat\",\n  \"prompt\": \"prompts/agent.txt\",\n  \"output\": \"outputs/chat.json\",\n  \"turns\": [\n    { \"user\": \"inputs/turn0.txt\", \"assertions\": [{ \"type\": \"required\", \"value\": \"hello\" }] },\n    { \"user\": \"inputs/turn1.txt\" }\n  ],\n  \"assertions\": [{ \"type\": \"required\", \"value\": \"resolved\" }]\n}\n```\n\nSee `docs/cli-contract.md` for full semantics.\n\n\nCurrent stable release: **1.0.1**.\n","readmeFilename":"README.md"}