diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f73314..22a9bc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,13 @@ backwards-compatible fixes only. ## [Unreleased] +### Fixed + +- The registry is alphabetical again (`mandates_and_justice` sorts before + `map_overview`), and a unit test now fails if that order drifts. +- The release smoke check derives its expected tool count from `ALL_TOOLS` + instead of pinning a literal, so adding a tool no longer breaks it. + ## [1.4.1] - 2026-07-26 ### Fixed diff --git a/scripts/smoke-artifact.mjs b/scripts/smoke-artifact.mjs index 6d917a3..b6dc397 100644 --- a/scripts/smoke-artifact.mjs +++ b/scripts/smoke-artifact.mjs @@ -4,6 +4,7 @@ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { createRequire } from 'node:module'; import { join } from 'node:path'; +import { pathToFileURL } from 'node:url'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; @@ -20,6 +21,9 @@ try { writeFileSync(join(room, 'package.json'), JSON.stringify({ name: 'smoke', private: true })); run(`npm install "${tgz}"`, room); const bin = join(room, 'node_modules', 'dfhack-mcp', 'dist', 'index.js'); + const { SURFACE_ACTUATORS_ON } = await import( + pathToFileURL(join(room, 'node_modules', 'dfhack-mcp', 'dist', 'surface.js')).href + ); const childEnv = { ...process.env, DFHACK_MCP_ACTUATORS: '1' }; delete childEnv.DFHACK_MCP_DEV; @@ -47,7 +51,8 @@ try { const problems = []; if (handshakeVersion !== version) problems.push(`handshake version ${handshakeVersion} != package ${version}`); - if (tools.length !== 45) problems.push(`expected 45 tools (actuators on), got ${tools.length}`); + if (tools.length !== SURFACE_ACTUATORS_ON) + problems.push(`expected ${SURFACE_ACTUATORS_ON} tools (actuators on), got ${tools.length}`); if (missing.length) problems.push(`missing tools: ${missing.join(', ')}`); if (problems.length) { diff --git a/src/surface.ts b/src/surface.ts new file mode 100644 index 0000000..b7e9b11 --- /dev/null +++ b/src/surface.ts @@ -0,0 +1,6 @@ +import { ALL_TOOLS } from './tools/registry.ts'; +import { isGatedOff } from './register.ts'; + +export const SURFACE_ACTUATORS_ON = ALL_TOOLS.filter((def) => + !isGatedOff(def, { DFHACK_MCP_ACTUATORS: '1' }) +).length; diff --git a/src/tools/registry.ts b/src/tools/registry.ts index 28b9947..653f3ca 100644 --- a/src/tools/registry.ts +++ b/src/tools/registry.ts @@ -19,8 +19,8 @@ import { identifyDef } from './identify/index.ts'; import { injuriesAndHealthDef } from './injuriesAndHealth.ts'; import { jobsAndLaborDef } from './jobsAndLabor.ts'; import { livestockAndPasturesDef } from './livestockAndPastures.ts'; -import { mapOverviewDef } from './mapOverview.ts'; import { mandatesAndJusticeDef } from './mandatesAndJustice.ts'; +import { mapOverviewDef } from './mapOverview.ts'; import { mechanismsDef, pullLeverDef } from './mechanisms.ts'; import { militaryDef } from './military.ts'; import { moodsDef } from './moods.ts'; @@ -64,8 +64,8 @@ export const ALL_TOOLS: ToolDef[] = [ injuriesAndHealthDef, jobsAndLaborDef, livestockAndPasturesDef, - mapOverviewDef, mandatesAndJusticeDef, + mapOverviewDef, mechanismsDef, militaryDef, moodsDef, diff --git a/test/toolsurface.test.mjs b/test/toolsurface.test.mjs new file mode 100644 index 0000000..fdb01c1 --- /dev/null +++ b/test/toolsurface.test.mjs @@ -0,0 +1,18 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { ALL_TOOLS } from '../src/tools/registry.ts'; + +const names = ALL_TOOLS.map((tool) => tool.name); + +test('registry entries are alphabetical by tool name', () => { + const inversions = []; + for (let i = 1; i < names.length; i += 1) { + if (names[i - 1] > names[i]) inversions.push(`${names[i - 1]} > ${names[i]}`); + } + assert.deepEqual(inversions, [], `registry out of alphabetical order: ${inversions.join('; ')}`); +}); + +test('registry tool names are unique', () => { + const duplicates = names.filter((name, index) => names.indexOf(name) !== index); + assert.deepEqual(duplicates, [], `duplicate tool names: ${duplicates.join(', ')}`); +}); diff --git a/tsup.config.ts b/tsup.config.ts index 199da6e..1ce635b 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -2,7 +2,7 @@ import { defineConfig } from 'tsup'; import { cp } from 'node:fs/promises'; export default defineConfig({ - entry: ['src/index.ts'], + entry: ['src/index.ts', 'src/surface.ts'], outDir: 'dist', format: ['esm'], target: 'node20',