Skip to content

Auto-deny ignored pnpm builds#3843

Merged
wwwillchen merged 6 commits into
mainfrom
update-app-code-20260708172137
Jul 9, 2026
Merged

Auto-deny ignored pnpm builds#3843
wwwillchen merged 6 commits into
mainfrom
update-app-code-20260708172137

Conversation

@keppo-bot

@keppo-bot keppo-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Auto-deny ignored pnpm builds so users never get stuck on ERR_PNPM_IGNORED_BUILDS (pnpm 11 defaults strictDepBuilds to true, so a fresh install of an app with an unapproved-build dependency exits 1 β€” e.g. Rebuild on apps with custom install commands, or deploys/CI of exported repos).

Implements plans/pnpm-auto-deny-ignored-builds.md:

  • Proactive denial: after each Dyad-run pnpm install, read node_modules/.modules.yaml (JSON on pnpm 10/11, block-YAML fallback) and record pkg: false # dyad-auto-denied entries in pnpm-workspace.yaml outside the Dyad-managed block, then commit β€” so plain pnpm install succeeds everywhere (CI, Vercel, terminals).
  • Promotion & repair: when the curated allow-list later includes an auto-denied package, the tagged denial is removed, the managed block emits pkg: true, and callers run a best-effort pnpm rebuild <pkgs> (cross-shell-safe, works under cmd.exe) after install. User-authored entries are never touched.
  • Reactive self-heal: on ERR_PNPM_IGNORED_BUILDS from custom install commands or the Capacitor/component-tagger flows, record denials, clear node_modules, and retry once.
  • Agent visibility: the <dyad-add-dependency> results note when build scripts were denied.
  • Telemetry: pnpm:build-auto-denied events (bypassing non-Pro 10% sampling via the pnpm:build- prefix) feed curation of the remote allow-list.

Tests

  • Unit: allow-builds transform (denial tagging, promotion, ownership), real-format JSON .modules.yaml fixture, rebuild-command quoting/filtering, output-parser forms, telemetry bypass.
  • E2E: real-pnpm test where a custom strict install command hits ignored builds and Rebuild recovers to a working preview.

@keppo-bot keppo-bot Bot requested a review from a team July 9, 2026 00:23
@wwwillchen

Copy link
Copy Markdown
Collaborator

@BugBot run

@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: 58f4d4538b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 πŸ‘.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/ipc/services/app_runtime_service.ts Outdated
Comment thread src/ipc/services/app_runtime_service.ts
Comment thread src/ipc/services/app_runtime_service.ts Outdated

@dyad-assistant dyad-assistant Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Claude review: 2 inline finding(s).

Comment thread src/ipc/services/app_runtime_service.ts
Comment thread src/ipc/utils/cloud_sandbox_provider.ts Outdated
@dyad-assistant

dyad-assistant Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: βœ… YES - Ready to merge
Recommendation: ready

This is a well-designed and carefully implemented feature that solves a real user-facing problem (apps stuck on ERR_PNPM_IGNORED_BUILDS). The YAML manipulation is careful with markers and managed block boundaries, the retry logic is correctly bounded to one attempt, promotion/denial lifecycle is clean, and telemetry is properly wired with sampling bypass. Tests cover the key scenarios including denial recording, promotion, and the self-heal retry path.

Issues Summary

Severity File Issue
🟑 MEDIUM src/ipc/services/app_runtime_service.ts:638 processOutput accumulates unboundedly for all process lifetimes
🟑 MEDIUM src/ipc/utils/cloud_sandbox_provider.ts:141 quoteShellArg duplicated across two files
🟒 Low Priority Notes (2 items)
  • Plan doc included in production repo - plans/pnpm-auto-deny-ignored-builds.md is a 187-line design document committed to the repo. Consider whether this should live in a wiki or docs directory instead. (plans/pnpm-auto-deny-ignored-builds.md)

  • selfHealDeniedPnpmBuilds duplicated across files - Both app_runtime_service.ts and app_upgrade_utils.ts have their own self-heal functions (selfHealDeniedPnpmBuilds and selfHealDeniedPnpmBuildsFromError) with similar but slightly different signatures. These could share a common core. (src/ipc/utils/app_upgrade_utils.ts)


Generated by Dyadbot persona-based code review

@wwwillchen

Copy link
Copy Markdown
Collaborator

@BugBot run

@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: e656ab7f11

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 πŸ‘.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/ipc/utils/cloud_sandbox_provider.ts
Comment thread src/ipc/utils/socket_firewall.ts Outdated

@dyad-assistant dyad-assistant Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Claude review: 4 inline finding(s).

Comment thread src/ipc/services/app_runtime_service.ts
Comment thread src/ipc/services/app_runtime_service.ts
Comment thread src/ipc/utils/app_upgrade_utils.ts
Comment thread src/ipc/services/app_runtime_service.ts Outdated
@dyad-assistant

dyad-assistant Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: β›” NO - Do NOT merge
Recommendation: auto-fix

This PR implements a well-designed auto-deny mechanism for pnpm builds not on Dyad's curated allow-list, with proactive denial recording, self-healing for custom commands, promotion when the allow-list evolves, and telemetry for curation. The plan doc is thorough, tests are comprehensive, and the core YAML manipulation logic is correct (backward splice iteration, scoped package name parsing, idempotent writes all verified). One HIGH issue should be fixed before merge.

Issues Summary

Severity File Issue
πŸ”΄ HIGH src/ipc/services/app_runtime_service.ts:642 Unbounded processOutput accumulation causes memory growth for long-running dev servers
🟑 MEDIUM src/ipc/services/app_runtime_service.ts:716 Async IIFE in close handler has no top-level error boundary
🟑 MEDIUM src/ipc/utils/app_upgrade_utils.ts:100 Self-heal retry in upgrade utils does not remove node_modules unlike the runtime variant
🟑 MEDIUM src/ipc/services/app_runtime_service.ts:735 No user-visible feedback when self-heal triggers during app runtime

πŸ”΄ Unbounded processOutput accumulation β€” listenToProcess unconditionally appends all stdout and stderr to a processOutput string for the entire lifetime of the spawned process. For long-running dev servers (typical Dyad usage involves hours-long sessions with HMR logging), this string grows without bound. The accumulation happens even when onPnpmIgnoredBuildsFailure is undefined (all default/non-custom commands), despite only being needed in the close handler to detect ERR_PNPM_IGNORED_BUILDS. Fix: guard accumulation with if (onPnpmIgnoredBuildsFailure) and cap at ~256KB since the error appears early in the install phase.

🟑 Async IIFE in close handler β€” The close handler wraps all logic in void (async () => { ... })(). The onPnpmIgnoredBuildsFailure call is properly try/caught, but any future code additions after the catch block would have errors silently swallowed. This pattern is consistent with existing codebase conventions, so it's not a blocker, but adding a top-level catch around the IIFE body would make the critical lifecycle handler more robust.

🟑 Inconsistent node_modules removal β€” selfHealDeniedPnpmBuilds (runtime) removes node_modules before retrying, but selfHealDeniedPnpmBuildsFromError (upgrade utils) does not. The upgrade paths primarily use pnpm add commands that don't hit the "Already up to date" fast-path, so the practical risk is low, but the inconsistency could cause subtle failures if the upgrade paths evolve.

🟑 Silent self-heal β€” When self-heal triggers during app runtime (custom command), the user sees the process exit and restart with no explanation. The add-dependency flow provides a clear security-policy note, but the runtime path is silent. Adding an app:output message before retry would give users context.

🟒 Low Priority Notes (3 items)
  • quoteShellArg duplication β€” Identical function in app_runtime_service.ts and cloud_sandbox_provider.ts. Low risk since the function is trivially correct, but extracting to a shared utility would prevent future drift. (src/ipc/services/app_runtime_service.ts, src/ipc/utils/cloud_sandbox_provider.ts)

  • Near-duplicate self-heal functions β€” selfHealDeniedPnpmBuilds (runtime) and selfHealDeniedPnpmBuildsFromError (upgrade utils) perform essentially the same logic with slightly different input handling. If the self-heal logic needs to change, both must be updated in sync. (src/ipc/services/app_runtime_service.ts, src/ipc/utils/app_upgrade_utils.ts)

  • Verified non-issues β€” getPnpmIgnoredBuildPackageName correctly handles scoped packages via lastIndexOf("@"). removeAutoDeniedPromotedBuilds backward-splice iteration is correct. Self-heal retry cannot infinite-loop due to ignoredBuildsSelfHealAttempted boolean. recordDeniedPnpmBuilds uses atomic temp-file-then-rename writes.


Generated by Dyadbot persona-based code review

… chain, bounded output tail

- pnpm 10.x/11.x write node_modules/.modules.yaml as JSON; parse JSON first
  with the block-YAML line parser as fallback, so the proactive auto-deny
  path actually detects ignored builds on real installs
- Replace the inline "(pnpm rebuild 'x' || true)" chain with a shared
  getBestEffortPnpmRebuildCommand that emits unquoted validated names and
  an echo fallback, both of which work under cmd.exe as well as sh
- Cap the self-heal process-output buffer at a 64KB rolling tail and only
  accumulate when a self-heal callback is attached, so long-running dev
  servers don't grow memory unboundedly
- Strip the trailing period/box borders in the ignored-builds output parser
- Add unit coverage: real JSON .modules.yaml fixture, rebuild command
  quoting/filtering, output-parser forms

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wwwillchen

Copy link
Copy Markdown
Collaborator

@BugBot run

@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: 8a4ed54530

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 πŸ‘.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/ipc/services/app_runtime_service.ts
- Record ignored builds after successful default app installs (host and
  Docker) once the dev-server URL appears, so first-install-via-run apps
  also get pkg:false entries committed
- Detect "Ignored build scripts" in cloud sandbox log streams and record
  denials locally (node_modules never syncs back from the sandbox)
- Record denials against existing config when the remote allow-list fetch
  fails instead of skipping entirely
- Wrap the process close-handler async IIFE in a try/catch that falls back
  to removeAppIfCurrentProcess
- Emit a user-visible app:output message when runtime self-heal records
  denials and reinstalls
- Document why the upgrade-path self-heal retry doesn't need to remove
  node_modules

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wwwillchen

Copy link
Copy Markdown
Collaborator

@BugBot run

Custom install && start chains run strict pnpm inside the container too;
mirror the host retry path (no host node_modules cleanup β€” the container
volume is what matters and explicit false entries pass fast-path installs).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wwwillchen

Copy link
Copy Markdown
Collaborator

@BugBot run

@keppo-bot

keppo-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

πŸ€– Claude Code Review Summary

PR Confidence: 4/5

All 12 review threads were addressed with verified fixes and passing unit tests, typecheck, and lint; the remaining risk is that the Docker and cloud-sandbox self-heal paths rely on shared mechanisms rather than dedicated E2E coverage.

Unresolved Threads

No unresolved threads

Resolved Threads

Issue Rationale Link
Unbounded process-output accumulation (3 threads) Fixed in 8a4ed54: 64KB rolling tail, only accumulated while a self-heal callback is attached View
Windows-unsafe rebuild chain + duplicated quoteShellArg (2 threads) Fixed in 8a4ed54: shared getBestEffortPnpmRebuildCommand with unquoted validated names and an echo fallback that works under cmd.exe and sh View
Ignored builds not recorded after default app-run installs Fixed in 9f4e095: recorded once the dev-server URL appears (install phase complete), for host and Docker default runs View
Cloud-sandbox ignored builds never persisted locally Fixed in 9f4e095: sandbox log stream watches for the β€œIgnored build scripts” line (bounded tail) and records denials locally View
Denials skipped when the remote allow-list fetch fails Fixed in 9f4e095: denial-only insert against existing config; existing keys still respected; unit-tested View
Close-handler async IIFE lacked an error boundary Fixed in 9f4e095: try/catch with fallback removeAppIfCurrentProcess View
Upgrade-path self-heal doesn’t remove node_modules Addressed in 9f4e095 with the suggested comment: explicit false entries pass even fast-path installs (verified on pnpm 11.10), so removal is unnecessary View
No user-visible feedback when runtime self-heal restarts the app Fixed in 9f4e095 per Principle #4: Transparent Over Magical β€” an explanatory [dyad] message is emitted to app output before the retry View
Docker custom-command installs missed the self-heal retry Fixed in fac6aa7: same callback wired through the Docker listener; skips host node_modules cleanup since the container volume is authoritative View
Product Principle Suggestions

No suggestions β€” Principle #4 (Transparent Over Magical) directly resolved the one judgment-call thread; all other threads were objective correctness/robustness issues.


πŸ€– Generated by Claude Code

@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: fac6aa7059

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 πŸ‘.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/ipc/utils/socket_firewall.ts
Comment thread src/ipc/utils/socket_firewall.ts

@dyad-assistant dyad-assistant Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Claude review: 2 inline finding(s).

Comment thread src/ipc/utils/app_upgrade_utils.ts
Comment thread src/ipc/utils/socket_firewall.ts
@dyad-assistant

dyad-assistant Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: βœ… YES - Ready to merge
Recommendation: ready

This is a well-structured PR that solves a real user-facing problem (apps stuck on ERR_PNPM_IGNORED_BUILDS) with a sound design: proactive denial with # dyad-auto-denied markers, a promotion pass for curated allow-list updates, and reactive self-heal with a single-retry guard. The implementation is thorough across local, Docker, and cloud sandbox paths, with proper command injection protection (SAFE_PNPM_PACKAGE_NAME_PATTERN), atomic file writes, and bounded output buffers that prevent memory leaks. Test coverage is extensive, including unit tests for YAML manipulation, promotion/demotion round-trips, output parsing, rebuild command safety, telemetry bypass, and an E2E test verifying real pnpm strict-mode recovery.

Key correctness points verified:

  • No infinite retry: ignoredBuildsSelfHealAttempted flag prevents recursion in both local and Docker paths; simpleSpawnWithDeniedPnpmBuildSelfHeal retries exactly once.
  • Close handler async IIFE: The void (async () => { try { ... } catch { cleanup } })() pattern is correct; the outer try/catch ensures removeAppIfCurrentProcess is always called on unexpected errors.
  • Process output buffer: Bounded at 64KB, only allocated when self-heal is possible, and eligible for GC after the close handler completes.
  • Promotion logic: removeAutoDeniedPromotedBuilds correctly iterates in reverse to avoid index shifts during splice, only removes lines with the # dyad-auto-denied marker, and never touches user-authored entries.
  • Telemetry bypass: Added for pnpm:build- prefix with a unit test.

Issues Summary

Severity File Issue
🟑 MEDIUM src/ipc/utils/app_upgrade_utils.ts:61 Duplicated read-record-telemetry pattern across three functions
🟑 MEDIUM src/ipc/utils/socket_firewall.ts:443 insertAutoDeniedBuilds silently drops denials when allowBuilds key is absent
🟒 Low Priority Notes (2 items)
  • Telemetry bypass uses prefix matching - eventName?.startsWith("pnpm:build-") is broader than the single pnpm:build-auto-denied event documented in the plan. The pnpm:build- namespace is clearly owned so risk is low, but an exact match would be more defensive. (src/lib/posthogTelemetry.ts)

  • Capacitor fallback loses self-heal context - In app_upgrade_handlers.ts, when simpleSpawnWithDeniedPnpmBuildSelfHeal throws after its single retry, the catch falls back to npm install which is correct. However, the npm fallback runs all build scripts unconditionally (pre-existing posture), so a denied-then-npm-allowed build could surprise users if they later switch back to pnpm. This is noted in the plan as a known inconsistency and is not a regression. (src/ipc/handlers/app_upgrade_handlers.ts)


Generated by Dyadbot persona-based code review

@github-actions github-actions Bot added the needs-human:review-issue ai agent flagged an issue that requires human review label Jul 9, 2026
- Convert pnpm 11 placeholder allowBuilds entries ("set this to true or
  false") into tagged denials during every Dyad rewrite; verified the
  placeholder is written by non-strict installs, does not satisfy strict
  mode, and previously shadowed the auto-deny pass entirely
- Create the allowBuilds key when the offline denial-only path runs against
  a config that lost it
- Extract recordAndReportDeniedPnpmBuilds + resolvePnpmIgnoredBuilds into
  pnpm_denied_builds.ts so the record+telemetry contract has one owner
  across add-dependency, app-run, self-heal, and cloud-sandbox flows

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@wwwillchen

Copy link
Copy Markdown
Collaborator

@BugBot run

@keppo-bot

keppo-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

πŸ€– Claude Code Review Summary

PR Confidence: 4/5

All 16 review threads across both rounds are addressed with empirically verified fixes and 122 passing unit tests; remaining risk is limited to paths covered by shared mechanisms rather than dedicated E2E (Docker/cloud self-heal).

Unresolved Threads

No unresolved threads

Resolved Threads

Issue Rationale Link
pnpm 11 placeholder allowBuilds entries defeat the auto-deny pass (P1) Confirmed by repro (pnpm 11.10 appends set this to true or false, which still fails strict installs); every Dyad rewrite now converts placeholders into tagged denials or managed true. Fixed in d4dad15 View
file: dependency denials allegedly need full matchers Not reproducible on pnpm 10.28.1 (the cited version), 10.33.2, or 11.10.0 β€” bare-name false suppresses the strict failure on all three; likely confounded by the placeholder bug above, which is now fixed. Resolved with repro details View
Duplicated read-record-telemetry pattern across three functions Extracted recordAndReportDeniedPnpmBuilds + resolvePnpmIgnoredBuilds into pnpm_denied_builds.ts; all five flows share them. Fixed in d4dad15 View
Offline denial path silently drops denials when the allowBuilds key is absent The denial-only path now creates the key before inserting, with a unit test. Fixed in d4dad15 View
Product Principle Suggestions

No suggestions β€” all four threads were objective correctness/maintainability issues; two were settled by direct empirical testing of pnpm behavior rather than judgment calls.


πŸ€– Generated by Claude Code

@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: d4dad15948

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 πŸ‘.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +568 to +570
const packagesToDeny = [
...autoDeniedPackageNames,
...removePlaceholderAllowBuildsEntries(lines),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Rebuild packages promoted from pnpm placeholders

When an existing pnpm-workspace.yaml has a pnpm placeholder such as sharp: set this to true or false and the refreshed allow-list now includes sharp, these placeholder names are only fed into packagesToDeny; insertAutoDeniedBuilds then filters them out because source.packages allows them, while promotedPackages stays empty. Callers therefore skip the rebuild command used for # dyad-auto-denied promotions, so a dependency that was already installed with its build script skipped can remain unrepaired after Dyad converts it to sharp: true.

Useful? React with πŸ‘Β / πŸ‘Ž.

@dyad-assistant dyad-assistant Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Claude review: 1 inline finding(s).

if (deniedBuilds.length === 0) {
return { deniedBuilds: [] };
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟑 MEDIUM

Uncommitted workspace file when recordDeniedPnpmBuilds promotes without denying

In recordDeniedPnpmBuilds, when updatePnpmAllowBuildsConfigContentWithSource produces promotions (removing dyad-auto-denied lines) but no new denials, the file is written to disk (content !== existingContent) but the git commit is skipped (deniedBuilds.length === 0). This leaves an uncommitted pnpm-workspace.yaml change. In the normal app-run path this is harmless because commitPnpmAllowBuildsConfigIfChanged already committed promotions. However, in the self-heal path (called from selfHealDeniedPnpmBuilds without a prior commitPnpmAllowBuildsConfigIfChanged), a concurrent allow-list update could leave a dirty working tree. The scenario is narrow (self-heal + concurrent curated list update) and the uncommitted change is benign (a promotion), but it breaks the invariant that recordDeniedPnpmBuilds leaves the repo clean.

πŸ’‘ Suggestion: After writing the file, also commit when updateResult.promotedPackages.length > 0 even if deniedBuilds is empty, or early-return before writing when deniedPackages is empty and promotedPackages would be handled by a separate commit.

@dyad-assistant

dyad-assistant Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: βœ… YES - Ready to merge
Recommendation: ready

Well-engineered PR that solves a real user-facing problem (pnpm 11 ERR_PNPM_IGNORED_BUILDS breaking Rebuild and exported repos). The implementation follows the design doc closely with careful attention to security, correctness, and edge cases.

Issues Summary

Severity File Issue
🟑 MEDIUM src/ipc/utils/socket_firewall.ts:1086 Uncommitted workspace file when recordDeniedPnpmBuilds promotes without denying

MEDIUM detail: In recordDeniedPnpmBuilds, if the allow-list source promotes previously auto-denied packages (removing # dyad-auto-denied lines) but no new denials are produced, the updated pnpm-workspace.yaml is written to disk but the git commit is skipped (deniedBuilds.length === 0 guard). In the normal app-run path this is harmless since commitPnpmAllowBuildsConfigIfChanged already committed promotions upstream. In the self-heal path, however, there is no prior commit call, so a concurrent curated-list update could leave a dirty working tree. The scenario is narrow and the uncommitted change is benign, but it breaks the repo-clean invariant.

🟒 Low Priority Notes (5 items)
  • Close handler async IIFE is correctly structured - The void (async () => { ... })() pattern in the close handler properly wraps removeAppIfCurrentProcess in both the success and catch paths, preventing stale runningApps entries. The guard currentAppInfo.process !== spawnedProcess correctly handles the case where a retry has already overwritten the entry. (src/ipc/services/app_runtime_service.ts)

  • Shell injection protection in getBestEffortPnpmRebuildCommand is sound - The SAFE_PNPM_PACKAGE_NAME_PATTERN regex (/^(@[a-z0-9-_.]+\/)?[a-z0-9-_.]+$/i) correctly rejects spaces, semicolons, backticks, $(), and other shell metacharacters. The cross-shell fallback (echo instead of || true) is correct for cmd.exe compatibility. (src/ipc/utils/socket_firewall.ts)

  • Process output buffer is properly bounded - processOutput is capped at 64KB via slice(-MAX_PROCESS_OUTPUT_TAIL_LENGTH) and only accumulated when onPnpmIgnoredBuildsFailure is set (custom commands only), preventing memory waste for default install-and-dev chains. (src/ipc/services/app_runtime_service.ts)

  • Single-retry design in simpleSpawnWithDeniedPnpmBuildSelfHeal is correct - The function calls simpleSpawn directly on retry (not itself), guaranteeing at most one retry attempt. This matches the design doc's "retry exactly once" requirement. (src/ipc/utils/app_upgrade_utils.ts)

  • YAML duplicate key prevention is thorough - insertAutoDeniedBuilds checks both existingKeys (all current allowBuilds entries) and sourcePackageSet (curated allow-list), and the promotion pass runs before the managed-block rewrite, ensuring no state can contain both an outside false and a managed true for the same key. (src/ipc/utils/socket_firewall.ts)


Generated by Dyadbot persona-based code review

@wwwillchen wwwillchen merged commit cc00c6e into main Jul 9, 2026
16 of 22 checks passed
@wwwillchen wwwillchen deleted the update-app-code-20260708172137 branch July 9, 2026 02:31
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

❌ Some tests failed

OS Passed Failed Flaky Skipped
🍎 macOS 383 2 4 119
πŸͺŸ Windows 381 3 2 119

Summary: 764 passed, 5 failed, 6 flaky, 238 skipped

Failed Tests

🍎 macOS

  • package_manager.spec.ts > build mode - safe npm package installs through the real socket firewall path
    • Error: Command failed: npx --prefer-offline --yes sfw@2.0.4 --help
  • package_manager.spec.ts > custom pnpm install auto-denies ignored builds and recovers preview
    • Test timeout of 360000ms exceeded.

πŸͺŸ Windows

  • edit_code.spec.ts > edit code edits the right file during rapid switches
    • Error: expect(received).toEqual(expected) // deep equality
  • package_manager.spec.ts > custom pnpm install auto-denies ignored builds and recovers preview
    • Test timeout of 360000ms exceeded.
  • template-create-nextjs.spec.ts > create next.js app
    • Error: expect(locator).toBeEnabled() failed

πŸ“‹ Re-run Failing Tests (macOS)

Copy and paste to re-run all failing spec files locally:

npm run e2e \
  e2e-tests/package_manager.spec.ts

⚠️ Flaky Tests

🍎 macOS

  • approve.spec.ts > write to index, approve, check preview (passed after 1 retry)
  • cloud_sandbox.spec.ts > cloud sandbox runtime mode runs previews (passed after 1 retry)
  • package_manager.spec.ts > build mode - blocked unsafe npm package shows the real socket verdict and preserves app files (passed after 2 retries)
  • template-create-nextjs.spec.ts > create next.js app (passed after 1 retry)

πŸͺŸ Windows

  • app_screenshot.spec.ts > captures an app screenshot after the first generated commit (passed after 1 retry)
  • concurrent_chat.spec.ts > concurrent chat (passed after 1 retry)

πŸ“Š View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human:review-issue ai agent flagged an issue that requires human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant