diff --git a/CHANGELOG.md b/CHANGELOG.md index 68cf52b..367a4e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- **The theme validator passes `formatVersion: null`.** lich decodes a null + `formatVersion` the way it decodes an omitted one and installs the theme; + the validator rejected it as not a positive integer. + ## [0.18.3] - 2026-10-08 ### Fixed diff --git a/skills/theme/validate.mjs b/skills/theme/validate.mjs index 3cee86e..9f5a652 100644 --- a/skills/theme/validate.mjs +++ b/skills/theme/validate.mjs @@ -40,9 +40,9 @@ if (!target) { } function formatVersionError(document) { - if (!("formatVersion" in document)) return null const version = document.formatVersion - // 0 is what lich decodes an omitted formatVersion to, so it reads as 1. + // lich decodes an omitted or null formatVersion to 0, and reads 0 as 1. + if (version === undefined || version === null) return null if (!Number.isInteger(version) || version < 0) return `theme formatVersion ${JSON.stringify(version)} must be a positive integer` if (version > FORMAT_VERSION) diff --git a/tests/theme-validate.test.mjs b/tests/theme-validate.test.mjs index 3ba0c5b..e1eb00d 100644 --- a/tests/theme-validate.test.mjs +++ b/tests/theme-validate.test.mjs @@ -56,6 +56,11 @@ test('formatVersion 0 passes, the way lich reads an omitted one', () => { assert.equal(result.status, 0, result.stderr) }) +test('formatVersion null passes, as decoding null into an int leaves lich at 0', () => { + const result = validateTheme({ formatVersion: null }) + assert.equal(result.status, 0, result.stderr) +}) + test('a negative formatVersion is rejected with lich\'s message', () => { const result = validateTheme({ formatVersion: -1 }) assert.equal(result.status, 1)