{"_id":"@curly-message/conformance","_rev":"14-a20d7322b3350d6edf1b83eb39ef9087","name":"@curly-message/conformance","dist-tags":{"next":"1.0.0-next.2","latest":"4.0.1"},"versions":{"1.0.0-next.0":{"name":"@curly-message/conformance","version":"1.0.0-next.0","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@1.0.0-next.0","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://github.com/curly-message/spec/tree/main/conformance#readme","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"4a3952e70fb338b8c1781f33dc620e70b4817db7","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-1.0.0-next.0.tgz","fileCount":25,"integrity":"sha512-dN7VJnn4mYkcFMmvNmDYU5f05mf0iv2+ZDWUO2imrxta1gY6qwMOJLMGOtLie4zOwLnGstGy86EGRqaO2XJywg==","signatures":[{"sig":"MEQCIEP0h8kpejI1tNzUaoSmbG0M+Jo1Wc2NGYXDRooEY2o+AiAD2X2k1Ie2k+YwDK54DFNOLEAo4zmqxzUyXbt4rERUXQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":330756},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"},"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.15.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"22.20.0","_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_1.0.0-next.0_1788960794073_0.9791240312577536","host":"s3://npm-registry-packages-npm-production"}},"1.0.0-next.1":{"name":"@curly-message/conformance","version":"1.0.0-next.1","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@1.0.0-next.1","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://github.com/curly-message/spec/tree/main/conformance#readme","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"840dc9b29673a8ac4572c29cefe1d3175fa17d00","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-1.0.0-next.1.tgz","fileCount":25,"integrity":"sha512-2lZLfdjDYKLMlpESN1EfUjD7B8yj7SojCJdFIMzBO+k9O3IbjVjvW/+Ne4guERox2ElxOl+gS9SeDSPnoRs9Gw==","signatures":[{"sig":"MEUCIBfnoLIUt4l9Sdb2P60RP3E/AQTmTTlPOOLLj5KqVsaeAiEA049nyB7wT+6NfD3haJBPWhgBkryJNl+sAUt6WlU8sSs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@1.0.0-next.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":330756},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_1.0.0-next.1_1788961316450_0.08484189820557564","host":"s3://npm-registry-packages-npm-production"}},"1.0.0-next.2":{"name":"@curly-message/conformance","version":"1.0.0-next.2","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@1.0.0-next.2","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://github.com/curly-message/spec/tree/main/conformance#readme","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"ea3278aab9a987a93ce1f77dff03a4b147df1d8b","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-1.0.0-next.2.tgz","fileCount":25,"integrity":"sha512-lWwbT5G2U5k8g8OEVRxXZxxSmB/Cvq6d5HGhEvwjC7+dDXcb2kMGDPYd4j3qC2Q95k/tt/yot9UFI6lDENtmDg==","signatures":[{"sig":"MEQCIAHHFaSpPJq8rXEOtFPNHb9A6PBagTthcHZsE95GBCY9AiASGxA4XiM66DOZmkmFvWXts+vI0u2CanFsdwGpV62jcQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@1.0.0-next.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":330817},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","version":"npm run manifest","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_1.0.0-next.2_1788963940973_0.7219523502415366","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@curly-message/conformance","version":"1.0.0","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@1.0.0","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://github.com/curly-message/spec/tree/main/conformance#readme","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"dcd5785b899cb78d971b4cbcc9dd8566882a1b1d","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-1.0.0.tgz","fileCount":25,"integrity":"sha512-e7OcJbLwrQ+vTN9WU+AAG84Rq1HUcPHpolPMyQ8ai1oGi+1jKr0YRkoDRsgTfwf9kYJNi5yzlA8vbhUtJmcfyQ==","signatures":[{"sig":"MEUCIDbuICQgQ/6y7/h90bJpulgELxh/teFOYTinRDdPH/EVAiEAtXU4QqaWm7EMy2m6RcAN7AJpZQF/SN8tFF2d8YkK97U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":331777},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","version":"npm run manifest","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"deprecated":"1.0.0 shipped a broken contract and should not be used: it names the message key rather than its id. Install 1.0.1 or later.","repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_1.0.0_1789213550978_0.5894654111782835","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@curly-message/conformance","version":"1.0.1","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@1.0.1","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://github.com/curly-message/spec/tree/main/conformance#readme","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"7eca061ed07c471de79ebd9b9e683b3b4266f6f4","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-1.0.1.tgz","fileCount":25,"integrity":"sha512-u27U65FJeeXaIyot4MFTGYDywhBz5BP6r/5UZBn1NmzDCD2JlNHzWWE1W4Rydm6AWdOLrF4NoVwl78Z1zEBwig==","signatures":[{"sig":"MEYCIQCjTjP1xQKJ4f0OquITWMD1ePfx3MvG77GQ/ZhwIoivowIhALGYMcetKiw6RxpOCNGxPaPbnm79WIs5x329e2GAyQpv","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":326619},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","version":"npm run manifest","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_1.0.1_1789261992873_0.3224751317842143","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@curly-message/conformance","version":"2.0.0","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@2.0.0","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://github.com/curly-message/spec/tree/main/conformance#readme","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"9450a8f4b10e7532838123c370a00a94403f655a","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-2.0.0.tgz","fileCount":25,"integrity":"sha512-sywsezdBryBLd9Mcn+rc9nCaRStorvVVZ2+Pq6yvMd6xzGjI1D3f8xOF5UaDGf95RKz6LQy8bY5mb+o6fg7NHA==","signatures":[{"sig":"MEQCIET0vLoK1SlrwS3mHVVWWIPufWJz3kzE0UNMkuAEwOkbAiBApuclpkG6aqxqWgvxVECvtCs3Kzg+JMEaYvZHuhbl8w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@2.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":326619},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","version":"npm run manifest","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"deprecated":"2.0.0 was published in error and is not part of this package's line. Install 1.0.1.","repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_2.0.0_1789322222909_0.09877004105621268","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@curly-message/conformance","version":"1.1.0","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@1.1.0","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://github.com/curly-message/spec/tree/main/conformance#readme","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"36574f16c3f8dd74ed8fd567c7b2255411d495be","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-1.1.0.tgz","fileCount":29,"integrity":"sha512-TfAVMkNlQ7txESsGWk/EcH4plOCJaMOUirZt+zEp1O23BBiDd5HGzAPrNAC3SIfVLoxDRraGemi+goEAAuYj+w==","signatures":[{"sig":"MEMCH1BG3qU9VYIAs4zJhch2AHrDbosd01LN9xn2CGq8BDUCIHJcIeujOKd05Wpq4wnK8iNIz8dpyTxQbQzQNWQzuOef","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDp9VTh45H+oPwtAa+rIyMS4tvp3VJyXYa+XhqdQWOlAwIgegDBORYy/pWo58TYgsYdH1Vob0sfYw1WshTfKv37DMU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":422285},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./defects.json":"./defects.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/defect.schema.json":"./schema/defect.schema.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","version":"npm run manifest","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_1.1.0_1789816586159_0.3431791639540409","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@curly-message/conformance","version":"3.0.0","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@3.0.0","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://github.com/curly-message/spec/tree/main/conformance#readme","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"1f269321813c0096defaeebf12552b63a4b93d6c","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-3.0.0.tgz","fileCount":29,"integrity":"sha512-1pbjZG6lOYafD+mt2xWH+5VBDLKyVcHe/Jhl//soOF1ch9Etol68K5bUGxNTFXY5nrscrdS/Iv65WyhnK5UDgg==","signatures":[{"sig":"MEQCIGLEvokd9RL6z2pcR+dB3AdQeeQZ2M36IJfaa48Qx3XWAiBg/TMtIiE7XqL7HRSdXpf7d+cYEMwLKkqEBNAkMshqhQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDfSx1wMVi3auSH8+ggLB95FKbPAUrNa8OGq+bO1Q3ZZAIgCzDomNRFyT8iFoGtZ8x4fvQ62EhsBCvlmXbIyR/Ass0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@3.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":429904},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./defects.json":"./defects.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/defect.schema.json":"./schema/defect.schema.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","version":"npm run manifest","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_3.0.0_1789835945821_0.7193957010295777","host":"s3://npm-registry-packages-npm-production"}},"4.0.0":{"name":"@curly-message/conformance","version":"4.0.0","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"author":{"name":"Jarda Svoboda"},"license":"MIT","_id":"@curly-message/conformance@4.0.0","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"homepage":"https://curlymessage.dev/conformance/","bugs":{"url":"https://github.com/curly-message/spec/issues"},"bin":{"curly-message-conformance":"bin/conformance.js"},"dist":{"shasum":"9ba3a8cc4a1ea7e21b369352c6f11cd87d7a9fa3","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-4.0.0.tgz","fileCount":29,"integrity":"sha512-og1qIy244/ztKDbTn8ELOaU5mVVgVzdpPy2SpDcXFzlBYUWc4rKdZBhGzeSibRwi1RHUm5S4Dyg4LXo79HnMOQ==","signatures":[{"sig":"MEQCIHzxL2qebpi1Af2YHXDuWzQopl5sVAcoAaCl+om30zLFAiB7Swuw8mmoI1Y1HxGmGs5s2glLyYLtxY//kYwKOtUiSw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIC9DgIRP0xxBD3VX/msphUzSaeOs6DuF/EX9AcV5gWbHAiEA17xCOJ+sdw88RHwbKFFESERhmZ4U64r5dI9vI9cz0jI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@4.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":430248},"type":"module","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./defects.json":"./defects.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/defect.schema.json":"./schema/defect.schema.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","version":"npm run manifest","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"tmp":"tmp/conformance_4.0.0_1789849717981_0.2354093761128262","host":"s3://npm-registry-packages-npm-production"}},"4.0.1":{"_id":"@curly-message/conformance@4.0.1","bin":{"curly-message-conformance":"bin/conformance.js"},"bugs":{"url":"https://github.com/curly-message/spec/issues"},"dist":{"shasum":"d3057a8ad63314181405edd4372af059b05eccdd","tarball":"https://registry.npmjs.org/@curly-message/conformance/-/conformance-4.0.1.tgz","fileCount":29,"integrity":"sha512-urdbYJCOGZA7nB1DsTU586VXwkOL1nQDioIDZY8NtHb1naq3OcMxl9oCfoVgkR6gUUHX/Ut4LGC02kfpSVkXhw==","signatures":[{"sig":"MEYCIQCReEI/z355OCjUdTB0uLxUvT8uXZOeFePSnYIzrg+7xgIhAJIR3OI0GkH0Zo3Ui77CXMRzYrHBbnY3RqHKucOIBm1B","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICD/norWWiFDI6q+ysSwAqFkVUNT1MPc5vDlP/aH7Fw8AiB3HOaxjHLzo9O2rU+GfLOr8r7R7Zm+NWXJBr6ztpfI9A=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@curly-message%2fconformance@4.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":429603},"name":"@curly-message/conformance","type":"module","types":"./dist/index.d.ts","author":{"name":"Jarda Svoboda"},"engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./index.json":"./index.json","./defects.json":"./defects.json","./package.json":"./package.json","./fixtures/*.json":"./fixtures/*.json","./schema/defect.schema.json":"./schema/defect.schema.json","./schema/fixture.schema.json":"./schema/fixture.schema.json"},"license":"MIT","scripts":{"dev":"tsup --watch","lint":"eslint . --max-warnings=0","test":"vitest run","build":"tsup","prepack":"npm run build","prepare":"cd .. && simple-git-hooks conformance/.simple-git-hooks.json","pretest":"npm run build && npm run typecheck && npm run lint","version":"npm run manifest","lint:fix":"eslint --fix .","manifest":"node ./bin/manifest.js","typecheck":"tsc --noEmit -p tsconfig.json"},"version":"4.0.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f40b71cd-c65c-418e-9163-b41a7535b9e8"}},"homepage":"https://curlymessage.dev/conformance/","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"_npmVersion":"11.19.0","description":"Conformance fixtures and runner for the Curly Message Format.","directories":{},"maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"_nodeVersion":"24.20.0","_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.20.0","tsup":"^8.0.1","eslint":"^10.8.1","vitest":"^4.1.10","globals":"^17.11.0","@eslint/js":"^10.0.1","typescript":"^5.1.6","@types/node":"^22.20.1","simple-git-hooks":"^2.13.1","typescript-eslint":"^8.67.0","eslint-plugin-import-x":"^4.17.1","@stylistic/eslint-plugin":"^5.10.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/conformance_4.0.1_1789946768763_0.6098660771710727"}}},"time":{"created":"2026-09-09T13:33:13.875Z","modified":"2026-09-20T23:26:09.248Z","1.0.0-next.0":"2026-09-09T13:33:14.209Z","1.0.0-next.1":"2026-09-09T13:41:56.598Z","1.0.0-next.2":"2026-09-09T14:25:41.109Z","1.0.0":"2026-09-12T11:45:51.127Z","1.0.1":"2026-09-13T01:13:13.054Z","2.0.0":"2026-09-13T17:57:03.064Z","1.1.0":"2026-09-19T11:16:26.251Z","3.0.0":"2026-09-19T16:39:05.918Z","4.0.0":"2026-09-19T20:28:38.161Z","4.0.1":"2026-09-20T23:26:08.840Z"},"bugs":{"url":"https://github.com/curly-message/spec/issues"},"author":{"name":"Jarda Svoboda"},"license":"MIT","homepage":"https://curlymessage.dev/conformance/","keywords":["curly-message","conformance","fixtures","i18n","internationalization","translations","interpolation"],"repository":{"url":"git+ssh://git@github.com/curly-message/spec.git","type":"git","directory":"conformance"},"description":"Conformance fixtures and runner for the Curly Message Format.","maintainers":[{"name":"jarda-svoboda","email":"scarabs04_chirps@icloud.com"}],"readme":"# @curly-message/conformance\n\nThe conformance set of the [Curly Message Format](../SPEC.md): fixtures that\nan implementation in any language is measured against, and a JavaScript runner\nthat drives one through the adapter of section 14.3.\n[RUNNER.md](./RUNNER.md) states what a runner in another language is held to.\n\nA fixture is a resolution written out — the inputs section 4 lists, and the\noutput and the reports they must produce. The set is derived from the\nspecification, and each case names the section it pins, so a failure points at\nthe sentence the implementation disagrees with.\n\n```json\n{\n  \"id\": \"fallback/payload-outranks-inline\",\n  \"section\": \"10\",\n  \"description\": \"The payload's own default takes precedence over the inline one.\",\n  \"message\": \"Hello, {{name; default:Guest;}}!\",\n  \"payload\": { \"default\": \"Friend\" },\n  \"expected\": { \"output\": \"Hello, Friend!\" }\n}\n```\n\nA second kind of file pins the concrete syntax tree of [CST.md](../CST.md)\nrather than a resolution: the same message, and the nodes an implementation\nthat offers a tree describes it with. An implementation conforms without\noffering one, and those cases are then left out.\n\n## Status\n\n**Stable**, on npm as `@curly-message/conformance`. The set lives in the\nspecification's repository because its fixtures are artifacts of the format,\nnot of any one implementation, and every file states the format version it\ntargets: this set targets `curly-message-3`. The set carries a version line of\nits own, because a case may be corrected without the format changing.\n\n## The fixture files\n\n`fixtures/*.json` groups the cases by the section of the specification they\npin, one file per group, and `index.json` lists the files with the level or the\nkind, and the section, each covers. `schema/fixture.schema.json` is the JSON\nSchema every file validates against, so a runner in another language checks the\nset before it reads it.\n\nThose files are the set. Nothing in them is JavaScript, so an implementation in\nanother language needs nothing else from this package: every release carries\nthem as `conformance-<version>.zip` — the fixtures, the manifest, the defect\ncatalogue, both schemas and the two documents that state what they hold, under\none directory, with its digest in the release notes — attached to the\n[release](https://github.com/curly-message/spec/releases) that named it.\n\nA file has a `format`, the versioned identifier of the format it targets; a\n`level`, the conformance level of section 2 that requires every case in it;\na `section`, the heading of the specification the file pins; and its `cases`.\nA file that pins the tree declares `kind` as `tree` and no level — `CST.md` is\nnot one of the levels — and its `section` is a heading of that document.\n\nA case is either written out or generated. A written-out case has:\n\n| Field | Meaning |\n| --- | --- |\n| `id` | Unique across the set: the file's group, a slash, and a slug. |\n| `description` | One sentence naming what the case pins, for the failure it would print. |\n| `section` | A more specific heading than the file's, where the case pins one. |\n| `message` | The message. Usually text; any other JSON value is a message a host wrote as something else (section 4), and the `undefined` tag below is a message the caller did not supply, which resolves to the empty string (section 4). |\n| `payload` | The payload (section 3). Entries hold values, wrappers (section 4.1) or tagged values. |\n| `props` | The caller's formatting properties, grouped by modifier name (section 11.2). |\n| `locale` | The locale. |\n| `messageId` | The message's id (section 4), spelled out because a case's own `id` names the case. Any JSON value: no step of resolution reads it, and reports name it (section 14.3). |\n| `modifiers` | Host-defined modifiers to register (section 11.3): a name to a behaviour from the catalogue below. |\n| `defaults` | The implementation-configured defaults, the bottom formatting layer of section 11.2, grouped by modifier name. |\n| `expected` | What the resolution must produce: an `output`, or for a locale-dependent one a `format` request; and the `reports`, in the order they are emitted, none where the field is omitted. |\n\nA generated case has an `id`, a `description`, optionally a `section`, and a\n`generate` naming one of the constructions under *Generated cases* below. The\nrunner builds its inputs and its expectation from the limits the adapter\ndeclares.\n\n### Tagged values\n\nA fixture is JSON, and the format takes inputs JSON cannot spell. Three tagged\nobjects stand in for them, anywhere in a message, a payload, props, an id or\nthe defaults. A runner decodes each into the host value it names before the\nadapter sees it; nothing else is decoded, so a payload entry of any other shape\nreaches the implementation as the plain data JSON describes.\n\nA tag is read on a case's **inputs** and nowhere else. An expectation is\ncompared as written, so a tag in one would be compared as the object it is\nspelled as, which no implementation answers with; the schema therefore holds the\nid of an expected report to text. A case whose id is not text leaves that id out\nof its expectation and the id goes unobserved.\n\n| Tag | Stands for |\n| --- | --- |\n| `{ \"$curly\": \"undefined\" }` | The host's undefined (sections 4.1, 9.2, 10). A message so tagged is one the caller did not supply. |\n| `{ \"$curly\": \"unserializable\" }` | A value that no conversion can describe (section 4). The JavaScript runner builds a plain object that references itself. |\n| `{ \"$curly\": \"nodes\", \"count\": N }` | A value whose serialization visits at least `N` nodes (section 13). The runner builds a tree of shared references — each level an array naming the level below twice — deep enough to visit `N`. |\n\n### Host-defined modifiers\n\nA case at the Extensions level may register modifiers. It cannot ship code, so\nit names behaviours from a catalogue every runner implements in its own\nlanguage and hands to the adapter as functions of section 11's inputs: the\nvalue and the default as text, the options as the placeholder wrote them, the\nprops composed under the modifier's own name, and the locale the caller\nsupplied, as it supplied it (section 11.3). The adapter wraps each into its\nimplementation's own modifier signature.\n\n| Behaviour | Answers with |\n| --- | --- |\n| `upper` | The value with its ASCII letters uppercased. |\n| `echo` | The value, unchanged. |\n| `empty` | The empty string — an answer, not the absence of one. |\n| `nothing` | The host's nothing: no answer, so the placeholder takes the fallback chain (section 11). |\n| `raise` | Nothing; it raises, and the failure must be contained (section 11.3). |\n| `default` | The default, read through the chain (section 10). |\n| `options` | The options in the order they were handed over, each `key=value`, joined by commas: `a=A,b=,c=c` (section 9.4). |\n| `props` | The props it received, each own property `name=value` with the value as JSON, sorted by name and joined by commas: `maximumFractionDigits=1,useGrouping=true` (sections 11.2, 11.3). |\n| `locale` | The locale it received, or `none` where it received none. An empty locale answers empty. |\n| `object` | A plain object holding the value under `answer`, so the answer serializes (section 11): `{\"answer\":\"X\"}`. |\n\n### Locale-dependent expectations\n\nThe formatting modifiers of section 11.2 delegate to the host's\ninternationalization facilities, whose output varies with the host's locale\ndata. A case for one therefore states the formatting request rather than its\nresult: which facility, the options it is constructed with, and the input the\nmodifier hands it. The options are the properties the facility reads, as the\nlayers of section 11.2 compose them and the modifier pins them — `number`'s\ndefault maximum, `currency`'s style, `ago`'s `numeric` — and not the format's\nown `ratio` and `format`, which the input already reflects. The runner performs\nthat request on the host it runs on and expects the implementation's output to\nmatch it, so the case pins what the specification pins — the request — and the\nlocale data stays the host's.\n\n| `api` | `input` | The request |\n| --- | --- | --- |\n| `NumberFormat` | a number | `Intl.NumberFormat(locale, options).format(input)` |\n| `DateTimeFormat` | milliseconds since the epoch | `Intl.DateTimeFormat(locale, options).format(input)` |\n| `RelativeTimeFormat` | `[value, unit]` | `Intl.RelativeTimeFormat(locale, options).format(value, unit)` |\n\nThe locale is the case's own. The message of such a case is the placeholder\nalone, so that the whole output is the request's result. A date case names a\n`timeZone` in its props, because a request without one formats in the host's,\nwhich the fixture cannot know.\n\nAn implementation whose locale data is not the runner's cannot be held to the\ntext, and section 11.2 lets it expose the request it made instead. An adapter\nthat answers with `formats` is measured on that: such a case compares the\nfacility, the properties and the input, and the locale data on each side stays\nits own. One that leaves `formats` undefined is measured on the text, which is\nwhat an implementation sharing the runner's host can be held to.\n\nA property the host's facility cannot express is a different matter, and\nsection 11.2 has such an implementation document what it cannot express. The\nadapter states it as `unexpressible`, and every case whose request reads one of\nthose properties is left out — listed among the skipped, the way an unclaimed\nlevel's cases are.\n\n### Generated cases\n\nSection 13 lets an implementation permit more than its minima and requires it\nto document what it permits, so a case at a limit cannot be written out: it is\nbuilt from the limits the adapter declares, and exercises the implementation at\nthe bounds it documents. `L` is the declared output limit, `R` the read limit,\n`C` the conversion limit, `N` the nesting limit, and every generated case\nreports under the id `limits`.\n\nEach construction spends one budget and leaves the others room, so a case\nbuilt at one limit cannot be failed by another: the output constructions write\nfrom an option value, which is the message's own text and costs no reading,\nand the read construction selects nothing, so the value it spends the read\nbudget on never reaches the output.\n\n| `generate` | Message and payload | Expected |\n| --- | --- | --- |\n| `output-at-limit` | `{{v; a:<x × L>;}}`, with `v` holding `a`. | `x` repeated `L` times, no reports. |\n| `output-over-limit` | `A{{v; a:<x × (L + 1)>;}}B`, with `v` holding `a`. | `AB` — the placeholder resolved to the empty string, and the message's own text around it is the caller's and counts against nothing — and one `output-limit` report of origin `limit`. |\n| `output-over-limit-continues` | The same placeholder followed by `{{w}}`, with `w` holding `tail`. | `tail` and one `output-limit` report: a result the output has no room for spends nothing, so what follows it still resolves. |\n| `read-at-limit` | `{{v:eq; nomatch:X; default:ok;}}`, with `v` holding `x` repeated `R` times. | `ok`, no reports. |\n| `read-over-limit` | The same placeholder followed by `{{w}}`, with `v` one character longer and `w` holding `tail`. | `ok` and one `read-limit` report of origin `limit`: the budget is tested before a placeholder reads, so the one that spent it past the limit still resolves and the one after it pays. |\n| `conversion-over-limit` | `{{v; default:D}}`, with `v` a `nodes` value of `C + 1`. | `D` and one `unserializable-value` report of origin `payload`: a serialization that reaches the limit describes nothing, so the placeholder takes the chain. |\n| `nesting-at-limit` | `N` placeholders, each selecting the option that holds the next; the innermost is `{{v; a:settled; default:fallback;}}`. `v` holds `a`. | `settled`, no reports. |\n| `nesting-over-limit` | The same nesting one level deeper. | `fallback` and one `nesting-limit` report of origin `message`: the innermost placeholder is refused and takes its fallback chain, and every level around it selects the option that holds it. |\n\nAn adapter whose reports carry a `limit` is held to the declared limit on the\n`output-limit`, `read-limit` and `nesting-limit` reports.\n\n### Tree cases\n\nA file whose `kind` is `tree` pins the concrete syntax tree of\n[`CST.md`](../CST.md): what an implementation that offers one answers for a\nmessage. Such a case carries no input beyond the message, because a tree is a\nfunction of the message alone.\n\n| Field | Meaning |\n| --- | --- |\n| `id`, `description`, `section` | As above, except that the `section` is a heading of `CST.md`. |\n| `message` | The message, as text. |\n| `expected` | The children of the root node, in order. |\n| `resolves` | What the same message resolves to over no payload, where the case pins that the tree and the resolution read the same placeholders (section 5, property 4). The message then names no modifier, so the expectation holds at the Core level. |\n\nA node of `expected` states what it is and what it spells, never where it is:\n\n| Field | Meaning |\n| --- | --- |\n| `type` | The kind, as section 6 of `CST.md` spells it. |\n| `text` | The text the node spans. |\n| `name` | For a name kind: the span unescaped. |\n| `cancels` | For an escape: which of the two readings of section 7 the sequence takes. |\n| `nodes` | The children, in order, wherever the case reads into the node. |\n\nThe span is the one thing a case does not write. Section 4 of `CST.md` lets an\nimplementation count its spans in whatever unit its strings are indexed by, so\na case that wrote numbers would pin one implementation's unit on every other.\nA case writes the text instead, and the runner reads that text off the span the\nimplementation answered with, in the unit the adapter declared. The declaration\nis thereby observable: an implementation that counts UTF-16 code units and\nstates it counts code points fails the case whose message holds a character\noutside the basic multilingual plane.\n\nThe properties of section 5 are checked on every tree case before its own\nexpectation is compared, because a tree that is wrong about the message is\nwrong whatever the case says of its nodes: the leaves tile the message in order\nand spell it back, no span boundary falls inside a code point, no node lies\noutside the one that holds it, and two parses of one message agree.\n\n## The adapter\n\nSection 14.3 has the conformance set observe an implementation through an\nadapter the implementation supplies. It is three things:\n\n```ts\nimport type { Adapter } from '@curly-message/conformance';\n\nexport const adapter: Adapter = {\n  levels: ['core', 'intl', 'extensions'],\n  limits: { output: 100000, read: 100000, conversion: 100000, nesting: 8 },\n  resolve: ({ message, payload, props, locale, id, modifiers, defaults }) => {\n    // Call the implementation and answer with what it produced.\n    return { output, reports };\n  },\n};\n```\n\n`levels` is the statement section 2 requires: the levels the implementation\nsatisfies. The runner selects the fixtures those levels require and skips the\nrest, and the skipped cases are listed, not hidden. `limits` is the statement\nsection 13 requires, and is what the generated cases are built from. An adapter\nMAY make a third statement, `unexpressible`: the formatting properties the\nhost's facility cannot express (section 11.2), under the request that reads\nthem, which leaves out the cases that would measure the host rather than the\nimplementation.\n\nAn adapter MAY offer a fourth thing, `cst`: the concrete syntax tree of\n[`CST.md`](../CST.md), as the `unit` its spans are counted in — `utf-8`,\n`utf-16` or `code-point` — and the `parse` that produces one. An adapter that\nleaves it out has every tree case left out with that reason rather than failed,\nbecause an implementation conforms without offering a tree. A `cst` whose unit\nis none of the three is an error rather than a skip, the way an unknown level\nis: a tree whose unit is unstated says nothing about where anything is.\n\n`resolve` is handed one resolution's inputs, decoded into host values, and\nanswers with the `output` and the `reports` the implementation produced. The\noutput is compared exactly. A report is compared by its `code`; its `origin`,\n`id` and `limit` are compared where the adapter's reports carry them, since\nthe specification prescribes no shape for a report, only what a code names and\nwhich origin it declares. Reports are compared in order, because section 14.3\nhas an implementation report in the pass where the condition was met and\nsection 9 resolves a pass in source order. An adapter that leaves `reports`\nundefined says the implementation does not report at all — reporting is a\nSHOULD — and every expectation about reports is then skipped, and said to be:\nsuch a case passes on its output alone with an outcome of\n`{ ok: true, unobserved: 'reports' }`, `run` lists it under `unobserved`\nbeside `passed`, and the command counts those cases in its summary.\n\n`resolve` MAY answer with `formats` as well, the formatting requests the\nresolution made, in the order it made them. A case that states a request is\nthen compared on that request rather than on the output, as the section above\ndescribes; a case that states an output is compared on its output whether the\nadapter answers with `formats` or not.\n\n## Running the set\n\nThe set is a development dependency of the implementation it assesses:\n\n```bash\nnpm install --save-dev @curly-message/conformance\n```\n\nFrom a test:\n\n```ts\nimport { check, plan, run } from '@curly-message/conformance';\n\ncheck(adapter);          // throws with the list of failures, if any\n\nconst result = run(adapter);   // { passed, failed, skipped, unobserved }\n\nfor (const planned of plan(adapter).cases) {\n  test(planned.id, () => {\n    const outcome = planned.execute();\n\n    expect(outcome).toMatchObject({ ok: true });\n  });\n}\n```\n\n`plan` is for a test framework: one entry per case the adapter's levels\nrequire, each carrying its `id`, `file`, `section`, `description`, the `level`\nand the `document` where the case has them, and an `execute` that runs it and\nanswers with an outcome — `{ ok: true }`, or the reason it failed beside what was expected and\nwhat came back. `run` executes a\nplan and sorts the outcomes. Both take options: `fixtures`, to run a set other\nthan the shipped one, and `levels`, to run a subset of the levels the adapter\nclaims. An adapter must claim `core`, and `levels` must name only levels it\nclaims; anything else is an error rather than a skip. A case at a level that\ndoes not run is skipped with a reason naming the level, and a tree case is\nskipped wherever the adapter offers no `cst`.\n\nThe package also exports what those are built from: `fixtures()` reads the\nshipped set and `load(directory)` any directory of fixture files, both sorted\nby file name, which is what the `fixtures` option takes; `summarize(result)`\nrenders what the command prints; and `decode` and `behaviours` are the tagged\nvalues and the catalogue as this runner implements them, for an adapter's own\ntests to reuse.\n\nFrom the command line, with a module that exports the adapter as `adapter` or\nas its default export:\n\n```bash\nnpx curly-message-conformance ./adapter.mjs\nnpx curly-message-conformance ./adapter.mjs --levels core,intl\nnpx curly-message-conformance ./adapter.mjs --fixtures ./my-fixtures\n```\n\nThe command prints one line per failure and a summary, and exits non-zero where\nanything failed. `--fixtures` points at a directory of fixture files, so a set\nunder development runs against an implementation before it ships.\n\n## Auditing a runner\n\nA runner is trusted with a verdict, so it needs one of its own: a runner that\ncompares nothing passes every implementation, including the ones that are\nwrong, and reports the same summary either way. `defects.json` is the catalogue\nof ways an adapter can be wrong, each with what a correct runner answers where\nit is present, and `schema/defect.schema.json` describes the file.\n\n```ts\nimport { audit } from '@curly-message/conformance';\n\nconst missed = audit(adapter).filter(({ outcome }) => outcome !== 'caught');\n```\n\n`audit` takes an adapter that passes the set, applies each defect to it in\nturn, and answers one entry per defect: what the catalogue expected, what this\nrunner observed, and whether that counts as `caught`, `missed` or\n`unreachable`. The last is for a defect the adapter gives the runner nothing to\ncatch — what an implementation that observes no reports does to every defect of\nits reports, one that claims Core alone to every defect of a level it does not\nclaim, and one that offers no tree to every defect of the tree. A defect names\nthe `section` it pins and, where that is a heading of `CST.md` rather than of\nthe specification, the `document` it is a heading of. `defects()` reads the\ncatalogue and `mutations` carries it, so a runner's own tests can reach one\ndefect without running them all.\n\n[RUNNER.md](./RUNNER.md) states what each defect pins.\n\n## Writing a fixture\n\nA case pins a sentence of the specification, and states which: the `section`\nis what a failure points at. Its expectation follows from the text, not from\nwhat an implementation happens to do, so a behaviour the specification leaves\nto the host — how its numeric conversion reads a literal, which text its date\nparsing accepts, what a host type converts to — is not a case. Where the\nspecification lets two conforming implementations differ, the set does not\nchoose between them.\n\nThe narrow reading of section 4 falls there as well. That a value of a type an\napplication declared or derived converts as a string rather than as JSON is\nnormative, but the string is the host's own, and a case that stated one would\npin it on every other host. So the set pins the values that do serialize, and\nan implementation that reads section 4 too widely passes it.\n\nThe reference implementation is what the set is checked against before it\nlands, and the set is what the reference is checked against in turn. Where\nthe two disagree, the specification decides which is wrong.\n\n`npm run manifest` regenerates `index.json` from the files, and a version bump\nruns it; the tests fail where it is stale, where an `id` repeats, where a file\ndoes not validate against the schema, or where a `section` names no heading of\nthe document its file reads against.\n\n## Development\n\n```bash\nnpm install\nnpm test         # builds, typechecks, lints, then runs vitest\nnpm run lint:fix # applies what the lint step only reports\n```\n\nRequires Node.js 22 or newer.\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}