Skip to content

fix: expose bin/* in package exports for Node 22+ (closes #734) - #737

Merged
rafaelscosta merged 4 commits into
mainfrom
fix/issue-734-exports-bin
May 15, 2026
Merged

fix: expose bin/* in package exports for Node 22+ (closes #734)#737
rafaelscosta merged 4 commits into
mainfrom
fix/issue-734-exports-bin

Conversation

@rafaelscosta

@rafaelscosta rafaelscosta commented May 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #734@aiox-squads/core@5.2.2/5.2.3/5.2.4 all crash on Node 22+ with ERR_PACKAGE_PATH_NOT_EXPORTED because the exports field omits ./bin/*.

Three commits, atomic and reviewable independently:

SHA Type Scope
5df6d061 fix package.json + compat/aiox-core/package.json — add "./bin/*": "./bin/*" to exports, bump 5.2.4 → 5.2.5
09b80b87 ci npm-publish.yml — new smoke_test_exports job with Node 20/22/24 matrix to catch this regression class
4aa7d539 docs STORY-124.13

Root cause

Story 124.8 introduced compat/aiox-core/bin/aiox-core.js which does:

require(`@aiox-squads/core/bin/${targetBin}`);

The root package.json exports field (Epic 124) only exposes ./resilience/*, ./installer/*, ./package.json. Node 22+ enforces the package-exports spec strictly and rejects subpaths not declared, even when the file physically exists.

Why CI missed it 3 releases in a row: the existing Smoke test legacy npx step uses npx --yes aiox-core --version, which resolves via npm bin shims — those bypass Node's package-exports gate (internal resolution within node_modules). Only external require('@aiox-squads/core/bin/aiox.js') triggers the gate, which is what happens when a user runs npm i -g aiox-core@5.2.x in Node 22+.

The fix

   "exports": {
     "./resilience": "./.aiox-core/core/resilience/index.js",
     "./resilience/agent-immortality": "./.aiox-core/core/resilience/agent-immortality.js",
+    "./bin/*": "./bin/*",
     "./installer/aiox-core-installer": "./packages/installer/src/installer/aiox-core-installer.js",
     ...
   }

Pass-through pattern (no .js suffix transform) because the shim already passes the full filename including extension.

CI hardening (regression guard)

New job smoke_test_exports runs after publish/publish_legacy_aiox_core:

Local validation (Node 22.16)

Reproduced the bug against aiox-core@5.2.4 then validated the fix locally via npm pack + tempdir install:

✅ aiox --version → 5.2.5
✅ aiox-core --version (legacy wrapper) → 5.2.5
✅ require('@aiox-squads/core/bin/aiox.js') → loads CLI banner

Pre-fix, the same require() call threw ERR_PACKAGE_PATH_NOT_EXPORTED.

Test plan

Related


🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Restored compatibility with Node.js 22+ for requiring bin utilities.
  • Chores

    • Bumped package version to 5.2.5 and aligned compat wrapper dependency.
  • Tests

    • Added a CI smoke test that installs the published package and verifies external requiring of the bin entry; publish notifications now fail if this smoke test fails.
  • Documentation

    • Added a story documenting the fix, acceptance criteria, and validation guidance.

Review Change Stack

rafaelscosta and others added 3 commits May 15, 2026 10:31
@aiox-squads/core 5.2.2/5.2.3/5.2.4 broke under Node 22+ with
ERR_PACKAGE_PATH_NOT_EXPORTED. The exports field introduced during
Epic 124 only exposed ./resilience/* and ./installer/*, blocking the
compat/aiox-core/bin/aiox-core.js shim from require()-ing the canonical
CLI binaries.

Fix:
- Add "./bin/*": "./bin/*" pass-through pattern to exports.
- Bump @aiox-squads/core 5.2.4 -> 5.2.5.
- Bump compat aiox-core 5.2.4 -> 5.2.5 + dependency pin.

Validated locally on Node 22.16 against packed tarballs:
- aiox --version: 5.2.5
- aiox-core --version (legacy wrapper): 5.2.5
- require('@aiox-squads/core/bin/aiox.js'): loads CLI without
  ERR_PACKAGE_PATH_NOT_EXPORTED

Closes #734

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The existing publish_legacy_aiox_core smoke uses npx --yes which
resolves bin shims internally and does NOT trigger Node's
package-exports gate. That gap let Issue #734
(ERR_PACKAGE_PATH_NOT_EXPORTED) slip into 3 consecutive releases
(5.2.2/.3/.4) unnoticed by CI.

Add smoke_test_exports job:
- Matrix Node 20/22/24
- Runs after publish (depends on build + publish + publish_legacy_aiox_core)
- Forces external require('@aiox-squads/core/bin/aiox.js') which DOES
  trigger the exports gate
- notify job updated to surface failures

This is a regression guard, not a replacement for the existing
bin-shim smoke. Both paths are now validated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Story documenting Issue #734 fix:
- Root cause analysis (Story 124.8 wrapper + restrictive exports field)
- Acceptance criteria
- Tasks (impl + CI hardening + publish + deprecation)
- File list
- Dev notes including CI gap analysis (why npx smoke missed it 3 times)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented May 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aiox-core Ready Ready Preview, Comment May 15, 2026 3:26pm

Request Review

@github-actions github-actions Bot added area: docs Documentation (docs/) area: devops CI/CD, GitHub Actions (.github/) labels May 15, 2026
@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4e76be1c-78d4-4e63-a85f-b10bec2e9c92

📥 Commits

Reviewing files that changed from the base of the PR and between 4aa7d53 and be47d90.

📒 Files selected for processing (2)
  • .github/workflows/npm-publish.yml
  • docs/stories/epic-124-aiox-squads-scope-migration/STORY-124.13-fix-issue-734-exports-bin.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/npm-publish.yml

Walkthrough

Adds ./bin/* to package exports and bumps versions to 5.2.5, introduces a post-publish Node 20/22/24 smoke test that installs the published package and verifies external require('@aiox-squads/core/bin/aiox.js'), and documents the change and acceptance criteria.

Changes

Package exports and version alignment with CI regression guard

Layer / File(s) Summary
Root package exports and version bump
package.json
The root package.json adds an explicit ./bin/*./bin/* subpath export mapping and version is incremented from 5.2.4 to 5.2.5.
Compatibility wrapper version and dependency alignment
compat/aiox-core/package.json
The compat wrapper version and its @aiox-squads/core dependency are updated from 5.2.4 to 5.2.5.
CI smoke test job for exports regression guard
.github/workflows/npm-publish.yml
A new smoke_test_exports job runs after publish (Node 20/22/24), waits for npm registry sync, installs the published package in a temporary environment, validates require('@aiox-squads/core/bin/aiox.js') succeeds, and is wired into the notify job's needs and failure/cancel logic.
Story documentation and acceptance criteria
docs/stories/epic-124-aiox-squads-scope-migration/STORY-124.13-fix-issue-734-exports-bin.md
Adds the story document recording acceptance criteria, implementation tasks, affected files, root cause, CI smoke approach, and risks.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related issues

  • #734: Implements the fix for ERR_PACKAGE_PATH_NOT_EXPORTED by exposing ./bin/* and adding CI validation.

Possibly related PRs

  • SynkraAI/aiox-core#730: Related changes touching the npm publish workflow and compat wrapper integration with @aiox-squads/core/bin/*.

Suggested labels

type: test, area: core, area: cli

Suggested reviewers

  • Pedrovaleriolopez
  • oalanicolas
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: exposing bin/* in package exports to fix Node 22+ compatibility issues.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-734-exports-bin

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 15, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage Report

Coverage report not available

📈 Full coverage report available in Codecov


Generated by PR Automation (Story 6.1)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/npm-publish.yml:
- Around line 499-506: The shell pipeline in the smoke test (the block that
creates SMOKE_DIR and runs node -e "require('@aiox-squads/core/bin/aiox.js')
2>&1 | head -20") can hide failures because the exit status of the first command
is lost; add a shell option to enable failing on any pipe element by invoking
set -o pipefail (or equivalently set -euo pipefail if you prefer stricter mode)
before running the pipeline so a failing node require() will correctly cause the
if-condition to fail and surface export/require regressions.

In
`@docs/stories/epic-124-aiox-squads-scope-migration/STORY-124.13-fix-issue-734-exports-bin.md`:
- Line 41: Update the incorrect story filename reference by replacing
`STORY-124.9-fix-issue-734-exports-bin.md` with the correct
`STORY-124.13-fix-issue-734-exports-bin.md` in the File List entry so the
documentation points to the current story file.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 22b53962-b8ca-4701-b70f-8dec3c7f3194

📥 Commits

Reviewing files that changed from the base of the PR and between c577250 and 4aa7d53.

📒 Files selected for processing (4)
  • .github/workflows/npm-publish.yml
  • compat/aiox-core/package.json
  • docs/stories/epic-124-aiox-squads-scope-migration/STORY-124.13-fix-issue-734-exports-bin.md
  • package.json

Comment thread .github/workflows/npm-publish.yml
- ci: add `set -o pipefail` to smoke_test_exports so node's non-zero
  exit from require() failure isn't masked by `head -20`. Without this,
  the regression guard silently passes on any future ERR_PACKAGE_PATH_
  NOT_EXPORTED, defeating its purpose.
- docs: correct File List self-reference in STORY-124.13 (was pointing
  to the old 124.9 filename used during draft).

CodeRabbit findings:
- Major (workflow L506): pipefail missing
- Minor (story L41): stale filename reference

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rafaelscosta

Copy link
Copy Markdown
Collaborator Author

@Pedrovaleriolopez @oalanicolas — codeowners review request

PR fixes Issue #734 (broken CLI on Node 22+, affects every fresh install of aiox-core@5.2.x).

Status:

  • ✅ All 33 CI checks passing (Jest matrix Node 18/20/22/24/25)
  • ✅ Local smoke validated on Node 22.16
  • ✅ CodeRabbit 2 findings addressed in be47d900:
    • set -o pipefail added to smoke_test_exports
    • Stale filename ref in story doc corrected

Quando puderem revisar — fix bloqueia release. Obrigado.

@rafaelscosta
rafaelscosta merged commit f949b42 into main May 15, 2026
36 checks passed
@rafaelscosta
rafaelscosta deleted the fix/issue-734-exports-bin branch May 15, 2026 16:19
tuanmedeiros pushed a commit to tuanmedeiros/aios-core-synkraay that referenced this pull request Jun 2, 2026
… (SynkraAI#737)

* fix: expose bin/* in exports for Node 22+ compat [Story 124.13]

@aiox-squads/core 5.2.2/5.2.3/5.2.4 broke under Node 22+ with
ERR_PACKAGE_PATH_NOT_EXPORTED. The exports field introduced during
Epic 124 only exposed ./resilience/* and ./installer/*, blocking the
compat/aiox-core/bin/aiox-core.js shim from require()-ing the canonical
CLI binaries.

Fix:
- Add "./bin/*": "./bin/*" pass-through pattern to exports.
- Bump @aiox-squads/core 5.2.4 -> 5.2.5.
- Bump compat aiox-core 5.2.4 -> 5.2.5 + dependency pin.

Validated locally on Node 22.16 against packed tarballs:
- aiox --version: 5.2.5
- aiox-core --version (legacy wrapper): 5.2.5
- require('@aiox-squads/core/bin/aiox.js'): loads CLI without
  ERR_PACKAGE_PATH_NOT_EXPORTED

Closes SynkraAI#734

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci: add Node 22/24 exports regression guard [Story 124.13]

The existing publish_legacy_aiox_core smoke uses npx --yes which
resolves bin shims internally and does NOT trigger Node's
package-exports gate. That gap let Issue SynkraAI#734
(ERR_PACKAGE_PATH_NOT_EXPORTED) slip into 3 consecutive releases
(5.2.2/.3/.4) unnoticed by CI.

Add smoke_test_exports job:
- Matrix Node 20/22/24
- Runs after publish (depends on build + publish + publish_legacy_aiox_core)
- Forces external require('@aiox-squads/core/bin/aiox.js') which DOES
  trigger the exports gate
- notify job updated to surface failures

This is a regression guard, not a replacement for the existing
bin-shim smoke. Both paths are now validated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(stories): add STORY-124.13 [Story 124.13]

Story documenting Issue SynkraAI#734 fix:
- Root cause analysis (Story 124.8 wrapper + restrictive exports field)
- Acceptance criteria
- Tasks (impl + CI hardening + publish + deprecation)
- File list
- Dev notes including CI gap analysis (why npx smoke missed it 3 times)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(ci,docs): address CodeRabbit review [Story 124.13]

- ci: add `set -o pipefail` to smoke_test_exports so node's non-zero
  exit from require() failure isn't masked by `head -20`. Without this,
  the regression guard silently passes on any future ERR_PACKAGE_PATH_
  NOT_EXPORTED, defeating its purpose.
- docs: correct File List self-reference in STORY-124.13 (was pointing
  to the old 124.9 filename used during draft).

CodeRabbit findings:
- Major (workflow L506): pipefail missing
- Minor (story L41): stale filename reference

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: devops CI/CD, GitHub Actions (.github/) area: docs Documentation (docs/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(packaging): v5.2.3 CLI fails with ERR_PACKAGE_PATH_NOT_EXPORTED — @aiox-squads/core exports map blocks bin/*

1 participant