Skip to content

fix(raijin): enforce ESM runtime boundaries#797

Merged
TorinAsakura merged 67 commits into
masterfrom
fix/service-webpack-external-type
Jul 8, 2026
Merged

fix(raijin): enforce ESM runtime boundaries#797
TorinAsakura merged 67 commits into
masterfrom
fix/service-webpack-external-type

Conversation

@TorinAsakura

@TorinAsakura TorinAsakura commented Jul 2, 2026

Copy link
Copy Markdown
Member

Task

Scope

This hotfix restores the Raijin contract after the public package-surface collapse from the last known working @atls/raijin@0.5.2 line.

The scope covers two connected regression classes:

  1. ESM runtime boundary regressions introduced while moving the runtime/config/package surface into the single public @atls/raijin package.
  2. Command execution context regressions caused by package commands resolving this.context.cwd / process.cwd() independently instead of going through one owned project/workspace context boundary.

Release window:

Findings and audit inputs that define this PR:

Runtime boundary scope:

  • service webpack dependency externals stay in the ESM module graph without turning static dependencies into Promise-shaped async externals;
  • optional dependencies remain lazy dynamic externals;
  • undeclared transitive npm package roots stay bundled instead of being externalized through a missing consumer dependency boundary;
  • service and renderer start commands run built entrypoints through the owned Raijin PnP/runtime boundary;
  • renderer standalone output keeps the module boundary that Next actually emits instead of launching a CommonJS Next server file as ESM;
  • Raijin runtime child processes strip only the PnP ESM loader while preserving the PnP CJS hook;
  • PnP TypeScript dependency sources are classified through the dependency source boundary instead of local package CommonJS fallback;
  • Raijin TypeScript loader preserves Node ESM package resolution failures for bare package specifiers and does not fall back to CommonJS require.resolve package subpaths;
  • workspace-targeted test commands keep workspace ignore configuration while resolving root-relative explicit test files through the project root;
  • initialized projects are normalized to type: module even when packageManager is already current;
  • local commitlint parity keeps default ignored messages, footer length checks, and multi-scope validation;
  • release/version actions and decisions keep the single public @atls/raijin release boundary.

Command context refactor scope:

  • command context determination moved out of scattered command bodies into @atls/yarn-plugin-tools/command-context;
  • workspace commands resolve the containing workspace from any nested invocation cwd and use workspace.cwd for package-local files and child process cwd;
  • project commands use project.cwd / top-level workspace state;
  • scaffold commands keep current cwd as the explicit generation target;
  • explicit file-target commands resolve user-provided paths against invocation cwd and project/workspace root only where that is the documented command contract;
  • normalized command groups:
    • renderer build, renderer start, renderer dev
    • service build, service dev, service start
    • library build
    • ui icons generate
    • image pack
    • lint, format, check, checks lint
    • badges generate.

How to verify

Before the fix

  1. Build or start an ESM service that statically imports a manifest dependency and dynamically imports an optional dependency.
    Expected result: static dependency externals can be emitted through a broken async/CommonJS boundary, while optional dependencies can be resolved too early.

  2. Start existing Serenity or Pathfinder services/renderers with the published @atls/raijin@0.6.2 runtime.
    Expected result: Raijin runtime can fail before the consumer application boundary because the runtime contract was changed away from the ESM-only path.

  3. Run workspace-targeted explicit test files.
    Expected result: root-relative explicit paths and workspace ignore configuration can be resolved from the wrong cwd.

  4. Re-run raijin init in an already-current project.
    Expected result: package.json may keep a missing or CommonJS type value.

  5. Run commit-msg checks for merge/revert commits, long footers, or multi-scope commit subjects.
    Expected result: the hand-rolled path can diverge from the previous commitlint behavior.

  6. Build a clean single-project Next application with type: module and output: 'standalone'.
    Expected result: Next build completes, then Raijin fails while copying standalone files or later starts the Next standalone CommonJS server file as ESM.

  7. Run workspace commands from a nested directory inside a workspace.
    Expected result: commands that should operate on the containing workspace can read package-local files, src, dist, icons, package.json, or README.md from the nested directory instead of the workspace root.

  8. Import a package whose conditional exports select a missing ESM import target while a CommonJS require target exists.
    Expected result: the current loader can mask the selected ESM failure by resolving the CommonJS branch through require.resolve.

After the fix

  1. Service production builds emit valid ESM output for regular dependencies, lazy dynamic externals for optional dependencies, and bundle undeclared transitive npm roots.
  2. service start and renderer start execute built entrypoints under the owned Raijin PnP/runtime boundary.
  3. Renderer build copies Next standalone output from the actual Next standalone root and preserves the module boundary required by Next's generated server entrypoint.
  4. Runtime child environments preserve --require .pnp.cjs and remove only .pnp.loader.mjs state.
  5. PnP dependency TypeScript sources and local TypeScript sources follow separate ESM boundaries.
  6. Workspace-targeted explicit tests keep workspace ignore rules and resolve project-root file targets.
  7. Initializer normalization always writes type: module for current projects.
  8. Commitlint keeps footer checks, default ignored messages, and multi-scope validation.
  9. Version gate releases only @atls/raijin and explicitly declines modified internal workspaces.
  10. Workspace-level commands behave the same when launched from the workspace root and from a nested directory inside that workspace.
  11. Project-level commands keep project-root behavior regardless of the invocation directory inside the project.
  12. Scaffold commands still generate into the explicit current directory.
  13. TypeScript runtime loading preserves Node ESM resolver failures for bare package specifiers instead of crossing into CommonJS package-subpath fallback.

Proofs

Final branch commits:

  • b38bcead7 centralizes project/workspace/current-cwd command context.
  • 7c50d8ff preserves the renderer standalone ESM start path.
  • 2fc67000 resolves import-sort workspace context from nested cwd.
  • f244b6c5 restores service ESM webpack dependency boundaries.
  • 2da5a366 rebuilds the standard runtime bundle.
  • 05ce688a restores the official commitlint parser path for breaking shorthand and parser parity.
  • a4239790 declines modified internal command plugin workspaces through the Yarn deferred version boundary.
  • a2b41ebb2 resolves ESLint runtime imports through the nearest Raijin package boundary.
  • 52f1588c2 preserves patched TypeScript descriptors when the normalized range already matches.
  • a58c00047 keeps workspace peer dependencies local before service externalization.
  • 601bb614f completes internal workspace version decisions.
  • eff526473 runs renderer dev from the src Next app directory.

Local proof before push:

yarn test unit yarn/plugin-tools/sources/command-context.test.ts yarn/plugin-renderer/sources/commands/renderer-build.utils.test.ts yarn/raijin/src/runtime/prettier-plugin/import-sort/import-sort.api.test.ts code/code-service/src/webpack.config.test.ts code/code-service/src/webpack.externals.test.ts code/code-service/unit/webpack-ignore.test.ts --test-reporter=tap
yarn format <changed source/test/package files>
yarn typecheck <changed source/test/package files>
yarn lint <changed source/test files>
yarn workspace @atls/code-service build
yarn workspace @atls/yarn-plugin-tools build
yarn workspace @atls/yarn-plugin-renderer build
yarn workspace @atls/yarn-plugin-library build
yarn workspace @atls/yarn-plugin-ui build
yarn workspace @atls/yarn-plugin-format build
yarn workspace @atls/yarn-plugin-lint build
yarn workspace @atls/yarn-plugin-checks build
yarn workspace @atls/yarn-plugin-badges build
yarn workspace @atls/yarn-plugin-image build
yarn workspace @atls/yarn-plugin-service build
yarn workspace @atls/raijin build
yarn workspace @atls/yarn-cli build
cmp -s yarn/cli/dist/runtime/yarn.mjs .yarn/releases/yarn.mjs
yarn raijin:check
yarn workspace @atls/raijin pack --out /tmp/atls-raijin-pr797.tgz
yarn check
git diff --check -- . ':!.yarn/releases/yarn.mjs'

Follow-up remediation proof for review findings 3 and 4:

yarn test unit code/code-commit/src/commit.linter.test.ts yarn/plugin-release/sources/tests/release-version.utils.test.ts yarn/plugin-release/sources/tests/release-version-defer.command.test.ts --test-reporter=tap
yarn typecheck code/code-commit/package.json code/code-commit/src/commit.linter.ts code/code-commit/src/commit.linter.test.ts yarn/plugin-release/sources/release-version-defer.command.ts yarn/plugin-release/sources/release-version.utils.ts yarn/plugin-release/sources/tests/release-version.utils.test.ts yarn/plugin-release/sources/tests/release-version-defer.command.test.ts
yarn lint code/code-commit/src/commit.linter.ts code/code-commit/src/commit.linter.test.ts yarn/plugin-release/sources/release-version-defer.command.ts yarn/plugin-release/sources/release-version.utils.ts yarn/plugin-release/sources/tests/release-version.utils.test.ts yarn/plugin-release/sources/tests/release-version-defer.command.test.ts
yarn workspace @atls/code-commit build
yarn workspace @atls/yarn-plugin-release build
yarn workspace @atls/yarn-cli build
cmp -s yarn/cli/dist/runtime/yarn.mjs .yarn/releases/yarn.mjs
yarn release version defer --since origin/master..HEAD --dry-run
yarn version check
yarn raijin:check
yarn check
git diff --check -- . ':!.yarn/releases/yarn.mjs'

Latest current-head remediation proof:

yarn test unit code/code-lint/src/linter.test.ts --test-reporter=tap
yarn typecheck code/code-lint/src/linter.ts code/code-lint/src/linter.test.ts
yarn lint code/code-lint/src/linter.ts code/code-lint/src/linter.test.ts

yarn test unit yarn/plugin-tools/sources/commands/sync/typescript.command.test.ts --test-reporter=tap
yarn typecheck yarn/plugin-tools/sources/commands/sync/typescript.command.ts yarn/plugin-tools/sources/commands/sync/typescript.command.test.ts
yarn lint yarn/plugin-tools/sources/commands/sync/typescript.command.ts yarn/plugin-tools/sources/commands/sync/typescript.command.test.ts

yarn test unit yarn/plugin-service/sources/workspace-package-names.test.ts --test-reporter=tap
yarn typecheck yarn/plugin-service/sources/workspace-package-names.ts yarn/plugin-service/sources/workspace-package-names.test.ts
yarn lint yarn/plugin-service/sources/workspace-package-names.ts yarn/plugin-service/sources/workspace-package-names.test.ts

yarn version check

yarn test unit yarn/plugin-renderer/sources/commands/renderer-dev.command.test.ts --test-reporter=tap
yarn typecheck yarn/plugin-renderer/sources/commands/renderer-dev.command.ts yarn/plugin-renderer/sources/commands/renderer-dev.command.test.ts
yarn lint yarn/plugin-renderer/sources/commands/renderer-dev.command.ts yarn/plugin-renderer/sources/commands/renderer-dev.command.test.ts

yarn workspace @atls/yarn-cli build
cmp -s yarn/cli/dist/runtime/yarn.mjs .yarn/releases/yarn.mjs
yarn raijin:check
yarn check
git diff --check -- . ':!.yarn/releases/yarn.mjs'

Consumer smoke from packed /tmp/atls-raijin-pr797.tgz:

  • Serenity renderer build from nested cwd passed; renderer start reached the app and then failed inside the consumer Next/React boundary with head_1.default.rewind is not a function.
  • Serenity service build from nested cwd passed; service start reached Nest/TypeORM and then failed on consumer dependency/application boundaries: missing class-validator, missing @nestjs/platform-express, then rxjs.lastValueFrom after adding smoke-only deps in the temporary worktree.
  • Pathfinder strategy API service build from nested cwd passed; service start reached Nest DI and then failed on the consumer app dependency graph: ExplorerService / ModulesContainer.
  • Earlier Pathfinder trade-bot nested build passed and start reached the consumer env-validation boundary.

No remaining observed failure in these smokes is a Raijin cwd, ESM loader, webpack externals, PnP hook, import-meta, or runtime entrypoint failure.

@TorinAsakura TorinAsakura self-assigned this Jul 2, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70af4237e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread code/code-service/src/webpack.externals.ts
Comment thread .yarn/versions/a9003efd.yml
Comment thread code/code-service/src/webpack.externals.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 350996f4ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread code/code-service/src/webpack.externals.ts Outdated
@archeon-atls archeon-atls changed the title fix(service): preserve module dependency externals fix(raijin): enforce ESM runtime boundaries Jul 2, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

if (manifest.packageManager === packageManager) {
return

P2 Badge Normalize type before returning from manifest check

When an existing project already has the current packageManager (for example, rerunning raijin init in a project created before this change), this early return skips adding type: 'module'. The same patch now makes the service build and TypeScript loaders require an ESM package boundary, so those projects remain un-normalized and can still fail the new checks immediately after initialization; include manifest.type === 'module' in the no-op condition or rewrite the manifest when it is missing.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread code/code-service/src/webpack.config.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 88edb7e5a2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yarn/raijin/src/initializer/project.ts
Comment thread yarn/plugin-test/sources/test.command.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 849b0ae848

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .yarn/versions/a9003efd.yml
Comment thread code/code-commit/src/commit.linter.ts Outdated
Comment thread code/code-commit/src/commit.linter.ts
Comment thread code/code-commit/src/commit.linter.ts Outdated
@TorinAsakura
TorinAsakura force-pushed the fix/service-webpack-external-type branch from 9ac356f to 07e8edc Compare July 3, 2026 15:14

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 07e8edc36f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yarn/plugin-renderer/sources/commands/renderer-start.command.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ec44fb8fb0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yarn/plugin-pnp-patch/src/esm-loader/hooks/resolve.utils.ts Outdated
Comment thread yarn/plugin-renderer/sources/commands/renderer-build.utils.ts
Comment thread yarn/plugin-typescript/sources/typecheck.command.tsx

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7152a3cb84

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yarn/plugin-renderer/sources/commands/renderer-build.utils.ts Outdated
Comment thread yarn/plugin-renderer/sources/commands/renderer-build.utils.ts Outdated
Comment thread yarn/plugin-typescript/sources/typecheck.command.tsx Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b7d1a5f8f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yarn/plugin-tools/sources/commands/sync/tsconfig.command.ts
Comment thread code/code-typescript/src/typescript.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc8b83a649

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yarn/raijin/src/runtime/typescript-loader.ts Outdated
Comment thread yarn/plugin-tools/sources/commands/sync/typescript.command.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0c3bbe2b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yarn/plugin-lint/sources/lint.command.tsx Outdated
Comment thread yarn/plugin-ui/sources/commands/ui-icons-generate.command.tsx Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0ddf26ac10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .pnp.loader.mjs Outdated
Comment thread yarn/plugin-renderer/sources/commands/renderer-build.utils.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3765f8a3d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread yarn/raijin/src/runtime/typescript-loader.ts Outdated
@TorinAsakura
TorinAsakura merged commit a069ad4 into master Jul 8, 2026
7 checks passed
@TorinAsakura
TorinAsakura deleted the fix/service-webpack-external-type branch July 8, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Restore Raijin ESM runtime and command context boundaries

2 participants