diff --git a/server/engagement-triggers.json b/server/engagement-triggers.json index 6bc05a8..bfa13b9 100644 --- a/server/engagement-triggers.json +++ b/server/engagement-triggers.json @@ -1,6 +1,6 @@ { "_comment": "Generated event-trigger inventory - the authoritative freeze of CORE's engagement contract (docs/website/ENGAGEMENT.md 4.3). Regenerate with `npm run engagement:manifest` in website/server. A renamed variable, a changed type or a widened ceiling breaks stored templates and rules, so the diff here is the review signal. A module ships its own copy in its bundle; this file never contains one.", - "moduleApiVersion": "1.9.0", + "moduleApiVersion": "1.10.0", "triggers": [ { "id": "news.post", diff --git a/server/scripts/engagementManifest.js b/server/scripts/engagementManifest.js index dd28be5..f22f4ba 100644 --- a/server/scripts/engagementManifest.js +++ b/server/scripts/engagementManifest.js @@ -108,7 +108,21 @@ function main() { return } - const current = fs.existsSync(MANIFEST_PATH) ? fs.readFileSync(MANIFEST_PATH, 'utf8') : '' + // **Line endings are normalised before the comparison**, exactly as + // `routeManifest.js` does one file along, and for a reason that is not + // cosmetic: this repo is developed on Windows under `core.autocrlf=true`, so + // git checks a committed LF blob out as CRLF and a byte comparison then calls + // an unchanged manifest stale. That failure is worse than useless — it fires on + // every Windows checkout, says "a trigger declaration changed", and is fixed by + // regenerating a file whose CONTENT was already correct, which teaches a + // developer to ignore the one check that exists to be believed. + // + // What is being asserted is that the committed manifest describes the same + // declarations, and a line ending is not a declaration. Policing the encoding + // is `.gitattributes`' job, not this check's. + const current = fs.existsSync(MANIFEST_PATH) + ? fs.readFileSync(MANIFEST_PATH, 'utf8').replace(/\r\n/g, '\n') + : '' if (current === next) { process.stdout.write('engagement-triggers.json is current\n') return diff --git a/server/test/engagementManifest.test.js b/server/test/engagementManifest.test.js index 9743971..17cd58a 100644 --- a/server/test/engagementManifest.test.js +++ b/server/test/engagementManifest.test.js @@ -26,8 +26,16 @@ afterEach(() => registries._reset()) const MANIFEST_PATH = path.join(__dirname, '..', 'engagement-triggers.json') const serialize = (m) => `${JSON.stringify(m, null, 2)}\n` +// **Normalised, like `routeManifest.test.js`'s `read()` one file along.** Under +// `core.autocrlf=true` git checks the committed LF blob out as CRLF, so a byte +// comparison fails on every Windows checkout while CI stays green — and it fails +// saying "the manifest is stale", which is the one thing it is not. The claim +// here is that the committed file describes the same declarations; a line ending +// is not a declaration. +const committedManifest = () => fs.readFileSync(MANIFEST_PATH, 'utf8').replace(/\r\n/g, '\n') + test('the committed manifest matches the declarations in the tree', () => { - const committed = fs.readFileSync(MANIFEST_PATH, 'utf8') + const committed = committedManifest() assert.equal( serialize(build()), committed,