diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index fe6ebc0..5aa1d25 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -3,6 +3,11 @@ name: Publish @synapt-dev/extract to npm on: release: types: [published] + workflow_dispatch: + # Manual re-trigger — needed because this workflow has no version-mismatch retry path: + # a `release` event fires it exactly once, and if npm's version hadn't moved yet at that + # point (e.g. a Python-only release, or this repo's own version-sync-deferred slices), + # there is no automatic second attempt once the npm version is later bumped. permissions: contents: write @@ -26,12 +31,27 @@ jobs: - run: npm run build + - name: Check if this version is already published + id: check + run: | + VERSION=$(node -p "require('./package.json').version") + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + if npm view "@synapt-dev/extract@$VERSION" version >/dev/null 2>&1; then + echo "already_published=true" >> "$GITHUB_OUTPUT" + echo "@synapt-dev/extract@$VERSION is already published to npm -- skipping publish (this is expected on every release where only the PyPI side bumped, not an error)." + else + echo "already_published=false" >> "$GITHUB_OUTPUT" + fi + - run: npm publish --provenance --access public + if: steps.check.outputs.already_published != 'true' - name: Generate SBOM + if: steps.check.outputs.already_published != 'true' run: npm sbom --omit=dev --sbom-format cyclonedx > sbom.cdx.json - name: Upload SBOM to release + if: steps.check.outputs.already_published != 'true' && github.event_name == 'release' env: GH_TOKEN: ${{ github.token }} run: gh release upload ${{ github.event.release.tag_name }} sbom.cdx.json --clobber diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d14ea2..514971a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## v0.6.0 -Temporal validity role + resolution anchor — additive Stage-1 IL enrichment (config/design/extract-temporal-role-2026-07-14.md). `synapt-extract` (PyPI) bumps to 0.6.0. `@synapt-dev/extract` (npm) carries the same additive-role parity but keeps its version at 0.5.0 for now — the npm version-sync is part of the deferred full-parity effort, not this additive-role slice. +Temporal validity role + resolution anchor — additive Stage-1 IL enrichment (config/design/extract-temporal-role-2026-07-14.md). `synapt-extract` (PyPI) bumps to 0.6.0. `@synapt-dev/extract` (npm) also bumps to 0.6.0 — main already carries the full additive-role parity slice, so the version number is honest — but publishes on a short lag behind PyPI (npm's publish workflow had no `workflow_dispatch` retrigger, added alongside this bump). The FULL ts/py parity effort (a TS `extract_batch`/`batch.ts` port) remains the deferred post-validation follow-up, separate from this version-sync. - Added `role` (`effective` | `expiry` | `range` | `superseded` | `point`) to the temporal-ref schema, capturing the validity DIRECTION a date constrains (e.g. "expires April 30" → `expiry`, vs "effective March 2026" → `effective`) — a semantic distinction the source sentence carries but prior extraction dropped - `role` and `resolved_end` are now BASE-tier on the `temporal_refs` capability (no longer gated behind the separate `temporal_classes` capability) — always available to any caller requesting `temporal_refs`; `type`/`context` remain `temporal_classes`-gated @@ -11,7 +11,7 @@ Temporal validity role + resolution anchor — additive Stage-1 IL enrichment (c - Fixed a prompt-rendering gap where an absent `date` param rendered the literal string "Resolve relative dates using: None." instead of omitting the instruction (wrapped in `{{#if date}}`; supported identically by both prompt renderers) - `_detect_capabilities`'s `temporal_classes` heuristic now keys on `type` presence only (`resolved_end` no longer implies the gated capability was exercised, since it moved to base tier) - Published JSON schema (`schemas/temporal-ref/v1.json`, both the repo-root canonical copy and the Python package copy) updated to match — schema-drift-check green -- **ts/py parity — the additive `role` coherence slice IS included** (`@synapt-dev/extract` TypeScript): `schema.ts` types `role`, `builder.ts` emits `role`/`resolved_end` base-tier, `validate.ts` accepts/enum-validates `role` (+ `role === "range"` → `resolved_end`), `finalize.ts` drops the `resolved_end` inference, and the embedded prompt fragment matches the shared file byte-for-byte. TS and Python produce identical schema/validation/finalize output on the same inputs (verified cross-language). The FULL parity effort (a TS `extract_batch`/`batch.ts` port + version-sync) remains the post-validation follow-up per config/design/extract-ts-py-parity-plan-2026-07-15.md — this release only carries the additive-role coherence needed to keep the shared prompt/schema surface consistent. +- **ts/py parity — the additive `role` coherence slice IS included** (`@synapt-dev/extract` TypeScript): `schema.ts` types `role`, `builder.ts` emits `role`/`resolved_end` base-tier, `validate.ts` accepts/enum-validates `role` (+ `role === "range"` → `resolved_end`), `finalize.ts` drops the `resolved_end` inference, and the embedded prompt fragment matches the shared file byte-for-byte. TS and Python produce identical schema/validation/finalize output on the same inputs (verified cross-language). The FULL parity effort (a TS `extract_batch`/`batch.ts` port) remains the post-validation follow-up per config/design/extract-ts-py-parity-plan-2026-07-15.md — the version number now matches PyPI (see above), but the additive-role coherence slice is still what's shipped, not the full `batch.ts` port. ## v0.5.0 diff --git a/packages/ts/package-lock.json b/packages/ts/package-lock.json index 4556753..0fde876 100644 --- a/packages/ts/package-lock.json +++ b/packages/ts/package-lock.json @@ -1,12 +1,12 @@ { "name": "@synapt-dev/extract", - "version": "0.5.0", + "version": "0.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@synapt-dev/extract", - "version": "0.5.0", + "version": "0.6.0", "license": "MIT", "devDependencies": { "@types/node": "^25.6.0", diff --git a/packages/ts/package.json b/packages/ts/package.json index b1e95b4..474977f 100644 --- a/packages/ts/package.json +++ b/packages/ts/package.json @@ -1,6 +1,6 @@ { "name": "@synapt-dev/extract", - "version": "0.5.0", + "version": "0.6.0", "description": "SynaptExtraction IL v1 -- schema, validation, and finalization", "type": "module", "main": "dist/index.js",