diff --git a/CHANGELOG.md b/CHANGELOG.md index 36bc199..32d11ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Fixed - Core: preserve `verification.on_fail` through compilation (#64, PR #71). The recovery action (`retry`/`escalate`/`skip`/`abort`/`revise`) was silently dropped at the compile boundary. Now carried as a first-class `CompiledVerification` on a singular `CompiledStep.verification`; the gate-validator return shape got its own name `QualityGateResult`. Parametrised across all five `OnFailAction` values plus the null case. +- Core: forward `quality_gates.pre_output[].on_fail` into compiled output via `QualityGateResult.onFail` (#72, PR #82). The pre_output gate recovery action was dropped at the compile boundary; now surfaced on the failing result and omitted when the author omits it. Parametrised across all five `OnFailAction` values plus the absent case. - MCP: HTTP transport responds with a structured 500 on handler error instead of hanging until socket timeout (#66, PR #79). `headersSent`/`writableEnded` guards prevent a double-write. - Build: cli/mcp `postbuild` schema copy now fails loud instead of `|| true` swallowing both copy attempts (#67, PR #78). The bundled core validator reads its own `dist/schema.json` at runtime, so the copy is required. - Fixtures: `run-fixtures.mjs` fails loud (exit 2) on non-ENOENT `readdir` errors instead of treating every error as "directory not found" and reporting partial success as full success (#68, PR #80). @@ -20,10 +21,17 @@ ### Changed - Docs: replace stale `ROADMAP.md` with `STATUS.md` as the user-facing status doc; ignore contributor PDFs (#77). +- Core: the dry-run executor now reads a step's verification from `CompiledStep.verification` instead of the un-compiled spec (#73, PR #84). Consumer side of #64; behaviour preserved (the compiler maps `on_fail_message` to `message`). +- Core/LangGraph: the executor reflects `CompiledStep.executionPlan` onto `StepTrace.executionPlan`, and the LangGraph adapter reflects it onto `StateGraphNode.metadata.executionPlan` (#75, PRs #85 and #86). Consumer side of #65; consume-and-reflect only, no concurrent scheduler. ### Tests - CLI: pin `toCanonical` failure modes for malformed frontmatter, distinguishing throw (malformed / tab YAML) from null (unbalanced delimiters, no frontmatter) (#69, PR #81). +## [1.5.1] - 2026-07-24 + +### Fixed +- Core: `schema.ts`, `parser.ts`, `validator.ts` load `gray-matter`/`ajv-formats`/`schema.json` via static ESM imports instead of `createRequire`/`readFileSync`. The `createRequire` path broke under single-file bundlers (bun `--compile`); consumers were carrying this as a local patch. Matches the fix already shipped in `@marchese-md/core`. + ## [1.5.0] - 2026-05-15 ### Added diff --git a/packages/core/package.json b/packages/core/package.json index fa5a55b..7750340 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@logic-md/core", - "version": "1.5.0", + "version": "1.5.1", "description": "Parser, validator, expression engine, DAG resolver, and reasoning compiler for the LOGIC.md specification", "type": "module", "main": "./dist/index.js", diff --git a/packages/core/parser.ts b/packages/core/parser.ts index 8feca60..fb167cc 100644 --- a/packages/core/parser.ts +++ b/packages/core/parser.ts @@ -7,12 +7,9 @@ // only extracts and casts. // ============================================================================= -import { createRequire } from "node:module"; +import matter from "gray-matter"; import type { LogicSpec } from "./types.js"; -const require = createRequire(import.meta.url); -const matter = require("gray-matter") as typeof import("gray-matter"); - // ----------------------------------------------------------------------------- // Result Types // ----------------------------------------------------------------------------- diff --git a/packages/core/schema.ts b/packages/core/schema.ts index 7b9b764..53c127f 100644 --- a/packages/core/schema.ts +++ b/packages/core/schema.ts @@ -5,32 +5,23 @@ // ValidateFunction for runtime validation of LogicSpec objects. // ============================================================================= -import { readFileSync } from "node:fs"; -import { createRequire } from "node:module"; -import { dirname, join } from "node:path"; -import { fileURLToPath } from "node:url"; import { Ajv, type ValidateFunction } from "ajv"; +import addFormatsMod from "ajv-formats"; +import schemaJson from "./schema.json" with { type: "json" }; import type { LogicSpec } from "./types.js"; -const require = createRequire(import.meta.url); -// ajv-formats is a CJS module with `export default` that doesn't resolve -// correctly under verbatimModuleSyntax + nodenext. Use createRequire instead. -const addFormats = require("ajv-formats") as { - default: (ajv: Ajv) => Ajv; -}; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); +// ajv-formats is CJS; unwrap the interop default so this works under both +// Node ESM and single-file bundlers. +const addFormats = ((addFormatsMod as { default?: unknown }).default ?? addFormatsMod) as ( + ajv: Ajv, +) => Ajv; /** - * Reads and parses the embedded JSON Schema from disk. - * Uses `import.meta.url` for path resolution so it works regardless - * of the caller's working directory. + * Returns the embedded JSON Schema (statically imported so it survives + * bundling into single-file executables). */ export function getSchema(): Record { - const schemaPath = join(__dirname, "schema.json"); - const raw = readFileSync(schemaPath, "utf8"); - return JSON.parse(raw) as Record; + return structuredClone(schemaJson) as Record; } /** Cached validator instance (module-level singleton) */ @@ -52,8 +43,7 @@ export function createValidator(): ValidateFunction { } const ajv = new Ajv({ allErrors: true, strict: true }); - const applyFormats = addFormats.default ?? addFormats; - (applyFormats as (ajv: Ajv) => Ajv)(ajv); + addFormats(ajv); const schema = getSchema(); cachedValidator = ajv.compile(schema); diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 4f93176..3d3ab24 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -5,6 +5,6 @@ "rootDir": ".", "composite": true }, - "include": ["*.ts", "**/*.ts"], + "include": ["*.ts", "**/*.ts", "schema.json"], "exclude": ["dist", "node_modules", "**/*.test.ts"] } diff --git a/packages/core/validator.ts b/packages/core/validator.ts index 331fa06..039049e 100644 --- a/packages/core/validator.ts +++ b/packages/core/validator.ts @@ -6,14 +6,11 @@ // and maps ajv error paths back to YAML source line numbers. // ============================================================================= -import { createRequire } from "node:module"; +import matter from "gray-matter"; import { type Document, LineCounter, type Node, parseDocument } from "yaml"; import { createValidator } from "./schema.js"; import type { LogicSpec, ValidationError, ValidationResult } from "./types.js"; -const require = createRequire(import.meta.url); -const matter = require("gray-matter") as typeof import("gray-matter"); - /** * Offset added to YAML line numbers to account for the opening `---` * delimiter line that gray-matter strips before returning `result.matter`. diff --git a/tsconfig.json b/tsconfig.json index 1ad8a13..28262b8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ "declarationMap": true, "sourceMap": true, "esModuleInterop": true, + "resolveJsonModule": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true,