// ── The engagement trigger manifest ──────────────────────────────────────── // // ENGAGEMENT.md §4.3 property 4. CI runs `npm run engagement:manifest -- --check` // and that is the gate; this file is here for the reason // `checkModuleIdentifiers.test.js` exists — **a check that silently stops // checking is worse than no check**. So there are two tests: the committed file // is current, and the generator actually notices a changed declaration. // // It also makes a stale manifest fail `npm test`, which is the run a developer // does before pushing. process.env.DB_HOST = '127.0.0.1' process.env.DB_PORT = '59999' const { test, afterEach, after } = require('node:test') const assert = require('node:assert/strict') const fs = require('fs') const path = require('path') const { build } = require('../scripts/engagementManifest') const registries = require('../src/modules/registries') const db = require('../src/utils/db') after(() => db.close()) afterEach(() => registries._reset()) const MANIFEST_PATH = path.join(__dirname, '..', 'engagement-triggers.json') const serialize = (m) => `${JSON.stringify(m, null, 2)}\n` test('the committed manifest matches the declarations in the tree', () => { const committed = fs.readFileSync(MANIFEST_PATH, 'utf8') assert.equal( serialize(build()), committed, 'engagement-triggers.json is stale — run `npm run engagement:manifest` and commit the result', ) }) test('the manifest holds core\'s triggers only, never a module\'s', () => { // A module ships its own copy in its bundle (MODULE_API.md §6.1a), because // core never has its sources to analyse. If a module's declarations leaked // into core's manifest, the file would change depending on which modules // happened to be installed on the machine that regenerated it. registries._reset() const api = registries.stage('uo') api.registerEventTriggers([{ id: 'uo.house.idoc_warning', label: 'House approaching collapse', ceiling: 'owner', variables: [{ name: 'house', type: 'string', required: true, example: 'The Silver Anvil' }], }]) registries.apply(api.staged) const manifest = build() assert.equal(manifest.triggers.every((t) => t.owner === 'core'), true) assert.equal(manifest.triggers.some((t) => t.id === 'uo.house.idoc_warning'), false) }) test('and it notices a changed declaration — the check is live', () => { const before = serialize(build()) // Register one more trigger AS CORE, then rebuild. `build()` calls // registerCore(), which is a no-op once core has registered, so this lands // beside core's five rather than replacing them. registries._reset() const api = registries.stage('core') api.registerEventTriggers([{ id: 'core.probe', label: 'A declaration the committed manifest does not have', ceiling: 'staff', variables: [{ name: 'why', type: 'string', required: true, example: 'proving the check works' }], }]) registries.apply(api.staged) const after_ = serialize(build()) assert.notEqual(after_, before) assert.match(after_, /core\.probe/) })