diff --git a/CHANGELOG.md b/CHANGELOG.md index bc92d04..622c2ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## [Unreleased] +## [1.14.1] - 2026-04-07 + +### Fixed +- **`forge-patterns` bin entry**: `package.json` declared `"forge-patterns": "dist/cli.js"`, but no `src/cli.ts` ever existed and `dist/cli.js` was never built, so `npx @forgespace/core forge-patterns` failed for every npm consumer of v1.4.0–v1.14.0. The bin now points at the existing `scripts/forge-patterns-cli.js` (already shipped under `pkg.files`, has a `#!/usr/bin/env node` shebang). The script was also marked executable. Added `src/bin-entries.test.js` to assert that every `pkg.bin` entry resolves to a real file, has a node shebang, and lives under a path declared in `pkg.files` — preventing this regression class going forward. + ## [1.14.0] - 2026-04-04 ### Fixed diff --git a/etc/core.api.md b/etc/core.api.md index 255e07b..89405a6 100644 --- a/etc/core.api.md +++ b/etc/core.api.md @@ -711,7 +711,7 @@ export interface ToggleStrategyConfig { export function validateTenantProfile(value: unknown): value is TenantProfile; // @public -export const VERSION = "1.14.0"; +export const VERSION = "1.14.1"; // (No @packageDocumentation comment for this package) diff --git a/package.json b/package.json index 01b0300..6d7c71f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@forgespace/core", - "version": "1.14.0", + "version": "1.14.1", "description": "Shared configuration, workflows, and architectural patterns for the Forgespace ecosystem", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -78,7 +78,7 @@ "mcp-context:start": "node dist/mcp-context-server/index.js" }, "bin": { - "forge-patterns": "dist/cli.js", + "forge-patterns": "scripts/forge-patterns-cli.js", "forge-scorecard": "dist/patterns/idp/scorecards/cli.js", "forge-policy": "dist/patterns/idp/policy-engine/cli.js", "forge-features": "dist/patterns/idp/feature-toggles/cli.js", diff --git a/scripts/forge-patterns-cli.js b/scripts/forge-patterns-cli.js old mode 100644 new mode 100755 diff --git a/src/bin-entries.test.js b/src/bin-entries.test.js new file mode 100644 index 0000000..b6e171e --- /dev/null +++ b/src/bin-entries.test.js @@ -0,0 +1,30 @@ +const fs = require('node:fs'); +const path = require('node:path'); + +const repoRoot = path.resolve(__dirname, '..'); +const pkg = require('../package.json'); + +describe('package.json bin entries', () => { + const binEntries = Object.entries(pkg.bin || {}); + + it('declares at least one bin entry', () => { + expect(binEntries.length).toBeGreaterThan(0); + }); + + it.each(binEntries)('bin "%s" -> "%s" exists in the published files', (name, relPath) => { + const absPath = path.join(repoRoot, relPath); + expect(fs.existsSync(absPath)).toBe(true); + }); + + it.each(binEntries)('bin "%s" -> "%s" starts with a node shebang', (name, relPath) => { + const absPath = path.join(repoRoot, relPath); + if (!fs.existsSync(absPath)) return; + const firstLine = fs.readFileSync(absPath, 'utf8').split('\n', 1)[0]; + expect(firstLine).toMatch(/^#!.*\bnode\b/); + }); + + it.each(binEntries)('bin "%s" -> "%s" lives under a path declared in pkg.files', (name, relPath) => { + const topDir = relPath.split('/')[0] + '/'; + expect(pkg.files).toEqual(expect.arrayContaining([topDir])); + }); +}); diff --git a/src/index.ts b/src/index.ts index 8a36e83..dbc3f8b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,7 @@ */ // Version information — kept in sync with package.json by scripts/release-core.sh -export const VERSION = '1.14.0'; +export const VERSION = '1.14.1'; // Type definitions export interface ProjectConfig {