[PR #1999] [MERGED] fix(process): report the Swift compiler outcome with bounded diagnostics #4956

Closed
opened 2026-10-31 00:57:22 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1999
Author: @jimpablo
Created: 10/12/2026
Status: ✅ Merged
Merged: 10/12/2026
Merged by: @morluto

Base: main ← Head: fix/darwin-compiler-diagnostics


📝 Commits (2)

  • 8591083 fix(process): report the Swift compiler outcome with bounded diagnostics
  • 1ccc26e fix(process): keep a signaled compiler's null exit code

📊 Changes

2 files changed (+153 additions, -12 deletions)

View changed files

📝 src/process/DarwinProcessRunTokenReader.ts (+56 -8)
📝 tests/boundary/process/darwinProcessRunTokenReader.test.ts (+97 -4)

📄 Description

Summary

Fixes #1993. The Darwin process-ownership helper compilation surfaced only cause.code and cause.message from the rejected compile. At the 60 s deadline that produced compiler result: ETIMEDOUT): Command timed out after 60000 ms: /usr/bin/xcrun with the compiler's captured stderr discarded, so a broken Swift/SDK pairing was indistinguishable from a genuinely slow compile — the exact report in #1993.

Problem and expected behavior

  • Smallest trigger: a Command Line Tools pairing where xcrun swiftc prints SDK-mismatch diagnostics and stops responding; the helper failure reports only the generic timeout, with no exit code and no diagnostics.
  • Violated invariant: a failure must preserve its meaningful reason; the rejected execFileOutput error already carries stdout/stderr, and the reader dropped them.
  • New behavior: the failure message names the observed compiler outcome — exit code N, timed out after N ms, or stopped by signal S — followed by a bounded stderr excerpt (512 characters, truncation marked), or an explicit no compiler diagnostics were captured when nothing was captured. Toolchain breakage is now distinguishable from a slow compile in both shapes.

Change and scope

  • src/process/DarwinProcessRunTokenReader.ts: the compile catch now reads the failure through the existing execFileOutputFailure extractor. compilerOutcome names the outcome without implying an exit code a timeout lacks; compilerDiagnostics bounds the excerpt at 512 characters (following the stderr_excerpt precedent in AdbConfiguration/ApktoolConfiguration) and marks truncation, including the ERR_CHILD_PROCESS_STDIO_MAXBUFFER case. COMPILER_TIMEOUT_MS replaces the inline 60_000, and a compileTimeoutMs factory option lets verification exercise the deadline in milliseconds; the production default is unchanged.
  • ENOENT wording and the cancellation mapping are unchanged. NativeUiHelperRuntime compiles a sibling Swift helper with the same shape; it is left unchanged here and can follow separately with its own report.
  • Not attempted: root-causing why the reporter's mismatched-CLT invocation reached the deadline under REA's environment while a direct run failed in ~23 s. This change surfaces whatever the compiler printed in either shape.

Contract and boundary impact

  • Semantic owner and earliest changed stage: the Darwin helper compilation failure mapping in src/process/DarwinProcessRunTokenReader.ts, before normalizeCaptureFailure wraps the message.
  • CLI and MCP/tool-catalog contract: none. Error message text only; no tool, schema, parameter, or error-code change.
  • Provider, bridge, target-format, or platform compatibility: macOS-only helper; no engine, bridge, or target-format change.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Process execution, authorization, cleanup, or containment impact: none. Spawn, stop signal, grace kill, timeout semantics, and root cleanup are unchanged; the existing cancellation and cleanup tests in the same lane are unmodified and green.
  • Generated metadata, package, or installation impact: none.

Evidence and regression coverage

  • Tests added or updated in tests/boundary/process/darwinProcessRunTokenReader.test.ts: the fast-failure case now asserts the exact message …(compiler result: exit code 1): module cache is not writable; a new deadline case runs a compiler that prints an SDK-style diagnostic and then stops responding, and asserts …(compiler result: timed out after 500 ms): <diagnostic>; a new bound case asserts a 600-character diagnostic is cut at 512 characters with an explicit truncation marker.

  • Base reproduction: with the source change stashed, the exact-message assertion fails on f28f33828 — the base message is Node's Command failed: … text and the captured stderr never reaches the message.

  • Real coverage: the whole lane ran on macOS 27 arm64, Node 24.18.0 — 21 passed, including the unmodified real-Darwin tests (parser probe, ownership keys, executable padding).

  • Remaining proof gaps: the reporter's mismatched-CLT hang itself was not reproduced (this host has a healthy toolchain); failure shapes are exercised with fake compilers, which is what the lane already uses for this boundary.

  • Observed, derived, and inferred claims remain distinguishable.

  • Artifact identity, source provenance, and failed attempts remain preserved.

  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm run test:focused -- tests/boundary/process/darwinProcessRunTokenReader.test.ts — 21 passed
  • npm run check:fast — green (typecheck, lint)
  • npm run verify:test-discovery — 884 files discovered exactly once
  • npm run check — green (typecheck, lint, format, knip, metadata, architecture guards)
  • Base-failure check via git stash of the source change — new assertion fails on unmodified main

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Failure message text changes for the compile-failure path only.
  • Real Hopper/Ghidra, browser, or OS coverage: real macOS 27 arm64 host for the lane above; Hopper, Ghidra, browser, and Windows not applicable to this code path.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: the excerpt is bounded at 512 characters; no new subprocess, capability, or write path. Request arguments and environment redaction are unchanged.

Review checklist

  • This PR addresses a concrete problem, not an unscoped refactor.
  • The PR has one focused outcome, and the title follows type(scope): outcome.
  • Related issue is linked.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed (none referenced this message).
  • User-visible CLI/MCP changes include representative output (shown in the tests above).
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1999 **Author:** [@jimpablo](https://github.com/jimpablo) **Created:** 10/12/2026 **Status:** ✅ Merged **Merged:** 10/12/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/darwin-compiler-diagnostics` --- ### 📝 Commits (2) - [`8591083`](https://github.com/morluto/rea/commit/85910838bea1ad70a46a238f97489034c1156a8d) fix(process): report the Swift compiler outcome with bounded diagnostics - [`1ccc26e`](https://github.com/morluto/rea/commit/1ccc26e9a083a7892b49dd3c92259841c6c68373) fix(process): keep a signaled compiler's null exit code ### 📊 Changes **2 files changed** (+153 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `src/process/DarwinProcessRunTokenReader.ts` (+56 -8) 📝 `tests/boundary/process/darwinProcessRunTokenReader.test.ts` (+97 -4) </details> ### 📄 Description ## Summary Fixes #1993. The Darwin process-ownership helper compilation surfaced only `cause.code` and `cause.message` from the rejected compile. At the 60 s deadline that produced `compiler result: ETIMEDOUT): Command timed out after 60000 ms: /usr/bin/xcrun` with the compiler's captured stderr discarded, so a broken Swift/SDK pairing was indistinguishable from a genuinely slow compile — the exact report in #1993. ## Problem and expected behavior - Smallest trigger: a Command Line Tools pairing where `xcrun swiftc` prints SDK-mismatch diagnostics and stops responding; the helper failure reports only the generic timeout, with no exit code and no diagnostics. - Violated invariant: a failure must preserve its meaningful reason; the rejected `execFileOutput` error already carries `stdout`/`stderr`, and the reader dropped them. - New behavior: the failure message names the observed compiler outcome — `exit code N`, `timed out after N ms`, or `stopped by signal S` — followed by a bounded stderr excerpt (512 characters, truncation marked), or an explicit `no compiler diagnostics were captured` when nothing was captured. Toolchain breakage is now distinguishable from a slow compile in both shapes. ## Change and scope - `src/process/DarwinProcessRunTokenReader.ts`: the compile `catch` now reads the failure through the existing `execFileOutputFailure` extractor. `compilerOutcome` names the outcome without implying an exit code a timeout lacks; `compilerDiagnostics` bounds the excerpt at 512 characters (following the `stderr_excerpt` precedent in `AdbConfiguration`/`ApktoolConfiguration`) and marks truncation, including the `ERR_CHILD_PROCESS_STDIO_MAXBUFFER` case. `COMPILER_TIMEOUT_MS` replaces the inline `60_000`, and a `compileTimeoutMs` factory option lets verification exercise the deadline in milliseconds; the production default is unchanged. - ENOENT wording and the cancellation mapping are unchanged. `NativeUiHelperRuntime` compiles a sibling Swift helper with the same shape; it is left unchanged here and can follow separately with its own report. - Not attempted: root-causing why the reporter's mismatched-CLT invocation reached the deadline under REA's environment while a direct run failed in ~23 s. This change surfaces whatever the compiler printed in either shape. ## Contract and boundary impact - Semantic owner and earliest changed stage: the Darwin helper compilation failure mapping in `src/process/DarwinProcessRunTokenReader.ts`, before `normalizeCaptureFailure` wraps the message. - CLI and MCP/tool-catalog contract: none. Error message text only; no tool, schema, parameter, or error-code change. - Provider, bridge, target-format, or platform compatibility: macOS-only helper; no engine, bridge, or target-format change. - Evidence, artifact, provenance, or reconstruction contract: none. - Process execution, authorization, cleanup, or containment impact: none. Spawn, stop signal, grace kill, timeout semantics, and root cleanup are unchanged; the existing cancellation and cleanup tests in the same lane are unmodified and green. - Generated metadata, package, or installation impact: none. ## Evidence and regression coverage - Tests added or updated in `tests/boundary/process/darwinProcessRunTokenReader.test.ts`: the fast-failure case now asserts the exact message `…(compiler result: exit code 1): module cache is not writable`; a new deadline case runs a compiler that prints an SDK-style diagnostic and then stops responding, and asserts `…(compiler result: timed out after 500 ms): <diagnostic>`; a new bound case asserts a 600-character diagnostic is cut at 512 characters with an explicit truncation marker. - Base reproduction: with the source change stashed, the exact-message assertion fails on `f28f33828` — the base message is Node's `Command failed: …` text and the captured stderr never reaches the message. - Real coverage: the whole lane ran on macOS 27 arm64, Node 24.18.0 — 21 passed, including the unmodified real-Darwin tests (parser probe, ownership keys, executable padding). - Remaining proof gaps: the reporter's mismatched-CLT hang itself was not reproduced (this host has a healthy toolchain); failure shapes are exercised with fake compilers, which is what the lane already uses for this boundary. - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm run test:focused -- tests/boundary/process/darwinProcessRunTokenReader.test.ts` — 21 passed - `npm run check:fast` — green (typecheck, lint) - `npm run verify:test-discovery` — 884 files discovered exactly once - `npm run check` — green (typecheck, lint, format, knip, metadata, architecture guards) - Base-failure check via `git stash` of the source change — new assertion fails on unmodified main ## Compatibility, safety, and release - Breaking changes or migration steps: none. Failure message text changes for the compile-failure path only. - Real Hopper/Ghidra, browser, or OS coverage: real macOS 27 arm64 host for the lane above; Hopper, Ghidra, browser, and Windows not applicable to this code path. - Package or release metadata impact: none. - Security, privacy, process, or containment review: the excerpt is bounded at 512 characters; no new subprocess, capability, or write path. Request arguments and environment redaction are unchanged. ## Review checklist - [x] This PR addresses a concrete problem, not an unscoped refactor. - [x] The PR has one focused outcome, and the title follows `type(scope): outcome`. - [x] Related issue is linked. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed (none referenced this message). - [x] User-visible CLI/MCP changes include representative output (shown in the tests above). - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 00:57:22 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4956
No description provided.