Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
6df4b1e6 fix(misc): resolve CSS url() assets on Windows in postcss-cli-resources (#36353)
## Current Behavior
On Windows, CSS `url(...)` references to local assets (SVGs, fonts such
as `codicon.ttf`, etc.) fail to resolve during an `@nx/rspack`,
`@nx/webpack`, or `@nx/angular-rspack` build, even when the file exists
on disk. The build reports
`RspackResolver(NotFound("/C:/.../file.svg"))`. It is most visible when
the workspace path contains spaces.
## Expected Behavior
CSS `url()` assets resolve on Windows regardless of the drive letter or
spaces in the path.
## Related Issue(s)
Fixes #36336
## Implementation Details
The `postcss-cli-resources` plugin resolved assets by passing
`pathToFileURL(resolvedPath).pathname` to the bundler resolver. That
value is a URL path (`/C:/Users/...`, with spaces percent-encoded), not
a filesystem path, so the resolver could not find the file. On POSIX the
URL pathname coincides with the filesystem path, which is why only
Windows was affected. #34676 fixed an earlier `new URL(winPath,
'file:///')` drive-letter misparse but kept feeding the pathname into
the resolver.
The fix resolves a relative filesystem path derived from `resolvedPath`
instead, and drops the paired `decodeURI` that only existed to undo the
pathname encoding. It is applied to the `@nx/rspack`, `@nx/webpack`, and
`@nx/angular-rspack` copies of the plugin.
The plugin has no existing unit coverage and the resolver needs a real
webpack/rspack loader context, so no automated test was added; the
change was validated with build and lint and cross-checked against
upstream `@angular-devkit/build-angular`.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/gh-36336-b7b11fff)
<!-- polygraph-session-end --> 6df4b1e6 fix(misc): resolve CSS url() assets on Windows in postcss-cli-resources (#36353)
## Current Behavior
On Windows, CSS `url(...)` references to local assets (SVGs, fonts such
as `codicon.ttf`, etc.) fail to resolve during an `@nx/rspack`,
`@nx/webpack`, or `@nx/angular-rspack` build, even when the file exists
on disk. The build reports
`RspackResolver(NotFound("/C:/.../file.svg"))`. It is most visible when
the workspace path contains spaces.
## Expected Behavior
CSS `url()` assets resolve on Windows regardless of the drive letter or
spaces in the path.
## Related Issue(s)
Fixes #36336
## Implementation Details
The `postcss-cli-resources` plugin resolved assets by passing
`pathToFileURL(resolvedPath).pathname` to the bundler resolver. That
value is a URL path (`/C:/Users/...`, with spaces percent-encoded), not
a filesystem path, so the resolver could not find the file. On POSIX the
URL pathname coincides with the filesystem path, which is why only
Windows was affected. #34676 fixed an earlier `new URL(winPath,
'file:///')` drive-letter misparse but kept feeding the pathname into
the resolver.
The fix resolves a relative filesystem path derived from `resolvedPath`
instead, and drops the paired `decodeURI` that only existed to undo the
pathname encoding. It is applied to the `@nx/rspack`, `@nx/webpack`, and
`@nx/angular-rspack` copies of the plugin.
The plugin has no existing unit coverage and the resolver needs a real
webpack/rspack loader context, so no automated test was added; the
change was validated with build and lint and cross-checked against
upstream `@angular-devkit/build-angular`.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/gh-36336-b7b11fff)
<!-- polygraph-session-end --> 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 6df4b1e6 fix(misc): resolve CSS url() assets on Windows in postcss-cli-resources (#36353)
## Current Behavior
On Windows, CSS `url(...)` references to local assets (SVGs, fonts such
as `codicon.ttf`, etc.) fail to resolve during an `@nx/rspack`,
`@nx/webpack`, or `@nx/angular-rspack` build, even when the file exists
on disk. The build reports
`RspackResolver(NotFound("/C:/.../file.svg"))`. It is most visible when
the workspace path contains spaces.
## Expected Behavior
CSS `url()` assets resolve on Windows regardless of the drive letter or
spaces in the path.
## Related Issue(s)
Fixes #36336
## Implementation Details
The `postcss-cli-resources` plugin resolved assets by passing
`pathToFileURL(resolvedPath).pathname` to the bundler resolver. That
value is a URL path (`/C:/Users/...`, with spaces percent-encoded), not
a filesystem path, so the resolver could not find the file. On POSIX the
URL pathname coincides with the filesystem path, which is why only
Windows was affected. #34676 fixed an earlier `new URL(winPath,
'file:///')` drive-letter misparse but kept feeding the pathname into
the resolver.
The fix resolves a relative filesystem path derived from `resolvedPath`
instead, and drops the paired `decodeURI` that only existed to undo the
pathname encoding. It is applied to the `@nx/rspack`, `@nx/webpack`, and
`@nx/angular-rspack` copies of the plugin.
The plugin has no existing unit coverage and the resolver needs a real
webpack/rspack loader context, so no automated test was added; the
change was validated with build and lint and cross-checked against
upstream `@angular-devkit/build-angular`.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/gh-36336-b7b11fff)
<!-- polygraph-session-end --> 6df4b1e6 fix(misc): resolve CSS url() assets on Windows in postcss-cli-resources (#36353)
## Current Behavior
On Windows, CSS `url(...)` references to local assets (SVGs, fonts such
as `codicon.ttf`, etc.) fail to resolve during an `@nx/rspack`,
`@nx/webpack`, or `@nx/angular-rspack` build, even when the file exists
on disk. The build reports
`RspackResolver(NotFound("/C:/.../file.svg"))`. It is most visible when
the workspace path contains spaces.
## Expected Behavior
CSS `url()` assets resolve on Windows regardless of the drive letter or
spaces in the path.
## Related Issue(s)
Fixes #36336
## Implementation Details
The `postcss-cli-resources` plugin resolved assets by passing
`pathToFileURL(resolvedPath).pathname` to the bundler resolver. That
value is a URL path (`/C:/Users/...`, with spaces percent-encoded), not
a filesystem path, so the resolver could not find the file. On POSIX the
URL pathname coincides with the filesystem path, which is why only
Windows was affected. #34676 fixed an earlier `new URL(winPath,
'file:///')` drive-letter misparse but kept feeding the pathname into
the resolver.
The fix resolves a relative filesystem path derived from `resolvedPath`
instead, and drops the paired `decodeURI` that only existed to undo the
pathname encoding. It is applied to the `@nx/rspack`, `@nx/webpack`, and
`@nx/angular-rspack` copies of the plugin.
The plugin has no existing unit coverage and the resolver needs a real
webpack/rspack loader context, so no automated test was added; the
change was validated with build and lint and cross-checked against
upstream `@angular-devkit/build-angular`.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/gh-36336-b7b11fff)
<!-- polygraph-session-end --> 6df4b1e6 fix(misc): resolve CSS url() assets on Windows in postcss-cli-resources (#36353)
## Current Behavior
On Windows, CSS `url(...)` references to local assets (SVGs, fonts such
as `codicon.ttf`, etc.) fail to resolve during an `@nx/rspack`,
`@nx/webpack`, or `@nx/angular-rspack` build, even when the file exists
on disk. The build reports
`RspackResolver(NotFound("/C:/.../file.svg"))`. It is most visible when
the workspace path contains spaces.
## Expected Behavior
CSS `url()` assets resolve on Windows regardless of the drive letter or
spaces in the path.
## Related Issue(s)
Fixes #36336
## Implementation Details
The `postcss-cli-resources` plugin resolved assets by passing
`pathToFileURL(resolvedPath).pathname` to the bundler resolver. That
value is a URL path (`/C:/Users/...`, with spaces percent-encoded), not
a filesystem path, so the resolver could not find the file. On POSIX the
URL pathname coincides with the filesystem path, which is why only
Windows was affected. #34676 fixed an earlier `new URL(winPath,
'file:///')` drive-letter misparse but kept feeding the pathname into
the resolver.
The fix resolves a relative filesystem path derived from `resolvedPath`
instead, and drops the paired `decodeURI` that only existed to undo the
pathname encoding. It is applied to the `@nx/rspack`, `@nx/webpack`, and
`@nx/angular-rspack` copies of the plugin.
The plugin has no existing unit coverage and the resolver needs a real
webpack/rspack loader context, so no automated test was added; the
change was validated with build and lint and cross-checked against
upstream `@angular-devkit/build-angular`.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/gh-36336-b7b11fff)
<!-- polygraph-session-end --> fc869886 docs(misc): refresh high-impact seo pages and add nx vs lerna comparison (#36307)
## Current Behavior
High-impression pages have near-zero CTR ("pnpm workspace" 450k
impressions, "what is a monorepo", microfrontend, eslint flat config,
GitHub Actions intents). Titles miss query intent and content is stale
(deprecated MF host/remote generators, old screenshots, duplicate
"GitHub Integration"
titles).
## Expected Behavior
- **What is a Monorepo?** (renamed from `why-monorepos`):
definition-first, benefits aligned with monorepo.tools, monolith
distinction, AI agents section
- **Monorepo vs Polyrepo** (renamed from `overview`): tradeoffs table,
corrected release-cadence and version-policy claims, Polygraph for AI
agents across polyrepos
- **pnpm/npm/yarn/bun workspaces**: standalone setup, commands, and best
practices per tool; Nx confined to one final section
- **GitHub Actions integration**: copy-pasteable workflow (Node 24,
latest action majors), Nx Cloud as a delta, current PR bot screenshot;
outdated source-control GitHub guide deleted and redirected here
- **ESLint flat config**: retitled for migration intent, automated path
first with an agent prompt, Next.js native flat config and the
FlatCompat TypeError fix
- **Micro frontend architecture**: definition-first, v23
consumer/provider + `@module-federation/vite` examples, honest
when-not-to guidance
- **Rspack introduction**: real "what is Rspack" opening (fixes the
meaningless Google snippet)
- **Self-hosted remote cache**: retitled to match sidebar, version gate
removed, single Cloud CTA
- **Folder structure**: move/remove generators dropped, folders are
plain `mv`/`rm`
- Redirects added for both renamed slugs and the deleted guide
Previews:
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/concepts/decisions/what-is-a-monorepo
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/concepts/decisions/monorepo-vs-polyrepo
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/features/ci-features/github-integration
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/technologies/eslint/guides/flat-config
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tips-n-tricks/npm-workspaces
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tips-n-tricks/pnpm-workspaces
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tips-n-tricks/yarn-workspaces
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tips-n-tricks/bun-workspaces
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/technologies/build-tools/rspack/introduction
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/technologies/module-federation/concepts/micro-frontend-architecture
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tasks--caching/self-hosted-caching
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/concepts/decisions/folder-structure
## Related Issue(s)
Fixes DOC-549
<!-- polygraph-session-start -->
---
[View session information
↗](https://snapshot.app.trypolygraph.com/orgs/69cdc268b6aa527e4129c2b4/sessions/doc-549-0ca12dc9)
<!-- polygraph-session-end --> fc869886 docs(misc): refresh high-impact seo pages and add nx vs lerna comparison (#36307)
## Current Behavior
High-impression pages have near-zero CTR ("pnpm workspace" 450k
impressions, "what is a monorepo", microfrontend, eslint flat config,
GitHub Actions intents). Titles miss query intent and content is stale
(deprecated MF host/remote generators, old screenshots, duplicate
"GitHub Integration"
titles).
## Expected Behavior
- **What is a Monorepo?** (renamed from `why-monorepos`):
definition-first, benefits aligned with monorepo.tools, monolith
distinction, AI agents section
- **Monorepo vs Polyrepo** (renamed from `overview`): tradeoffs table,
corrected release-cadence and version-policy claims, Polygraph for AI
agents across polyrepos
- **pnpm/npm/yarn/bun workspaces**: standalone setup, commands, and best
practices per tool; Nx confined to one final section
- **GitHub Actions integration**: copy-pasteable workflow (Node 24,
latest action majors), Nx Cloud as a delta, current PR bot screenshot;
outdated source-control GitHub guide deleted and redirected here
- **ESLint flat config**: retitled for migration intent, automated path
first with an agent prompt, Next.js native flat config and the
FlatCompat TypeError fix
- **Micro frontend architecture**: definition-first, v23
consumer/provider + `@module-federation/vite` examples, honest
when-not-to guidance
- **Rspack introduction**: real "what is Rspack" opening (fixes the
meaningless Google snippet)
- **Self-hosted remote cache**: retitled to match sidebar, version gate
removed, single Cloud CTA
- **Folder structure**: move/remove generators dropped, folders are
plain `mv`/`rm`
- Redirects added for both renamed slugs and the deleted guide
Previews:
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/concepts/decisions/what-is-a-monorepo
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/concepts/decisions/monorepo-vs-polyrepo
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/features/ci-features/github-integration
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/technologies/eslint/guides/flat-config
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tips-n-tricks/npm-workspaces
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tips-n-tricks/pnpm-workspaces
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tips-n-tricks/yarn-workspaces
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tips-n-tricks/bun-workspaces
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/technologies/build-tools/rspack/introduction
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/technologies/module-federation/concepts/micro-frontend-architecture
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/guides/tasks--caching/self-hosted-caching
-
https://deploy-preview-36307--nx-docs.netlify.app/docs/concepts/decisions/folder-structure
## Related Issue(s)
Fixes DOC-549
<!-- polygraph-session-start -->
---
[View session information
↗](https://snapshot.app.trypolygraph.com/orgs/69cdc268b6aa527e4129c2b4/sessions/doc-549-0ca12dc9)
<!-- polygraph-session-end --> 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 8da06a7c chore(repo): add performance-analyzer agent to review-pr skill (#36342)
## Current Behavior
The `/review-pr` skill runs the pr-review-toolkit agents (correctness,
tests, comments, types, silent failures), the alternative-approach
agent, and the reproduce-verifier agent — but nothing in the pipeline
examines a PR's runtime cost or its security posture. A change that adds
an accidental per-commit graph walk, or one that extracts an untrusted
tarball without path containment, passes review with no dedicated
scrutiny.
## Expected Behavior
Two new review agents are dispatched in parallel with the existing
toolkit, each with an explicit calibration so it reports only real
findings and endorses sound code otherwise:
- **`performance-analyzer`** (Step 5a.2) — checks CPU/memory footprint
and execution speed. Classifies each changed runtime path as
hot/warm/cold and only reports findings on hot or warm paths; every
finding must carry a call-frequency/scaling argument. Verdicts:
`PERFORMANCE_REGRESSION` (critical), `PERFORMANCE_CONCERN` (important),
`PERFORMANCE_SOUND` (folds into Strengths).
- **`security-analyzer`** (Step 5a.3) — hunts injection-class
vulnerabilities (command injection, zip-slip/path traversal, prototype
pollution, SSRF, credential leakage). Built around an explicit nx trust
model: workspace config, CLI args, and migration metadata are trusted
(nx executes workspace code by design), so a finding requires a complete
chain from an *untrusted* source (network responses, downloaded
archives, other people's git data) into a dangerous sink. Verdicts:
`SECURITY_VULNERABILITY` (critical), `SECURITY_CONCERN` (important),
`SECURITY_SOUND` (folds into Strengths).
The `PERFORMANCE_REGRESSION` bar is set so that any command measurably
slower at scale is critical — a blowup confined to a single command
(e.g. `nx release`) still counts.
Both agents were validated blind against real historical PRs: the
performance agent flagged the `nx release` slowdown from #32915 (issue
#33865) and correctly endorsed the deliberate hot-path trade-offs in
#34971; the security agent independently rediscovered the
self-hosted-cache zip-slip introduced in #30593 and later fixed in
#36116.
## Related Issue(s)
N/A 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 8da06a7c chore(repo): add performance-analyzer agent to review-pr skill (#36342)
## Current Behavior
The `/review-pr` skill runs the pr-review-toolkit agents (correctness,
tests, comments, types, silent failures), the alternative-approach
agent, and the reproduce-verifier agent — but nothing in the pipeline
examines a PR's runtime cost or its security posture. A change that adds
an accidental per-commit graph walk, or one that extracts an untrusted
tarball without path containment, passes review with no dedicated
scrutiny.
## Expected Behavior
Two new review agents are dispatched in parallel with the existing
toolkit, each with an explicit calibration so it reports only real
findings and endorses sound code otherwise:
- **`performance-analyzer`** (Step 5a.2) — checks CPU/memory footprint
and execution speed. Classifies each changed runtime path as
hot/warm/cold and only reports findings on hot or warm paths; every
finding must carry a call-frequency/scaling argument. Verdicts:
`PERFORMANCE_REGRESSION` (critical), `PERFORMANCE_CONCERN` (important),
`PERFORMANCE_SOUND` (folds into Strengths).
- **`security-analyzer`** (Step 5a.3) — hunts injection-class
vulnerabilities (command injection, zip-slip/path traversal, prototype
pollution, SSRF, credential leakage). Built around an explicit nx trust
model: workspace config, CLI args, and migration metadata are trusted
(nx executes workspace code by design), so a finding requires a complete
chain from an *untrusted* source (network responses, downloaded
archives, other people's git data) into a dangerous sink. Verdicts:
`SECURITY_VULNERABILITY` (critical), `SECURITY_CONCERN` (important),
`SECURITY_SOUND` (folds into Strengths).
The `PERFORMANCE_REGRESSION` bar is set so that any command measurably
slower at scale is critical — a blowup confined to a single command
(e.g. `nx release`) still counts.
Both agents were validated blind against real historical PRs: the
performance agent flagged the `nx release` slowdown from #32915 (issue
#33865) and correctly endorsed the deliberate hot-path trade-offs in
#34971; the security agent independently rediscovered the
self-hosted-cache zip-slip introduced in #30593 and later fixed in
#36116.
## Related Issue(s)
N/A 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 658c6ee7 fix(core): close daemon log descriptors after spawn to avoid Node 26 crash (#36280)
## Current Behavior
Nx commands that start the daemon open two file descriptors on the
daemon log and keep them open for the whole process, letting garbage
collection close them. On Node 26 a file descriptor closed during
garbage collection is a fatal `ERR_INVALID_STATE` error, so when GC
collects those descriptors before the process exits, the command crashes
with a non-zero exit code after its work has already completed. On Node
20-24 the same pattern only prints a deprecation warning.
This surfaces as flaky failures on Node 26, e.g. the release lock-file
e2e (`should not update pnpm-lock.yaml when package manager is pnpm (>=
9)`), where the crash makes `execSync` throw even though the release ran
correctly.
## Expected Behavior
The daemon's stdout/stderr are redirected into the log through
descriptors that the parent closes immediately after spawning the
detached daemon. The child keeps its own dup'd descriptors, so daemon
logging is unchanged, while the parent no longer holds a descriptor that
GC can close. Commands that start the daemon now exit cleanly on Node
26.
## Implementation Details
`startInBackground` opened the log with `fs/promises` `open` (a
`FileHandle`) and stored the handles on the client, closing them only in
`reset()`, which runs on daemon socket-close. A command that starts the
daemon and leaves it running never hit that path, so the handles were
left for GC to close. The handles are now opened with `openSync` and
closed with `closeSync` right after `spawn`; a raw descriptor has no GC
finalizer, so the failure cannot recur. This also removes the `reset()`
cleanup and the earlier reset-race workaround, since nothing is retained
on the client.
<!-- polygraph-session-start -->
---
[View session information
↗](https://app.trypolygraph.com/orgs/6a061dcb561c062131116eca/sessions/troubleshoot-flaky-tasks-e92822a8)
<!-- polygraph-session-end -->
---------
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> 8da06a7c chore(repo): add performance-analyzer agent to review-pr skill (#36342)
## Current Behavior
The `/review-pr` skill runs the pr-review-toolkit agents (correctness,
tests, comments, types, silent failures), the alternative-approach
agent, and the reproduce-verifier agent — but nothing in the pipeline
examines a PR's runtime cost or its security posture. A change that adds
an accidental per-commit graph walk, or one that extracts an untrusted
tarball without path containment, passes review with no dedicated
scrutiny.
## Expected Behavior
Two new review agents are dispatched in parallel with the existing
toolkit, each with an explicit calibration so it reports only real
findings and endorses sound code otherwise:
- **`performance-analyzer`** (Step 5a.2) — checks CPU/memory footprint
and execution speed. Classifies each changed runtime path as
hot/warm/cold and only reports findings on hot or warm paths; every
finding must carry a call-frequency/scaling argument. Verdicts:
`PERFORMANCE_REGRESSION` (critical), `PERFORMANCE_CONCERN` (important),
`PERFORMANCE_SOUND` (folds into Strengths).
- **`security-analyzer`** (Step 5a.3) — hunts injection-class
vulnerabilities (command injection, zip-slip/path traversal, prototype
pollution, SSRF, credential leakage). Built around an explicit nx trust
model: workspace config, CLI args, and migration metadata are trusted
(nx executes workspace code by design), so a finding requires a complete
chain from an *untrusted* source (network responses, downloaded
archives, other people's git data) into a dangerous sink. Verdicts:
`SECURITY_VULNERABILITY` (critical), `SECURITY_CONCERN` (important),
`SECURITY_SOUND` (folds into Strengths).
The `PERFORMANCE_REGRESSION` bar is set so that any command measurably
slower at scale is critical — a blowup confined to a single command
(e.g. `nx release`) still counts.
Both agents were validated blind against real historical PRs: the
performance agent flagged the `nx release` slowdown from #32915 (issue
#33865) and correctly endorsed the deliberate hot-path trade-offs in
#34971; the security agent independently rediscovered the
self-hosted-cache zip-slip introduced in #30593 and later fixed in
#36116.
## Related Issue(s)
N/A